[ADD]组织模块相关代码

This commit is contained in:
viletyy 2021-01-11 17:44:11 +08:00
parent 178991b245
commit 2434ca9681
36 changed files with 655 additions and 1 deletions

View File

@ -113,6 +113,8 @@ http://localhost:3000/
### API ### API
- [API](api_document.md) - [API](api_document.md)
- [API](showdoc.com.cn)
账号forgeplus@admin.com 密码forge123
## 贡献代码 ## 贡献代码

View File

@ -0,0 +1,11 @@
class Organizations::BaseController < ApplicationController
include ApplicationHelper
def load_organization
@organization = Organization.find_by(login: params[:id]) || Organization.find_by(id: params[:id])
render_not_found if @organization.nil?
@organization
end
end

View File

@ -0,0 +1,74 @@
class Organizations::OrganizationsController < Organizations::BaseController
before_action :require_login, except: [:index]
before_action :convert_base64_image!, only: [:create, :update]
before_action :load_organization, only: [:update, :destroy]
def index
if current_user.logged?
@organizations = Organization.with_visibility(%w(common limited)) +
Organization.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id})
else
@organizations = Organization.with_visibility("common")
end
kaminary_array_paginate(@organizations)
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(current_user.gitea_token, login, @organization)
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
render_unauthorized unless current_user.check_password?(password)
render_forbidden("您没有权限进行该操作") unless @organization.check_owner?(current_user)
ActiveRecord::Base.transaction do
Gitea::Organization::DeleteService.call(current_user.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_base64_image!
max_size = EduSetting.get('upload_avatar_max_size')
@image = Util.convert_base64_image(params[:image].to_s.strip, max_size: max_size)
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
end

View File

@ -11,6 +11,11 @@
# sync_subject :boolean default("0") # sync_subject :boolean default("0")
# sync_shixun :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 class Laboratory < ApplicationRecord
belongs_to :school, optional: true belongs_to :school, optional: true

View File

@ -6,6 +6,10 @@
# laboratory_id :integer # laboratory_id :integer
# config :text(65535) # config :text(65535)
# #
# Indexes
#
# index_laboratory_settings_on_laboratory_id (laboratory_id)
#
class LaboratorySetting < ApplicationRecord class LaboratorySetting < ApplicationRecord
belongs_to :laboratory belongs_to :laboratory

View File

@ -0,0 +1,88 @@
# == 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 < ApplicationRecord
self.table_name = "users"
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
delegate :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, 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)
self.create!(login: name)
end
def owner_team
teams.where(authorize: 4).take
end
def check_owner?(user)
owner_team.team_users.where(user_id: user.id).present?
end
end

View File

@ -0,0 +1,36 @@
# == 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
#
# Indexes
#
# index_organization_extensions_on_organization_id (organization_id)
#
class OrganizationExtension < ApplicationRecord
belongs_to :organization
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

View File

@ -0,0 +1,25 @@
# == Schema Information
#
# Table name: organization_users
#
# id :integer not null, primary key
# user_id :integer
# organization_id :integer
# is_creator :boolean default("0")
# 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
def self.build(organization_id, user_id, is_creator)
self.create!(organization_id: organization_id, user_id: user_id, is_creator: is_creator)
end
end

44
app/models/team.rb Normal file
View File

@ -0,0 +1,44 @@
# == 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
has_many :team_projects, dependent: :destroy
has_many :team_units, dependent: :destroy
has_many :team_users, dependent: :destroy
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 self.build_owner(organization_id)
self.build(organization_id, "Owner", "", 4, true, true)
end
end

View File

@ -0,0 +1,28 @@
# == 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
def self.build(organization_id, team_id, project_id)
self.create!(organization_id: organization_id, team_id: team_id, project_id: project_id)
end
end

36
app/models/team_unit.rb Normal file
View File

@ -0,0 +1,36 @@
# == 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, issue: 2, pull_request: 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
def self.build_owner(organization_id, team_id)
self.unit_types.keys.each do |u_type|
self.build(organization_id, team_id, u_type)
end
end
end

28
app/models/team_user.rb Normal file
View File

@ -0,0 +1,28 @@
# == 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
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

View File

@ -59,6 +59,7 @@
# #
class User < ApplicationRecord class User < ApplicationRecord
default_scope {where(type: %w(User AnonymousUser))}
extend Enumerize extend Enumerize
include Watchable include Watchable

View File

@ -132,7 +132,8 @@ class Gitea::ClientService < ApplicationService
when 204 when 204
puts "[gitea] " puts "[gitea] "
raise Error, "[gitea] delete ok" # raise Error, "[gitea] delete ok"
{status: 204}
when 409 when 409
message = "创建失败,请检查该分支合并是否已存在" message = "创建失败,请检查该分支合并是否已存在"
raise Error, mark + message raise Error, mark + message

View File

@ -0,0 +1,43 @@
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
}
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

View File

@ -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

View File

@ -0,0 +1,44 @@
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 = {
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
}
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

View File

@ -0,0 +1,28 @@
class Organizations::CreateService < ApplicationService
attr_reader :user, :params
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
@organization = Organization.build(params[:name])
org_extension = OrganizationExtension.build(@organization.id, params[:description], params[:website],
params[:location], params[:repo_admin_change_team_access],
params[:visibility], params[:max_repo_creation])
team = Team.build_owner(@organization.id)
TeamUnit.build_owner(@organization.id, team.id)
OrganizationUser.build(@organization.id, user.id, true)
TeamUser.build(@organization.id, user.id, team.id)
Gitea::Organization::CreateService.call(user.gitea_token, @organization)
Rails.logger.info("######Organization create_service end######")
end
@organization
end
end

View File

@ -0,0 +1,9 @@
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.avatar_url url_to_avatar(organization)

View File

@ -0,0 +1 @@
json.partial! "detail", organization: @organization

View File

@ -0,0 +1,3 @@
json.organizations @organizations do |organization|
json.partial! "detail", organization: organization
end

View File

@ -0,0 +1 @@
json.partial! "detail", organization: @organization

View File

@ -103,6 +103,19 @@ 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'
scope module: :organizations do
resources :organizations do
end
resources :teams do
resources :team_users do
end
resources :team_projects do
end
end
end
resources :issues, except: [:index, :new,:create, :update, :edit, :destroy] do resources :issues, except: [:index, :new,:create, :update, :edit, :destroy] do
resources :journals, only: [:index, :create, :destroy, :edit, :update] do resources :journals, only: [:index, :create, :destroy, :edit, :update] do
member do member do

View File

@ -0,0 +1,11 @@
class CreateOrganizationUsers < ActiveRecord::Migration[5.2]
def change
create_table :organization_users do |t|
t.references :user
t.references :organization
t.boolean :is_creator, comment: "是否为创建者", default: false
t.timestamps
end
end
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

1
public/react/build Submodule

@ -0,0 +1 @@
Subproject commit 6348a15cdb954862dc1b7b5f045a432bcfde7dc4

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe OrganizationExtension, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe OrganizationUser, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe TeamProject, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

5
spec/models/team_spec.rb Normal file
View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Team, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe TeamUnit, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe TeamUser, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end