| @@ -1,12 +1,14 @@ | |||||
| module PaginateHelper | module PaginateHelper | ||||
| def paginate(objs, **opts) | |||||
| page = params[:page].to_i <= 0 ? 1 : params[:page].to_i | |||||
| per_page = params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : opts[:per_page] || 20 | |||||
| if objs.is_a?(Array) | |||||
| Kaminari.paginate_array(objs).page(page).per(per_page) | |||||
| def paginate(relation) | |||||
| limit = params[:limit] || params[:per_page] | |||||
| limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i | |||||
| page = params[:page].to_i.zero? ? 1 : params[:page].to_i | |||||
| if relation.is_a?(Array) | |||||
| Kaminari.paginate_array(relation).page(page).per(limit) | |||||
| else | else | ||||
| objs.page(page).per(per_page) | |||||
| relation.page(page).per(limit) | |||||
| end | end | ||||
| end | end | ||||
| end | end | ||||
| @@ -1,10 +1,15 @@ | |||||
| class Organizations::BaseController < ApplicationController | class Organizations::BaseController < ApplicationController | ||||
| include ApplicationHelper | include ApplicationHelper | ||||
| include PaginateHelper | |||||
| protected | protected | ||||
| def organization_owner | |||||
| @organization.team_users.joins(:team).where(teams: {authorize: 'owner'}).take.user | |||||
| def can_edit_org? | |||||
| current_user.admin? || @organization.is_owner?(current_user.id) | |||||
| end | |||||
| def check_user_can_edit_org | |||||
| tip_exception("您没有权限进行该操作") unless can_edit_org? | |||||
| end | end | ||||
| def org_limited_condition | def org_limited_condition | ||||
| @@ -16,7 +21,7 @@ class Organizations::BaseController < ApplicationController | |||||
| end | end | ||||
| def team_not_found_condition | def team_not_found_condition | ||||
| @team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user) | |||||
| @team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id) | |||||
| end | end | ||||
| def user_mark | def user_mark | ||||
| @@ -1,7 +1,6 @@ | |||||
| class Organizations::OrganizationUsersController < Organizations::BaseController | class Organizations::OrganizationUsersController < Organizations::BaseController | ||||
| before_action :load_organization | before_action :load_organization | ||||
| before_action :load_operate_user, only: [:destroy] | |||||
| before_action :load_organization_user, only: [:destroy] | |||||
| before_action :load_operate_user, :load_organization_user, :check_user_can_edit_org, only: [:destroy] | |||||
| def index | def index | ||||
| @organization_users = @organization.organization_users.includes(:user) | @organization_users = @organization.organization_users.includes(:user) | ||||
| @@ -10,11 +9,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController | |||||
| end | end | ||||
| def destroy | def destroy | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @organization.is_owner_team_last_one?(@operate_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| @organization_user.destroy! | @organization_user.destroy! | ||||
| TeamUser.where(organization_id: @organization.id, user_id: @operate_user.id).map{|u| u.destroy!} | TeamUser.where(organization_id: @organization.id, user_id: @operate_user.id).map{|u| u.destroy!} | ||||
| Gitea::Organization::OrganizationUser::DeleteService.call(current_user.gitea_token, @organization.login, @operate_user.login) | |||||
| Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, @operate_user.login) | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -25,10 +24,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController | |||||
| def quit | def quit | ||||
| @organization_user = @organization.organization_users.find_by(user_id: current_user.id) | @organization_user = @organization.organization_users.find_by(user_id: current_user.id) | ||||
| tip_exception("您不在该组织中") if @organization_user.nil? | tip_exception("您不在该组织中") if @organization_user.nil? | ||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @organization.is_owner_team_last_one?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| @organization_user.destroy! | @organization_user.destroy! | ||||
| TeamUser.where(organization_id: @organization.id, user_id: current_user.id).map{|u| u.destroy!} | TeamUser.where(organization_id: @organization.id, user_id: current_user.id).map{|u| u.destroy!} | ||||
| Gitea::Organization::OrganizationUser::DeleteService.call(organization_owner.gitea_token, @organization.login, current_user.login) | |||||
| Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, current_user.login) | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -2,6 +2,7 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||||
| before_action :require_login, except: [:index, :show] | before_action :require_login, except: [:index, :show] | ||||
| before_action :convert_base64_image!, only: [:create, :update] | before_action :convert_base64_image!, only: [:create, :update] | ||||
| before_action :load_organization, only: [:show, :update, :destroy] | before_action :load_organization, only: [:show, :update, :destroy] | ||||
| before_action :check_user_can_edit_org, only: [:update, :destroy] | |||||
| def index | def index | ||||
| if current_user.logged? | if current_user.logged? | ||||
| @@ -29,12 +30,11 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||||
| end | end | ||||
| def update | def update | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| login = @organization.login | login = @organization.login | ||||
| @organization.update!(login: organization_params[:name]) if organization_params[:name].present? | @organization.update!(login: organization_params[:name]) if organization_params[:name].present? | ||||
| @organization.organization_extension.update_attributes!(organization_params.except(:name)) | @organization.organization_extension.update_attributes!(organization_params.except(:name)) | ||||
| Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload) | |||||
| Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload) | |||||
| Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -44,9 +44,8 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||||
| def destroy | def destroy | ||||
| tip_exception("密码不正确") unless current_user.check_password?(password) | tip_exception("密码不正确") unless current_user.check_password?(password) | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| Gitea::Organization::DeleteService.call(current_user.gitea_token, @organization.login) | |||||
| Gitea::Organization::DeleteService.call(@organization.gitea_token, @organization.login) | |||||
| @organization.destroy! | @organization.destroy! | ||||
| end | end | ||||
| render_ok | render_ok | ||||
| @@ -0,0 +1,32 @@ | |||||
| class Organizations::ProjectsController < Organizations::BaseController | |||||
| before_action :load_organization | |||||
| def index | |||||
| public_projects_sql = @organization.projects.where(is_public: true).to_sql | |||||
| private_projects_sql = @organization.projects | |||||
| .where(is_public: false) | |||||
| .joins(team_projects: {team: :team_users}) | |||||
| .where(team_users: {user_id: current_user.id}).to_sql | |||||
| @projects = Project.from("( #{ public_projects_sql} UNION #{ private_projects_sql } ) AS projects") | |||||
| @projects = @projects.ransack(name_or_identifier_cont: params[:search]).result if params[:search].present? | |||||
| @projects = @projects.includes(:owner).order("projects.#{sort} #{sort_direction}") | |||||
| @projects = paginate(@projects) | |||||
| end | |||||
| private | |||||
| def load_organization | |||||
| @organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id]) | |||||
| tip_exception("组织不存在") if @organization.nil? | |||||
| tip_exception("没有查看组织的权限") if org_limited_condition || org_privacy_condition | |||||
| end | |||||
| def sort | |||||
| params.fetch(:sort_by, "updated_on") | |||||
| end | |||||
| def sort_direction | |||||
| params.fetch(:sort_direction, "desc") | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,56 @@ | |||||
| class Organizations::TeamProjectsController < Organizations::BaseController | |||||
| before_action :load_organization | |||||
| before_action :load_team | |||||
| before_action :load_operate_project, :check_user_can_edit_org, only: [:create, :destroy] | |||||
| before_action :load_team_project, only: [:destroy] | |||||
| def index | |||||
| @team_projects = @team.team_projects | |||||
| @team_projects = paginate(@team_projects) | |||||
| end | |||||
| def create | |||||
| ActiveRecord::Base.transaction do | |||||
| @team_project = TeamProject.build(@organization.id, @team.id, @operate_project.id) | |||||
| Gitea::Organization::TeamProject::CreateService.call(@organization.gitea_token, @team.gtid, @organization.login, @operate_project.identifier) | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| end | |||||
| def destroy | |||||
| ActiveRecord::Base.transaction do | |||||
| @team_projects.destroy! | |||||
| Gitea::Organization::TeamProject::DeleteService.call(@organization.gitea_token, @team.gtid, @organization.login, @operate_project.identifier) | |||||
| render_ok | |||||
| end | |||||
| rescue Exception => e | |||||
| uid_logger_error(e.message) | |||||
| tip_exception(e.message) | |||||
| end | |||||
| private | |||||
| def load_organization | |||||
| @organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id]) | |||||
| tip_exception("组织不存在") if @organization.nil? | |||||
| tip_exception("没有查看组织的权限") if org_limited_condition || org_privacy_condition | |||||
| end | |||||
| def load_team | |||||
| @team = Team.find_by_id(params[:team_id]) | |||||
| tip_exception("组织团队不存在") if @team.nil? | |||||
| tip_exception("没有查看组织团队的权限") if team_not_found_condition | |||||
| end | |||||
| def load_operate_project | |||||
| @operate_project = Project.find_by(name: params[:id]) || Project.find_by(identifier: params[:id]) | |||||
| tip_exception("项目不存在") if @operate_project.nil? | |||||
| end | |||||
| def load_team_project | |||||
| @team_project = TeamProject.find_by(organization_id: @organization.id, team_id: @team.id, project_id: @operate_project.id) | |||||
| tip_exception("组织团队项目不存在") if @team_project.nil? | |||||
| end | |||||
| end | |||||
| @@ -2,6 +2,7 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||||
| before_action :load_organization, :load_team | before_action :load_organization, :load_team | ||||
| before_action :load_operate_user, only: [:create, :destroy] | before_action :load_operate_user, only: [:create, :destroy] | ||||
| before_action :load_team_user, only: [:destroy] | before_action :load_team_user, only: [:destroy] | ||||
| before_action :check_user_can_edit_org, only: [:create, :destroy] | |||||
| def index | def index | ||||
| @team_users = @team.team_users | @team_users = @team.team_users | ||||
| @@ -10,11 +11,10 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||||
| end | end | ||||
| def create | def create | ||||
| render_forbidden("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) | @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) | ||||
| @organization_user = OrganizationUser.build(@organization.id, @operate_user.id) | @organization_user = OrganizationUser.build(@organization.id, @operate_user.id) | ||||
| Gitea::Organization::TeamUser::CreateService.call(current_user.gitea_token, @team.gtid, @operate_user.login) | |||||
| Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login) | |||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -22,11 +22,10 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||||
| end | end | ||||
| def destroy | def destroy | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @team.owner? && @team.num_users == 1 | |||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @organization.is_owner_team_last_one?(@operate_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| @team_user.destroy! | @team_user.destroy! | ||||
| Gitea::Organization::TeamUser::DeleteService.call(current_user.gitea_token, @team.gtid, @operate_user.login) | |||||
| Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login) | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -37,10 +36,10 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||||
| def quit | def quit | ||||
| @team_user = @team.team_users.find_by(user_id: current_user.id) | @team_user = @team.team_users.find_by(user_id: current_user.id) | ||||
| tip_exception("您不在该组织团队中") if @team_user.nil? | tip_exception("您不在该组织团队中") if @team_user.nil? | ||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @team.owner? && @team.num_users == 1 | |||||
| tip_exception("您不能从 Owner 团队中删除最后一个用户") if @organization.is_owner_team_last_one?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| @team_user.destroy! | @team_user.destroy! | ||||
| Gitea::Organization::TeamUser::DeleteService.call(organization_owner.gitea_token, @team.gtid, current_user.login) | |||||
| Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, current_user.login) | |||||
| render_ok | render_ok | ||||
| end | end | ||||
| rescue Exception => e | rescue Exception => e | ||||
| @@ -1,6 +1,7 @@ | |||||
| class Organizations::TeamsController < Organizations::BaseController | class Organizations::TeamsController < Organizations::BaseController | ||||
| before_action :load_organization | before_action :load_organization | ||||
| before_action :load_team, only: [:show, :update, :destroy] | before_action :load_team, only: [:show, :update, :destroy] | ||||
| before_action :check_user_can_edit_org, only: [:create, :update, :destroy] | |||||
| def index | def index | ||||
| if @organization.is_owner?(current_user) | if @organization.is_owner?(current_user) | ||||
| @@ -16,7 +17,6 @@ class Organizations::TeamsController < Organizations::BaseController | |||||
| end | end | ||||
| def create | def create | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) | @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -24,7 +24,6 @@ class Organizations::TeamsController < Organizations::BaseController | |||||
| end | end | ||||
| def update | def update | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| @team = Organizations::Teams::UpdateService.call(current_user, @team, team_params) | @team = Organizations::Teams::UpdateService.call(current_user, @team, team_params) | ||||
| rescue Exception => e | rescue Exception => e | ||||
| uid_logger_error(e.message) | uid_logger_error(e.message) | ||||
| @@ -32,9 +31,8 @@ class Organizations::TeamsController < Organizations::BaseController | |||||
| end | end | ||||
| def destroy | def destroy | ||||
| tip_exception("您没有权限进行该操作") unless @organization.is_owner?(current_user) | |||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| Gitea::Organization::Team::DeleteService.call(current_user.gitea_token, @team.gtid) | |||||
| Gitea::Organization::Team::DeleteService.call(@organization.gitea_token, @team.gtid) | |||||
| @team.destroy! | @team.destroy! | ||||
| end | end | ||||
| render_ok | render_ok | ||||
| @@ -0,0 +1,12 @@ | |||||
| class OwnersController < ApplicationController | |||||
| before_action :require_login | |||||
| def index | |||||
| @owners = [] | |||||
| @owners += [current_user] | |||||
| @owners += Organization.joins(team_users: :team) | |||||
| .where(team_users: {user_id: current_user.id}, | |||||
| teams: {can_create_org_project: true}) | |||||
| .distinct | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,10 @@ | |||||
| class Projects::TeamsController < Projects::BaseController | |||||
| def index | |||||
| if @project.owner.is_a?(Organization) | |||||
| @teams = @project.owner.teams | |||||
| else | |||||
| @teams = Team.none | |||||
| end | |||||
| @teams = paginate(@teams) | |||||
| end | |||||
| end | |||||
| @@ -163,7 +163,7 @@ class ProjectsController < ApplicationController | |||||
| private | private | ||||
| def project_params | def project_params | ||||
| params.permit(:user_id, :name, :description, :repository_name, | params.permit(:user_id, :name, :description, :repository_name, | ||||
| :project_category_id, :project_language_id, :license_id, :ignore_id) | |||||
| :project_category_id, :project_language_id, :license_id, :ignore_id, :private) | |||||
| end | end | ||||
| def mirror_params | def mirror_params | ||||
| @@ -7,7 +7,7 @@ class Projects::CreateForm < BaseForm | |||||
| :project_category_id, :project_language_id, presence: true | :project_category_id, :project_language_id, presence: true | ||||
| validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | ||||
| validate :check_ignore, :check_license | |||||
| validate :check_ignore, :check_license, :check_owner | |||||
| validate do | validate do | ||||
| check_project_category(project_category_id) | check_project_category(project_category_id) | ||||
| check_project_language(project_language_id) | check_project_language(project_language_id) | ||||
| @@ -20,4 +20,8 @@ class Projects::CreateForm < BaseForm | |||||
| def check_ignore | def check_ignore | ||||
| raise "ignore_id值无效." if ignore_id && Ignore.find_by(id: ignore_id).blank? | raise "ignore_id值无效." if ignore_id && Ignore.find_by(id: ignore_id).blank? | ||||
| end | end | ||||
| def check_owner | |||||
| raise "user_id值无效." if user_id && Owner.find_by(id: user_id).blank? | |||||
| end | |||||
| end | end | ||||
| @@ -143,7 +143,7 @@ module ApplicationHelper | |||||
| def url_to_avatar(source) | def url_to_avatar(source) | ||||
| if File.exist?(disk_filename(source&.class, source&.id)) | if File.exist?(disk_filename(source&.class, source&.id)) | ||||
| ctime = File.ctime(disk_filename(source.class, source.id)).to_i | ctime = File.ctime(disk_filename(source.class, source.id)).to_i | ||||
| if source.class.to_s == 'User' | |||||
| if %w(User Organization).include?(source.class.to_s) | |||||
| File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" | File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" | ||||
| else | else | ||||
| File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" | File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}" | ||||
| @@ -8,6 +8,7 @@ module ProjectOperable | |||||
| has_many :developers, -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member' | has_many :developers, -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member' | ||||
| has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member' | has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member' | ||||
| has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member' | has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member' | ||||
| has_many :team_projects, dependent: :destroy | |||||
| end | end | ||||
| def add_member!(user_id, role_name='Developer') | def add_member!(user_id, role_name='Developer') | ||||
| @@ -21,7 +22,13 @@ module ProjectOperable | |||||
| end | end | ||||
| def member?(user_id) | def member?(user_id) | ||||
| members.exists?(user_id: user_id) | |||||
| if owner.is_a?(User) | |||||
| members.exists?(user_id: user_id) | |||||
| elsif owner.is_a?(Organization) | |||||
| members.exists?(user_id: user_id) || team_projects.joins(team: :team_users).where(team_users: {user_id: user_id}).present? | |||||
| else | |||||
| false | |||||
| end | |||||
| end | end | ||||
| # 除了项目创建者本身 | # 除了项目创建者本身 | ||||
| @@ -35,22 +42,46 @@ module ProjectOperable | |||||
| end | end | ||||
| def owner?(user) | def owner?(user) | ||||
| self.owner == user | |||||
| if owner.is_a?(User) | |||||
| self.owner == user | |||||
| elsif owner.is_a?(Organization) | |||||
| owner.is_owner?(user.id) | |||||
| else | |||||
| false | |||||
| end | |||||
| end | end | ||||
| # 项目管理员(包含项目拥有者),权限:仓库设置、仓库可读可写 | # 项目管理员(包含项目拥有者),权限:仓库设置、仓库可读可写 | ||||
| def manager?(user) | def manager?(user) | ||||
| managers.exists?(user_id: user.id) | |||||
| if owner.is_a?(User) | |||||
| managers.exists?(user_id: user.id) | |||||
| elsif owner.is_a?(Organization) | |||||
| managers.exists?(user_id: user.id) || owner.is_admin?(user.id) | |||||
| else | |||||
| false | |||||
| end | |||||
| end | end | ||||
| # 项目开发者,可读可写权限 | # 项目开发者,可读可写权限 | ||||
| def develper?(user) | def develper?(user) | ||||
| developers.exists?(user_id: user.id) | |||||
| if owner.is_a?(User) | |||||
| developers.exists?(user_id: user.id) | |||||
| elsif owner.is_a?(Organization) | |||||
| developers.exists?(user_id: user.id) || owner.is_write?(user.id) | |||||
| else | |||||
| false | |||||
| end | |||||
| end | end | ||||
| # 报告者,只有可读权限 | # 报告者,只有可读权限 | ||||
| def reporter?(user) | def reporter?(user) | ||||
| reporters.exists?(user_id: user.id) | |||||
| if owner.is_a?(User) | |||||
| reporters.exists?(user_id: user.id) | |||||
| elsif owner.is_a?(Organization) | |||||
| reporters.exists?(user_id: user.id) || owner.is_read?(user.id) | |||||
| else | |||||
| false | |||||
| end | |||||
| end | end | ||||
| def set_developer_role(member) | def set_developer_role(member) | ||||
| @@ -77,8 +77,38 @@ class Organization < Owner | |||||
| self.create!(login: name, gitea_token: gitea_token) | self.create!(login: name, gitea_token: gitea_token) | ||||
| end | end | ||||
| def is_owner?(user) | |||||
| team_users.joins(:team).where(user_id: user.id, teams: {authorize: %w(owner)}).present? | |||||
| def is_owner?(user_id) | |||||
| team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(owner)}).present? | |||||
| end | end | ||||
| def is_admin?(user_id) | |||||
| team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(admin owner)}).present? | |||||
| end | |||||
| def is_write?(user_id) | |||||
| team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(write admin owner)}).present? | |||||
| end | |||||
| def is_read?(user_id) | |||||
| team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read write admin owner)}).present? | |||||
| end | |||||
| # 是不是所有者团队的最后一个成员 | |||||
| def is_owner_team_last_one?(user_id) | |||||
| owner_team_users = team_users.joins(:team).where(teams: {authorize: %w(owner)}) | |||||
| owner_team_users.pluck(:user_id).include?(user_id) && owner_team_users.size == 1 | |||||
| end | |||||
| def real_name | |||||
| login | |||||
| end | |||||
| def show_real_name | |||||
| name = lastname + firstname | |||||
| if name.blank? | |||||
| nickname.blank? ? login : nickname | |||||
| else | |||||
| name | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -5,7 +5,6 @@ | |||||
| # id :integer not null, primary key | # id :integer not null, primary key | ||||
| # user_id :integer | # user_id :integer | ||||
| # organization_id :integer | # organization_id :integer | ||||
| # is_creator :boolean default("0") | |||||
| # created_at :datetime not null | # created_at :datetime not null | ||||
| # updated_at :datetime not null | # updated_at :datetime not null | ||||
| # | # | ||||
| @@ -22,10 +21,10 @@ class OrganizationUser < ApplicationRecord | |||||
| validates :user_id, uniqueness: {scope: :organization_id} | validates :user_id, uniqueness: {scope: :organization_id} | ||||
| def self.build(organization_id, user_id, is_creator = false) | |||||
| def self.build(organization_id, user_id) | |||||
| org_user = self.find_by(organization_id: organization_id, user_id: user_id) | org_user = self.find_by(organization_id: organization_id, user_id: user_id) | ||||
| return org_user unless org_user.nil? | return org_user unless org_user.nil? | ||||
| self.create!(organization_id: organization_id, user_id: user_id, is_creator: is_creator) | |||||
| self.create!(organization_id: organization_id, user_id: user_id) | |||||
| end | end | ||||
| def teams | def teams | ||||
| @@ -1,3 +1,63 @@ | |||||
| # == Schema Information | |||||
| # | |||||
| # Table name: users | |||||
| # | |||||
| # id :integer not null, primary key | |||||
| # login :string(255) default(""), not null | |||||
| # hashed_password :string(40) default(""), not null | |||||
| # firstname :string(30) default(""), not null | |||||
| # lastname :string(255) default(""), not null | |||||
| # mail :string(60) | |||||
| # admin :boolean default("0"), not null | |||||
| # status :integer default("1"), not null | |||||
| # last_login_on :datetime | |||||
| # language :string(5) default("") | |||||
| # auth_source_id :integer | |||||
| # created_on :datetime | |||||
| # updated_on :datetime | |||||
| # type :string(255) | |||||
| # identity_url :string(255) | |||||
| # mail_notification :string(255) default(""), not null | |||||
| # salt :string(64) | |||||
| # gid :integer | |||||
| # visits :integer default("0") | |||||
| # excellent_teacher :integer default("0") | |||||
| # excellent_student :integer default("0") | |||||
| # phone :string(255) | |||||
| # authentication :boolean default("0") | |||||
| # grade :integer default("0") | |||||
| # experience :integer default("0") | |||||
| # nickname :string(255) | |||||
| # show_realname :boolean default("1") | |||||
| # professional_certification :boolean default("0") | |||||
| # ID_number :string(255) | |||||
| # certification :integer default("0") | |||||
| # homepage_teacher :boolean default("0") | |||||
| # homepage_engineer :boolean default("0") | |||||
| # is_test :integer default("0") | |||||
| # ecoder_user_id :integer default("0") | |||||
| # business :boolean default("0") | |||||
| # profile_completed :boolean default("0") | |||||
| # laboratory_id :integer | |||||
| # platform :string(255) default("0") | |||||
| # gitea_token :string(255) | |||||
| # gitea_uid :integer | |||||
| # is_shixun_marker :boolean default("0") | |||||
| # is_sync_pwd :boolean default("1") | |||||
| # watchers_count :integer default("0") | |||||
| # devops_step :integer default("0") | |||||
| # | |||||
| # Indexes | |||||
| # | |||||
| # index_users_on_ecoder_user_id (ecoder_user_id) | |||||
| # index_users_on_homepage_engineer (homepage_engineer) | |||||
| # index_users_on_homepage_teacher (homepage_teacher) | |||||
| # index_users_on_laboratory_id (laboratory_id) | |||||
| # index_users_on_login (login) | |||||
| # index_users_on_mail (mail) | |||||
| # index_users_on_type (type) | |||||
| # | |||||
| class Owner < ApplicationRecord | class Owner < ApplicationRecord | ||||
| self.table_name = "users" | self.table_name = "users" | ||||
| @@ -6,4 +66,4 @@ class Owner < ApplicationRecord | |||||
| has_many :projects, foreign_key: :user_id, dependent: :destroy | has_many :projects, foreign_key: :user_id, dependent: :destroy | ||||
| has_many :repositories, foreign_key: :user_id, dependent: :destroy | has_many :repositories, foreign_key: :user_id, dependent: :destroy | ||||
| end | |||||
| end | |||||
| @@ -40,4 +40,11 @@ class Team < ApplicationRecord | |||||
| can_create_org_project: can_create_org_project) | can_create_org_project: can_create_org_project) | ||||
| end | end | ||||
| def setup_team_project! | |||||
| return unless includes_all_project | |||||
| organization.projects.each do |project| | |||||
| TeamProject.build(organization.id, id, project.id) | |||||
| end | |||||
| end | |||||
| end | end | ||||
| @@ -22,9 +22,9 @@ class TeamProject < ApplicationRecord | |||||
| belongs_to :project | belongs_to :project | ||||
| belongs_to :team, counter_cache: :num_projects | belongs_to :team, counter_cache: :num_projects | ||||
| validates :project_id, uniqueness: {scope: :organization_id} | |||||
| validates :project_id, uniqueness: {scope: [:organization_id, :team_id]} | |||||
| def self.build(organization_id, team_id, project_id) | def self.build(organization_id, team_id, project_id) | ||||
| self.create!(organization_id: organization_id, team_id: team_id, project_id: project_id) | |||||
| self.find_or_create_by!(organization_id: organization_id, team_id: team_id, project_id: project_id) | |||||
| end | end | ||||
| end | end | ||||
| @@ -0,0 +1,25 @@ | |||||
| class Gitea::Organization::Repository::CreateService < Gitea::ClientService | |||||
| attr_reader :token, :org_name, :params | |||||
| def initialize(token, org_name, params) | |||||
| @token = token | |||||
| @org_name = org_name | |||||
| @params = params | |||||
| end | |||||
| def call | |||||
| response = post(url, request_params) | |||||
| render_201_response(response) | |||||
| end | |||||
| private | |||||
| def request_params | |||||
| create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: create_params) | |||||
| end | |||||
| def url | |||||
| "/orgs/#{org_name}/repos".freeze | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,24 @@ | |||||
| class Gitea::Organization::TeamProject::CreateService < Gitea::ClientService | |||||
| attr_reader :token, :gtid, :org_name, :repo_name | |||||
| def initialize(token, gtid, org_name, repo_name) | |||||
| @token = token | |||||
| @gtid = gtid | |||||
| @org_name = org_name | |||||
| @repo_name = repo_name | |||||
| end | |||||
| def call | |||||
| response = put(url, request_params) | |||||
| render_status(response) | |||||
| end | |||||
| private | |||||
| def request_params | |||||
| Hash.new.merge(token: token) | |||||
| end | |||||
| def url | |||||
| "/teams/#{gtid}/repos/#{org_name}/#{repo_name}".freeze | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,24 @@ | |||||
| class Gitea::Organization::TeamProject::DeleteService < Gitea::ClientService | |||||
| attr_reader :token, :gtid, :org_name, :repo_name | |||||
| def initialize(token, gtid, org_name, repo_name) | |||||
| @token = token | |||||
| @gtid = gtid | |||||
| @org_name = org_name | |||||
| @repo_name = repo_name | |||||
| end | |||||
| def call | |||||
| response = delete(url, params) | |||||
| render_status(response) | |||||
| end | |||||
| private | |||||
| def params | |||||
| Hash.new.merge(token: token) | |||||
| end | |||||
| def url | |||||
| "/teams/#{gtid}/repos/#{org_name}/#{repo_name}".freeze | |||||
| end | |||||
| end | |||||
| @@ -63,7 +63,7 @@ class Organizations::CreateService < ApplicationService | |||||
| end | end | ||||
| def create_gitea_org | def create_gitea_org | ||||
| @gitea_organization = Gitea::Organization::CreateService.call(user.gitea_token, organization) | |||||
| @gitea_organization = Gitea::Organization::CreateService.call(@organization.gitea_token, organization) | |||||
| end | end | ||||
| def sync_owner_team_gtid | def sync_owner_team_gtid | ||||
| @@ -16,6 +16,7 @@ class Organizations::Teams::CreateService < ApplicationService | |||||
| create_units | create_units | ||||
| create_gitea_team | create_gitea_team | ||||
| sync_team_gtid | sync_team_gtid | ||||
| team.setup_team_project! | |||||
| end | end | ||||
| Rails.logger.info("######Team create_service end######") | Rails.logger.info("######Team create_service end######") | ||||
| @@ -64,7 +65,7 @@ class Organizations::Teams::CreateService < ApplicationService | |||||
| end | end | ||||
| def create_gitea_team | def create_gitea_team | ||||
| @gitea_team = Gitea::Organization::Team::CreateService.call(user.gitea_token, org, team) | |||||
| @gitea_team = Gitea::Organization::Team::CreateService.call(org.gitea_token, org, team) | |||||
| end | end | ||||
| def sync_team_gtid | def sync_team_gtid | ||||
| @@ -14,6 +14,7 @@ class Organizations::Teams::UpdateService < ApplicationService | |||||
| update_team(update_params) | update_team(update_params) | ||||
| update_units | update_units | ||||
| team.reload | team.reload | ||||
| team.setup_team_project! | |||||
| update_gitea_team | update_gitea_team | ||||
| end | end | ||||
| Rails.logger.info("######Team update_service end######") | Rails.logger.info("######Team update_service end######") | ||||
| @@ -53,6 +54,6 @@ class Organizations::Teams::UpdateService < ApplicationService | |||||
| end | end | ||||
| def update_gitea_team | def update_gitea_team | ||||
| Gitea::Organization::Team::UpdateService.call(user.gitea_token, team) | |||||
| Gitea::Organization::Team::UpdateService.call(team&.organization&.gitea_token, team) | |||||
| end | end | ||||
| end | end | ||||
| @@ -1,5 +1,6 @@ | |||||
| class Repositories::CreateService < ApplicationService | class Repositories::CreateService < ApplicationService | ||||
| attr_reader :user, :project, :params | attr_reader :user, :project, :params | ||||
| attr_accessor :repository, :gitea_repository | |||||
| def initialize(user, project, params) | def initialize(user, project, params) | ||||
| @project = project | @project = project | ||||
| @@ -10,10 +11,10 @@ class Repositories::CreateService < ApplicationService | |||||
| def call | def call | ||||
| @repository = Repository.new(repository_params) | @repository = Repository.new(repository_params) | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| if @repository.save! | |||||
| gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call | |||||
| sync_project(@repository, gitea_repository) | |||||
| sync_repository(@repository, gitea_repository) | |||||
| if repository.save! | |||||
| create_gitea_repository | |||||
| sync_project | |||||
| sync_repository | |||||
| # if project.project_type == "common" | # if project.project_type == "common" | ||||
| # chain_params = { | # chain_params = { | ||||
| # type: "create", | # type: "create", | ||||
| @@ -29,7 +30,7 @@ class Repositories::CreateService < ApplicationService | |||||
| else | else | ||||
| Rails.logger.info("#############___________create_repository_erros______###########{@repository.errors.messages}") | Rails.logger.info("#############___________create_repository_erros______###########{@repository.errors.messages}") | ||||
| end | end | ||||
| @repository | |||||
| repository | |||||
| end | end | ||||
| rescue => e | rescue => e | ||||
| puts "create repository service error: #{e.message}" | puts "create repository service error: #{e.message}" | ||||
| @@ -38,7 +39,16 @@ class Repositories::CreateService < ApplicationService | |||||
| private | private | ||||
| def sync_project(repository, gitea_repository) | |||||
| def create_gitea_repository | |||||
| if project.owner.is_a?(User) | |||||
| @gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call | |||||
| elsif project.owner.is_a?(Organization) | |||||
| @gitea_repository = Gitea::Organization::Repository::CreateService.call(user.gitea_token, project.owner.login, gitea_repository_params) | |||||
| project.owner.teams.map{|t|t.setup_team_project!} | |||||
| end | |||||
| end | |||||
| def sync_project | |||||
| if gitea_repository | if gitea_repository | ||||
| project.update_columns( | project.update_columns( | ||||
| gpid: gitea_repository["id"], | gpid: gitea_repository["id"], | ||||
| @@ -47,7 +57,7 @@ class Repositories::CreateService < ApplicationService | |||||
| end | end | ||||
| end | end | ||||
| def sync_repository(repository, gitea_repository) | |||||
| def sync_repository | |||||
| repository.update_columns(url: remote_repository_url,) if gitea_repository | repository.update_columns(url: remote_repository_url,) if gitea_repository | ||||
| end | end | ||||
| @@ -0,0 +1,7 @@ | |||||
| json.total_count @projects.total_count | |||||
| json.projects @projects.each do |project| | |||||
| json.(project, :name, :identifier, :description, :forked_count, :praises_count) | |||||
| json.praised project.praised_by?(current_user) | |||||
| json.last_update_time render_unix_time(project.updated_on) | |||||
| json.time_ago time_from_now(project.updated_on) | |||||
| end | |||||
| @@ -0,0 +1,7 @@ | |||||
| json.total_count @owners.size | |||||
| json.owners @owners.each do |owner| | |||||
| json.id owner.id | |||||
| json.type owner.type | |||||
| json.name owner.login | |||||
| json.avatar_url url_to_avatar(owner) | |||||
| end | |||||
| @@ -0,0 +1,4 @@ | |||||
| json.total_count @teams.total_count | |||||
| json.teams @teams.each do |team| | |||||
| json.(team, :id, :name, :authorize) | |||||
| end | |||||
| @@ -103,6 +103,8 @@ Rails.application.routes.draw do | |||||
| put 'commons/unhidden', to: 'commons#unhidden' | put 'commons/unhidden', to: 'commons#unhidden' | ||||
| delete 'commons/delete', to: 'commons#delete' | delete 'commons/delete', to: 'commons#delete' | ||||
| resources :owners, only: [:index] | |||||
| scope module: :organizations do | scope module: :organizations do | ||||
| resources :organizations, except: [:edit, :new] do | resources :organizations, except: [:edit, :new] do | ||||
| resources :organization_users, only: [:index, :destroy] do | resources :organization_users, only: [:index, :destroy] do | ||||
| @@ -118,6 +120,7 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| resources :team_projects, only: [:index, :create, :destroy] do ;end | resources :team_projects, only: [:index, :create, :destroy] do ;end | ||||
| end | end | ||||
| resources :projects, only: [:index] | |||||
| end | end | ||||
| end | end | ||||
| @@ -512,6 +515,7 @@ Rails.application.routes.draw do | |||||
| end | end | ||||
| scope module: :projects do | scope module: :projects do | ||||
| resources :teams, only: [:index] | |||||
| scope do | scope do | ||||
| get( | get( | ||||
| '/blob/*id/diff', | '/blob/*id/diff', | ||||
| @@ -3,7 +3,6 @@ class CreateOrganizationUsers < ActiveRecord::Migration[5.2] | |||||
| create_table :organization_users do |t| | create_table :organization_users do |t| | ||||
| t.references :user | t.references :user | ||||
| t.references :organization | t.references :organization | ||||
| t.boolean :is_creator, comment: "是否为创建者", default: false | |||||
| t.timestamps | t.timestamps | ||||
| end | end | ||||