新增:邀请用户链接生成
This commit is contained in:
parent
42d2b51f7f
commit
c42f3d5928
|
@ -0,0 +1,36 @@
|
|||
class Projects::ProjectInviteLinksController < Projects::BaseController
|
||||
before_action :require_manager!, except: [:redirect_link]
|
||||
before_action :require_login
|
||||
|
||||
def current_link
|
||||
@project_invite_link = ProjectInviteLink.find_by(user_id: current_user.id, project_id: @project.id)
|
||||
@project_invite_link = ProjectInviteLink.build!(@project, current_user) unless @project_invite_link.present?
|
||||
end
|
||||
|
||||
def generate_link
|
||||
ActiveRecord::Base.transaction do
|
||||
params_data = link_params.merge({user_id: current_user.id, project_id: @project.id})
|
||||
puts params_data
|
||||
Projects::ProjectInviteLinks::CreateForm.new(params_data).validate!
|
||||
@project_invite_link = ProjectInviteLink.create!(params_data.merge(sign: ProjectInviteLink.random_hex_sign))
|
||||
render_ok
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def redirect_link
|
||||
Projects::LinkJoinService.call(current_user, @project, params[:invite_sign])
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def link_params
|
||||
params.require(:project_invite_link).permit(:role, :is_apply)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class Projects::ProjectInviteLinks::CreateForm < BaseForm
|
||||
attr_accessor :user_id, :project_id, :role, :is_apply
|
||||
|
||||
validates :user_id, :project_id, :role, presence: true
|
||||
validates :role, inclusion: { in: %w(manager developer reporter), message: "请输入正确的权限." }
|
||||
validates :is_apply, inclusion: {in: [true, false], message: "请输入是否需要管理员审核."}
|
||||
end
|
||||
|
|
@ -2,24 +2,27 @@
|
|||
#
|
||||
# Table name: forge_applied_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_invite_link_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_project_invite_link_id (project_invite_link_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class AppliedProject < ApplicationRecord
|
||||
self.table_name = "forge_applied_projects"
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :project_invite_link, optional: true
|
||||
|
||||
has_many :applied_messages, as: :applied, dependent: :destroy
|
||||
# has_many :forge_activities, as: :forge_act, dependent: :destroy
|
||||
|
|
|
@ -128,6 +128,7 @@ class Project < ApplicationRecord
|
|||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :project_invite_links, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_invite_links
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("4")
|
||||
# is_apply :boolean default("1")
|
||||
# sign :string(255)
|
||||
# expired_at :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_invite_links_on_project_id (project_id)
|
||||
# index_project_invite_links_on_sign (sign)
|
||||
# index_project_invite_links_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class ProjectInviteLink < ApplicationRecord
|
||||
|
||||
default_scope { where("expired_at > ?", Time.now).or(where(expired_at: nil)) }
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
has_many :applied_projects
|
||||
|
||||
scope :with_project_id, -> (project_id) {where(project_id: project_id)}
|
||||
scope :with_user_id, -> (user_id) {where(user_id: user_id)}
|
||||
|
||||
enum role: {manager: 3, developer: 4, reporter: 5}
|
||||
|
||||
before_create :set_old_data_expired_at
|
||||
|
||||
def self.random_hex_sign
|
||||
SecureRandom.hex
|
||||
end
|
||||
|
||||
def self.build!(project, user, role="developer", is_apply=true)
|
||||
self.create!(
|
||||
project_id: project&.id,
|
||||
user_id: user&.id,
|
||||
role: role,
|
||||
is_apply: is_apply,
|
||||
sign: random_hex_sign
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def set_old_data_expired_at
|
||||
ProjectInviteLink.where(user_id: self.user_id, project_id: self.project).update_all(expired_at: Time.now)
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
class Projects::LinkJoinService < ApplicationService
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
attr_reader :user, :project, :invite_sign, :params
|
||||
|
||||
def initialize(user, project, invite_sign, params={})
|
||||
@user = user
|
||||
@project = project
|
||||
@invite_sign = invite_sign
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
ActiveRecord::Base.transaction do
|
||||
validate!
|
||||
if invite_link.is_apply
|
||||
# 如果需要申请才能加入,创建一条申请记录
|
||||
create_applied_project!
|
||||
else
|
||||
# 如果不需要申请,直接为项目添加该成员
|
||||
create_member!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, 'invite_sign必须存在!' if invite_sign.blank?
|
||||
raise Error, '邀请链接不存在!' unless invite_link.present?
|
||||
raise Error, '邀请链接已失效!' unless invite_user_in_project
|
||||
raise Error, '用户已加入该项目!' if project.member?(user.id)
|
||||
end
|
||||
|
||||
def create_applied_project!
|
||||
user.applied_projects.create!(project: project, role: role_value)
|
||||
end
|
||||
|
||||
def create_member!
|
||||
Projects::AddMemberInteractor.call(project.owner, project, user, permission)
|
||||
end
|
||||
|
||||
def invite_link
|
||||
ProjectInviteLink.find_by(project_id: project.id, sign: invite_sign)
|
||||
end
|
||||
|
||||
def invite_user_in_project
|
||||
in_project = project.member?(invite_link.user)
|
||||
invite_link.update_column(:expired_at, Time.now) unless in_project
|
||||
in_project
|
||||
end
|
||||
|
||||
def role_value
|
||||
@_role ||=
|
||||
case invite_link&.role
|
||||
when 'manager' then 3
|
||||
when 'developer' then 4
|
||||
when 'reporter' then 5
|
||||
else
|
||||
5
|
||||
end
|
||||
end
|
||||
|
||||
def permission
|
||||
case invite_link&.role
|
||||
when 'manager'
|
||||
'admin'
|
||||
when 'developer'
|
||||
'write'
|
||||
when 'reporter'
|
||||
'read'
|
||||
else
|
||||
'read'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
json.id project.id
|
||||
json.identifier project.identifier
|
||||
json.name project.name
|
||||
json.description project.description
|
||||
json.is_public project.is_public
|
||||
json.owner do
|
||||
json.partial! "/users/user_simple", locals: {user: project.owner}
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
json.(project_invite_link, :id, :role, :is_apply, :sign)
|
||||
|
||||
json.user do
|
||||
json.partial! "/users/user_simple", locals: {user: project_invite_link.user}
|
||||
end
|
||||
if project_invite_link&.project.present?
|
||||
json.project do
|
||||
json.partial! "/projects/detail", locals: {project: project_invite_link.project}
|
||||
end
|
||||
else
|
||||
json.project nil
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
json.partial! 'detail', locals: { project_invite_link: @project_invite_link }
|
|
@ -603,6 +603,13 @@ Rails.application.routes.draw do
|
|||
post :cancel
|
||||
end
|
||||
end
|
||||
resources :project_invite_links, only: [:index] do
|
||||
collection do
|
||||
get :current_link
|
||||
post :generate_link
|
||||
post :redirect_link
|
||||
end
|
||||
end
|
||||
resources :webhooks, except: [:show, :new] do
|
||||
member do
|
||||
get :tasks
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
class CreateProjectInviteLinks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :project_invite_links do |t|
|
||||
t.references :project
|
||||
t.references :user
|
||||
t.integer :role, default: 4
|
||||
t.boolean :is_apply, default: true
|
||||
t.string :sign
|
||||
t.datetime :expired_at
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :project_invite_links, :sign
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class AddProjectInviteLinkToAppliedProjects < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :forge_applied_projects, :project_invite_link_id, :integer
|
||||
add_index :forge_applied_projects, :project_invite_link_id
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ProjectInviteLink, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue