diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index b8783c44e..4244287b8 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -9,6 +9,7 @@ class AccountsController < ApplicationController # 其他平台同步注册的用户 def remote_register + Register::RemoteForm.new(remote_register_params).validate! username = params[:username]&.gsub(/\s+/, "") tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username) email = params[:email]&.gsub(/\s+/, "") @@ -367,5 +368,9 @@ class AccountsController < ApplicationController def register_params params.permit(:login, :namespace, :password, :code) end + + def remote_register_params + params.permit(:username, :email, :password, :platform) + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d7707391f..4e59a7e07 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -709,14 +709,20 @@ class ApplicationController < ActionController::Base Rails.application.config_for(:configuration)['platform_url'] || request.base_url end + def image_type?(str) + default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd) + default_type.include?(str&.downcase) + end + def convert_image! @image = params[:image] @image = @image.nil? && params[:user].present? ? params[:user][:image] : @image return unless @image.present? max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M if @image.class == ActionDispatch::Http::UploadedFile - render_error('请上传文件') if @image.size.zero? - render_error('文件大小超过限制') if @image.size > max_size.to_i + return render_error('请上传文件') if @image.size.zero? + return render_error('文件大小超过限制') if @image.size > max_size.to_i + return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1]) else image = @image.to_s.strip return render_error('请上传正确的图片') if image.blank? diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb index c8918d1c4..07691d79f 100644 --- a/app/controllers/compare_controller.rb +++ b/app/controllers/compare_controller.rb @@ -42,12 +42,14 @@ class CompareController < ApplicationController end def load_compare_params - @base = Addressable::URI.unescape(params[:base]) + # @base = Addressable::URI.unescape(params[:base]) + @base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base]) @head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head] - + # @head = Addressable::URI.unescape(@head) + @head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head) end def gitea_compare(base, head) - Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token) + Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token) end end diff --git a/app/controllers/concerns/ci/cloud_account_manageable.rb b/app/controllers/concerns/ci/cloud_account_manageable.rb index 13edb09c6..9f0998edc 100644 --- a/app/controllers/concerns/ci/cloud_account_manageable.rb +++ b/app/controllers/concerns/ci/cloud_account_manageable.rb @@ -179,7 +179,7 @@ module Ci::CloudAccountManageable def drone_oauth_user!(url, state) logger.info "[drone] drone_oauth_user url: #{url}" - conn = Faraday.new(url: url) do |req| + conn = Faraday.new(url: "#{Gitea.gitea_config[:domain]}#{url}") do |req| req.request :url_encoded req.adapter Faraday.default_adapter req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}" @@ -188,7 +188,8 @@ module Ci::CloudAccountManageable response = conn.get logger.info "[drone] response headers: #{response.headers}" - response.headers['location'].include?('error') ? false : true + true + # response.headers['location'].include?('error') ? false : true end private diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 6ea8fb8ef..73b3ee4c3 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -486,7 +486,8 @@ class IssuesController < ApplicationController end def operate_issue_permission - return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?) + @issue = Issue.find_by_id(params[:id]) unless @issue.present? + return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id)) end def export_issues(issues) diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 3c2a92aa4..58aa0d29d 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -28,7 +28,7 @@ class Organizations::OrganizationsController < Organizations::BaseController def create ActiveRecord::Base.transaction do tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name]) - Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate! + Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate! @organization = Organizations::CreateService.call(current_user, organization_params) Util.write_file(@image, avatar_path(@organization)) if params[:image].present? end diff --git a/app/controllers/organizations/team_users_controller.rb b/app/controllers/organizations/team_users_controller.rb index 0a5ff28a1..7a71dbbad 100644 --- a/app/controllers/organizations/team_users_controller.rb +++ b/app/controllers/organizations/team_users_controller.rb @@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController ActiveRecord::Base.transaction do @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) @organization_user = OrganizationUser.build(@organization.id, @operate_user.id) - SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu? + SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu? Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login) end rescue Exception => e @@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController ActiveRecord::Base.transaction do @team_user.destroy! Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login) + SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu? org_team_users = @organization.team_users.where(user_id: @operate_user.id) unless org_team_users.present? @organization.organization_users.find_by(user_id: @operate_user.id).destroy! diff --git a/app/controllers/organizations/teams_controller.rb b/app/controllers/organizations/teams_controller.rb index c599ac420..09f5bc3f0 100644 --- a/app/controllers/organizations/teams_controller.rb +++ b/app/controllers/organizations/teams_controller.rb @@ -4,15 +4,24 @@ class Organizations::TeamsController < Organizations::BaseController 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) + if params[:is_full].present? + if can_edit_org? + @teams = @organization.teams + else + @teams = [] + end + else + #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 end def search @@ -34,8 +43,12 @@ class Organizations::TeamsController < Organizations::BaseController def create ActiveRecord::Base.transaction do - Organizations::CreateTeamForm.new(team_params).validate! - @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + if @organization.teams.count >= 50 + return tip_exception("组织的团队数量已超过限制!") + else + Organizations::CreateTeamForm.new(team_params).validate! + @team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) + end end rescue Exception => e uid_logger_error(e.message) diff --git a/app/controllers/project_trends_controller.rb b/app/controllers/project_trends_controller.rb index 66702608d..f283d05f7 100644 --- a/app/controllers/project_trends_controller.rb +++ b/app/controllers/project_trends_controller.rb @@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController before_action :check_project_public def index - project_trends = @project.project_trends.preload(:user, trend: :user) + project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner) check_time = params[:time] #时间的筛选 check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 77b818cad..6802dd063 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -59,18 +59,23 @@ class ProjectsController < ApplicationController Projects::MigrateForm.new(mirror_params).validate! @project = - if enable_accelerator?(mirror_params[:clone_addr]) + # if enable_accelerator?(mirror_params[:clone_addr]) + # source_clone_url = mirror_params[:clone_addr] + # uid_logger("########## 已动加速器 ##########") + # result = Gitea::Accelerator::MigrateService.call(mirror_params) + # if result[:status] == :success + # Rails.logger.info "########## 加速镜像成功 ########## " + # Projects::MigrateService.call(current_user, + # mirror_params.merge(source_clone_url: source_clone_url, + # clone_addr: accelerator_url(mirror_params[:repository_name]))) + # else + # Projects::MigrateService.call(current_user, mirror_params) + # end + if mirror_params[:clone_addr].include?("github.com") source_clone_url = mirror_params[:clone_addr] - uid_logger("########## 已动加速器 ##########") - result = Gitea::Accelerator::MigrateService.call(mirror_params) - if result[:status] == :success - Rails.logger.info "########## 加速镜像成功 ########## " - Projects::MigrateService.call(current_user, - mirror_params.merge(source_clone_url: source_clone_url, - clone_addr: accelerator_url(mirror_params[:repository_name]))) - else - Projects::MigrateService.call(current_user, mirror_params) - end + clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org') + uid_logger("########## 更改clone_addr ##########") + Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url)) else Projects::MigrateService.call(current_user, mirror_params) end @@ -82,8 +87,9 @@ class ProjectsController < ApplicationController def branches return @branches = [] unless @project.forge? - result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) - @branches = result.is_a?(Hash) && result.key?(:status) ? [] : result + # result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) + result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier) + @branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result end def branches_slice diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index bd9ae7701..2417e4fd5 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -274,12 +274,12 @@ class PullRequestsController < ApplicationController base: params[:base], #目标分支 milestone: 0, #里程碑,未与本地的里程碑关联 } + assignee_login = User.find_by_id(params[:assigned_to_id])&.login @requests_params = @local_params.merge({ - assignee: current_user.try(:login), # assignees: ["#{params[:assigned_login].to_s}"], - assignees: ["#{current_user.try(:login).to_s}"], - labels: params[:issue_tag_ids], - due_date: Time.now + assignees: ["#{assignee_login.to_s}"], + labels: params[:issue_tag_ids] + # due_date: Time.now }) @issue_params = { author_id: current_user.id, diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index b1df355e8..5ebc00b3f 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -238,7 +238,7 @@ class RepositoriesController < ApplicationController def archive domain = Gitea.gitea_config[:domain] api_url = Gitea.gitea_config[:base_url] - archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{URI.escape(params[:archive])}" + archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}" file_path = [domain, api_url, archive_url].join file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden? @@ -252,11 +252,11 @@ class RepositoriesController < ApplicationController domain = Gitea.gitea_config[:domain] api_url = Gitea.gitea_config[:base_url] - url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}" + url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}" file_path = [domain, api_url, url].join file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") - redirect_to URI.escape(file_path) + redirect_to file_path end private diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 90e050707..00ea926fd 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,7 +6,7 @@ class UsersController < ApplicationController before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] before_action :require_login, only: %i[me list sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] - before_action :convert_image!, only: [:update] + before_action :convert_image!, only: [:update, :update_image] skip_before_action :check_sign, only: [:attachment_show] def connect_to_ci_db(options={}) @@ -82,10 +82,21 @@ class UsersController < ApplicationController Util.write_file(@image, avatar_path(@user)) if user_params[:image].present? @user.attributes = user_params.except(:image) unless @user.save - render_error(@user.errors.full_messages.join(", ")) + render_error(-1, @user.errors.full_messages.join(", ")) end end + def update_image + return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id]) + return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) + + Util.write_file(@image, avatar_path(@user)) + return render_ok({message: '头像修改成功'}) + rescue Exception => e + uid_logger_error(e.message) + render_error(-1, '头像修改失败!') + end + def me @user = current_user end diff --git a/app/forms/register/remote_form.rb b/app/forms/register/remote_form.rb new file mode 100644 index 000000000..59a5fbc82 --- /dev/null +++ b/app/forms/register/remote_form.rb @@ -0,0 +1,16 @@ +module Register + class RemoteForm < Register::BaseForm + # login 登陆方式,支持邮箱、登陆、手机号等 + attr_accessor :username, :email, :password, :platform + + validates :username, :email, :password, presence: true + validate :check! + + def check! + Rails.logger.info "Register::RemoteForm params: username: #{username}; email: #{email}; password: #{password}; platform: #{platform}" + check_login(username) + check_mail(email) + check_password(password) + end + end +end diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 6eca8f776..c69241858 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -11,11 +11,11 @@ module RepositoriesHelper def download_type(str) default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv) - default_type.include?(str&.downcase) + default_type.include?(str&.downcase) || str.blank? end def image_type?(str) - default_type = %w(png jpg gif tif psd svg bmp webp jpeg) + default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd) default_type.include?(str&.downcase) end diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index 4ded66e1a..dcf3c457c 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -29,8 +29,9 @@ module TagChosenHelper if project.educoder? return ['master'] else - branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier) - branches.collect{|i| i["name"] if i.is_a?(Hash)} + branches = Gitea::Repository::Branches::ListNameService.call(project&.owner, project.identifier) + return branches.collect{|i| i["name"] if i.is_a?(Hash)} if branches.is_a?(Array) + return branches["branch_name"] if branches.is_a?(Hash) end end diff --git a/app/jobs/migrate_remote_repository_job.rb b/app/jobs/migrate_remote_repository_job.rb index e54eaf2bc..488141910 100644 --- a/app/jobs/migrate_remote_repository_job.rb +++ b/app/jobs/migrate_remote_repository_job.rb @@ -6,7 +6,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob return if repo.blank? puts "############ MigrateRemoteRepositoryJob starting ... ############" - + params.except!(:auth_password, :auth_username) if params[:auth_username].nil? gitea_repository = Gitea::Repository::MigrateService.new(token, params).call puts "#gitea_repository#{gitea_repository}" if gitea_repository[0]==201 diff --git a/app/jobs/send_template_message_job.rb b/app/jobs/send_template_message_job.rb index 900e8b84d..f17755420 100644 --- a/app/jobs/send_template_message_job.rb +++ b/app/jobs/send_template_message_job.rb @@ -94,18 +94,6 @@ class SendTemplateMessageJob < ApplicationJob receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) end - when 'OrganizationRole' - user_id, organization_id, role = args[0], args[1], args[2] - user = User.find_by_id(user_id) - organization = Organization.find_by_id(organization_id) - return unless user.present? && organization.present? - receivers = User.where(id: user.id) - receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role) - Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role}) - receivers.find_each do |receiver| - receivers_email_string, email_title, email_content = MessageTemplate::OrganizationRole.get_email_message_content(receiver, organization, role) - Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) - end when 'ProjectIssue' operator_id, issue_id = args[0], args[1] operator = User.find_by_id(operator_id) @@ -276,6 +264,32 @@ class SendTemplateMessageJob < ApplicationJob receivers_email_string, email_title, email_content = MessageTemplate::PullRequestMerged.get_email_message_content(receiver, operator, pull_request) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) end + when 'TeamJoined' + user_id, organization_id, team_id = args[0], args[1], args[2] + user = User.find_by_id(user_id) + organization = Organization.find_by_id(organization_id) + team = Team.find_by_id(team_id) + return unless user.present? && organization.present? && team.present? + receivers = User.where(id: user.id) + receivers_string, content, notification_url = MessageTemplate::TeamJoined.get_message_content(receivers, organization, team) + Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id}) + receivers.find_each do |receiver| + receivers_email_string, email_title, email_content = MessageTemplate::TeamJoined.get_email_message_content(receiver, organization, team) + Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) + end + when 'TeamLeft' + user_id, organization_id, team_id = args[0], args[1], args[2] + user = User.find_by_id(user_id) + organization = Organization.find_by_id(organization_id) + team = Team.find_by_id(team_id) + return unless user.present? && organization.present? && team.present? + receivers = User.where(id: user.id) + receivers_string, content, notification_url = MessageTemplate::TeamLeft.get_message_content(receivers, organization, team) + Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id}) + receivers.find_each do |receiver| + receivers_email_string, email_title, email_content = MessageTemplate::TeamLeft.get_email_message_content(receiver, organization, team) + Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) + end end end end \ No newline at end of file diff --git a/app/libs/util.rb b/app/libs/util.rb index 1db9460f0..691ed7cab 100644 --- a/app/libs/util.rb +++ b/app/libs/util.rb @@ -29,6 +29,7 @@ module Util file.write(io) end end + true end def download_file(url, save_path) diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index a6dc0dd35..ee361d2cf 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -21,13 +21,37 @@ module ProjectOperable end def add_member!(user_id, role_name='Developer') - member = members.create!(user_id: user_id) + if self.owner.is_a?(Organization) + case role_name + when 'Manager' + team = self.owner.teams.admin.take + team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = TeamUser.build(self.user_id, user_id, team.id) + when 'Developer' + team = self.owner.teams.write.take + team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = TeamUser.build(self.user_id, user_id, team.id) + when 'Reporter' + team = self.owner.teams.read.take + team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = TeamUser.build(self.user_id, user_id, team.id) + end + end + member = members.create!(user_id: user_id, team_user_id: team_user&.id) set_developer_role(member, role_name) end def remove_member!(user_id) member = members.find_by(user_id: user_id) member.destroy! if member && self.user_id != user_id + team_user = TeamUser.find_by_id(member&.team_user_id) + team_user.destroy! if team_user end def member?(user_id) @@ -47,6 +71,28 @@ module ProjectOperable def change_member_role!(user_id, role) member = self.member(user_id) + if self.owner.is_a?(Organization) && member.team_user.present? + case role&.name + when 'Manager' + team = self.owner.teams.admin.take + team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = member.team_user.update(team_id: team&.id) + when 'Developer' + team = self.owner.teams.write.take + team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = member.team_user.update(team_id: team&.id) + when 'Reporter' + team = self.owner.teams.read.take + team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team + TeamProject.build(self.user_id, team.id, self.id) + OrganizationUser.build(self.user_id, user_id) + team_user = member.team_user.update(team_id: team&.id) + end + end member.member_roles.last.update_attributes!(role: role) end diff --git a/app/models/gitea/webhook_task.rb b/app/models/gitea/webhook_task.rb index d19a163aa..325352c69 100644 --- a/app/models/gitea/webhook_task.rb +++ b/app/models/gitea/webhook_task.rb @@ -1,7 +1,6 @@ class Gitea::WebhookTask < Gitea::Base serialize :payload_content, JSON serialize :request_content, JSON - serialize :response_content, JSON self.inheritance_column = nil @@ -10,4 +9,10 @@ class Gitea::WebhookTask < Gitea::Base belongs_to :webhook, class_name: "Gitea::Webhook", foreign_key: :hook_id enum type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9} + + def response_content_json + JSON.parse(response_content) + rescue + {} + end end \ No newline at end of file diff --git a/app/models/member.rb b/app/models/member.rb index e72ae7c6b..521f939c5 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -11,23 +11,26 @@ # course_group_id :integer default("0") # is_collect :integer default("1") # graduation_group_id :integer default("0") +# team_user_id :integer # # Indexes # # index_members_on_course_id (course_id) # index_members_on_project_id (project_id) +# index_members_on_team_user_id (team_user_id) # index_members_on_user_id (user_id) # index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE # -class Member < ApplicationRecord - belongs_to :user - # belongs_to :course, optional: true - belongs_to :project, optional: true - - has_many :member_roles, dependent: :destroy - has_many :roles, through: :member_roles - - validates :user_id, :project_id, presence: true - -end +class Member < ApplicationRecord + belongs_to :user + # belongs_to :course, optional: true + belongs_to :project, optional: true + belongs_to :team_user, optional: true + + has_many :member_roles, dependent: :destroy + has_many :roles, through: :member_roles + + validates :user_id, :project_id, presence: true + +end diff --git a/app/models/message_template.rb b/app/models/message_template.rb index f1d0baa85..c9812e511 100644 --- a/app/models/message_template.rb +++ b/app/models/message_template.rb @@ -31,8 +31,6 @@ class MessageTemplate < ApplicationRecord self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 {organization} 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织') email_html = File.read("#{email_template_html_dir}/organization_left.html") self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 {organization} 组织', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {organization} 组织') - email_html = File.read("#{email_template_html_dir}/organization_role.html") - self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 {organization} 已把你的角色改为 {role}', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}') self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '') self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '{nickname} 关注了你管理的仓库', notification_url: '{baseurl}/{login}') self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '{nickname1} 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') @@ -66,6 +64,10 @@ class MessageTemplate < ApplicationRecord self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}:{notes}', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') email_html = File.read("#{email_template_html_dir}/pull_request_merged.html") self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} 已通过', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') + email_html = File.read("#{email_template_html_dir}/team_joined.html") + self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 {organization} 的 {team} 团队,拥有{role}权限', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}') + email_html = File.read("#{email_template_html_dir}/team_left.html") + self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 {organization} 的 {team} 团队', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}') end def self.sys_notice diff --git a/app/models/message_template/team_joined.rb b/app/models/message_template/team_joined.rb new file mode 100644 index 000000000..f49940952 --- /dev/null +++ b/app/models/message_template/team_joined.rb @@ -0,0 +1,58 @@ +# == Schema Information +# +# Table name: message_templates +# +# id :integer not null, primary key +# type :string(255) +# sys_notice :text(65535) +# email :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# notification_url :string(255) +# email_title :string(255) +# + +# 账号被拉入组织团队 +class MessageTemplate::TeamJoined < MessageTemplate + + # MessageTemplate::TeamJoined.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take) + def self.get_message_content(receivers, organization, team) + receivers.each do |receiver| + if receiver.user_template_message_setting.present? + receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"] + end + end + return '', '', '' if receivers.blank? + content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name) + url = notification_url.gsub('{login}', organization&.login) + return receivers_string(receivers), content, url + rescue => e + Rails.logger.info("MessageTemplate::TeamJoined.get_message_content [ERROR] #{e}") + return '', '', '' + end + + def self.get_email_message_content(receiver, organization, role) + if receiver.user_template_message_setting.present? + return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"] + title = email_title + title.gsub!('{organization}', organization&.real_name) + title.gsub!('{team}', team&.nickname) + title.gsub!('{role}', team&.authorize_name) + content = email + content.gsub!('{receiver}', receiver&.real_name) + content.gsub!('{baseurl}', base_url) + content.gsub!('{login}', organization&.login) + content.gsub!('{organization}', organization&.real_name) + content.gsub!('{team}', team&.nickname) + content.gsub!('{role}', team&.authorize_name) + + return receiver&.mail, title, content + else + return '', '', '' + end + + rescue => e + Rails.logger.info("MessageTemplate::TeamJoined.get_email_message_content [ERROR] #{e}") + return '', '', '' + end +end diff --git a/app/models/message_template/team_left.rb b/app/models/message_template/team_left.rb new file mode 100644 index 000000000..572422633 --- /dev/null +++ b/app/models/message_template/team_left.rb @@ -0,0 +1,58 @@ +# == Schema Information +# +# Table name: message_templates +# +# id :integer not null, primary key +# type :string(255) +# sys_notice :text(65535) +# email :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# notification_url :string(255) +# email_title :string(255) +# + +# 账号被移出组织团队 +class MessageTemplate::TeamLeft < MessageTemplate + + # MessageTemplate::TeamLeft.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take) + def self.get_message_content(receivers, organization, team) + receivers.each do |receiver| + if receiver.user_template_message_setting.present? + receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"] + end + end + return '', '', '' if receivers.blank? + content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name) + url = notification_url.gsub('{login}', organization&.login) + return receivers_string(receivers), content, url + rescue => e + Rails.logger.info("MessageTemplate::TeamLeft.get_message_content [ERROR] #{e}") + return '', '', '' + end + + def self.get_email_message_content(receiver, organization, team) + if receiver.user_template_message_setting.present? + return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"] + title = email_title + title.gsub!('{organization}', organization&.real_name) + title.gsub!('{team}', team&.nickname) + title.gsub!('{role}', team&.authorize_name) + content = email + content.gsub!('{receiver}', receiver&.real_name) + content.gsub!('{baseurl}', base_url) + content.gsub!('{login}', organization&.login) + content.gsub!('{organization}', organization&.real_name) + content.gsub!('{team}', team&.nickname) + content.gsub!('{role}', team&.authorize_name) + + return receiver&.mail, title, content + else + return '', '', '' + end + + rescue => e + Rails.logger.info("MessageTemplate::TeamLeft.get_email_message_content [ERROR] #{e}") + return '', '', '' + end +end diff --git a/app/models/team.rb b/app/models/team.rb index 19d05c77a..c2e633380 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -56,10 +56,10 @@ class Team < ApplicationRecord def authorize_name case self.authorize - when 'read' then '报告者' - when 'write' then '开发者' + when 'read' then '读取' + when 'write' then '写入' when 'admin' then '管理员' - when 'owner' then '拥有者' + when 'owner' then '管理员' else '' end diff --git a/app/models/team_user.rb b/app/models/team_user.rb index 9670013a7..9f90bc15b 100644 --- a/app/models/team_user.rb +++ b/app/models/team_user.rb @@ -22,9 +22,17 @@ class TeamUser < ApplicationRecord belongs_to :team, counter_cache: :num_users belongs_to :user + has_one :member + validates :user_id, uniqueness: {scope: [:organization_id, :team_id]} + before_destroy :remove_project_member + def self.build(organization_id, user_id, team_id) self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id) end + + def remove_project_member + member.destroy if member.present? + end end diff --git a/app/models/user.rb b/app/models/user.rb index 3f37ab1ea..5ca3356b6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -773,7 +773,7 @@ class User < Owner end def profile_is_completed? - self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? + self.nickname.present? && self.mail.present? end protected diff --git a/app/services/gitea/repository/branches/list_name_service.rb b/app/services/gitea/repository/branches/list_name_service.rb new file mode 100644 index 000000000..716ee464c --- /dev/null +++ b/app/services/gitea/repository/branches/list_name_service.rb @@ -0,0 +1,22 @@ +class Gitea::Repository::Branches::ListNameService < Gitea::ClientService + attr_reader :user, :repo + + def initialize(user, repo) + @user = user + @repo = repo + end + + def call + response = get(url, params) + render_200_response(response) + end + + private + def params + Hash.new.merge(token: user.gitea_token) + end + + def url + "/repos/#{user.login}/#{repo}/branch_name_set".freeze + end +end diff --git a/app/services/gitea/repository/entries/create_service.rb b/app/services/gitea/repository/entries/create_service.rb index 5e1a4c4b3..1bdc7246d 100644 --- a/app/services/gitea/repository/entries/create_service.rb +++ b/app/services/gitea/repository/entries/create_service.rb @@ -55,7 +55,12 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService when 201 then success(json_parse!(body)) when 403 then error("你没有权限操作!") when 404 then error("你操作的链接不存在!") - when 422 then error("#{filepath}文件已存在,不能重复创建!") + when 422 + if @body[:new_branch].include?('/') || @body[:new_branch].include?('\'') || @body[:new_branch].include?('^') || @body[:new_branch].include?('*') + error("不合法的分支名称!") + else + error("#{filepath}文件已存在,不能重复创建!") + end else error("系统错误!") end end diff --git a/app/services/pull_requests/create_service.rb b/app/services/pull_requests/create_service.rb index eaf931f38..d15b3f9fc 100644 --- a/app/services/pull_requests/create_service.rb +++ b/app/services/pull_requests/create_service.rb @@ -125,12 +125,17 @@ class PullRequests::CreateService < ApplicationService end def gitea_pull_request_params - merge_original_pull_params.except(:milestone) + assignee_login = User.find_by_id(params[:assigned_to_id])&.login + merge_original_pull_params.except(:milestone).merge( + # assignees: ["#{params[:assigned_login].to_s}"], + assignees: ["#{assignee_login.to_s}"]) end def merge_original_pull_params + base_pull_params[:head] = CGI.escape(base_pull_params[:head]) + base_pull_params[:base] = CGI.escape(base_pull_params[:base]) if pull_request.is_original && @params[:merge_user_login] - base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{@params[:head]}") + base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}") else base_pull_params end @@ -160,7 +165,7 @@ class PullRequests::CreateService < ApplicationService def compare_head_base! head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head] - compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, @params[:base], head, @current_user.gitea_token) + compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(@params[:base]), CGI.escape(head), @current_user.gitea_token) raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank? end diff --git a/app/views/issues/show.json.jbuilder b/app/views/issues/show.json.jbuilder index be6de14e0..5c8cbc410 100644 --- a/app/views/issues/show.json.jbuilder +++ b/app/views/issues/show.json.jbuilder @@ -13,6 +13,7 @@ json.tracker @issue.tracker.try(:name) json.issue_status @issue.issue_status.try(:name) json.priority @issue.priority.try(:name) json.version @issue.version.try(:name) +json.version_id @issue.version.try(:id) json.issue_tags @issue.get_issue_tags json.done_ratio @issue.done_ratio.to_s + "%" json.issue_type @issue.issue_type diff --git a/app/views/organizations/teams/_simple_detail.json.jbuilder b/app/views/organizations/teams/_simple_detail.json.jbuilder new file mode 100644 index 000000000..5e9a6246d --- /dev/null +++ b/app/views/organizations/teams/_simple_detail.json.jbuilder @@ -0,0 +1,3 @@ +json.id team.id +json.name team.name +json.nickname team.nickname.blank? ? team.name : team.nickname \ No newline at end of file diff --git a/app/views/organizations/teams/index.json.jbuilder b/app/views/organizations/teams/index.json.jbuilder index ad3479ec4..189047fc4 100644 --- a/app/views/organizations/teams/index.json.jbuilder +++ b/app/views/organizations/teams/index.json.jbuilder @@ -1,4 +1,8 @@ -json.total_count @teams.total_count +json.total_count params[:is_full].present? ? @teams.count : @teams.total_count json.teams @teams do |team| - json.partial! "detail", team: team, organization: @organization + if params[:is_full].present? + json.partial! "simple_detail", team: team, organization: @organization + else + json.partial! "detail", team: team, organization: @organization + end end diff --git a/app/views/project_trends/_detail.json.jbuilder b/app/views/project_trends/_detail.json.jbuilder index 75bcf2237..04de10f6a 100644 --- a/app/views/project_trends/_detail.json.jbuilder +++ b/app/views/project_trends/_detail.json.jbuilder @@ -6,6 +6,13 @@ json.user_name trend.user.try(:show_real_name) json.user_login trend.user.login json.user_avatar url_to_avatar(trend.user) json.action_time time_from_now(trend.created_at) +json.project do + json.owner do + json.partial! 'users/user_simple', locals: {user: trend&.project&.owner} + end + json.identifier trend&.project&.identifier + json.description trend&.project&.description +end if trend.trend_type == "Issue" json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} diff --git a/app/views/projects/branches.json.jbuilder b/app/views/projects/branches.json.jbuilder index c7c2025b3..3bfc9f46b 100644 --- a/app/views/projects/branches.json.jbuilder +++ b/app/views/projects/branches.json.jbuilder @@ -1,21 +1,22 @@ json.array! @branches do |branch| - json.name branch['name'] - json.user_can_push branch['user_can_push'] - json.user_can_merge branch['user_can_merge'] - json.protected branch['protected'] + branch_name = branch.is_a?(Hash) ? branch['name'] : branch + json.name branch_name + # json.user_can_push branch['user_can_push'] + # json.user_can_merge branch['user_can_merge'] + # json.protected branch['protected'] json.http_url render_http_url(@project) - json.zip_url render_zip_url(@owner, @repository, branch['name']) - json.tar_url render_tar_url(@owner, @repository, branch['name']) - json.last_commit do - json.sha branch['commit']['id'] - json.message branch['commit']['message'] - json.timestamp render_unix_time(branch['commit']['timestamp']) - json.time_from_now time_from_now(branch['commit']['timestamp']) - json.author do - json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name'] - end - json.committer do - json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name'] - end - end + json.zip_url render_zip_url(@owner, @repository, branch_name) + json.tar_url render_tar_url(@owner, @repository, branch_name) + # json.last_commit do + # json.sha branch['commit']['id'] + # json.message branch['commit']['message'] + # json.timestamp render_unix_time(branch['commit']['timestamp']) + # json.time_from_now time_from_now(branch['commit']['timestamp']) + # json.author do + # json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name'] + # end + # json.committer do + # json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name'] + # end + # end end diff --git a/app/views/projects/webhooks/_detail.json.jbuilder b/app/views/projects/webhooks/_detail.json.jbuilder index 2497e5c64..41a91f4ad 100644 --- a/app/views/projects/webhooks/_detail.json.jbuilder +++ b/app/views/projects/webhooks/_detail.json.jbuilder @@ -1,4 +1,4 @@ json.(webhook, :id, :url, :http_method, :is_active) -json.type webhook.hook_task_type +json.type webhook.type json.last_status webhook.last_status json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S") \ No newline at end of file diff --git a/app/views/projects/webhooks/edit.json.jbuilder b/app/views/projects/webhooks/edit.json.jbuilder index 2ee6d24e8..c54d10306 100644 --- a/app/views/projects/webhooks/edit.json.jbuilder +++ b/app/views/projects/webhooks/edit.json.jbuilder @@ -1,6 +1,6 @@ json.id @webhook.id json.(@webhook, :id, :http_method, :content_type, :url, :secret, :last_status, :is_active) -json.type @webhook.hook_task_type +json.type @webhook.type json.create_time Time.at(@webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S") event = @webhook.events json.branch_filter event["branch_filter"] diff --git a/app/views/projects/webhooks/tasks.json.jbuilder b/app/views/projects/webhooks/tasks.json.jbuilder index b8aef99f5..82b2eae4a 100644 --- a/app/views/projects/webhooks/tasks.json.jbuilder +++ b/app/views/projects/webhooks/tasks.json.jbuilder @@ -1,5 +1,6 @@ json.total_count @tasks.total_count json.tasks @tasks.each do |task| - json.(task, :id, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content, :response_content) + json.(task, :id, :event_type, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content) + json.response_content task.response_content_json json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S") end \ No newline at end of file diff --git a/app/views/pull_requests/_commit.json.jbuilder b/app/views/pull_requests/_commit.json.jbuilder index 52b776008..2cd2bab78 100644 --- a/app/views/pull_requests/_commit.json.jbuilder +++ b/app/views/pull_requests/_commit.json.jbuilder @@ -1,12 +1,27 @@ -json.author do - json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] } -end +if commit['Status'].present? + json.author do + json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] } + end + + json.committer do + json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] } + end + json.timestamp render_unix_time(commit['Committer']['When']) + json.time_from_now time_from_now(commit['Committer']['When']) + json.created_at render_format_time_with_date(commit['Committer']['When']) + json.message commit['CommitMessage'] + json.sha commit['Sha'] +else + json.author do + json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] } + end -json.committer do - json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] } -end -json.timestamp render_unix_time(commit['Committer']['When']) -json.time_from_now time_from_now(commit['Committer']['When']) -json.created_at render_format_time_with_date(commit['Committer']['When']) -json.message commit['CommitMessage'] -json.sha commit['Sha'] + json.committer do + json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] } + end + json.timestamp render_unix_time(commit['commit']['committer']['date']) + json.time_from_now time_from_now(commit['commit']['committer']['date']) + json.created_at render_format_time_with_date(commit['commit']['committer']['date']) + json.message commit['commit']['message'] + json.sha commit['sha'] +end \ No newline at end of file diff --git a/app/views/repositories/_simple_entry.json.jbuilder b/app/views/repositories/_simple_entry.json.jbuilder index 80a54d477..9d0998c82 100644 --- a/app/views/repositories/_simple_entry.json.jbuilder +++ b/app/views/repositories/_simple_entry.json.jbuilder @@ -9,7 +9,7 @@ if @project.forge? json.type entry['type'] json.size entry['size'] - json.content decode64_content(entry, @owner, @repository, @ref, @path) + json.content direct_download ? nil : decode64_content(entry, @owner, @repository, @ref, @path) json.target entry['target'] download_url = diff --git a/config/routes.rb b/config/routes.rb index d4e1ba1c5..be87e7e68 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -213,6 +213,7 @@ Rails.application.routes.draw do get :watch_users get :fan_users get :hovercard + put :update_image end collection do post :following diff --git a/db/migrate/20211222015006_add_team_user_to_members.rb b/db/migrate/20211222015006_add_team_user_to_members.rb new file mode 100644 index 000000000..b3ca8edf0 --- /dev/null +++ b/db/migrate/20211222015006_add_team_user_to_members.rb @@ -0,0 +1,5 @@ +class AddTeamUserToMembers < ActiveRecord::Migration[5.2] + def change + add_reference :members, :team_user + end +end diff --git a/public/message_template/team_joined.html b/public/message_template/team_joined.html new file mode 100755 index 000000000..231f8b795 --- /dev/null +++ b/public/message_template/team_joined.html @@ -0,0 +1,47 @@ + +
+
+ {receiver},您好!
+ 你已被拉入组织 {organization} 的 {team} 团队,拥有{role}权限
+
如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见
+ QQ群:1071514693
GitLink团队
+ +
+ {receiver},您好!
+ 你已被移出组织 {organization} 的 {team} 团队
+
如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见
+ QQ群:1071514693
GitLink团队
+ +