ADD project's members api

dev_forge
Jasder 5 years ago
parent 29e8337f35
commit 0fbf4a86ec

@ -632,13 +632,18 @@ class ApplicationController < ActionController::Base
render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
end
def find_user_with_id
@user = User.find_by_id params[:user_id]
render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
end
def find_repository
@repo = @user.repositories.find_by_identifier params[:repo_identifier]
render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo
end
def find_project
@project = Project.find_by_identifier! params[:id]
@project = Project.find_by_identifier!(params[:id]) || (Project.find params[:project_id])
render_not_found("未找到’#{params[:id]}’相关的项目") unless @project
end
@ -649,6 +654,14 @@ class ApplicationController < ActionController::Base
tip_exception(e.message)
end
def render_response(interactor)
if interactor.success?
render_ok
else
render_error(interactor.error)
end
end
private
def object_not_found
uid_logger("Missing template or cant't find record, responding with 404")

@ -0,0 +1,59 @@
class MembersController < ApplicationController
before_action :require_login
before_action :find_project_with_id
before_action :find_user_with_id, only: %i[create remove change_role]
before_action :operate!, except: %i[index]
before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role]
def create
interactor = Projects::AddMemberInteractor.call(current_user, @project, @user)
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def index
scope = @project.members.includes(:user, :roles)
@total_count = scope.size
@members = paginate(scope)
end
def remove
interactor = Projects::DeleteMemberInteractor.call(current_user, @project, @user)
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def change_role
interactor = Projects::ChangeMemberRoleInteractor.call(current_user, @project, @user, params[:role])
render_response(interactor)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
private
def can_operate?
current_user.project_manager?(@project)
end
def member_exists?
@project.member?(params[:user_id])
end
def operate!
return render_forbidden('你不是管理员,没有权限操作') unless can_operate?
end
def check_member_exists!
return render_result(1, "user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
end
def check_member_not_exists!
return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
end
end

@ -0,0 +1,10 @@
class Projects::ChangeMemberRoleForm < BaseForm
attr_accessor :user_id, :role
validates :user_id, :role, presence: true
validate :check_roles
def check_roles
raise '无效的role值.' unless ["Manager","Developer", "Reporter"].include? role
end
end

@ -0,0 +1,2 @@
module MembersHelper
end

@ -0,0 +1,42 @@
module Projects
class AddMemberInteractor
def self.call(owner, project, collaborator, permission="write")
interactor = new(owner, project, collaborator, permission)
interactor.run
interactor
end
attr_reader :error, :result
def initialize(owner, project, collaborator, permission)
@owner = owner
@project = project
@collaborator = collaborator
@permission = permission
end
def success?
@error.nil?
end
def run
ActiveRecord::Base.transaction do
gitea_result = Gitea::Repository::Members::AddService.new(owner, project.identifier, collaborator.login, permission).call
if gitea_result.status == 204
project.add_member!(collaborator.id)
end
fail!(nil)
end
rescue Exception => exception
fail!(exception.message)
end
private
attr_reader :owner, :project, :collaborator, :permission
def fail!(error)
@error = error
end
end
end

@ -0,0 +1,51 @@
module Projects
class ChangeMemberRoleInteractor
def self.call(owner, project, collaborator, role)
interactor = new(owner, project, collaborator, role)
interactor.run
interactor
end
attr_reader :error, :result
def initialize(owner, project, collaborator, role)
@owner = owner
@collaborator = collaborator
@project = project
@role = role
end
def success?
@error.nil?
end
def run
Projects::ChangeMemberRoleForm.new({user_id: collaborator.id, role: role}).validate!
ActiveRecord::Base.transaction do
gitea_result = Gitea::Repository::Members::AddService.new(owner, project.identifier, collaborator.login, treated_role).call
if gitea_result.status == 204
Projects::ChangeMemberRoleService.new(project, collaborator.id, role).call
fail!(nil)
end
end
rescue Exception => exception
fail!(exception.message)
end
private
attr_reader :role, :project, :collaborator, :owner
def fail!(error)
@error = error
end
def treated_role
case role
when "Manager" then "admin"
when "Developer" then "write"
when "Reporter" then "read"
end
end
end
end

@ -0,0 +1,41 @@
module Projects
class DeleteMemberInteractor
def self.call(owner, project, collaborator)
interactor = new(owner, project, collaborator)
interactor.run
interactor
end
attr_reader :error, :result
def initialize(owner, project, collaborator)
@owner = owner
@project = project
@collaborator = collaborator
end
def success?
@error.nil?
end
def run
ActiveRecord::Base.transaction do
gitea_result = Gitea::Repository::Members::DeleteService.new(owner, project.identifier, collaborator.login).call
if gitea_result.status == 204
project.remove_member!(collaborator.id)
end
fail!(nil)
end
rescue Exception => exception
fail!(exception.message)
end
private
attr_reader :owner, :project, :collaborator
def fail!(error)
@error = error
end
end
end

@ -0,0 +1,43 @@
module ProjectOperable
extend ActiveSupport::Concern
included do
has_many :members
# has_many :except_owner_members, -> { members.where("members.use_id != ? ", self.owner.id ) }
has_many :manager_members, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
end
def add_member!(user_id, role_name='Developer')
member = members.create!(user_id: user_id)
set_developer_role(member)
end
def remove_member!(user_id)
member = members.find_by(user_id: user_id)
member.destroy! if member && self.user_id != user_id
end
def member?(user_id)
members.exists?(user_id: user_id)
end
# 除了项目创建者本身
def member(user_id)
members.where.not("members.user_id = ? ", owner.id).find_by(user_id: user_id)
end
def change_member_role!(user_id, role)
member = self.member(user_id)
member.member_roles.last.update_attributes!(role: role)
end
def owner?(user)
self.owner == user
end
def set_developer_role(member)
role = Role.find_by_name 'Developer'
member.member_roles.create!(role: role)
end
end

@ -6,4 +6,6 @@ class Member < ApplicationRecord
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
validates :user_id, :project_id, presence: true
end

@ -1,4 +1,6 @@
class MemberRole < ApplicationRecord
belongs_to :role
belongs_to :member
validates :member_id, :role_id, presence: true
end

@ -2,6 +2,7 @@ class Project < ApplicationRecord
include Matchable
include Publicable
include Watchable
include ProjectOperable
enum project_type: { mirror: 1, common: 0 } # common:开源托管项目, mirror:开源镜像项目
@ -14,8 +15,6 @@ class Project < ApplicationRecord
has_many :commits
has_many :members
has_many :manager_members, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
has_one :project_score, dependent: :destroy
has_one :repository, dependent: :destroy
has_many :issue_tags
@ -37,14 +36,6 @@ class Project < ApplicationRecord
User.find(user_id).full_name
end
def project_members
self.members
end
def member?(user)
members.exists?(user_id: user.id) || user.id == self.user_id
end
def members_user_infos
members.joins("left join users on members.user_id = users.id").includes(:user)
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")

@ -2,6 +2,7 @@ class User < ApplicationRecord
include Watchable
include Likeable
include BaseModel
include ProjectOperable
include Searchable::Dependents::User
# Account statuses
@ -32,6 +33,9 @@ class User < ApplicationRecord
LOGIN_CHARS = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z).freeze
# FIX Invalid single-table inheritance type
self.inheritance_column = nil
# educoder: 来自Educoder平台
# trustie: 来自Trustie平台
# forge: 平台本身注册的用户
@ -216,6 +220,10 @@ class User < ApplicationRecord
mail.blank? ? "#{login}@educoder.net" : mail
end
def project_manager?(project)
project.manager_members.exists?(user: self) || self.admin?
end
# 学号
def student_id
self.user_extension.try(:student_id)

@ -0,0 +1,28 @@
# 添加协作者/或者更改协作这的可读写权限
class Gitea::Repository::Members::AddService < Gitea::ClientService
attr_reader :owner, :repo_name, :collaborator, :permission
# owner: owner of the repo
# repo_name: name of the repo
# collaborator: username of the collaborator
# permission: permission name, FIX: admin | read | write
def initialize(owner, repo_name, collaborator, permission)
@owner = owner
@repo_name = repo_name
@collaborator = collaborator
@permission = permission
end
def call
put(url, params)
end
private
def params
Hash.new.merge(token: owner.gitea_token, data: {permission: permission})
end
def url
"/repos/#{owner.login}/#{repo_name}/collaborators/#{collaborator}".freeze
end
end

@ -0,0 +1,25 @@
class Gitea::Repository::Members::DeleteService < Gitea::ClientService
attr_reader :owner, :repo_name, :collaborator
# owner: owner of the repo
# repo_name: name of the repo
# collaborator: username of the collaborator
def initialize(owner, repo_name, collaborator)
@owner = owner
@repo_name = repo_name
@collaborator = collaborator
end
def call
delete(url, params)
end
private
def params
Hash.new.merge(token: owner.gitea_token)
end
def url
"/repos/#{owner.login}/#{repo_name}/collaborators/#{collaborator}".freeze
end
end

@ -0,0 +1,18 @@
class Projects::ChangeMemberRoleService < ApplicationService
attr_reader :project, :user_id, :role
def initialize(project, user_id, role)
@project = project
@user_id = user_id
@role = role
end
def call
ActiveRecord::Base.transaction do
tmp_role = Role.find_by_name role
@project.change_member_role!(user_id, tmp_role)
end
rescue => e
raise Error, e.message
end
end

@ -0,0 +1,4 @@
json.id user.id
json.name user.real_name
json.login user.login
json.image_url url_to_avatar(user)

@ -0,0 +1,6 @@
json.total_count @total_count
json.members @members do |member|
json.partial! 'member', user: member.user
json.is_owner @project.owner?(member.user)
json.role member.roles.last.name
end

@ -74,6 +74,13 @@ Rails.application.routes.draw do
end
end
resources :members, only: [:index, :create] do
collection do
delete :remove
put :change_role
end
end
collection do
post :migrate
get :group_type_list

Loading…
Cancel
Save