Browse Source

新增:邀请用户链接生成

pull/313/head
yystopf 4 years ago
parent
commit
c42f3d5928
13 changed files with 245 additions and 9 deletions
  1. +36
    -0
      app/controllers/projects/project_invite_links_controller.rb
  2. +8
    -0
      app/forms/projects/project_invite_links/create_form.rb
  3. +12
    -9
      app/models/applied_project.rb
  4. +1
    -0
      app/models/project.rb
  5. +57
    -0
      app/models/project_invite_link.rb
  6. +76
    -0
      app/services/projects/link_join_service.rb
  7. +8
    -0
      app/views/projects/_detail.json.jbuilder
  8. +12
    -0
      app/views/projects/project_invite_links/_detail.json.jbuilder
  9. +1
    -0
      app/views/projects/project_invite_links/current_link.json.jbuilder
  10. +7
    -0
      config/routes.rb
  11. +16
    -0
      db/migrate/20220614070028_create_project_invite_links.rb
  12. +6
    -0
      db/migrate/20220614081950_add_project_invite_link_to_applied_projects.rb
  13. +5
    -0
      spec/models/project_invite_link_spec.rb

+ 36
- 0
app/controllers/projects/project_invite_links_controller.rb View File

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

+ 8
- 0
app/forms/projects/project_invite_links/create_form.rb View File

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

+ 12
- 9
app/models/applied_project.rb View File

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


+ 1
- 0
app/models/project.rb View File

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


+ 57
- 0
app/models/project_invite_link.rb View File

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

+ 76
- 0
app/services/projects/link_join_service.rb View File

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

+ 8
- 0
app/views/projects/_detail.json.jbuilder View File

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

+ 12
- 0
app/views/projects/project_invite_links/_detail.json.jbuilder View File

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

+ 1
- 0
app/views/projects/project_invite_links/current_link.json.jbuilder View File

@@ -0,0 +1 @@
json.partial! 'detail', locals: { project_invite_link: @project_invite_link }

+ 7
- 0
config/routes.rb View File

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


+ 16
- 0
db/migrate/20220614070028_create_project_invite_links.rb View File

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

+ 6
- 0
db/migrate/20220614081950_add_project_invite_link_to_applied_projects.rb View File

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

+ 5
- 0
spec/models/project_invite_link_spec.rb View File

@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe ProjectInviteLink, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

Loading…
Cancel
Save