合并组织模块功能
This commit is contained in:
commit
8e4d6c7064
|
@ -36,6 +36,7 @@ public/react/yarn.lock
|
|||
/.idea/*
|
||||
|
||||
# Ignore react node_modules
|
||||
public/react/*
|
||||
/public/react/.cache
|
||||
/public/react/node_modules/
|
||||
/public/react/config/stats.json
|
||||
|
|
|
@ -113,6 +113,8 @@ http://localhost:3000/
|
|||
|
||||
### API
|
||||
- [API](api_document.md)
|
||||
- [API](showdoc.com.cn)
|
||||
账号:forgeplus@admin.com 密码:forge123
|
||||
|
||||
## 贡献代码
|
||||
|
||||
|
|
|
@ -680,6 +680,14 @@ class ApplicationController < ActionController::Base
|
|||
relation.page(page).per(limit)
|
||||
end
|
||||
|
||||
def kaminari_array_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
|
||||
|
||||
Kaminari.paginate_array(relation).page(page).per(limit)
|
||||
end
|
||||
|
||||
def strf_time(time)
|
||||
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
end
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
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
|
||||
objs.page(page).per(per_page)
|
||||
relation.page(page).per(limit)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
class Organizations::BaseController < ApplicationController
|
||||
include ApplicationHelper
|
||||
include PaginateHelper
|
||||
|
||||
protected
|
||||
|
||||
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
|
||||
|
||||
def org_limited_condition
|
||||
@organization.organization_extension.limited? && !current_user.logged?
|
||||
end
|
||||
|
||||
def org_privacy_condition
|
||||
@organization.organization_extension.privacy? && @organization.organization_users.where(user_id: current_user.id).blank?
|
||||
end
|
||||
|
||||
def team_not_found_condition
|
||||
@team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id)
|
||||
end
|
||||
|
||||
def user_mark
|
||||
params[:username] || params[:id]
|
||||
end
|
||||
|
||||
def project_mark
|
||||
params[:repo_name] || params[:id]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
class Organizations::OrganizationUsersController < Organizations::BaseController
|
||||
before_action :load_organization
|
||||
before_action :load_operate_user, :load_organization_user, :check_user_can_edit_org, only: [:destroy]
|
||||
|
||||
def index
|
||||
@organization_users = @organization.organization_users.includes(:user)
|
||||
search = params[:search].to_s.downcase
|
||||
@organization_users = @organization_users.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
|
||||
|
||||
@organization_users = kaminari_paginate(@organization_users)
|
||||
end
|
||||
|
||||
def destroy
|
||||
tip_exception("您不能从所有者团队中删除最后一个用户") if @organization.is_owner_team_last_one?(@operate_user.id)
|
||||
ActiveRecord::Base.transaction do
|
||||
@organization_user.destroy!
|
||||
TeamUser.where(organization_id: @organization.id, user_id: @operate_user.id).map{|u| u.destroy!}
|
||||
Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, @operate_user.login)
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def quit
|
||||
@organization_user = @organization.organization_users.find_by(user_id: current_user.id)
|
||||
tip_exception("您不在该组织中") if @organization_user.nil?
|
||||
tip_exception("您不能从所有者团队中删除最后一个用户") if @organization.is_owner_team_last_one?(current_user.id)
|
||||
ActiveRecord::Base.transaction do
|
||||
@organization_user.destroy!
|
||||
TeamUser.where(organization_id: @organization.id, user_id: current_user.id).map{|u| u.destroy!}
|
||||
Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, current_user.login)
|
||||
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])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def load_operate_user
|
||||
@operate_user = User.find_by(login: user_mark) if user_mark.present?
|
||||
tip_exception("平台用户不存在") if @operate_user.nil?
|
||||
end
|
||||
|
||||
def load_organization_user
|
||||
@organization_user = OrganizationUser.find_by(organization_id: @organization.id, user_id: @operate_user.id)
|
||||
tip_exception("组织成员不存在") if @organization_user.nil?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,106 @@
|
|||
class Organizations::OrganizationsController < Organizations::BaseController
|
||||
before_action :require_login, except: [:index, :show]
|
||||
before_action :convert_image!, only: [:create, :update]
|
||||
before_action :load_organization, only: [:show, :update, :destroy]
|
||||
before_action :check_user_can_edit_org, only: [:update, :destroy]
|
||||
|
||||
def index
|
||||
if current_user.logged?
|
||||
logged_organizations_sql = Organization.with_visibility(%w(common limited)).to_sql
|
||||
privacy_organizations_sql = Organization.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).to_sql
|
||||
@organizations = Organization.from("( #{ logged_organizations_sql } UNION #{ privacy_organizations_sql } ) AS users")
|
||||
else
|
||||
@organizations = Organization.with_visibility("common")
|
||||
end
|
||||
@organizations = @organizations.ransack(login_cont: params[:search]).result if params[:search].present?
|
||||
@organizations = @organizations.includes(:organization_extension).order("organization_extensions.#{sort_by} #{sort_direction}")
|
||||
@organizations = kaminari_paginate(@organizations)
|
||||
end
|
||||
|
||||
def show
|
||||
@can_create_project = @organization.can_create_project?(current_user.id)
|
||||
@is_admin = can_edit_org?
|
||||
@is_member = @organization.is_member?(current_user.id)
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
login = @organization.login
|
||||
@organization.update!(login: organization_params[:name]) if organization_params[:name].present?
|
||||
@organization.organization_extension.update_attributes!(organization_params.except(:name))
|
||||
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
tip_exception("密码不正确") unless current_user.check_password?(password)
|
||||
ActiveRecord::Base.transaction do
|
||||
Gitea::Organization::DeleteService.call(@organization.gitea_token, @organization.login)
|
||||
@organization.destroy!
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def convert_image!
|
||||
return unless params[:image].present?
|
||||
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
||||
if params[:image].class == ActionDispatch::Http::UploadedFile
|
||||
@image = params[:image]
|
||||
render_error('请上传文件') if @image.size.zero?
|
||||
render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||
else
|
||||
image = params[:image].to_s.strip
|
||||
return render_error('请上传正确的图片') if image.blank?
|
||||
@image = Util.convert_base64_image(image, max_size: max_size.to_i)
|
||||
end
|
||||
rescue Base64ImageConverter::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
def avatar_path(organization)
|
||||
ApplicationController.helpers.disk_filename(organization.class, organization.id)
|
||||
end
|
||||
|
||||
def organization_params
|
||||
params.permit(:name, :description, :website, :location,
|
||||
:repo_admin_change_team_access, :visibility,
|
||||
:max_repo_creation)
|
||||
end
|
||||
|
||||
def password
|
||||
params.fetch(:password, "")
|
||||
end
|
||||
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:id]) || Organization.find_by(id: params[:id])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def sort_by
|
||||
params.fetch(:sort_by, "created_at")
|
||||
end
|
||||
|
||||
def sort_direction
|
||||
params.fetch(:sort_direction, "desc")
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
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
|
||||
|
||||
def search
|
||||
tip_exception("请输入搜索关键词") if params[:search].nil?
|
||||
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
|
||||
@projects = @projects.includes(:owner).order("projects.#{sort} #{sort_direction}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") 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,58 @@
|
|||
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
|
||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||
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
|
||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_project.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])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def load_team
|
||||
@team = Team.find_by_id(params[:team_id])
|
||||
return render_not_found("组织团队不存在") if @team.nil?
|
||||
return render_forbidden("没有查看组织团队的权限") if team_not_found_condition
|
||||
end
|
||||
|
||||
def load_operate_project
|
||||
@operate_project = Project.find_by(id: project_mark) || Project.find_by(identifier: project_mark)
|
||||
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
|
|
@ -0,0 +1,76 @@
|
|||
class Organizations::TeamUsersController < Organizations::BaseController
|
||||
before_action :load_organization, :load_team
|
||||
before_action :load_operate_user, only: [:create, :destroy]
|
||||
before_action :load_team_user, only: [:destroy]
|
||||
before_action :check_user_can_edit_org, only: [:create, :destroy]
|
||||
|
||||
def index
|
||||
@team_users = @team.team_users.includes(:user)
|
||||
|
||||
search = params[:search].to_s.downcase
|
||||
@team_users = @team_users.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
|
||||
|
||||
@team_users = kaminari_paginate(@team_users)
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
||||
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
||||
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
tip_exception("您不能从所有者团队中删除最后一个用户") if @team.owner? && @organization.is_owner_team_last_one?(@operate_user.id)
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_user.destroy!
|
||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def quit
|
||||
@team_user = @team.team_users.find_by(user_id: current_user.id)
|
||||
tip_exception("您不在该组织团队中") if @team_user.nil?
|
||||
tip_exception("您不能从所有者团队中删除最后一个用户") if @team.owner? && @organization.is_owner_team_last_one?(current_user.id)
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_user.destroy!
|
||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, current_user.login)
|
||||
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])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def load_team
|
||||
@team = Team.find_by_id(params[:team_id])
|
||||
return render_not_found("组织团队不存在") if @team.nil?
|
||||
return render_forbidden("没有查看组织团队的权限") if team_not_found_condition
|
||||
end
|
||||
|
||||
def load_operate_user
|
||||
@operate_user = User.find_by(login: user_mark) if user_mark.present?
|
||||
tip_exception("平台用户不存在") if @operate_user.nil?
|
||||
end
|
||||
|
||||
def load_team_user
|
||||
@team_user = TeamUser.find_by(team_id: @team.id, user_id: @operate_user.id)
|
||||
tip_exception("组织团队成员不存在") if @team_user.nil?
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
class Organizations::TeamsController < Organizations::BaseController
|
||||
before_action :load_organization
|
||||
before_action :load_team, only: [:show, :update, :destroy]
|
||||
before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
|
||||
|
||||
def index
|
||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
#else
|
||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
#end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
|
||||
@teams = kaminari_paginate(@teams)
|
||||
end
|
||||
|
||||
def search
|
||||
tip_exception("请输入搜索关键词") if params[:search].nil?
|
||||
if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
else
|
||||
@teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.ransack(name_cont: params[:search]).result if params[:search].present?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
end
|
||||
|
||||
def show
|
||||
@is_admin = can_edit_org?
|
||||
@is_member = @team.is_member?(current_user.id)
|
||||
end
|
||||
|
||||
def create
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def update
|
||||
@team = Organizations::Teams::UpdateService.call(current_user, @team, team_params)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
tip_exception("组织团队不允许被删除") if @team.owner?
|
||||
ActiveRecord::Base.transaction do
|
||||
Gitea::Organization::Team::DeleteService.call(@organization.gitea_token, @team.gtid)
|
||||
@team.destroy!
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def team_params
|
||||
params.permit(:name, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => [])
|
||||
end
|
||||
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
|
||||
return render_not_found("组织不存在") if @organization.nil?
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
end
|
||||
|
||||
def load_team
|
||||
@team = Team.find_by_id(params[:id])
|
||||
return render_not_found("组织团队不存在") if @team.nil?
|
||||
return render_forbidden("没有查看组织团队的权限") if team_not_found_condition
|
||||
end
|
||||
end
|
|
@ -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,47 @@
|
|||
class Projects::TeamsController < Projects::BaseController
|
||||
before_action :load_operate_team, only: [:create, :destroy]
|
||||
before_action :load_team_project, only: :destroy
|
||||
|
||||
def index
|
||||
if @project.owner.is_a?(Organization)
|
||||
@teams = Team.joins(:team_projects).where(team_projects: {project_id: @project.id})
|
||||
else
|
||||
@teams = Team.none
|
||||
end
|
||||
@teams = paginate(@teams)
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_project = TeamProject.build(@owner.id, @operate_team.id, @project.id)
|
||||
Gitea::Organization::TeamProject::CreateService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
ActiveRecord::Base.transaction do
|
||||
@team_project.destroy!
|
||||
Gitea::Organization::TeamProject::DeleteService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier)
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def load_operate_team
|
||||
@operate_team = Team.find_by(id: params[:team_id]) || Team.find_by(id: params[:id])
|
||||
tip_exception("项目不存在") if @operate_team.nil?
|
||||
tip_exception("该组织团队拥有组织所有项目,无法进行操作") if @operate_team.includes_all_project
|
||||
end
|
||||
|
||||
def load_team_project
|
||||
@team_project = TeamProject.find_by(organization_id: @owner.id, team_id: @operate_team.id, project_id: @project.id)
|
||||
tip_exception("组织团队项目不存在") if @team_project.nil?
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@ class ProjectsController < ApplicationController
|
|||
scope = Projects::ListQuery.call(params)
|
||||
|
||||
# @projects = kaminari_paginate(scope)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, owner: :user_extension)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner)
|
||||
|
||||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
|
@ -128,7 +128,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def recommend
|
||||
@projects = Project.recommend.includes(:repository, :project_category, owner: :user_extension).limit(5)
|
||||
@projects = Project.recommend.includes(:repository, :project_category, :owner).limit(5)
|
||||
end
|
||||
|
||||
def about
|
||||
|
@ -163,7 +163,7 @@ class ProjectsController < ApplicationController
|
|||
private
|
||||
def project_params
|
||||
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
|
||||
|
||||
def mirror_params
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
class Users::OrganizationsController < Users::BaseController
|
||||
|
||||
def index
|
||||
if current_user.logged?
|
||||
logged_organizations_sql = observed_user.organizations.with_visibility(%w(common limited)).to_sql
|
||||
privacy_organizations_sql = observed_user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).to_sql
|
||||
@organizations = Organization.from("( #{ logged_organizations_sql } UNION #{ privacy_organizations_sql } ) AS users")
|
||||
else
|
||||
@organizations = observed_user.organizations.with_visibility("common")
|
||||
end
|
||||
|
||||
@organizations = @organizations.ransack(login_cont: params[:search]).result if params[:search].present?
|
||||
@organizations = @organizations.includes(:organization_extension).order("organization_extensions.#{sort_by} #{sort_direction}")
|
||||
@organizations = kaminari_paginate(@organizations)
|
||||
end
|
||||
|
||||
private
|
||||
def sort_by
|
||||
params.fetch(:sort_by, "created_at")
|
||||
end
|
||||
|
||||
def sort_direction
|
||||
params.fetch(:sort_direction, "desc")
|
||||
end
|
||||
end
|
|
@ -31,6 +31,7 @@ class UsersController < ApplicationController
|
|||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
@user_org_count = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)).size + @user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).size : @user.organizations.with_visibility("common").size
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
|
|
|
@ -124,7 +124,7 @@ class VersionReleasesController < ApplicationController
|
|||
|
||||
private
|
||||
def set_user
|
||||
@user = @repository.user
|
||||
@user = @repository.owner
|
||||
end
|
||||
|
||||
def find_version
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
class Projects::CreateForm < BaseForm
|
||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
||||
:project_language_id, :ignore_id, :license_id, :private
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner
|
||||
|
||||
validates :user_id, :name, :description,:repository_name,
|
||||
:project_category_id, :project_language_id, presence: true
|
||||
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
validate :check_ignore, :check_license
|
||||
validate :check_ignore, :check_license, :check_owner, :check_max_repo_creation
|
||||
validate do
|
||||
check_project_category(project_category_id)
|
||||
check_project_language(project_language_id)
|
||||
|
@ -20,4 +20,15 @@ class Projects::CreateForm < BaseForm
|
|||
def check_ignore
|
||||
raise "ignore_id值无效." if ignore_id && Ignore.find_by(id: ignore_id).blank?
|
||||
end
|
||||
|
||||
def check_owner
|
||||
@owner = Owner.find_by(id: user_id)
|
||||
raise "user_id值无效." if user_id && owner.blank?
|
||||
end
|
||||
|
||||
def check_max_repo_creation
|
||||
return unless owner.is_a?(Organization)
|
||||
return if owner.max_repo_creation <= -1
|
||||
raise "已超过组织设置最大仓库数" if owner.max_repo_creation == owner.num_projects
|
||||
end
|
||||
end
|
||||
|
|
|
@ -143,7 +143,7 @@ module ApplicationHelper
|
|||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
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}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
|
|
|
@ -61,12 +61,14 @@ module ProjectsHelper
|
|||
{
|
||||
login: project.project_educoder.owner,
|
||||
name: project.project_educoder.owner,
|
||||
type: 'Educoder',
|
||||
image_url: project.project_educoder.image_url
|
||||
}
|
||||
else
|
||||
{
|
||||
login: @owner.login,
|
||||
name: @owner.real_name,
|
||||
type: @owner.type,
|
||||
image_url: url_to_avatar(@owner)
|
||||
}
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class SyncMirroredRepositoryJob < ApplicationJob
|
|||
repo = Repository.find_by(id: repo_id)
|
||||
current_user = User.find_by(id: user_id)
|
||||
return if repo.blank? || current_user.blank?
|
||||
result = Gitea::Repository::SyncMirroredService.new(repo.user.login, repo.identifier, token: current_user.gitea_token).call
|
||||
result = Gitea::Repository::SyncMirroredService.new(repo.owner.login, repo.identifier, token: current_user.gitea_token).call
|
||||
repo&.mirror.set_status! if result[:status] === 200
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,11 +8,12 @@ module ProjectOperable
|
|||
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 :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member'
|
||||
has_many :team_projects, dependent: :destroy
|
||||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
member = members.create!(user_id: user_id)
|
||||
set_developer_role(member)
|
||||
set_developer_role(member, role_name)
|
||||
end
|
||||
|
||||
def remove_member!(user_id)
|
||||
|
@ -21,7 +22,13 @@ module ProjectOperable
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
# 除了项目创建者本身
|
||||
|
@ -35,26 +42,50 @@ module ProjectOperable
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
# 项目管理员(包含项目拥有者),权限:仓库设置、仓库可读可写
|
||||
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
|
||||
|
||||
# 项目开发者,可读可写权限
|
||||
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
|
||||
|
||||
# 报告者,只有可读权限
|
||||
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
|
||||
|
||||
def set_developer_role(member)
|
||||
role = Role.find_by_name 'Developer'
|
||||
def set_developer_role(member, role_name)
|
||||
role = Role.find_by(name: role_name)
|
||||
member.member_roles.create!(role: role)
|
||||
end
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
# sync_subject :boolean default("0")
|
||||
# sync_shixun :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_laboratories_on_identifier (identifier) UNIQUE
|
||||
# index_laboratories_on_school_id (school_id)
|
||||
#
|
||||
|
||||
class Laboratory < ApplicationRecord
|
||||
belongs_to :school, optional: true
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
# laboratory_id :integer
|
||||
# config :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_laboratory_settings_on_laboratory_id (laboratory_id)
|
||||
#
|
||||
|
||||
class LaboratorySetting < ApplicationRecord
|
||||
belongs_to :laboratory
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
# == 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 Organization < Owner
|
||||
alias_attribute :name, :login
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
|
||||
default_scope { where(type: "Organization") }
|
||||
|
||||
has_one :organization_extension, dependent: :destroy
|
||||
has_many :teams, dependent: :destroy
|
||||
has_many :organization_users, dependent: :destroy
|
||||
has_many :team_users, dependent: :destroy
|
||||
|
||||
validates :login, presence: true
|
||||
validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, case_sensitive: false
|
||||
validates :login, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
delegate :description, :website, :location, :repo_admin_change_team_access,
|
||||
:visibility, :max_repo_creation, :num_projects, :num_users, :num_teams, to: :organization_extension, allow_nil: true
|
||||
|
||||
scope :with_visibility, ->(visibility) { joins(:organization_extension).where(organization_extensions: {visibility: visibility}) if visibility.present? }
|
||||
|
||||
def self.build(name, gitea_token=nil)
|
||||
self.create!(login: name, gitea_token: gitea_token)
|
||||
end
|
||||
|
||||
def can_create_project?(user_id)
|
||||
team_users.joins(:team).where(user_id: user_id, teams: {can_create_org_project: true}).present?
|
||||
end
|
||||
|
||||
def is_member?(user_id)
|
||||
organization_users.where(user_id: user_id).present?
|
||||
end
|
||||
|
||||
def is_owner?(user_id)
|
||||
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(owner)}).present?
|
||||
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
|
|
@ -0,0 +1,42 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: organization_extensions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# organization_id :integer
|
||||
# description :string(255)
|
||||
# website :string(255)
|
||||
# location :string(255)
|
||||
# repo_admin_change_team_access :boolean default("0")
|
||||
# visibility :integer default("0")
|
||||
# max_repo_creation :integer default("-1")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# num_projects :integer default("0")
|
||||
# num_users :integer default("0")
|
||||
# num_teams :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_organization_extensions_on_organization_id (organization_id)
|
||||
#
|
||||
|
||||
class OrganizationExtension < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
has_many :organization_users, foreign_key: :organization_id, primary_key: :organization_id
|
||||
has_many :projects, foreign_key: :user_id, primary_key: :organization_id
|
||||
has_many :teams, foreign_key: :organization_id, primary_key: :organization_id
|
||||
|
||||
enum visibility: {common: 0, limited: 1, privacy: 2}
|
||||
|
||||
def self.build(organization_id, description, website, location, repo_admin_change_team_access, visibility, max_repo_creation)
|
||||
self.create!(organization_id: organization_id,
|
||||
description: description,
|
||||
website: website,
|
||||
location: location,
|
||||
repo_admin_change_team_access: repo_admin_change_team_access,
|
||||
visibility: visibility,
|
||||
max_repo_creation: max_repo_creation)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: organization_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# organization_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_organization_users_on_organization_id (organization_id)
|
||||
# index_organization_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OrganizationUser < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
belongs_to :organization_extension, foreign_key: :organization_id, primary_key: :organization_id, counter_cache: :num_users
|
||||
belongs_to :user
|
||||
|
||||
validates :user_id, uniqueness: {scope: :organization_id}
|
||||
|
||||
def self.build(organization_id, user_id)
|
||||
org_user = self.find_by(organization_id: organization_id, user_id: user_id)
|
||||
return org_user unless org_user.nil?
|
||||
self.create!(organization_id: organization_id, user_id: user_id)
|
||||
end
|
||||
|
||||
def teams
|
||||
organization.teams.joins(:team_users).where(team_users: {user_id: user_id})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
# == 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
|
||||
self.table_name = "users"
|
||||
|
||||
include ProjectAbility
|
||||
|
||||
has_many :projects, foreign_key: :user_id, dependent: :destroy
|
||||
has_many :repositories, foreign_key: :user_id, dependent: :destroy
|
||||
end
|
|
@ -1,73 +1,74 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# homepage :string(255) default("")
|
||||
# is_public :boolean default("1"), not null
|
||||
# parent_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# identifier :string(255)
|
||||
# status :integer default("1"), not null
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# inherit_members :boolean default("0"), not null
|
||||
# project_type :integer default("0")
|
||||
# hidden_repo :boolean default("0"), not null
|
||||
# attachmenttype :integer default("1")
|
||||
# user_id :integer
|
||||
# dts_test :integer default("0")
|
||||
# enterprise_name :string(255)
|
||||
# organization_id :integer
|
||||
# project_new_type :integer
|
||||
# gpid :integer
|
||||
# forked_from_project_id :integer
|
||||
# forked_count :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# hot :integer default("0")
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# script :text(65535)
|
||||
# training_status :integer default("0")
|
||||
# rep_identifier :string(255)
|
||||
# project_category_id :integer
|
||||
# project_language_id :integer
|
||||
# license_id :integer
|
||||
# ignore_id :integer
|
||||
# praises_count :integer default("0")
|
||||
# watchers_count :integer default("0")
|
||||
# issues_count :integer default("0")
|
||||
# pull_requests_count :integer default("0")
|
||||
# language :string(255)
|
||||
# versions_count :integer default("0")
|
||||
# issue_tags_count :integer default("0")
|
||||
# closed_issues_count :integer default("0")
|
||||
# open_devops :boolean default("0")
|
||||
# gitea_webhook_id :integer
|
||||
# open_devops_count :integer default("0")
|
||||
# recommend :boolean default("0")
|
||||
# platform :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
||||
# index_projects_on_identifier (identifier)
|
||||
# index_projects_on_is_public (is_public)
|
||||
# index_projects_on_lft (lft)
|
||||
# index_projects_on_name (name)
|
||||
# index_projects_on_platform (platform)
|
||||
# index_projects_on_project_type (project_type)
|
||||
# index_projects_on_recommend (recommend)
|
||||
# index_projects_on_rgt (rgt)
|
||||
# index_projects_on_status (status)
|
||||
# index_projects_on_updated_on (updated_on)
|
||||
#
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# homepage :string(255) default("")
|
||||
# is_public :boolean default("1"), not null
|
||||
# parent_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# identifier :string(255)
|
||||
# status :integer default("1"), not null
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# inherit_members :boolean default("0"), not null
|
||||
# project_type :integer default("0")
|
||||
# hidden_repo :boolean default("0"), not null
|
||||
# attachmenttype :integer default("1")
|
||||
# user_id :integer
|
||||
# dts_test :integer default("0")
|
||||
# enterprise_name :string(255)
|
||||
# organization_id :integer
|
||||
# project_new_type :integer
|
||||
# gpid :integer
|
||||
# forked_from_project_id :integer
|
||||
# forked_count :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# hot :integer default("0")
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# script :text(65535)
|
||||
# training_status :integer default("0")
|
||||
# rep_identifier :string(255)
|
||||
# project_category_id :integer
|
||||
# project_language_id :integer
|
||||
# license_id :integer
|
||||
# ignore_id :integer
|
||||
# praises_count :integer default("0")
|
||||
# watchers_count :integer default("0")
|
||||
# issues_count :integer default("0")
|
||||
# pull_requests_count :integer default("0")
|
||||
# language :string(255)
|
||||
# versions_count :integer default("0")
|
||||
# issue_tags_count :integer default("0")
|
||||
# closed_issues_count :integer default("0")
|
||||
# open_devops :boolean default("0")
|
||||
# gitea_webhook_id :integer
|
||||
# open_devops_count :integer default("0")
|
||||
# recommend :boolean default("0")
|
||||
# platform :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
||||
# index_projects_on_identifier (identifier)
|
||||
# index_projects_on_is_public (is_public)
|
||||
# index_projects_on_lft (lft)
|
||||
# index_projects_on_name (name)
|
||||
# index_projects_on_platform (platform)
|
||||
# index_projects_on_project_type (project_type)
|
||||
# index_projects_on_recommend (recommend)
|
||||
# index_projects_on_rgt (rgt)
|
||||
# index_projects_on_status (status)
|
||||
# index_projects_on_updated_on (updated_on)
|
||||
#
|
||||
|
||||
|
||||
class Project < ApplicationRecord
|
||||
include Matchable
|
||||
include Publicable
|
||||
|
@ -85,7 +86,8 @@ class Project < ApplicationRecord
|
|||
|
||||
belongs_to :ignore, optional: true
|
||||
belongs_to :license, optional: true
|
||||
belongs_to :owner, class_name: 'User', foreign_key: :user_id, optional: true
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
||||
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
|
||||
belongs_to :project_category, optional: true , :counter_cache => true
|
||||
belongs_to :project_language, optional: true , :counter_cache => true
|
||||
has_many :project_trends, dependent: :destroy
|
||||
|
@ -106,6 +108,7 @@ class Project < ApplicationRecord
|
|||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||
has_one :project_detail, dependent: :destroy
|
||||
has_many :team_projects, dependent: :destroy
|
||||
|
||||
after_save :check_project_members
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
|
@ -248,7 +251,7 @@ class Project < ApplicationRecord
|
|||
def self.find_with_namespace(namespace_path, identifier)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = User.find_by_login namespace_path
|
||||
user = Owner.find_by_login namespace_path
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
return nil if project.blank?
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
class Repository < ApplicationRecord
|
||||
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
|
||||
belongs_to :project, :touch => true
|
||||
belongs_to :user, optional: true
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
||||
has_one :mirror, foreign_key: :repo_id
|
||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :repo_id
|
||||
has_many :version_releases, dependent: :destroy
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: teams
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# organization_id :integer
|
||||
# name :string(255)
|
||||
# description :string(255)
|
||||
# authorize :integer default("0")
|
||||
# num_projects :integer default("0")
|
||||
# num_users :integer default("0")
|
||||
# includes_all_project :boolean default("0")
|
||||
# can_create_org_project :boolean default("0")
|
||||
# gtid :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_teams_on_organization_id (organization_id)
|
||||
#
|
||||
|
||||
class Team < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
belongs_to :organization_extension, foreign_key: :organization_id, primary_key: :organization_id, counter_cache: :num_teams
|
||||
has_many :team_projects, dependent: :destroy
|
||||
has_many :team_units, dependent: :destroy
|
||||
has_many :team_users, dependent: :destroy
|
||||
|
||||
validates :name, uniqueness: {scope: :organization_id}
|
||||
|
||||
enum authorize: {common: 0, read: 1, write: 2, admin: 3, owner: 4}
|
||||
|
||||
def self.build(organization_id, name, description, authorize, includes_all_project, can_create_org_project)
|
||||
self.create!(organization_id: organization_id,
|
||||
name: name,
|
||||
description: description,
|
||||
authorize: authorize,
|
||||
includes_all_project: includes_all_project,
|
||||
can_create_org_project: can_create_org_project)
|
||||
end
|
||||
|
||||
def setup_team_project!
|
||||
return unless includes_all_project
|
||||
organization.projects.each do |project|
|
||||
TeamProject.build(organization.id, id, project.id)
|
||||
end
|
||||
end
|
||||
|
||||
def is_member?(user_id)
|
||||
team_users.where(user_id: user_id).present?
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: team_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# organization_id :integer
|
||||
# project_id :integer
|
||||
# team_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_team_projects_on_organization_id (organization_id)
|
||||
# index_team_projects_on_project_id (project_id)
|
||||
# index_team_projects_on_team_id (team_id)
|
||||
#
|
||||
|
||||
class TeamProject < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
belongs_to :project
|
||||
belongs_to :team, counter_cache: :num_projects
|
||||
|
||||
validates :project_id, uniqueness: {scope: [:organization_id, :team_id]}
|
||||
|
||||
def self.build(organization_id, team_id, project_id)
|
||||
self.find_or_create_by!(organization_id: organization_id, team_id: team_id, project_id: project_id)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: team_units
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# organization_id :integer
|
||||
# team_id :integer
|
||||
# unit_type :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_team_units_on_organization_id (organization_id)
|
||||
# index_team_units_on_team_id (team_id)
|
||||
#
|
||||
|
||||
class TeamUnit < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
belongs_to :team
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, releases: 4}
|
||||
|
||||
validates :unit_type, uniqueness: { scope: [:organization_id, :team_id]}
|
||||
|
||||
def self.build(organization_id, team_id, unit_type)
|
||||
self.create!(organization_id: organization_id, team_id: team_id, unit_type: unit_type)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: team_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# organization_id :integer
|
||||
# team_id :integer
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_team_users_on_organization_id (organization_id)
|
||||
# index_team_users_on_team_id (team_id)
|
||||
# index_team_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class TeamUser < ApplicationRecord
|
||||
|
||||
belongs_to :organization
|
||||
belongs_to :team, counter_cache: :num_users
|
||||
belongs_to :user
|
||||
|
||||
validates :user_id, uniqueness: {scope: [:organization_id, :team_id]}
|
||||
|
||||
def self.build(organization_id, user_id, team_id)
|
||||
self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id)
|
||||
end
|
||||
end
|
|
@ -58,14 +58,13 @@
|
|||
# index_users_on_type (type)
|
||||
#
|
||||
|
||||
class User < ApplicationRecord
|
||||
class User < Owner
|
||||
default_scope {where(type: %w(User AnonymousUser))}
|
||||
extend Enumerize
|
||||
|
||||
include Watchable
|
||||
include Likeable
|
||||
include BaseModel
|
||||
include ProjectOperable
|
||||
include ProjectAbility
|
||||
include Droneable
|
||||
# include Searchable::Dependents::User
|
||||
|
||||
|
@ -136,8 +135,8 @@ class User < ApplicationRecord
|
|||
has_many :attachments,foreign_key: :author_id, :dependent => :destroy
|
||||
|
||||
# 关注
|
||||
has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
|
||||
has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
|
||||
# has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
|
||||
# has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
|
||||
has_many :watchers, as: :watchable, dependent: :destroy
|
||||
|
||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy
|
||||
|
@ -154,21 +153,21 @@ class User < ApplicationRecord
|
|||
# 项目
|
||||
has_many :applied_projects, dependent: :destroy
|
||||
|
||||
has_many :projects, dependent: :destroy
|
||||
has_many :repositories, dependent: :destroy
|
||||
|
||||
# 教学案例
|
||||
# has_many :libraries, dependent: :destroy
|
||||
has_many :project_trends, dependent: :destroy
|
||||
has_many :oauths , dependent: :destroy
|
||||
|
||||
has_many :organization_users, dependent: :destroy
|
||||
has_many :organizations, through: :organization_users
|
||||
|
||||
# Groups and active users
|
||||
scope :active, lambda { where(status: STATUS_ACTIVE) }
|
||||
scope :like, lambda { |keywords|
|
||||
where("LOWER(concat(lastname, firstname, login, mail)) LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
scope :simple_select, -> {select(:id, :login, :lastname,:firstname, :nickname, :gitea_uid)}
|
||||
scope :simple_select, -> {select(:id, :login, :lastname,:firstname, :nickname, :gitea_uid, :type)}
|
||||
|
||||
attr_accessor :password, :password_confirmation
|
||||
|
||||
|
|
|
@ -132,7 +132,8 @@ class Gitea::ClientService < ApplicationService
|
|||
when 204
|
||||
|
||||
puts "[gitea] "
|
||||
raise Error, "[gitea] delete ok"
|
||||
# raise Error, "[gitea] delete ok"
|
||||
{status: 204}
|
||||
when 409
|
||||
message = "创建失败,请检查该分支合并是否已存在"
|
||||
raise Error, mark + message
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
class Gitea::Organization::CreateService < Gitea::ClientService
|
||||
attr_reader :token, :org
|
||||
|
||||
def initialize(token, org)
|
||||
@token = token
|
||||
@org = org
|
||||
end
|
||||
|
||||
def call
|
||||
response = post(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
create_params = {
|
||||
username: org.login,
|
||||
description: org.description,
|
||||
location: org.location,
|
||||
repo_admin_change_team_access: org.repo_admin_change_team_access,
|
||||
visibility: visibility(org.visibility),
|
||||
website: org.website,
|
||||
max_repo_creation: org.max_repo_creation
|
||||
}
|
||||
Hash.new.merge(token: token, data: create_params)
|
||||
end
|
||||
|
||||
def visibility(visibility)
|
||||
case visibility
|
||||
when "common"
|
||||
"public"
|
||||
when "limited"
|
||||
"limited"
|
||||
when "privacy"
|
||||
"private"
|
||||
else
|
||||
"public"
|
||||
end
|
||||
end
|
||||
|
||||
def url
|
||||
"/orgs".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
class Gitea::Organization::DeleteService < Gitea::ClientService
|
||||
attr_reader :token, :name
|
||||
|
||||
def initialize(token, name)
|
||||
@token = token
|
||||
@name = name
|
||||
end
|
||||
|
||||
def call
|
||||
response = delete(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def params
|
||||
Hash.new.merge(token: token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/orgs/#{name}".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
class Gitea::Organization::OrganizationUser::DeleteService < Gitea::ClientService
|
||||
attr_reader :token, :org_name, :username
|
||||
|
||||
def initialize(token, org_name, username)
|
||||
@token = token
|
||||
@org_name = org_name
|
||||
@username = username
|
||||
end
|
||||
|
||||
def call
|
||||
response = delete(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/orgs/#{org_name}/members/#{username}"
|
||||
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,50 @@
|
|||
class Gitea::Organization::Team::CreateService < Gitea::ClientService
|
||||
attr_reader :token, :org, :team
|
||||
|
||||
def initialize(token, org, team)
|
||||
@token = token
|
||||
@org = org
|
||||
@team = team
|
||||
end
|
||||
|
||||
def call
|
||||
response = post(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
create_params = {
|
||||
name: team.name,
|
||||
description: team.description,
|
||||
permission: permission(team.authorize),
|
||||
includes_all_repositories: team.includes_all_project,
|
||||
can_create_org_repo: team.can_create_org_project,
|
||||
units: unit_arrays
|
||||
}
|
||||
Hash.new.merge(token: token, data: create_params)
|
||||
end
|
||||
|
||||
def permission(authorize)
|
||||
case authorize
|
||||
when "read"
|
||||
"read"
|
||||
when "write"
|
||||
"write"
|
||||
when "admin"
|
||||
"admin"
|
||||
when "owner"
|
||||
"owner"
|
||||
else
|
||||
"none"
|
||||
end
|
||||
end
|
||||
|
||||
def unit_arrays
|
||||
team.team_units.pluck(:unit_type).collect{|t|"repo.#{t}"}
|
||||
end
|
||||
|
||||
def url
|
||||
"/orgs/#{org.login}/teams".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
class Gitea::Organization::Team::DeleteService < Gitea::ClientService
|
||||
attr_reader :token, :gtid
|
||||
|
||||
def initialize(token, gtid)
|
||||
@token = token
|
||||
@gtid = gtid
|
||||
end
|
||||
|
||||
def call
|
||||
response = delete(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/teams/#{gtid}".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
class Gitea::Organization::Team::UpdateService < Gitea::ClientService
|
||||
attr_reader :token, :team
|
||||
|
||||
def initialize(token, team)
|
||||
@token = token
|
||||
@team = team
|
||||
end
|
||||
|
||||
def call
|
||||
response = patch(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
update_params = {
|
||||
name: team.name,
|
||||
description: team.description,
|
||||
permission: permission(team.authorize),
|
||||
includes_all_repositories: team.includes_all_project,
|
||||
can_create_org_repo: team.can_create_org_project,
|
||||
units: unit_arrays
|
||||
}
|
||||
Hash.new.merge(token: token, data: update_params)
|
||||
end
|
||||
|
||||
def permission(authorize)
|
||||
case authorize
|
||||
when "read"
|
||||
"read"
|
||||
when "write"
|
||||
"write"
|
||||
when "admin"
|
||||
"admin"
|
||||
when "owner"
|
||||
"owner"
|
||||
else
|
||||
"none"
|
||||
end
|
||||
end
|
||||
|
||||
def unit_arrays
|
||||
team.team_units.pluck(:unit_type).collect{|t|"repo.#{t}"}
|
||||
end
|
||||
|
||||
def url
|
||||
"/teams/#{team.gtid}".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
|
|
@ -0,0 +1,23 @@
|
|||
class Gitea::Organization::TeamUser::CreateService < Gitea::ClientService
|
||||
attr_reader :token, :gtid, :username
|
||||
|
||||
def initialize(token, gtid, username)
|
||||
@token = token
|
||||
@gtid = gtid
|
||||
@username = username
|
||||
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}/members/#{username}".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
class Gitea::Organization::TeamUser::DeleteService < Gitea::ClientService
|
||||
attr_reader :token, :gtid, :username
|
||||
|
||||
def initialize(token, gtid, username)
|
||||
@token = token
|
||||
@gtid = gtid
|
||||
@username = username
|
||||
end
|
||||
|
||||
def call
|
||||
response = delete(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/teams/#{gtid}/members/#{username}"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
class Gitea::Organization::UpdateService < Gitea::ClientService
|
||||
attr_reader :token, :login, :org
|
||||
|
||||
def initialize(token, login, org)
|
||||
@token = token
|
||||
@login = login
|
||||
@org = org
|
||||
end
|
||||
|
||||
def call
|
||||
response = patch(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
update_params = {
|
||||
name: org.login,
|
||||
description: org.description,
|
||||
location: org.location,
|
||||
repo_admin_change_team_access: org.repo_admin_change_team_access,
|
||||
visibility: visibility(org.visibility),
|
||||
website: org.website,
|
||||
max_repo_creation: org.max_repo_creation
|
||||
}
|
||||
Hash.new.merge(token: token, data: update_params)
|
||||
end
|
||||
|
||||
def visibility(visibility)
|
||||
case visibility
|
||||
when "common"
|
||||
"public"
|
||||
when "limited"
|
||||
"limited"
|
||||
when "privacy"
|
||||
"private"
|
||||
else
|
||||
"public"
|
||||
end
|
||||
end
|
||||
|
||||
def url
|
||||
"/orgs/#{login}".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
class Gitea::Repository::TransferService < Gitea::ClientService
|
||||
attr_reader :token, :owner, :repo, :new_owner
|
||||
|
||||
def initialize(token, owner, repo, new_owner)
|
||||
@token = token
|
||||
@owner = owner
|
||||
@repo = repo
|
||||
@new_owner = new_owner
|
||||
end
|
||||
|
||||
def call
|
||||
response = post(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
transfer_params = {
|
||||
new_owner: new_owner
|
||||
}
|
||||
Hash.new.merge(token: token, data: transfer_params)
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/#{owner}/#{repo}/transfer".freeze
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
class Organizations::CreateService < ApplicationService
|
||||
attr_reader :user, :params
|
||||
attr_accessor :organization, :gitea_organization, :owner_team
|
||||
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("######Organization create_service begin######")
|
||||
Rails.logger.info("######params #{params}######")
|
||||
ActiveRecord::Base.transaction do
|
||||
create_org_and_extension
|
||||
create_owner_info
|
||||
create_gitea_org
|
||||
sync_gitea_info
|
||||
|
||||
Rails.logger.info("######Organization create_service end######")
|
||||
end
|
||||
@organization
|
||||
end
|
||||
|
||||
private
|
||||
def description
|
||||
params[:description]
|
||||
end
|
||||
|
||||
def website
|
||||
params[:website]
|
||||
end
|
||||
|
||||
def location
|
||||
params[:location].present? ? params[:location] : nil
|
||||
end
|
||||
|
||||
def repo_admin_change_team_access
|
||||
params[:repo_admin_change_team_access].present? ? params[:repo_admin_change_team_access] : false
|
||||
end
|
||||
|
||||
def visibility
|
||||
params[:visibility].present? ? params[:visibility] : "common"
|
||||
end
|
||||
|
||||
def max_repo_creation
|
||||
params[:max_repo_creation].present? ? params[:max_repo_creation] : -1
|
||||
end
|
||||
|
||||
def create_org_and_extension
|
||||
@organization = Organization.build(params[:name], user.gitea_token)
|
||||
org_extension = OrganizationExtension.build(organization.id, description, website,
|
||||
location, repo_admin_change_team_access,
|
||||
visibility, max_repo_creation)
|
||||
end
|
||||
|
||||
def create_owner_info
|
||||
@owner_team = Team.build(organization.id, "Owners", "", 4, true, true)
|
||||
TeamUnit.unit_types.keys.each do |u_type|
|
||||
TeamUnit.build(organization.id, owner_team.id, u_type)
|
||||
end
|
||||
OrganizationUser.build(organization.id, user.id)
|
||||
TeamUser.build(organization.id, user.id, owner_team.id)
|
||||
end
|
||||
|
||||
def create_gitea_org
|
||||
@gitea_organization = Gitea::Organization::CreateService.call(@organization.gitea_token, organization)
|
||||
end
|
||||
|
||||
def sync_gitea_info
|
||||
organization.update!(gitea_uid: gitea_organization["id"])
|
||||
owner_team.update!(gtid: gitea_organization["owner_team"]["id"])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,75 @@
|
|||
class Organizations::Teams::CreateService < ApplicationService
|
||||
attr_reader :user, :org, :params
|
||||
attr_accessor :team, :gitea_team
|
||||
|
||||
def initialize(user, org, params)
|
||||
@user = user
|
||||
@org = org
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("######Team create_service begin######")
|
||||
Rails.logger.info("######params #{params}######")
|
||||
ActiveRecord::Base.transaction do
|
||||
create_team
|
||||
create_units
|
||||
create_gitea_team
|
||||
sync_team_gtid
|
||||
team.setup_team_project!
|
||||
end
|
||||
Rails.logger.info("######Team create_service end######")
|
||||
|
||||
team
|
||||
end
|
||||
|
||||
private
|
||||
def name
|
||||
params[:name]
|
||||
end
|
||||
|
||||
def description
|
||||
params[:description]
|
||||
end
|
||||
|
||||
def authorize
|
||||
params[:authorize].present? ? params[:authorize] : "common"
|
||||
end
|
||||
|
||||
def includes_all_project
|
||||
params[:includes_all_project].present? ? params[:includes_all_project] : false
|
||||
end
|
||||
|
||||
def can_create_org_project
|
||||
params[:can_create_org_project].present? ? params[:can_create_org_project] : false
|
||||
end
|
||||
|
||||
def create_team
|
||||
@team = Team.build(org.id, name, description, authorize,
|
||||
includes_all_project, can_create_org_project)
|
||||
end
|
||||
|
||||
def units_params
|
||||
%w(admin owner).include?(authorize) ? %w(code issues pulls releases) : params[:unit_types]
|
||||
end
|
||||
|
||||
def create_units
|
||||
return if units_params.blank?
|
||||
begin
|
||||
units_params.each do |unit|
|
||||
TeamUnit.build(org.id, team.id, unit)
|
||||
end
|
||||
rescue
|
||||
raise ActiveRecord::Rollback, "TeamUnit create error"
|
||||
end
|
||||
end
|
||||
|
||||
def create_gitea_team
|
||||
@gitea_team = Gitea::Organization::Team::CreateService.call(org.gitea_token, org, team)
|
||||
end
|
||||
|
||||
def sync_team_gtid
|
||||
team.update!(gtid: gitea_team["id"])
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
class Organizations::Teams::UpdateService < ApplicationService
|
||||
attr_reader :user, :team, :params
|
||||
|
||||
def initialize(user, team, params)
|
||||
@user = user
|
||||
@team = team
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("######Team update_service begin######")
|
||||
Rails.logger.info("######params #{params}######")
|
||||
ActiveRecord::Base.transaction do
|
||||
update_team(update_params)
|
||||
update_units
|
||||
team.reload
|
||||
team.setup_team_project!
|
||||
update_gitea_team
|
||||
end
|
||||
Rails.logger.info("######Team update_service end######")
|
||||
|
||||
team
|
||||
end
|
||||
|
||||
private
|
||||
def update_params
|
||||
if team.authorize == "owner"
|
||||
update_params = params.slice(:description)
|
||||
else
|
||||
update_params = params.slice(:name, :description, :authorize, :includes_all_project, :can_create_org_project)
|
||||
end
|
||||
update_params
|
||||
end
|
||||
|
||||
def units_params
|
||||
%w(admin owner).include?(team.authorize) ? %w(code issues pulls releases) : params[:unit_types]
|
||||
end
|
||||
|
||||
def update_team(update_params)
|
||||
team.update_attributes!(update_params)
|
||||
end
|
||||
|
||||
def update_units
|
||||
return if units_params.blank?
|
||||
begin
|
||||
team.team_units.map{|u|u.destroy!}
|
||||
Rails.logger.info units_params
|
||||
units_params.each do |unit|
|
||||
TeamUnit.build(team&.organization&.id, team.id, unit)
|
||||
end
|
||||
rescue
|
||||
raise ActiveRecord::Rollback, "TeamUnit update error"
|
||||
end
|
||||
end
|
||||
|
||||
def update_gitea_team
|
||||
Gitea::Organization::Team::UpdateService.call(team&.organization&.gitea_token, team)
|
||||
end
|
||||
end
|
|
@ -20,7 +20,7 @@ class Projects::ForkService < ApplicationService
|
|||
clone_project.save!
|
||||
|
||||
new_repository = clone_project.repository
|
||||
new_repository.user = @target_owner
|
||||
new_repository.owner = @target_owner
|
||||
new_repository.identifier = @project.identifier
|
||||
new_repository.save!
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
class Projects::TransferService < ApplicationService
|
||||
attr_accessor :project, :owner, :new_owner
|
||||
|
||||
def initialize(project, new_owner)
|
||||
@project = project
|
||||
@owner = project.owner
|
||||
@new_owner = new_owner
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("###### Project transfer_service begin ######")
|
||||
ActiveRecord::Base.transaction do
|
||||
gitea_update_owner
|
||||
update_owner
|
||||
update_visit_teams
|
||||
end
|
||||
|
||||
Rails.logger.info("##### Project transfer_service end ######")
|
||||
|
||||
@project.reload
|
||||
end
|
||||
|
||||
private
|
||||
def update_owner
|
||||
project.update!(user_id: new_owner.id)
|
||||
end
|
||||
|
||||
def update_visit_teams
|
||||
if new_owner.is_a?(Organization)
|
||||
new_owner.teams.where(includes_all_project: true).each do |team|
|
||||
TeamProject.build(new_owner.id, team.id, project.id)
|
||||
end
|
||||
else
|
||||
project.team_projects.each(&:destroy!)
|
||||
end
|
||||
end
|
||||
|
||||
def gitea_update_owner
|
||||
begin
|
||||
Gitea::Repository::TransferService.call(owner&.gitea_token, owner&.login, project.identifier, new_owner&.login)
|
||||
rescue Exception => e
|
||||
Rails.logger.info("##### Project transfer_service, gitea transfer error #{e}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
class Repositories::CreateService < ApplicationService
|
||||
attr_reader :user, :project, :params
|
||||
attr_accessor :repository, :gitea_repository
|
||||
|
||||
def initialize(user, project, params)
|
||||
@project = project
|
||||
|
@ -10,10 +11,10 @@ class Repositories::CreateService < ApplicationService
|
|||
def call
|
||||
@repository = Repository.new(repository_params)
|
||||
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"
|
||||
# chain_params = {
|
||||
# type: "create",
|
||||
|
@ -29,7 +30,7 @@ class Repositories::CreateService < ApplicationService
|
|||
else
|
||||
Rails.logger.info("#############___________create_repository_erros______###########{@repository.errors.messages}")
|
||||
end
|
||||
@repository
|
||||
repository
|
||||
end
|
||||
rescue => e
|
||||
puts "create repository service error: #{e.message}"
|
||||
|
@ -38,7 +39,25 @@ class Repositories::CreateService < ApplicationService
|
|||
|
||||
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.each do |team|
|
||||
next unless team.includes_all_project
|
||||
TeamProject.build(project.user_id, team.id, project.id)
|
||||
end
|
||||
create_manager_member
|
||||
end
|
||||
end
|
||||
|
||||
def create_manager_member
|
||||
return if project.owner.is_owner?(user.id)
|
||||
project.add_member!(user.id, "Manager")
|
||||
end
|
||||
|
||||
def sync_project
|
||||
if gitea_repository
|
||||
project.update_columns(
|
||||
gpid: gitea_repository["id"],
|
||||
|
@ -47,7 +66,7 @@ class Repositories::CreateService < ApplicationService
|
|||
end
|
||||
end
|
||||
|
||||
def sync_repository(repository, gitea_repository)
|
||||
def sync_repository
|
||||
repository.update_columns(url: remote_repository_url,) if gitea_repository
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
json.user_id user.id
|
||||
json.login user.login
|
||||
json.name user.full_name
|
||||
json.mail user.mail
|
||||
json.identity user.identity
|
||||
json.watched current_user.watched?(user)
|
||||
# json.email user.mail # 邮箱原则上不暴露的,如果实在需要的话只能对某些具体的接口公开
|
||||
json.image_url url_to_avatar(user)
|
|
@ -0,0 +1,7 @@
|
|||
json.id org_user.id
|
||||
json.user do
|
||||
json.partial! "organizations/user_detail", user: org_user.user
|
||||
end
|
||||
|
||||
json.team_names org_user.teams.pluck(:name)
|
||||
json.created_at org_user.created_at.strftime("%Y-%m-%d")
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @organization_users.total_count
|
||||
json.organization_users @organization_users do |org_user|
|
||||
json.partial! "detail", org_user: org_user, organization: @organization
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
json.id organization.id
|
||||
json.name organization.login
|
||||
json.description organization.description
|
||||
json.website organization.website
|
||||
json.location organization.location
|
||||
json.repo_admin_change_team_access organization.repo_admin_change_team_access
|
||||
json.visibility organization.visibility
|
||||
json.max_repo_creation organization.max_repo_creation
|
||||
json.num_projects organization.num_projects
|
||||
json.num_users organization.num_users
|
||||
json.num_teams organization.num_teams
|
||||
json.avatar_url url_to_avatar(organization)
|
||||
json.created_at organization.created_on.strftime("%Y-%m-%d")
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", organization: @organization
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @organizations.total_count
|
||||
json.organizations @organizations do |organization|
|
||||
json.partial! "detail", organization: organization
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
json.partial! "detail", organization: @organization
|
||||
json.can_create_project @can_create_project
|
||||
json.is_admin @is_admin
|
||||
json.is_member @is_member
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", organization: @organization
|
|
@ -0,0 +1,9 @@
|
|||
json.total_count @projects.total_count
|
||||
json.projects @projects.each do |project|
|
||||
json.(project, :id, :name, :identifier, :description, :forked_count, :praises_count, :forked_from_project_id)
|
||||
json.mirror_url project.repository&.mirror_url
|
||||
json.type project.numerical_for_project_type
|
||||
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,9 @@
|
|||
json.total_count @projects.size
|
||||
json.projects @projects.each do |project|
|
||||
json.(project, :id, :name, :identifier, :description, :forked_count, :praises_count, :forked_from_project_id)
|
||||
json.mirror_url project.repository&.mirror_url
|
||||
json.type project.numerical_for_project_type
|
||||
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.id team_project.id
|
||||
json.project do
|
||||
json.owner_name team_project&.project&.owner&.login
|
||||
json.owner_image_url url_to_avatar(team_project&.project&.owner)
|
||||
json.name team_project&.project&.name
|
||||
json.identifier team_project&.project&.identifier
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", team_project: @team_project, team: @team, organization: @organization
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @team_projects.total_count
|
||||
json.team_projects @team_projects do |team_project|
|
||||
json.partial! "detail", team_project: team_project, team: @team, organization: @organization
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
json.id team_user.id
|
||||
json.user do
|
||||
json.partial! "organizations/user_detail", user: team_user.user
|
||||
end
|
||||
json.created_at team_user.created_at.strftime("%Y-%m-%d")
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", team_user: @team_user, team: @team, organization: @organization
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @team_users.total_count
|
||||
json.team_users @team_users do |team_user|
|
||||
json.partial! "detail", team_user: team_user, team: @team, organization: @organization
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
json.id team.id
|
||||
json.name team.name
|
||||
json.description team.description
|
||||
json.authorize team.authorize
|
||||
json.includes_all_project team.includes_all_project
|
||||
json.can_create_org_project team.can_create_org_project
|
||||
json.num_projects team.num_projects
|
||||
json.num_users team.num_users
|
||||
json.units team.team_units.pluck(:unit_type)
|
||||
json.users team.team_users.each do |user|
|
||||
json.partial! "organizations/user_detail", user: user&.user
|
||||
end
|
||||
json.is_admin @is_admin
|
||||
json.is_member team.is_member?(current_user.id)
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", team: @team, organization: @organization
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @teams.total_count
|
||||
json.teams @teams do |team|
|
||||
json.partial! "detail", team: team, organization: @organization
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @teams.size
|
||||
json.teams @teams do |team|
|
||||
json.partial! "detail", team: team, organization: @organization
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
json.partial! "detail", team: @team, organization: @organization
|
||||
json.is_admin @is_admin
|
||||
json.is_member @is_member
|
|
@ -0,0 +1 @@
|
|||
json.partial! "detail", team: @team, organization: @organization
|
|
@ -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
|
|
@ -18,11 +18,13 @@ json.author do
|
|||
if project.educoder?
|
||||
project_educoder = project.project_educoder
|
||||
json.name project_educoder&.owner
|
||||
json.type 'Educoder'
|
||||
json.login project_educoder&.repo_name.split('/')[0]
|
||||
json.image_url render_educoder_avatar_url(project.project_educoder)
|
||||
else
|
||||
user = project.owner
|
||||
json.name user.try(:show_real_name)
|
||||
json.type user&.type
|
||||
json.login user.login
|
||||
json.image_url render_avatar_url(user)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
json.total_count @teams.total_count
|
||||
json.teams @teams.each do |team|
|
||||
json.(team, :id, :name, :authorize)
|
||||
json.can_remove !team.includes_all_project && team&.organization&.repo_admin_change_team_access
|
||||
end
|
|
@ -1,11 +1,13 @@
|
|||
json.author do
|
||||
if @project.forge?
|
||||
json.login user.login
|
||||
json.type user&.type
|
||||
json.name user.real_name
|
||||
json.image_url url_to_avatar(user)
|
||||
else
|
||||
json.login @project.project_educoder&.repo_name&.split('/')[0]
|
||||
json.name @project.project_educoder&.owner
|
||||
json.type 'Educoder'
|
||||
json.image_url @project.project_educoder&.image_url
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
json.total_count @organizations.total_count
|
||||
json.organizations @organizations do |organization|
|
||||
json.partial! "/organizations/organizations/detail", organization: organization
|
||||
end
|
|
@ -12,6 +12,7 @@ json.watched_count @user.fan_count #粉丝
|
|||
json.watching_count @user.follow_count #关注数
|
||||
json.undo_events @undo_events
|
||||
json.user_composes_count @user_composes_count
|
||||
json.user_org_count @user_org_count
|
||||
json.common_projects_count @projects_common_count
|
||||
json.mirror_projects_count @projects_mirrior_count
|
||||
json.sync_mirror_projects_count @projects_sync_mirrior_count
|
|
@ -61,6 +61,8 @@ zh-CN:
|
|||
close_issue: 工单
|
||||
activerecord:
|
||||
attributes:
|
||||
organization:
|
||||
login: '组织名称'
|
||||
user:
|
||||
login: '登录名'
|
||||
lastname: '姓名'
|
||||
|
|
|
@ -103,6 +103,34 @@ Rails.application.routes.draw do
|
|||
put 'commons/unhidden', to: 'commons#unhidden'
|
||||
delete 'commons/delete', to: 'commons#delete'
|
||||
|
||||
resources :owners, only: [:index]
|
||||
|
||||
scope module: :organizations do
|
||||
resources :organizations, except: [:edit, :new] do
|
||||
resources :organization_users, only: [:index, :destroy] do
|
||||
collection do
|
||||
delete :quit
|
||||
end
|
||||
end
|
||||
resources :teams, except: [:edit, :new] do
|
||||
collection do
|
||||
get :search
|
||||
end
|
||||
resources :team_users, only: [:index, :create, :destroy] do
|
||||
collection do
|
||||
delete :quit
|
||||
end
|
||||
end
|
||||
resources :team_projects, only: [:index, :create, :destroy] do ;end
|
||||
end
|
||||
resources :projects, only: [:index] do
|
||||
collection do
|
||||
get :search
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
resources :issues, except: [:index, :new,:create, :update, :edit, :destroy] do
|
||||
resources :journals, only: [:index, :create, :destroy, :edit, :update] do
|
||||
member do
|
||||
|
@ -225,6 +253,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
scope module: :users do
|
||||
resources :organizations, only: [:index]
|
||||
# resources :projects, only: [:index]
|
||||
# resources :subjects, only: [:index]
|
||||
resources :project_packages, only: [:index]
|
||||
|
@ -493,6 +522,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
scope module: :projects do
|
||||
resources :teams, only: [:index, :create, :destroy]
|
||||
scope do
|
||||
get(
|
||||
'/blob/*id/diff',
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
class CreateOrganizationUsers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :organization_users do |t|
|
||||
t.references :user
|
||||
t.references :organization
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
class CreateOrganizationExtensions < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :organization_extensions do |t|
|
||||
t.references :organization
|
||||
t.string :description, comment: "组织描述"
|
||||
t.string :website, comment: "组织官方网站"
|
||||
t.string :location, comment: "组织地区"
|
||||
t.boolean :repo_admin_change_team_access, comment: "项目管理员是否可以添加或移除团队的访问权限", default: false
|
||||
t.integer :visibility, comment: "组织可见性", default: 0
|
||||
t.integer :max_repo_creation, comment: "组织最大仓库数", default: -1
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class CreateTeams < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :teams do |t|
|
||||
t.references :organization
|
||||
t.string :name, comment: "团队名称"
|
||||
t.string :description, comment: "团队描述"
|
||||
t.integer :authorize, comment: "团队权限", default: 0
|
||||
t.integer :num_projects, comment: "团队项目数量", default: 0
|
||||
t.integer :num_users, comment: "团队成员数量", default: 0
|
||||
t.boolean :includes_all_project, comment: "团队是否拥有所有项目", default: false
|
||||
t.boolean :can_create_org_project, comment: "团队是否能创建项目", default: false
|
||||
t.integer :gtid, comment: "团队在gitea里的id"
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
class CreateTeamProjects < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :team_projects do |t|
|
||||
t.references :organization
|
||||
t.references :project
|
||||
t.references :team
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class CreateTeamUsers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :team_users do |t|
|
||||
t.references :organization
|
||||
t.references :team
|
||||
t.references :user
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
class CreateTeamUnits < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :team_units do |t|
|
||||
t.references :organization
|
||||
t.references :team
|
||||
t.integer :unit_type, comment: "访问单元类型"
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class AddColumnsToOrganizationExtension < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :organization_extensions, :num_projects, :integer, default: 0
|
||||
add_column :organization_extensions, :num_users, :integer, default: 0
|
||||
add_column :organization_extensions, :num_teams, :integer, default: 0
|
||||
|
||||
OrganizationExtension.find_each do |e|
|
||||
OrganizationExtension.reset_counters(e.id, :organization_users)
|
||||
OrganizationExtension.reset_counters(e.id, :projects)
|
||||
OrganizationExtension.reset_counters(e.id, :teams)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe OrganizationExtension, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe OrganizationUser, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TeamProject, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Team, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TeamUnit, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe TeamUser, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue