Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
xiaoxiaoqiong 2022-01-21 15:50:41 +08:00
commit 98d8ee1fb6
45 changed files with 540 additions and 118 deletions

View File

@ -9,6 +9,7 @@ class AccountsController < ApplicationController
# 其他平台同步注册的用户 # 其他平台同步注册的用户
def remote_register def remote_register
Register::RemoteForm.new(remote_register_params).validate!
username = params[:username]&.gsub(/\s+/, "") username = params[:username]&.gsub(/\s+/, "")
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username) tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
email = params[:email]&.gsub(/\s+/, "") email = params[:email]&.gsub(/\s+/, "")
@ -368,4 +369,8 @@ class AccountsController < ApplicationController
params.permit(:login, :namespace, :password, :code) params.permit(:login, :namespace, :password, :code)
end end
def remote_register_params
params.permit(:username, :email, :password, :platform)
end
end end

View File

@ -709,14 +709,20 @@ class ApplicationController < ActionController::Base
Rails.application.config_for(:configuration)['platform_url'] || request.base_url Rails.application.config_for(:configuration)['platform_url'] || request.base_url
end 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! def convert_image!
@image = params[:image] @image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image @image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
return unless @image.present? return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile if @image.class == ActionDispatch::Http::UploadedFile
render_error('请上传文件') if @image.size.zero? return render_error('请上传文件') if @image.size.zero?
render_error('文件大小超过限制') if @image.size > max_size.to_i 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 else
image = @image.to_s.strip image = @image.to_s.strip
return render_error('请上传正确的图片') if image.blank? return render_error('请上传正确的图片') if image.blank?

View File

@ -42,12 +42,14 @@ class CompareController < ApplicationController
end end
def load_compare_params 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 = 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 end
def gitea_compare(base, head) 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
end end

View File

@ -179,7 +179,7 @@ module Ci::CloudAccountManageable
def drone_oauth_user!(url, state) def drone_oauth_user!(url, state)
logger.info "[drone] drone_oauth_user url: #{url}" 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.request :url_encoded
req.adapter Faraday.default_adapter req.adapter Faraday.default_adapter
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}" req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
@ -188,7 +188,8 @@ module Ci::CloudAccountManageable
response = conn.get response = conn.get
logger.info "[drone] response headers: #{response.headers}" logger.info "[drone] response headers: #{response.headers}"
response.headers['location'].include?('error') ? false : true true
# response.headers['location'].include?('error') ? false : true
end end
private private

View File

@ -486,7 +486,8 @@ class IssuesController < ApplicationController
end end
def operate_issue_permission 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 end
def export_issues(issues) def export_issues(issues)

View File

@ -28,7 +28,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name]) 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) @organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present? Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
end end

View File

@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
@organization_user = OrganizationUser.build(@organization.id, @operate_user.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) Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
end end
rescue Exception => e rescue Exception => e
@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
@team_user.destroy! @team_user.destroy!
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login) 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) org_team_users = @organization.team_users.where(user_id: @operate_user.id)
unless org_team_users.present? unless org_team_users.present?
@organization.organization_users.find_by(user_id: @operate_user.id).destroy! @organization.organization_users.find_by(user_id: @operate_user.id).destroy!

View File

@ -4,15 +4,24 @@ class Organizations::TeamsController < Organizations::BaseController
before_action :check_user_can_edit_org, only: [:create, :update, :destroy] before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
def index 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 end
def search def search
@ -34,8 +43,12 @@ class Organizations::TeamsController < Organizations::BaseController
def create def create
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
Organizations::CreateTeamForm.new(team_params).validate! if @organization.teams.count >= 50
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params) return tip_exception("组织的团队数量已超过限制!")
else
Organizations::CreateTeamForm.new(team_params).validate!
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
end
end end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)

View File

@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
before_action :check_project_public before_action :check_project_public
def index 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_time = params[:time] #时间的筛选
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version

View File

@ -59,18 +59,23 @@ class ProjectsController < ApplicationController
Projects::MigrateForm.new(mirror_params).validate! Projects::MigrateForm.new(mirror_params).validate!
@project = @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] source_clone_url = mirror_params[:clone_addr]
uid_logger("########## 已动加速器 ##########") clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
result = Gitea::Accelerator::MigrateService.call(mirror_params) uid_logger("########## 更改clone_addr ##########")
if result[:status] == :success Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
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
else else
Projects::MigrateService.call(current_user, mirror_params) Projects::MigrateService.call(current_user, mirror_params)
end end
@ -82,8 +87,9 @@ class ProjectsController < ApplicationController
def branches def branches
return @branches = [] unless @project.forge? return @branches = [] unless @project.forge?
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier) # result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier)
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
end end
def branches_slice def branches_slice

View File

@ -274,12 +274,12 @@ class PullRequestsController < ApplicationController
base: params[:base], #目标分支 base: params[:base], #目标分支
milestone: 0, #里程碑,未与本地的里程碑关联 milestone: 0, #里程碑,未与本地的里程碑关联
} }
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
@requests_params = @local_params.merge({ @requests_params = @local_params.merge({
assignee: current_user.try(:login),
# assignees: ["#{params[:assigned_login].to_s}"], # assignees: ["#{params[:assigned_login].to_s}"],
assignees: ["#{current_user.try(:login).to_s}"], assignees: ["#{assignee_login.to_s}"],
labels: params[:issue_tag_ids], labels: params[:issue_tag_ids]
due_date: Time.now # due_date: Time.now
}) })
@issue_params = { @issue_params = {
author_id: current_user.id, author_id: current_user.id,

View File

@ -238,7 +238,7 @@ class RepositoriesController < ApplicationController
def archive def archive
domain = Gitea.gitea_config[:domain] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] 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 = [domain, api_url, archive_url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden? 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] domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url] 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 = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
redirect_to URI.escape(file_path) redirect_to file_path
end end
private private

View File

@ -6,7 +6,7 @@ class UsersController < ApplicationController
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] 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 :require_login, only: %i[me list sync_user_info]
before_action :connect_to_ci_db, only: [:get_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] skip_before_action :check_sign, only: [:attachment_show]
def connect_to_ci_db(options={}) 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? Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
@user.attributes = user_params.except(:image) @user.attributes = user_params.except(:image)
unless @user.save unless @user.save
render_error(@user.errors.full_messages.join(", ")) render_error(-1, @user.errors.full_messages.join(", "))
end end
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 def me
@user = current_user @user = current_user
end end

View File

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

View File

@ -11,11 +11,11 @@ module RepositoriesHelper
def download_type(str) 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 = %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 end
def image_type?(str) 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) default_type.include?(str&.downcase)
end end

View File

@ -29,8 +29,9 @@ module TagChosenHelper
if project.educoder? if project.educoder?
return ['master'] return ['master']
else else
branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier) branches = Gitea::Repository::Branches::ListNameService.call(project&.owner, project.identifier)
branches.collect{|i| i["name"] if i.is_a?(Hash)} 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
end end

View File

@ -6,7 +6,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob
return if repo.blank? return if repo.blank?
puts "############ MigrateRemoteRepositoryJob starting ... ############" puts "############ MigrateRemoteRepositoryJob starting ... ############"
params.except!(:auth_password, :auth_username) if params[:auth_username].nil?
gitea_repository = Gitea::Repository::MigrateService.new(token, params).call gitea_repository = Gitea::Repository::MigrateService.new(token, params).call
puts "#gitea_repository#{gitea_repository}" puts "#gitea_repository#{gitea_repository}"
if gitea_repository[0]==201 if gitea_repository[0]==201

View File

@ -94,18 +94,6 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end 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' when 'ProjectIssue'
operator_id, issue_id = args[0], args[1] operator_id, issue_id = args[0], args[1]
operator = User.find_by_id(operator_id) 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) 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) Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end 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 end
end end

View File

@ -29,6 +29,7 @@ module Util
file.write(io) file.write(io)
end end
end end
true
end end
def download_file(url, save_path) def download_file(url, save_path)

View File

@ -21,13 +21,37 @@ module ProjectOperable
end end
def add_member!(user_id, role_name='Developer') 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) set_developer_role(member, role_name)
end end
def remove_member!(user_id) def remove_member!(user_id)
member = members.find_by(user_id: user_id) member = members.find_by(user_id: user_id)
member.destroy! if member && self.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 end
def member?(user_id) def member?(user_id)
@ -47,6 +71,28 @@ module ProjectOperable
def change_member_role!(user_id, role) def change_member_role!(user_id, role)
member = self.member(user_id) 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) member.member_roles.last.update_attributes!(role: role)
end end

View File

@ -1,7 +1,6 @@
class Gitea::WebhookTask < Gitea::Base class Gitea::WebhookTask < Gitea::Base
serialize :payload_content, JSON serialize :payload_content, JSON
serialize :request_content, JSON serialize :request_content, JSON
serialize :response_content, JSON
self.inheritance_column = nil self.inheritance_column = nil
@ -10,4 +9,10 @@ class Gitea::WebhookTask < Gitea::Base
belongs_to :webhook, class_name: "Gitea::Webhook", foreign_key: :hook_id 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} 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 end

View File

@ -11,11 +11,13 @@
# course_group_id :integer default("0") # course_group_id :integer default("0")
# is_collect :integer default("1") # is_collect :integer default("1")
# graduation_group_id :integer default("0") # graduation_group_id :integer default("0")
# team_user_id :integer
# #
# Indexes # Indexes
# #
# index_members_on_course_id (course_id) # index_members_on_course_id (course_id)
# index_members_on_project_id (project_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 (user_id)
# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE # index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE
# #
@ -24,6 +26,7 @@ class Member < ApplicationRecord
belongs_to :user belongs_to :user
# belongs_to :course, optional: true # belongs_to :course, optional: true
belongs_to :project, optional: true belongs_to :project, optional: true
belongs_to :team_user, optional: true
has_many :member_roles, dependent: :destroy has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles has_many :roles, through: :member_roles

View File

@ -31,8 +31,6 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织') self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_left.html") email_html = File.read("#{email_template_html_dir}/organization_left.html")
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {organization} 组织') self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', 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: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', 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::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '')
self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}') self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{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}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html") email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}') self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', 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: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', 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: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
end end
def self.sys_notice def self.sys_notice

View File

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

View File

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

View File

@ -56,10 +56,10 @@ class Team < ApplicationRecord
def authorize_name def authorize_name
case self.authorize case self.authorize
when 'read' then '报告者' when 'read' then '读取'
when 'write' then '开发者' when 'write' then '写入'
when 'admin' then '管理员' when 'admin' then '管理员'
when 'owner' then '拥有者' when 'owner' then '管理员'
else else
'' ''
end end

View File

@ -22,9 +22,17 @@ class TeamUser < ApplicationRecord
belongs_to :team, counter_cache: :num_users belongs_to :team, counter_cache: :num_users
belongs_to :user belongs_to :user
has_one :member
validates :user_id, uniqueness: {scope: [:organization_id, :team_id]} validates :user_id, uniqueness: {scope: [:organization_id, :team_id]}
before_destroy :remove_project_member
def self.build(organization_id, user_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) self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id)
end end
def remove_project_member
member.destroy if member.present?
end
end end

View File

@ -773,7 +773,7 @@ class User < Owner
end end
def profile_is_completed? def profile_is_completed?
self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? self.nickname.present? && self.mail.present?
end end
protected protected

View File

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

View File

@ -55,7 +55,12 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
when 201 then success(json_parse!(body)) when 201 then success(json_parse!(body))
when 403 then error("你没有权限操作!") when 403 then error("你没有权限操作!")
when 404 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("系统错误!") else error("系统错误!")
end end
end end

View File

@ -125,12 +125,17 @@ class PullRequests::CreateService < ApplicationService
end end
def gitea_pull_request_params 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 end
def merge_original_pull_params 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] 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 else
base_pull_params base_pull_params
end end
@ -160,7 +165,7 @@ class PullRequests::CreateService < ApplicationService
def compare_head_base! def compare_head_base!
head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head] 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? raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank?
end end

View File

@ -13,6 +13,7 @@ json.tracker @issue.tracker.try(:name)
json.issue_status @issue.issue_status.try(:name) json.issue_status @issue.issue_status.try(:name)
json.priority @issue.priority.try(:name) json.priority @issue.priority.try(:name)
json.version @issue.version.try(:name) json.version @issue.version.try(:name)
json.version_id @issue.version.try(:id)
json.issue_tags @issue.get_issue_tags json.issue_tags @issue.get_issue_tags
json.done_ratio @issue.done_ratio.to_s + "%" json.done_ratio @issue.done_ratio.to_s + "%"
json.issue_type @issue.issue_type json.issue_type @issue.issue_type

View File

@ -0,0 +1,3 @@
json.id team.id
json.name team.name
json.nickname team.nickname.blank? ? team.name : team.nickname

View File

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

View File

@ -6,6 +6,13 @@ json.user_name trend.user.try(:show_real_name)
json.user_login trend.user.login json.user_login trend.user.login
json.user_avatar url_to_avatar(trend.user) json.user_avatar url_to_avatar(trend.user)
json.action_time time_from_now(trend.created_at) 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" if trend.trend_type == "Issue"
json.partial! "issues/simple_issue_item", locals: {issue: trend.trend} json.partial! "issues/simple_issue_item", locals: {issue: trend.trend}

View File

@ -1,21 +1,22 @@
json.array! @branches do |branch| json.array! @branches do |branch|
json.name branch['name'] branch_name = branch.is_a?(Hash) ? branch['name'] : branch
json.user_can_push branch['user_can_push'] json.name branch_name
json.user_can_merge branch['user_can_merge'] # json.user_can_push branch['user_can_push']
json.protected branch['protected'] # json.user_can_merge branch['user_can_merge']
# json.protected branch['protected']
json.http_url render_http_url(@project) json.http_url render_http_url(@project)
json.zip_url render_zip_url(@owner, @repository, branch['name']) json.zip_url render_zip_url(@owner, @repository, branch_name)
json.tar_url render_tar_url(@owner, @repository, branch['name']) json.tar_url render_tar_url(@owner, @repository, branch_name)
json.last_commit do # json.last_commit do
json.sha branch['commit']['id'] # json.sha branch['commit']['id']
json.message branch['commit']['message'] # json.message branch['commit']['message']
json.timestamp render_unix_time(branch['commit']['timestamp']) # json.timestamp render_unix_time(branch['commit']['timestamp'])
json.time_from_now time_from_now(branch['commit']['timestamp']) # json.time_from_now time_from_now(branch['commit']['timestamp'])
json.author do # json.author do
json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name'] # json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name']
end # end
json.committer do # json.committer do
json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name'] # json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name']
end # end
end # end
end end

View File

@ -1,4 +1,4 @@
json.(webhook, :id, :url, :http_method, :is_active) 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.last_status webhook.last_status
json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S") json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")

View File

@ -1,6 +1,6 @@
json.id @webhook.id json.id @webhook.id
json.(@webhook, :id, :http_method, :content_type, :url, :secret, :last_status, :is_active) 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") json.create_time Time.at(@webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")
event = @webhook.events event = @webhook.events
json.branch_filter event["branch_filter"] json.branch_filter event["branch_filter"]

View File

@ -1,5 +1,6 @@
json.total_count @tasks.total_count json.total_count @tasks.total_count
json.tasks @tasks.each do |task| 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") json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S")
end end

View File

@ -1,12 +1,27 @@
json.author do if commit['Status'].present?
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] } json.author do
end json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
end
json.committer do json.committer do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] } 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['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 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']

View File

@ -9,7 +9,7 @@ if @project.forge?
json.type entry['type'] json.type entry['type']
json.size entry['size'] 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'] json.target entry['target']
download_url = download_url =

View File

@ -213,6 +213,7 @@ Rails.application.routes.draw do
get :watch_users get :watch_users
get :fan_users get :fan_users
get :hovercard get :hovercard
put :update_image
end end
collection do collection do
post :following post :following

View File

@ -0,0 +1,5 @@
class AddTeamUserToMembers < ActiveRecord::Migration[5.2]
def change
add_reference :members, :team_user
end
end

View File

@ -0,0 +1,47 @@
<html>
<head>
<title>被拉入组织团队</title>
<style type="text/css">
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;}
div,img,tr,td,table{ border:0;}
table,tr,td{border:0;}
ol,ul,li{ list-style-type:none}
.new_content{ background:#fff; width: 100%;}
.email-page-link{ }
.email-link-top{ }
.c_white{ color:#fff;}
.email-link-con{ }
.email-link-line{ }
.email-link-footer{ padding:15px; color:#333; line-height: 1.9; }
.c_grey02{ color: #888;}
.fb{ font-weight: normal;}
.f14{ }
</style>
</head>
<body style="background:#fff;">
<div class="new_content">
<div style="width: 598px; background:#fff; margin:20px auto;">
<div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.png" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
<p style="font-size: 14px; color:#333;">
{receiver},您好!<br/>
你已被拉入组织 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a><a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队,拥有{role}权限
</p>
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
</div>
<div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;">
<p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/>
QQ群1071514693</p>
<p style="color:#888; float:right;font-weight: bold;font-size: 16px;">GitLink团队</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<html>
<head>
<title>被移出组织团队</title>
<style type="text/css">
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;}
div,img,tr,td,table{ border:0;}
table,tr,td{border:0;}
ol,ul,li{ list-style-type:none}
.new_content{ background:#fff; width: 100%;}
.email-page-link{ }
.email-link-top{ }
.c_white{ color:#fff;}
.email-link-con{ }
.email-link-line{ }
.email-link-footer{ padding:15px; color:#333; line-height: 1.9; }
.c_grey02{ color: #888;}
.fb{ font-weight: normal;}
.f14{ }
</style>
</head>
<body style="background:#fff;">
<div class="new_content">
<div style="width: 598px; background:#fff; margin:20px auto;">
<div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.png" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
<p style="font-size: 14px; color:#333;">
{receiver},您好!<br/>
你已被移出组织 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a><a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队
</p>
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
</div>
<div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;">
<p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/>
QQ群1071514693</p>
<p style="color:#888; float:right;font-weight: bold;font-size: 16px;">GitLink团队</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
</div>
</div>
</body>
</html>