diff --git a/Gemfile b/Gemfile
index 8fd3e7cff..edaae8a75 100644
--- a/Gemfile
+++ b/Gemfile
@@ -141,4 +141,4 @@ gem 'doorkeeper'
gem 'doorkeeper-jwt'
-gem 'gitea-client', '~> 1.4.3'
+gem 'gitea-client', '~> 1.4.6'
diff --git a/app/controllers/api/v1/projects/actions/actions_controller.rb b/app/controllers/api/v1/projects/actions/actions_controller.rb
new file mode 100644
index 000000000..3825b4685
--- /dev/null
+++ b/app/controllers/api/v1/projects/actions/actions_controller.rb
@@ -0,0 +1,31 @@
+class Api::V1::Projects::Actions::ActionsController < Api::V1::Projects::Actions::BaseController
+
+ def index
+ begin
+ gitea_result = $gitea_hat_client.get_repos_actions_by_owner_repo(@project&.owner&.login, @project&.identifier)
+ @data = gitea_result[:data]["Workflows"]
+ rescue
+ @data = []
+ end
+ end
+
+ def disable
+ return render_error("请输入正确的流水线文件!") if params[:workflow].blank?
+ gitea_result = $gitea_hat_client.post_repos_actions_disable(@project&.owner&.login, @project&.identifier, {query: {workflow: params[:workflow]}}) rescue nil
+ if gitea_result
+ render_ok
+ else
+ render_error("禁用流水线失败")
+ end
+ end
+
+ def enable
+ return render_error("请输入正确的流水线文件!") if params[:workflow].blank?
+ gitea_result = $gitea_hat_client.post_repos_actions_enable(@project&.owner&.login, @project&.identifier, {query: {workflow: params[:workflow]}}) rescue nil
+ if gitea_result
+ render_ok
+ else
+ render_error("取消禁用流水线失败")
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/actions/base_controller.rb b/app/controllers/api/v1/projects/actions/base_controller.rb
new file mode 100644
index 000000000..d76b446ad
--- /dev/null
+++ b/app/controllers/api/v1/projects/actions/base_controller.rb
@@ -0,0 +1,4 @@
+class Api::V1::Projects::Actions::BaseController < Api::V1::BaseController
+ before_action :require_public_and_member_above
+
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/actions/runs_controller.rb b/app/controllers/api/v1/projects/actions/runs_controller.rb
new file mode 100644
index 000000000..05918dbe2
--- /dev/null
+++ b/app/controllers/api/v1/projects/actions/runs_controller.rb
@@ -0,0 +1,12 @@
+class Api::V1::Projects::Actions::RunsController < Api::V1::Projects::Actions::BaseController
+
+ def index
+ @result_object = Api::V1::Projects::Actions::Runs::ListService.call(@project, {workflow: params[:workflow], page: page, limit: limit}, current_user&.gitea_token)
+ puts @result_object
+ end
+
+ def job_show
+ @result_object = Api::V1::Projects::Actions::Runs::JobShowService.call(@project, params[:run_id], params[:job], params[:log_cursors], current_user&.gitea_token)
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/branches_controller.rb b/app/controllers/api/v1/projects/branches_controller.rb
index 40f44fea5..89ebb5825 100644
--- a/app/controllers/api/v1/projects/branches_controller.rb
+++ b/app/controllers/api/v1/projects/branches_controller.rb
@@ -2,14 +2,14 @@ class Api::V1::Projects::BranchesController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index, :all]
def index
- @result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
+ @result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], state: params[:state], page: page, limit: limit}, current_user&.gitea_token)
end
def all
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
end
- before_action :require_operate_above, only: [:create, :destroy]
+ before_action :require_operate_above, only: [:create, :destroy, :restore]
def create
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
@@ -33,6 +33,15 @@ class Api::V1::Projects::BranchesController < Api::V1::BaseController
end
end
+ def restore
+ @result_object = Api::V1::Projects::Branches::RestoreService.call(@project, params[:branch_id], params[:branch_name], current_user&.gitea_token)
+ if @result_object
+ return render_ok
+ else
+ return render_error('恢复分支失败!')
+ end
+ end
+
before_action :require_manager_above, only: [:update_default_branch]
def update_default_branch
diff --git a/app/controllers/api/v1/projects/commits_controller.rb b/app/controllers/api/v1/projects/commits_controller.rb
index a1545ae6f..21987f4fb 100644
--- a/app/controllers/api/v1/projects/commits_controller.rb
+++ b/app/controllers/api/v1/projects/commits_controller.rb
@@ -1,5 +1,5 @@
class Api::V1::Projects::CommitsController < Api::V1::BaseController
- before_action :require_public_and_member_above, only: [:index, :diff]
+ before_action :require_public_and_member_above, only: [:index, :diff, :recent]
def index
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
@@ -9,4 +9,8 @@ class Api::V1::Projects::CommitsController < Api::V1::BaseController
def diff
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
end
+
+ def recent
+ @result_object = Api::V1::Projects::Commits::RecentService.call(@project, {keyword: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
+ end
end
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 8981a0995..0c134a3bd 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -715,7 +715,7 @@ class ApplicationController < ActionController::Base
end
def find_user_with_id
- @user = User.find_by_id params[:user_id]
+ @user = User.find_by(type: 'User', id: params[:user_id])
# render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
render_error("未找到相关的用户") unless @user
end
diff --git a/app/controllers/bind_users_controller.rb b/app/controllers/bind_users_controller.rb
index f5ed33809..b8c25dd7d 100644
--- a/app/controllers/bind_users_controller.rb
+++ b/app/controllers/bind_users_controller.rb
@@ -8,7 +8,7 @@ class BindUsersController < ApplicationController
bind_user = User.try_to_login(params[:username], params[:password])
tip_exception '用户名或者密码错误' if bind_user.blank?
tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s)
- tip_exception '参数错误' unless ["qq", "wechat", "gitee", "github", "educoder"].include?(params[:type].to_s)
+ tip_exception '参数错误' unless ["qq", "wechat", "gitee", "github", "educoder", "acge"].include?(params[:type].to_s)
tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
"OpenUsers::#{params[:type].to_s.capitalize}".constantize.create!(user: bind_user, uid: session[:unionid])
diff --git a/app/controllers/oauth/acge_controller.rb b/app/controllers/oauth/acge_controller.rb
new file mode 100644
index 000000000..efa5cca08
--- /dev/null
+++ b/app/controllers/oauth/acge_controller.rb
@@ -0,0 +1,67 @@
+class Oauth::AcgeController < Oauth::BaseController
+ include RegisterHelper
+
+ def create
+ begin
+ uid = params['uid'].to_s.strip
+ tip_exception("uid不能为空") if uid.blank?
+ redirect_uri = params['redirect_uri'].to_s.strip
+ tip_exception("redirect_uri不能为空") if redirect_uri.blank?
+ email = params['email'].to_s.strip
+ tip_exception("email不能为空") if email.blank?
+ phone = params['phone'].to_s.strip
+ tip_exception("phone不能为空") if phone.blank?
+ name = params['name'].to_s.strip
+ tip_exception("name不能为空") if name.blank?
+
+ open_user = OpenUsers::Acge.find_by(uid: uid)
+ if open_user.present? && open_user.user.present?
+ successful_authentication(open_user.user)
+ redirect_to redirect_uri
+ return
+ else
+ if current_user.blank? || !current_user.logged?
+ session[:unionid] = uid
+ user = User.find_by(mail: email) || User.find_by(phone: phone)
+ if user.present?
+ OpenUsers::Acge.create!(user: user, uid: uid)
+ successful_authentication(user)
+ redirect_to redirect_uri
+
+ return
+ else
+ username = uid[0..7]
+ password = SecureRandom.hex(4)
+ reg_result = autologin_register(username, email, password, 'acge', phone, name)
+ existing_rows = CSV.read("public/操作系统大赛用户信息.csv")
+ new_row = [username, email, password, phone, name]
+ existing_rows << new_row
+ CSV.open("public/操作系统大赛用户信息.csv", 'wb') do |csv|
+ existing_rows.each { |row| csv << row }
+ end
+ if reg_result[:message].blank?
+ open_user = OpenUsers::Acge.create!(user_id: reg_result[:user][:id], uid: uid)
+ successful_authentication(open_user.user)
+ redirect_to redirect_uri
+
+ return
+ else
+ render_error(reg_result[:message])
+ end
+ end
+ else
+ OpenUsers::Acge.create!(user: current_user, uid: uid)
+ successful_authentication(current_user)
+ redirect_to redirect_uri
+
+ return
+ end
+ end
+
+ Rails.logger.info("[OAuth2] session[:unionid] -> #{session[:unionid]}")
+ # redirect_to "/bindlogin/acge?redirect_uri=#{redirect_uri}"
+ rescue Exception => ex
+ render_error(ex.message)
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/organizations/organization_users_controller.rb b/app/controllers/organizations/organization_users_controller.rb
index d9035dc14..171e9dcae 100644
--- a/app/controllers/organizations/organization_users_controller.rb
+++ b/app/controllers/organizations/organization_users_controller.rb
@@ -4,17 +4,31 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
before_action :check_user_can_edit_org, only: [:destroy]
def index
- @organization_users = @organization.organization_users.includes(:user)
+ # @organization_users = @organization.organization_users.includes(:user)
+ # if params[:search].present?
+ # search = params[:search].to_s.downcase
+ # user_condition_users = User.like(search).to_sql
+ # team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
+ # users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
+ #
+ # @organization_users = @organization_users.where(user_id: users).distinct
+ # end
+ #
+ # @organization_users = kaminari_paginate(@organization_users)
+
+ organization_user_ids = @organization.organization_users.pluck(:user_id).uniq
+ project_member_user_ids = @organization.projects.joins(:members).pluck("members.user_id").uniq
+ ids = organization_user_ids + project_member_user_ids
+ users = User.where(id: ids).reorder(Arel.sql("FIELD(users.id,#{ids.join(',')})"))
if params[:search].present?
search = params[:search].to_s.downcase
user_condition_users = User.like(search).to_sql
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
- users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
+ user_ids = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users").pluck(:id)
- @organization_users = @organization_users.where(user_id: users).distinct
+ users = users.where(id: user_ids)
end
-
- @organization_users = kaminari_paginate(@organization_users)
+ @users = kaminari_paginate(users)
end
def pm_check_user
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 2045eb7fd..a4e369c1f 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -193,13 +193,19 @@ class ProjectsController < ApplicationController
default_branch: @project.default_branch
}
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
+ elsif project_params.has_key?("has_actions")
+ gitea_params = {
+ has_actions: project_params[:has_actions]
+ }
+ Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
else
validate_params = project_params.slice(:name, :description,
:project_category_id, :project_language_id, :private, :identifier)
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
- private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
+ private = params[:private].nil? ? !@project.is_public : params[:private]
+ private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : private
new_project_params = project_params.except(:private).merge(is_public: !private)
@project.update_attributes!(new_project_params)
@@ -347,7 +353,7 @@ class ProjectsController < ApplicationController
def project_params
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
- :project_category_id, :project_language_id, :license_id, :ignore_id, :private,
+ :project_category_id, :project_language_id, :license_id, :ignore_id, :private, :has_actions,
:blockchain, :blockchain_token_all, :blockchain_init_token, :pr_view_admin)
end
diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb
index 037e201bf..1fe079f29 100644
--- a/app/controllers/pull_requests_controller.rb
+++ b/app/controllers/pull_requests_controller.rb
@@ -203,6 +203,7 @@ class PullRequestsController < ApplicationController
def pr_merge
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
+ return normal_status(-1, "该分支存在冲突,无法自动合并.") unless @pull_request.conflict_files.blank?
if params[:do].blank?
normal_status(-1, "请选择合并方式")
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index e26559f74..c8e4380e0 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -66,6 +66,8 @@ class RepositoriesController < ApplicationController
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
+ @repo_detail = $gitea_client.get_repos_by_owner_repo(@owner.login, @project.identifier)
+ return render_not_found if @entries.blank? && !@repo_detail["empty"]
end
end
diff --git a/app/forms/projects/create_form.rb b/app/forms/projects/create_form.rb
index c133175c2..8ef7befac 100644
--- a/app/forms/projects/create_form.rb
+++ b/app/forms/projects/create_form.rb
@@ -28,6 +28,10 @@ class Projects::CreateForm < BaseForm
raise "ignore_id值无效." if ignore_id && Ignore.find_by(id: ignore_id).blank?
end
+ def check_auto_init
+ raise "auto_init值无效." if ignore_id && license_id && !auto_init
+ end
+
def check_owner
@project_owner = Owner.find_by(id: user_id)
raise "user_id值无效." if user_id && @project_owner.blank?
diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb
index f364c11ff..dac637764 100644
--- a/app/helpers/repositories_helper.rb
+++ b/app/helpers/repositories_helper.rb
@@ -132,6 +132,8 @@ module RepositoriesHelper
src_regex_3 = /src= (.*?) /
src_regex_4 = /src =(.*?) /
src_regex_5 = /src =(.*?) /
+ href_regex = /href=\"(.*?)\"/
+ href_regex_1 = /href=\'(.*?)\'/
ss_c = content.to_s.scan(s_regex_c)
ss = content.to_s.scan(s_regex)
ss_1 = content.to_s.scan(s_regex_1)
@@ -142,7 +144,9 @@ module RepositoriesHelper
ss_src_3 = content.to_s.scan(src_regex_3)
ss_src_4 = content.to_s.scan(src_regex_4)
ss_src_5 = content.to_s.scan(src_regex_5)
- total_sources = {ss_c: ss_c,ss: ss, ss_1: ss_1, ss_2: ss_2, ss_src: ss_src, ss_src_1: ss_src_1, ss_src_2: ss_src_2, ss_src_3: ss_src_3, ss_src_4: ss_src_4, ss_src_5: ss_src_5}
+ ss_href = content.to_s.scan(href_regex)
+ ss_href_1 = content.to_s.scan(href_regex_1)
+ total_sources = {ss_c: ss_c,ss: ss, ss_1: ss_1, ss_2: ss_2, ss_src: ss_src, ss_src_1: ss_src_1, ss_src_2: ss_src_2, ss_src_3: ss_src_3, ss_src_4: ss_src_4, ss_src_5: ss_src_5, ss_href: ss_href, ss_href_1: ss_href_1}
# total_sources.uniq!
total_sources.except(:ss, :ss_c).each do |k, sources|
sources.each do |s|
@@ -173,13 +177,17 @@ module RepositoriesHelper
content = content.gsub("src=#{s[0]}", "src=\'#{s_content}\'")
when 'ss_2'
content = content.gsub(/]:#{s[0]}/, "]: #{s_content.to_s.gsub(" ","").gsub("\r", "")}")
- else
+ when 'ss_href'
+ content = content.gsub("href=\"#{s[0]}\"", "href=\"#{s_content}\"")
+ when 'ss_href_1'
+ content = content.gsub("href=\'#{s[0]}\'", "href=\'#{s_content}\'")
+ else
content = content.gsub("(#{s[0]})", "(#{s_content})")
end
else
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
s_content = File.expand_path(s_content, path)
- s_content = s_content.split("#{Rails.root}/")[1]
+ s_content = s_content.split("#{Rails.root}")[1]
case k.to_s
when 'ss_src'
content = content.gsub("src=\"#{s[0]}\"", "src=\"/#{s_content}\"")
@@ -187,7 +195,11 @@ module RepositoriesHelper
content = content.gsub("src=\'#{s[0]}\'", "src=\'/#{s_content}\'")
when 'ss_2'
content = content.gsub(/]:#{s[0]}/, "]: /#{s_content.to_s.gsub(" ","").gsub("\r", "")}")
- else
+ when 'ss_href'
+ content = content.gsub("href=\"#{s[0]}\"", "href=\"#{s_content}\"")
+ when 'ss_href_1'
+ content = content.gsub("href=\'#{s[0]}\'", "href=\'#{s_content}\'")
+ else
content = content.gsub("(#{s[0]})", "(/#{s_content})")
end
end
diff --git a/app/interactors/gitea/delete_file_interactor.rb b/app/interactors/gitea/delete_file_interactor.rb
index 03ddf4230..f94b8a205 100644
--- a/app/interactors/gitea/delete_file_interactor.rb
+++ b/app/interactors/gitea/delete_file_interactor.rb
@@ -45,6 +45,7 @@ module Gitea
else
Rails.logger.error("Gitea::Repository::Entries::DeleteService error[#{response.status}]======#{response.body}")
@error = "删除失败,请确认该分支是否是保护分支。"
+ @error = "删除失败,参数sha不匹配。" if response.body.to_s.include?("sha does not match")
end
end
diff --git a/app/jobs/delay_expired_issue_and_milestone_job.rb b/app/jobs/delay_expired_issue_and_milestone_job.rb
new file mode 100644
index 000000000..4bba7aaf1
--- /dev/null
+++ b/app/jobs/delay_expired_issue_and_milestone_job.rb
@@ -0,0 +1,16 @@
+class DelayExpiredIssueAndMilestoneJob < ApplicationJob
+ queue_as :message
+
+ def perform
+ Issue.where(due_date: Date.today + 1.days).find_each do |issue|
+ SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
+ end
+ Version.where(effective_date: Date.today + 1.days).find_each do |version|
+ SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', version.id) if Site.has_notice_menu?
+ end
+ Version.where(effective_date: Date.today - 1.days).find_each do |version|
+ SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', version.id) if Site.has_notice_menu?
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/app/jobs/delay_expired_issue_job.rb b/app/jobs/delay_expired_issue_job.rb
deleted file mode 100644
index ed390e15b..000000000
--- a/app/jobs/delay_expired_issue_job.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class DelayExpiredIssueJob < ApplicationJob
- queue_as :message
-
- def perform
- Issue.where(due_date: Date.today + 1.days).find_each do |issue|
- SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
- end
- end
-
-end
\ No newline at end of file
diff --git a/app/jobs/send_template_message_job.rb b/app/jobs/send_template_message_job.rb
index 1df1d8c7d..1b309fe35 100644
--- a/app/jobs/send_template_message_job.rb
+++ b/app/jobs/send_template_message_job.rb
@@ -221,6 +221,20 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
+ when 'ProjectMilestoneExpired'
+ milestone_id = args[0]
+ milestone = Version.find_by_id(milestone_id)
+ return unless milestone.present? && milestone&.project.present?
+ receivers = User.where(id: milestone.user_id)
+ receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneExpired.get_message_content(receivers, milestone)
+ Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
+ when 'ProjectMilestoneEarlyExpired'
+ milestone_id = args[0]
+ milestone = Version.find_by_id(milestone_id)
+ return unless milestone.present? && milestone&.project.present?
+ receivers = User.where(id: milestone.user_id)
+ receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(receivers, milestone)
+ Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
when 'ProjectPraised'
operator_id, project_id = args[0], args[1]
operator = User.find_by_id(operator_id)
diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb
index 9a5efd129..34386aae2 100644
--- a/app/models/concerns/project_operable.rb
+++ b/app/models/concerns/project_operable.rb
@@ -21,68 +21,69 @@ module ProjectOperable
end
def add_member!(user_id, role_name='Developer')
- if self.owner.is_a?(Organization)
- case role_name
- when 'Manager'
- # 构建相应的团队
- team = self.owner.teams.admin.take
- if team.nil?
- team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
-
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 新增对应的团队成员
- team_user = TeamUser.build(self.user_id, user_id, team.id)
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
-
- # 确保组织成员中有该用户
- OrganizationUser.build(self.user_id, user_id)
- when 'Developer'
- # 构建相应的团队
- team = self.owner.teams.write.take
- if team.nil?
- team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
-
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 新增对应的团队成员
- team_user = TeamUser.build(self.user_id, user_id, team.id)
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
-
- # 确保组织成员中有该用户
- OrganizationUser.build(self.user_id, user_id)
- when 'Reporter'
- # 构建相应的团队
- team = self.owner.teams.read.take
- if team.nil?
- team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
-
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 新增对应的团队成员
- team_user = TeamUser.build(self.user_id, user_id, team.id)
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
-
- # 确保组织成员中有该用户
- OrganizationUser.build(self.user_id, user_id)
- end
- end
- member = members.create!(user_id: user_id, team_user_id: team_user&.id)
+ # if self.owner.is_a?(Organization)
+ # case role_name
+ # when 'Manager'
+ # # 构建相应的团队
+ # team = self.owner.teams.admin.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ #
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 新增对应的团队成员
+ # team_user = TeamUser.build(self.user_id, user_id, team.id)
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ #
+ # # 确保组织成员中有该用户
+ # OrganizationUser.build(self.user_id, user_id)
+ # when 'Developer'
+ # # 构建相应的团队
+ # team = self.owner.teams.write.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ #
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 新增对应的团队成员
+ # team_user = TeamUser.build(self.user_id, user_id, team.id)
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ #
+ # # 确保组织成员中有该用户
+ # OrganizationUser.build(self.user_id, user_id)
+ # when 'Reporter'
+ # # 构建相应的团队
+ # team = self.owner.teams.read.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ #
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 新增对应的团队成员
+ # team_user = TeamUser.build(self.user_id, user_id, team.id)
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ #
+ # # 确保组织成员中有该用户
+ # OrganizationUser.build(self.user_id, user_id)
+ # end
+ # end
+ # member = members.create!(user_id: user_id, team_user_id: team_user&.id)
+ member = members.create!(user_id: user_id)
set_developer_role(member, role_name)
end
@@ -116,71 +117,71 @@ 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
- if team.nil?
- team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
-
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 更改对应的团队成员
- team_user = member.team_user
- $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
- team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
-
- # 确保组织成员中有该用户
- OrganizationUser.build(self.user_id, user_id)
- when 'Developer'
- # 构建相应的团队
- team = self.owner.teams.write.take
- if team.nil?
- team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 更改对应的团队成员
- team_user = member.team_user
- $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
- team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
-
- OrganizationUser.build(self.user_id, user_id)
- when 'Reporter'
- # 构建相应的团队
- team = self.owner.teams.read.take
- if team.nil?
- team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
- gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
- team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
- end
-
- # 设置项目在团队中的访问权限
- team_project = TeamProject.build(self.user_id, team.id, self.id)
- tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
-
- # 更改对应的团队成员
- team_user = member.team_user
- $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
- $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
- team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
-
- # 确保组织成员中有该用户
- OrganizationUser.build(self.user_id, user_id)
- end
- end
+ # if self.owner.is_a?(Organization) && member.team_user.present?
+ # case role&.name
+ # when 'Manager'
+ # # 构建相应的团队
+ # team = self.owner.teams.admin.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ #
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 更改对应的团队成员
+ # team_user = member.team_user
+ # $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ # team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
+ #
+ # # 确保组织成员中有该用户
+ # OrganizationUser.build(self.user_id, user_id)
+ # when 'Developer'
+ # # 构建相应的团队
+ # team = self.owner.teams.write.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 更改对应的团队成员
+ # team_user = member.team_user
+ # $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ # team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
+ #
+ # OrganizationUser.build(self.user_id, user_id)
+ # when 'Reporter'
+ # # 构建相应的团队
+ # team = self.owner.teams.read.take
+ # if team.nil?
+ # team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
+ # gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
+ # team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
+ # end
+ #
+ # # 设置项目在团队中的访问权限
+ # team_project = TeamProject.build(self.user_id, team.id, self.id)
+ # tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
+ #
+ # # 更改对应的团队成员
+ # team_user = member.team_user
+ # $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
+ # $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
+ # team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
+ #
+ # # 确保组织成员中有该用户
+ # OrganizationUser.build(self.user_id, user_id)
+ # end
+ # end
member.member_roles.last.update_attributes!(role: role)
end
diff --git a/app/models/message_template.rb b/app/models/message_template.rb
index 7ab7fdad8..75d64fa95 100644
--- a/app/models/message_template.rb
+++ b/app/models/message_template.rb
@@ -52,6 +52,8 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 {nickname2}/{repository} 创建了一个里程碑:{name}', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑")
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 {nickname}/{repository} 仓库,里程碑 {name} 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
+ self.create(type: 'MessageTemplate::ProjectMilestoneEarlyExpired', sys_notice: '您创建的里程碑 {name} 已临近截止日期,请尽快处理.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
+ self.create(type: 'MessageTemplate::ProjectMilestoneExpired', sys_notice: '您创建的里程碑 {name} 已逾期,请及时更新进度或联系项目团队.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '{nickname1} 点赞了你管理的仓库 {nickname2}/{repository}', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 {repository} 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops')
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
diff --git a/app/models/message_template/project_milestone_early_expired.rb b/app/models/message_template/project_milestone_early_expired.rb
new file mode 100644
index 000000000..3db1e1908
--- /dev/null
+++ b/app/models/message_template/project_milestone_early_expired.rb
@@ -0,0 +1,70 @@
+# == 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::ProjectMilestoneEarlyExpired < MessageTemplate
+
+ # MessageTemplate::ProjectMilestoneEarlyExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7))
+ def self.get_message_content(receivers, milestone)
+ receivers.each do |receiver|
+ if receiver.user_template_message_setting.present?
+ send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneExpired"]
+ send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneExpired"] : send_setting
+ receivers = receivers.where.not(id: receiver.id) unless send_setting
+ end
+ end
+ return '', '', '' if receivers.blank?
+ project = milestone&.project
+ owner = project&.owner
+ content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
+ url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
+
+ return receivers_string(receivers), content, url
+ rescue => e
+ Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_message_content [ERROR] #{e}")
+ return '', '', ''
+ end
+
+ def self.get_email_message_content(receiver, milestone)
+ if receiver.user_template_message_setting.present?
+ send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneExpired"]
+ send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneExpired"] : send_setting
+ return '', '', '' unless send_setting
+ project = milestone&.project
+ owner = project&.owner
+ title = email_title
+ title.gsub!('{nickname}', owner&.real_name)
+ title.gsub!('{repository}', project&.name)
+
+ content = email
+ content.gsub!('{receiver}', receiver&.real_name)
+ content.gsub!('{baseurl}', base_url)
+ content.gsub!('{nickname}', owner&.real_name)
+ content.gsub!('{repository}', project&.name)
+ content.gsub!('{login}', owner&.login)
+ content.gsub!('{identifier}', project&.identifier)
+ content.gsub!('{id}', milestone&.id.to_s)
+ content.gsub!('{name}', milestone&.name)
+ content.gsub!('{platform}', PLATFORM)
+
+ return receiver&.mail, title, content
+ else
+ return '', '', ''
+ end
+
+ rescue => e
+ Rails.logger.info("MessageTemplate::MilestoneEarlyExpired.get_email_message_content [ERROR] #{e}")
+ return '', '', ''
+ end
+end
diff --git a/app/models/message_template/project_milestone_expired.rb b/app/models/message_template/project_milestone_expired.rb
new file mode 100644
index 000000000..de6b8c10c
--- /dev/null
+++ b/app/models/message_template/project_milestone_expired.rb
@@ -0,0 +1,70 @@
+# == 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::ProjectMilestoneExpired < MessageTemplate
+
+ # MessageTemplate::ProjectMilestoneExpired.get_message_content(User.where(login: 'yystopf'), Version.find(7))
+ def self.get_message_content(receivers, milestone)
+ receivers.each do |receiver|
+ if receiver.user_template_message_setting.present?
+ send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneExpired"]
+ send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneExpired"] : send_setting
+ receivers = receivers.where.not(id: receiver.id) unless send_setting
+ end
+ end
+ return '', '', '' if receivers.blank?
+ project = milestone&.project
+ owner = project&.owner
+ content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
+ url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
+
+ return receivers_string(receivers), content, url
+ rescue => e
+ Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_message_content [ERROR] #{e}")
+ return '', '', ''
+ end
+
+ def self.get_email_message_content(receiver, milestone)
+ if receiver.user_template_message_setting.present?
+ send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneExpired"]
+ send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneExpired"] : send_setting
+ return '', '', '' unless send_setting
+ project = milestone&.project
+ owner = project&.owner
+ title = email_title
+ title.gsub!('{nickname}', owner&.real_name)
+ title.gsub!('{repository}', project&.name)
+
+ content = email
+ content.gsub!('{receiver}', receiver&.real_name)
+ content.gsub!('{baseurl}', base_url)
+ content.gsub!('{nickname}', owner&.real_name)
+ content.gsub!('{repository}', project&.name)
+ content.gsub!('{login}', owner&.login)
+ content.gsub!('{identifier}', project&.identifier)
+ content.gsub!('{id}', milestone&.id.to_s)
+ content.gsub!('{name}', milestone&.name)
+ content.gsub!('{platform}', PLATFORM)
+
+ return receiver&.mail, title, content
+ else
+ return '', '', ''
+ end
+
+ rescue => e
+ Rails.logger.info("MessageTemplate::ProjectMilestoneExpired.get_email_message_content [ERROR] #{e}")
+ return '', '', ''
+ end
+end
diff --git a/app/models/open_users/acge.rb b/app/models/open_users/acge.rb
new file mode 100644
index 000000000..59963b91f
--- /dev/null
+++ b/app/models/open_users/acge.rb
@@ -0,0 +1,27 @@
+# == Schema Information
+#
+# Table name: open_users
+#
+# id :integer not null, primary key
+# user_id :integer
+# type :string(255)
+# uid :string(255)
+# created_at :datetime not null
+# updated_at :datetime not null
+# extra :text(65535)
+#
+# Indexes
+#
+# index_open_users_on_type_and_uid (type,uid) UNIQUE
+# index_open_users_on_user_id (user_id)
+#
+
+class OpenUsers::Acge < OpenUser
+ def nickname
+ extra&.[]('nickname')
+ end
+
+ def en_type
+ 'acge'
+ end
+end
diff --git a/app/models/organization.rb b/app/models/organization.rb
index 237efbfe9..f978611b1 100644
--- a/app/models/organization.rb
+++ b/app/models/organization.rb
@@ -182,14 +182,6 @@ class Organization < Owner
organization_users.count
end
- def teams_count
- teams.count
- end
-
- def organization_users_count
- organization_users.count
- end
-
def real_name
name = lastname + firstname
name = name.blank? ? (nickname.blank? ? login : nickname) : name
@@ -217,4 +209,11 @@ class Organization < Owner
enabling_cla == true
end
+ def num_users
+ organization_user_ids = self.organization_users.pluck(:user_id).uniq
+ project_member_user_ids = self.projects.joins(:members).pluck("members.user_id").uniq
+ ids = organization_user_ids + project_member_user_ids
+ ids.uniq.size
+ end
+
end
diff --git a/app/models/template_message_setting/create_or_assign.rb b/app/models/template_message_setting/create_or_assign.rb
index 629051305..8f0817070 100644
--- a/app/models/template_message_setting/create_or_assign.rb
+++ b/app/models/template_message_setting/create_or_assign.rb
@@ -28,5 +28,6 @@ class TemplateMessageSetting::CreateOrAssign < TemplateMessageSetting
self.find_or_create_by(name: "疑修状态变更", key: "IssueChanged")
self.find_or_create_by(name: "合并请求状态变更", key: "PullRequestChanged")
self.find_or_create_by(name: "疑修截止日期到达最后一天", key: "IssueExpire", notification_disabled: false)
+ self.find_or_create_by(name: "里程碑逾期提醒", key: "MilestoneExpired", notification_disabled: false, email_disabled: true)
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 8ffa5b181..9d623f949 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -115,7 +115,7 @@ class User < Owner
# trustie: 来自Trustie平台
# forge: 平台本身注册的用户
# military: 军科的用户
- enumerize :platform, in: [:forge, :educoder, :trustie, :military, :github, :gitee, :qq, :wechat, :bot], default: :forge, scope: :shallow
+ enumerize :platform, in: [:forge, :educoder, :trustie, :military, :github, :gitee, :qq, :wechat, :bot, :acge], default: :forge, scope: :shallow
belongs_to :laboratory, optional: true
has_one :user_extension, dependent: :destroy
@@ -465,7 +465,7 @@ class User < Owner
$gitea_client.delete_users_tokens_by_username_token(self.login, e["name"], {query: {sudo: self.login} })
}
end
- new_result = $gitea_client.post_users_tokens_by_username(self.login, { query: {sudo: self.login}, body:{ name: self.login} })
+ new_result = $gitea_client.post_users_tokens_by_username(self.login, { query: {sudo: self.login}, body:{ name: "#{self.login}-#{SecureRandom.hex(6)}", scopes: ["all"]}.to_json })
if new_result["sha1"].present?
update(gitea_token: new_result["sha1"])
end
diff --git a/app/models/user_template_message_setting.rb b/app/models/user_template_message_setting.rb
index 49db51d4d..befd2be87 100644
--- a/app/models/user_template_message_setting.rb
+++ b/app/models/user_template_message_setting.rb
@@ -36,6 +36,7 @@ class UserTemplateMessageSetting < ApplicationRecord
"CreateOrAssign::IssueChanged": true,
"CreateOrAssign::PullRequestChanged": true,
"CreateOrAssign::IssueExpire": true,
+ "CreateOrAssign::MilestoneExpired": true,
"ManageProject::Issue": true,
"ManageProject::PullRequest": true,
"ManageProject::Member": true,
@@ -44,6 +45,8 @@ class UserTemplateMessageSetting < ApplicationRecord
"ManageProject::Forked": true,
"ManageProject::Milestone": true,
"ManageProject::MilestoneCompleted": true,
+ "ManageProject::MilestoneExpired": true,
+ "ManageProject::MilestoneEarlyExpired": true,
}.stringify_keys!
end
@@ -57,6 +60,7 @@ class UserTemplateMessageSetting < ApplicationRecord
"CreateOrAssign::IssueChanged": false,
"CreateOrAssign::PullRequestChanged": false,
"CreateOrAssign::IssueExpire": false,
+ "CreateOrAssign::MilestoneExpired": false,
"ManageProject::Issue": false,
"ManageProject::PullRequest": false,
"ManageProject::Member": false,
@@ -65,6 +69,8 @@ class UserTemplateMessageSetting < ApplicationRecord
"ManageProject::Forked": false,
"ManageProject::Milestone": false,
"ManageProject::MilestoneCompleted": false,
+ "ManageProject::MilestoneExpired": false,
+ "ManageProject::MilestoneEarlyExpired": false,
}.stringify_keys!
end
diff --git a/app/models/version.rb b/app/models/version.rb
index ec2ad68cd..871f63dfd 100644
--- a/app/models/version.rb
+++ b/app/models/version.rb
@@ -68,5 +68,7 @@ class Version < ApplicationRecord
def send_update_message_to_notice_system
SendTemplateMessageJob.perform_later('ProjectMilestoneCompleted', self.id) if Site.has_notice_menu? && self.issue_percent == 1.0
+ SendTemplateMessageJob.perform_later('ProjectMilestoneEarlyExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today + 1.days
+ SendTemplateMessageJob.perform_later('ProjectMilestoneExpired', self.id) if Site.has_notice_menu? && self.effective_date == Date.today - 1.days
end
end
diff --git a/app/services/api/v1/projects/actions/runs/job_show_service.rb b/app/services/api/v1/projects/actions/runs/job_show_service.rb
new file mode 100644
index 000000000..e80e882be
--- /dev/null
+++ b/app/services/api/v1/projects/actions/runs/job_show_service.rb
@@ -0,0 +1,42 @@
+class Api::V1::Projects::Actions::Runs::JobShowService < ApplicationService
+ include ActiveModel::Model
+
+ attr_reader :project, :token, :owner, :repo, :run, :job, :log_cursors
+ attr_accessor :gitea_data
+
+ validates :run, :job, :log_cursors, presence: true
+
+ def initialize(project, run, job, log_cursors, token = nil)
+ @project = project
+ @owner = project&.owner.login
+ @repo = project&.identifier
+ @run = run
+ @job = job
+ @log_cursors = log_cursors
+ @token = token
+ end
+
+ def call
+ raise Error, errors.full_messages.join(",") unless valid?
+ load_gitea_data
+
+ @gitea_data
+ end
+
+ private
+ def request_params
+ {
+ access_token: token
+ }
+ end
+
+ def request_body
+ {
+ logCursors: log_cursors
+ }
+ end
+
+ def load_gitea_data
+ @gitea_data = $gitea_hat_client.post_repos_actions_runs_jobs_by_owner_repo_run_job(owner, repo, run, job, {query: request_params, body: request_body.to_json})
+ end
+end
\ No newline at end of file
diff --git a/app/services/api/v1/projects/actions/runs/list_service.rb b/app/services/api/v1/projects/actions/runs/list_service.rb
new file mode 100644
index 000000000..5889518ce
--- /dev/null
+++ b/app/services/api/v1/projects/actions/runs/list_service.rb
@@ -0,0 +1,40 @@
+class Api::V1::Projects::Actions::Runs::ListService < ApplicationService
+ include ActiveModel::Model
+
+ attr_reader :project, :token, :owner, :repo, :workflow, :page, :limit
+ attr_accessor :gitea_data
+
+ validates :workflow, presence: true
+
+ def initialize(project, params, token =nil)
+ @project = project
+ @owner = project&.owner.login
+ @repo = project&.identifier
+ @workflow = params[:workflow]
+ @page = params[:page] || 1
+ @limit = params[:limit] || 15
+ @token = token
+ end
+
+ def call
+ raise Error, errors.full_messages.join(",") unless valid?
+ load_gitea_data
+
+ @gitea_data
+ end
+
+ private
+ def request_params
+ {
+ access_token: token,
+ workflow: workflow,
+ page: page,
+ limit: limit
+ }
+ end
+
+ def load_gitea_data
+ @gitea_data = $gitea_hat_client.get_repos_actions_by_owner_repo(owner, repo, {query: request_params}) rescue nil
+ raise Error, '获取流水线执行记录失败!' unless @gitea_data.is_a?(Hash)
+ end
+end
\ No newline at end of file
diff --git a/app/services/api/v1/projects/branches/delete_service.rb b/app/services/api/v1/projects/branches/delete_service.rb
index 28836c797..341079273 100644
--- a/app/services/api/v1/projects/branches/delete_service.rb
+++ b/app/services/api/v1/projects/branches/delete_service.rb
@@ -32,7 +32,7 @@ class Api::V1::Projects::Branches::DeleteService < ApplicationService
def excute_data_to_gitea
begin
- @gitea_data = $gitea_client.delete_repos_branches_by_owner_repo_branch(owner, repo, branch_name, {query: request_params})
+ @gitea_data = $gitea_client.delete_repos_branches_by_owner_repo_branch(owner, repo, CGI.escape(branch_name), {query: request_params})
rescue => e
raise Error, '保护分支无法删除!' if e.to_s.include?("branch protected")
raise Error, '删除分支失败!'
diff --git a/app/services/api/v1/projects/branches/list_service.rb b/app/services/api/v1/projects/branches/list_service.rb
index 590c4884f..6980b71ea 100644
--- a/app/services/api/v1/projects/branches/list_service.rb
+++ b/app/services/api/v1/projects/branches/list_service.rb
@@ -1,6 +1,6 @@
class Api::V1::Projects::Branches::ListService < ApplicationService
- attr_accessor :project, :token, :owner, :repo, :name, :page, :limit
+ attr_accessor :project, :token, :owner, :repo, :name, :state, :page, :limit
attr_accessor :gitea_data, :gitea_repo_data
def initialize(project, params, token=nil)
@@ -9,6 +9,7 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
@repo = project&.identifier
@token = token
@name = params[:name]
+ @state = params[:state]
@page = params[:page]
@limit = params[:limit]
end
@@ -18,7 +19,6 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
load_default_branch
@gitea_data[:default_branch] = @gitea_repo_data["default_branch"]
-
@gitea_data
end
@@ -30,7 +30,8 @@ class Api::V1::Projects::Branches::ListService < ApplicationService
limit: limit
}
params.merge!({name: name}) if name.present?
-
+ params.merge!({state: state}) if state.present?
+
params
end
diff --git a/app/services/api/v1/projects/branches/restore_service.rb b/app/services/api/v1/projects/branches/restore_service.rb
new file mode 100644
index 000000000..fbd6220ed
--- /dev/null
+++ b/app/services/api/v1/projects/branches/restore_service.rb
@@ -0,0 +1,47 @@
+class Api::V1::Projects::Branches::RestoreService < ApplicationService
+
+ include ActiveModel::Model
+
+ attr_accessor :project, :token, :owner, :repo, :branch_id, :branch_name
+ attr_accessor :gitea_data
+
+ validates :branch_id, :branch_name, presence: true
+
+ def initialize(project, branch_id, branch_name, token= nil)
+ @project = project
+ @owner = project&.owner&.login
+ @repo = project&.identifier
+ @branch_id = branch_id
+ @branch_name = branch_name
+ @token = token
+ end
+
+ def call
+ raise Error, errors.full_messages.join(",") unless valid?
+ excute_data_to_gitea
+
+ true
+ end
+
+ private
+ def request_params
+ {
+ access_token: token
+ }
+ end
+
+ def request_body
+ {
+ branch_id: branch_id,
+ name: branch_name,
+ }
+ end
+
+ def excute_data_to_gitea
+ begin
+ @gitea_data = $gitea_hat_client.post_repos_branches_restore_by_owner_repo(owner, repo, {query: request_params, body: request_body.to_json})
+ rescue => e
+ raise Error, '恢复分支失败!'
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/services/api/v1/projects/commits/recent_service.rb b/app/services/api/v1/projects/commits/recent_service.rb
new file mode 100644
index 000000000..9bc77dfc2
--- /dev/null
+++ b/app/services/api/v1/projects/commits/recent_service.rb
@@ -0,0 +1,39 @@
+class Api::V1::Projects::Commits::RecentService < ApplicationService
+
+ attr_reader :project, :page, :limit, :keyword, :owner, :repo, :token
+ attr_accessor :gitea_data
+
+ def initialize(project, params, token=nil)
+ @project = project
+ @page = params[:page] || 1
+ @limit = params[:limit] || 15
+ @keyword = params[:keyword]
+ @owner = project&.owner&.login
+ @repo = project&.identifier
+ @token = token
+ end
+
+ def call
+ load_gitea_data
+
+ gitea_data
+ end
+
+ private
+ def request_params
+ param = {
+ access_token: token,
+ page: page,
+ limit: limit
+ }
+ param.merge!(keyword: keyword) if keyword.present?
+
+ param
+ end
+
+ def load_gitea_data
+ @gitea_data = $gitea_hat_client.get_repos_recent_commits_by_owner_repo(owner, repo, {query: request_params}) rescue nil
+ raise Error, "获取最近提交列表失败" unless @gitea_data.is_a?(Hash)
+ end
+
+end
\ No newline at end of file
diff --git a/app/services/api/v1/projects/compare_service.rb b/app/services/api/v1/projects/compare_service.rb
index 23a248305..9e646326f 100644
--- a/app/services/api/v1/projects/compare_service.rb
+++ b/app/services/api/v1/projects/compare_service.rb
@@ -29,6 +29,6 @@ class Api::V1::Projects::CompareService < ApplicationService
end
def load_gitea_data
- @gitea_data = $gitea_client.get_repos_compare_by_owner_repo_from_to(owner, repo, from, to, {query: request_params}) rescue nil
+ @gitea_data = $gitea_hat_client.get_repos_compare_by_owner_repo_baseref_headref(owner, repo, to, from, {query: request_params}) rescue nil
end
end
\ No newline at end of file
diff --git a/app/services/api/v1/projects/tags/delete_service.rb b/app/services/api/v1/projects/tags/delete_service.rb
index d0d317aa8..8f898bf1a 100644
--- a/app/services/api/v1/projects/tags/delete_service.rb
+++ b/app/services/api/v1/projects/tags/delete_service.rb
@@ -32,7 +32,7 @@ class Api::V1::Projects::Tags::DeleteService < ApplicationService
def excute_data_to_gitea
begin
- @gitea_data = $gitea_client.delete_repos_tags_by_owner_repo_tag(owner, repo, tag_name, {query: request_params})
+ @gitea_data = $gitea_client.delete_repos_tags_by_owner_repo_tag(owner, repo, CGI.escape(tag_name), {query: request_params})
rescue => e
raise Error, '请先删除发行版!' if e.to_s.include?("409")
raise Error, '删除标签失败!'
diff --git a/app/services/getway/cms/get_service.rb b/app/services/getway/cms/get_service.rb
index 6b7050e84..76c5f27e8 100644
--- a/app/services/getway/cms/get_service.rb
+++ b/app/services/getway/cms/get_service.rb
@@ -16,6 +16,6 @@ class Getway::Cms::GetService < Getway::ClientService
end
def url
- "/cms/doc/open/#{doc_id}".freeze
+ "/cms/doc/open/baseInfo/#{doc_id}".freeze
end
end
\ No newline at end of file
diff --git a/app/services/gitea/user/generate_token_service.rb b/app/services/gitea/user/generate_token_service.rb
index 946bd68ce..e2dd6b0f4 100644
--- a/app/services/gitea/user/generate_token_service.rb
+++ b/app/services/gitea/user/generate_token_service.rb
@@ -29,7 +29,7 @@ class Gitea::User::GenerateTokenService < Gitea::ClientService
end
def request_params
- { name: "#{@username}-#{token_name}" }
+ { name: "#{@username}-#{token_name}", scopes: ["all"] }
end
def token_name
diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb
index e7ff8bd1d..4583838f1 100644
--- a/app/services/repositories/create_service.rb
+++ b/app/services/repositories/create_service.rb
@@ -67,7 +67,7 @@ class Repositories::CreateService < ApplicationService
end
def repository_params
- params.merge(project_id: project.id)
+ params.merge(project_id: project.id).except(:auto_init)
end
def gitea_repository_params
diff --git a/app/views/api/v1/projects/actions/actions/index.json.jbuilder b/app/views/api/v1/projects/actions/actions/index.json.jbuilder
new file mode 100644
index 000000000..530cfc6af
--- /dev/null
+++ b/app/views/api/v1/projects/actions/actions/index.json.jbuilder
@@ -0,0 +1,4 @@
+json.total_count @data.size
+json.files @data.each do |file|
+ json.name file["Name"]
+end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/actions/runs/index.json.jbuilder b/app/views/api/v1/projects/actions/runs/index.json.jbuilder
new file mode 100644
index 000000000..9122ef9cf
--- /dev/null
+++ b/app/views/api/v1/projects/actions/runs/index.json.jbuilder
@@ -0,0 +1,23 @@
+json.total_data @result_object[:total_data].to_i
+if @result_object[:data]["Runs"].present?
+ json.runs @result_object[:data]["Runs"].each do |run|
+ json.workflow run["WorkflowID"]
+ json.index run["Index"]
+ json.title run["Title"]
+ json.trigger_user do
+ json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(run['TriggerUser']), name: run['TriggerUser']['Name'] }
+ end
+
+ if run["Ref"].starts_with?("refs/tags")
+ json.ref run["Ref"].gsub!("/refs/tags/", "")
+ else
+ json.ref run["Ref"].gsub!("refs/heads/", "")
+ end
+
+ json.status run["Status"]
+ json.time_ago time_from_now(run["Created"])
+ json.holding_time run["Status"] == 6 ? Time.now.to_i - run["Created"] : run["Stopped"] - run["Created"]
+ end
+else
+ json.runs []
+end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/actions/runs/job_show.json.jbuilder b/app/views/api/v1/projects/actions/runs/job_show.json.jbuilder
new file mode 100644
index 000000000..bf5ce048a
--- /dev/null
+++ b/app/views/api/v1/projects/actions/runs/job_show.json.jbuilder
@@ -0,0 +1,16 @@
+json.state do
+ json.run do
+ json.title @result_object["state"]["run"]["title"]
+ json.status @result_object["state"]["run"]["status"]
+ json.done @result_object["state"]["run"]["done"]
+ json.jobs @result_object["state"]["run"]["jobs"]
+ json.current_job do
+ json.title @result_object["state"]["currentJob"]["title"]
+ json.detail @result_object["state"]["currentJob"]["detail"]
+ json.steps @result_object["state"]["currentJob"]["steps"]
+ end
+ end
+end
+json.logs do
+ json.steps_log @result_object["logs"]["stepsLog"]
+end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder b/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder
index c9235bdb4..ff0f0618a 100644
--- a/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder
+++ b/app/views/api/v1/projects/branches/_simple_gitea_detail.json.jbuilder
@@ -23,4 +23,14 @@ json.commit_time branch['commit']['timestamp']
json.default_branch default_branch || nil
json.http_url render_http_url(@project)
json.zip_url render_zip_url(@owner, @project.repository, branch['name'])
-json.tar_url render_tar_url(@owner, @project.repository, branch['name'])
\ No newline at end of file
+json.tar_url render_tar_url(@owner, @project.repository, branch['name'])
+json.branch_id branch['id']
+json.is_deleted branch['is_deleted']
+json.deleted_unix branch['deleted_unix']
+json.deleted_by do
+ if branch['is_deleted']
+ json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(branch['deleted_by']), name: branch['deleted_by']['name'] }
+ else
+ json.nil!
+ end
+end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/commits/recent.json.jbuilder b/app/views/api/v1/projects/commits/recent.json.jbuilder
new file mode 100644
index 000000000..2f954aadd
--- /dev/null
+++ b/app/views/api/v1/projects/commits/recent.json.jbuilder
@@ -0,0 +1,14 @@
+json.total_count @result_object[:total_data].to_i
+json.commits @result_object[:data].each do |commit|
+ json.sha commit['sha']
+ json.author do
+ json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] }
+ end
+
+ json.committer do
+ json.partial! 'api/v1/users/commit_user', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] }
+ end
+ json.commit_message commit['commit']['message']
+ json.time_from_now time_from_now(commit['created'])
+ json.parent_shas commit['parents'].map{|x|x['sha']}
+end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/compare.json.jbuilder b/app/views/api/v1/projects/compare.json.jbuilder
index 2d20c51e0..f45bceb86 100644
--- a/app/views/api/v1/projects/compare.json.jbuilder
+++ b/app/views/api/v1/projects/compare.json.jbuilder
@@ -14,5 +14,9 @@ json.commits @result_object['Commits'] do |commit|
json.parent_shas commit['Sha']['ParentShas']
end
json.diff do
- json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff']
+ if @result_object['Diff'].present?
+ json.partial! "api/v1/projects/simple_gitea_diff_detail", diff: @result_object['Diff']
+ else
+ json.nil!
+ end
end
\ No newline at end of file
diff --git a/app/views/api/v1/projects/git/trees.json.jbuilder b/app/views/api/v1/projects/git/trees.json.jbuilder
index 0eb08f048..b560fff2b 100644
--- a/app/views/api/v1/projects/git/trees.json.jbuilder
+++ b/app/views/api/v1/projects/git/trees.json.jbuilder
@@ -1,6 +1,6 @@
-json.total_count @result_object['total_count']
-json.sha @result_object['sha']
-json.entries @result_object['tree'].each do |entry|
+json.total_count @result_object[:data]['total_count'].to_i
+json.sha @result_object[:data]['sha']
+json.entries @result_object[:data]['tree'].each do |entry|
json.name entry['path']
json.mode entry['mode']
json.type entry['type'] === 'blob' ? 'file' : 'dir'
diff --git a/app/views/organizations/organization_users/_detail.json.jbuilder b/app/views/organizations/organization_users/_detail.json.jbuilder
index c7572971b..7590da02e 100644
--- a/app/views/organizations/organization_users/_detail.json.jbuilder
+++ b/app/views/organizations/organization_users/_detail.json.jbuilder
@@ -1,7 +1,14 @@
-json.id org_user.id
+json.id user&.id
json.user do
- json.partial! "organizations/user_detail", user: org_user.user
+ json.partial! "organizations/user_detail", user: user
end
-json.team_names org_user.teams.pluck(:nickname)
-json.created_at org_user.created_at.strftime("%Y-%m-%d")
+json.team_names user.teams.where("teams.organization_id=?", organization.id).pluck(:nickname)
+join_date = if user.organization_users.find_by(:organization_id => organization.id).present?
+ user.organization_users.find_by(:organization_id => organization.id).created_at.strftime("%Y-%m-%d")
+ elsif user.members.joins(:project).find_by(project: organization.projects).present?
+ user.members.joins(:project).find_by(project: organization.projects).created_on.strftime("%Y-%m-%d")
+ else
+ user.created_on.strftime("%Y-%m-%d")
+ end
+json.created_at join_date
diff --git a/app/views/organizations/organization_users/index.json.jbuilder b/app/views/organizations/organization_users/index.json.jbuilder
index 9f1f278bc..9241af184 100644
--- a/app/views/organizations/organization_users/index.json.jbuilder
+++ b/app/views/organizations/organization_users/index.json.jbuilder
@@ -1,5 +1,5 @@
-json.total_count @organization_users.total_count
-json.organization_users @organization_users do |org_user|
- next if org_user.user.blank?
- json.partial! "detail", org_user: org_user, organization: @organization
+json.total_count @users.total_count
+json.organization_users @users do |user|
+ next if user.blank?
+ json.partial! "detail", user: user, organization: @organization
end
diff --git a/app/views/repositories/detail.json.jbuilder b/app/views/repositories/detail.json.jbuilder
index d4299a1ff..0e5d850a5 100644
--- a/app/views/repositories/detail.json.jbuilder
+++ b/app/views/repositories/detail.json.jbuilder
@@ -1,3 +1,4 @@
+json.empty @result[:repo]["empty"]
json.content @project.content
json.website @project.website
json.lesson_url @project.lesson_url
diff --git a/app/views/template_message_settings/_detail.json.jbuilder b/app/views/template_message_settings/_detail.json.jbuilder
index d85a4c4ea..5f6a0bf62 100644
--- a/app/views/template_message_settings/_detail.json.jbuilder
+++ b/app/views/template_message_settings/_detail.json.jbuilder
@@ -3,6 +3,7 @@ json.type_name type.constantize.type_name
json.total_settings_count count
json.settings do
json.array! type.constantize.openning.limit(100).each do |setting|
- json.(setting, :name, :key, :notification_disabled, :email_disabled)
+ json.(setting, :name, :key, :email_disabled)
+ json.notification_disabled false
end
end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index a165a3d1e..b5f5c75ca 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -24,6 +24,7 @@ Rails.application.routes.draw do
# get 'auth/qq/callback', to: 'oauth/qq#create'
get 'auth/failure', to: 'oauth/base#auth_failure'
get 'auth/cas/callback', to: 'oauth/cas#create'
+ get 'auth/acge/callback', to: "oauth/acge#create"
get 'auth/:provider/callback', to: 'oauth/callbacks#create'
get 'oauth/bind', to: 'oauth/educoder#bind'
diff --git a/config/routes/api.rb b/config/routes/api.rb
index baa66412e..dde85fe3c 100644
--- a/config/routes/api.rb
+++ b/config/routes/api.rb
@@ -78,6 +78,15 @@ defaults format: :json do
# projects文件夹下的
scope module: :projects do
+ resources :actions, module: 'actions' do
+ collection do
+ post :disable
+ post :enable
+ resources :runs, only: [:index] do
+ post '/jobs/:job', to: 'runs#job_show'
+ end
+ end
+ end
resources :pulls, module: 'pulls' do
resources :versions, only: [:index] do
member do
@@ -98,6 +107,7 @@ defaults format: :json do
resources :branches, param: :name, only:[:index, :create, :destroy] do
collection do
get :all
+ post :restore
patch :update_default_branch
end
end
@@ -107,7 +117,11 @@ defaults format: :json do
delete 'tags/*name', to: "tags#destroy", via: :all
get 'tags/*name', to: "tags#show", via: :all
- resources :commits, only: [:index]
+ resources :commits, only: [:index] do
+ collection do
+ get :recent
+ end
+ end
resources :code_stats, only: [:index]
resources :contributors, only: [:index] do
collection do
diff --git a/config/sidekiq_cron.yml b/config/sidekiq_cron.yml
index 21b8f05f9..72a69bbad 100644
--- a/config/sidekiq_cron.yml
+++ b/config/sidekiq_cron.yml
@@ -5,7 +5,7 @@ sync_gitea_repo_update_time:
delay_expired_issue:
cron: "0 0 * * *"
- class: "DelayExpiredIssueJob"
+ class: "DelayExpiredIssueAndMilestoneJob"
queue: message
create_daily_project_statistics:
diff --git a/public/editormd/lib/marked.min.js b/public/editormd/lib/marked.min.js
index eb14b2545..9fdbc8481 100644
--- a/public/editormd/lib/marked.min.js
+++ b/public/editormd/lib/marked.min.js
@@ -1,22 +1,6 @@
/**
- * marked v0.3.3 - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
-
- 备注,这个改动没启用,只是做个记录:
- br不转成br
- 加了个 if (cap[0] != '' && cap[0] != ' "+e+"
') { out+=this.options.sanitize?escape(cap[0]):cap[0]; }
-
- out+=this.renderer.em(this.output(cap[2]||cap[1])) -->
- out+=this.renderer.em(this.output(cap[2]||cap[1]), cap.input)
+ * marked - a markdown parser
+ * Copyright (c) 2011-2021, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/markedjs/marked
*/
-// 0.4.0 /^ *(#{1,6}) ——》/^ *(#{1,6}) 去掉了一个空格
-/*if("string"!=typeof e)throw new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected");*/
-// 说明:左边 --> 右边 左边被替换成了右边的内容
-// b(i[1].replace(/^ *| *\| *$/g,"")) --> i[1].replace(/^ *| *\| *$/g, "").split(/ *\| */) table没识别的问题
-// header.length===a.align.length --> header.length table没识别的问题
-// 2个table: b(a.cells[p],a.header.length) -> a.cells[p].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */)
-// .replace(/(?: *\| *)?\n$/,"") --> .replace(/\n$/, "")
-// /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/ --> /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
-!function(e){"use strict";var t={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:d,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6})*([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:d,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)|(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:d,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function n(e){this.tokens=[],this.tokens.links={},this.options=e||m.defaults,this.rules=t.normal,this.options.pedantic?this.rules=t.pedantic:this.options.gfm&&(this.options.tables?this.rules=t.tables:this.rules=t.gfm)}t._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,t._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,t.def=p(t.def).replace("label",t._label).replace("title",t._title).getRegex(),t.bullet=/(?:[*+-]|\d+\.)/,t.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,t.item=p(t.item,"gm").replace(/bull/g,t.bullet).getRegex(),t.list=p(t.list).replace(/bull/g,t.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+t.def.source+")").getRegex(),t._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",t._comment=//,t.html=p(t.html,"i").replace("comment",t._comment).replace("tag",t._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),t.paragraph=p(t.paragraph).replace("hr",t.hr).replace("heading",t.heading).replace("lheading",t.lheading).replace("tag",t._tag).getRegex(),t.blockquote=p(t.blockquote).replace("paragraph",t.paragraph).getRegex(),t.normal=f({},t),t.gfm=f({},t.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6})+([^\n]+?) *#* *(?:\n+|$)/}),t.gfm.paragraph=p(t.paragraph).replace("(?!","(?!"+t.gfm.fences.source.replace("\\1","\\2")+"|"+t.list.source.replace("\\1","\\3")+"|").getRegex(),t.tables=f({},t.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),t.pedantic=f({},t.normal,{html:p("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|
\n":"'+(n?e:a(e,!0))+"
"},i.prototype.blockquote=function(e){return""+(n?e:a(e,!0))+"
\n"+e+"
\n"},i.prototype.html=function(e){return e},i.prototype.heading=function(e,t,n){return this.options.headerIds?"
\n":"
\n"},i.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+""+r+">\n"},i.prototype.listitem=function(e){return"\n\n"+e+"\n"+t+"
\n"},i.prototype.tablerow=function(e){return"\n"+e+" \n"},i.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+""+n+">\n"},i.prototype.strong=function(e){return""+e+""},i.prototype.em=function(e){return""+e+""},i.prototype.codespan=function(e){return""+e+"
"},i.prototype.br=function(){return this.options.xhtml?"
":"
"},i.prototype.del=function(e){return""+e+""},i.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(h(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return n}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:")||0===r.indexOf("data:"))return n}this.options.baseUrl&&!g.test(e)&&(e=u(this.options.baseUrl,e));try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return n}var s='"+n+""},i.prototype.image=function(e,t,n){this.options.baseUrl&&!g.test(e)&&(e=u(this.options.baseUrl,e));var r='":">"},i.prototype.text=function(e){return e},l.prototype.strong=l.prototype.em=l.prototype.codespan=l.prototype.del=l.prototype.text=function(e){return e},l.prototype.link=l.prototype.image=function(e,t,n){return""+n},l.prototype.br=function(){return""},o.parse=function(e,t){return new o(t).parse(e)},o.prototype.parse=function(e){this.inline=new s(e.links,this.options),this.inlineText=new s(e.links,f({},this.options,{renderer:new l})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},o.prototype.next=function(){return this.token=this.tokens.pop()},o.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},o.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},o.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,h(this.inlineText.output(this.token.text)));case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;e
"+a(e.message+"",!0)+"";throw e}}d.exec=d,m.options=m.setOptions=function(e){return f(m.defaults,e),m},m.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new i,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},m.defaults=m.getDefaults(),m.Parser=o,m.parser=o.parse,m.Renderer=i,m.TextRenderer=l,m.Lexer=n,m.lexer=n.lex,m.InlineLexer=s,m.inlineLexer=s.output,m.parse=m,"undefined"!=typeof module&&"object"==typeof exports?module.exports=m:"function"==typeof define&&define.amd?define(function(){return m}):e.marked=m}(this||("undefined"!=typeof window?window:global)); - +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).marked=t()}(this,function(){"use strict";function r(e,t){for(var u=0;u
'+(u?e:H(e,!0))+"
\n":""+(u?e:H(e,!0))+"
\n"},t.blockquote=function(e){return"\n"+e+"\n"},t.html=function(e){return e},t.heading=function(e,t,u,n){return this.options.headerIds?"
"+e+"
\n"},t.table=function(e,t){return""+e+"
"},t.br=function(){return this.options.xhtml?""+se(e.message+"",!0)+"";throw e}}return ae.options=ae.setOptions=function(e){return re(ae.defaults,e),le(ae.defaults),ae},ae.getDefaults=$,ae.defaults=x,ae.use=function(){for(var u=this,e=arguments.length,t=new Array(e),n=0;n
"+se(e.message+"",!0)+"";throw e}},ae.Parser=te,ae.parser=te.parse,ae.Renderer=ne,ae.TextRenderer=S,ae.Lexer=ee,ae.lexer=ee.lex,ae.Tokenizer=ue,ae.Slugger=B,ae.parse=ae}); \ No newline at end of file diff --git a/public/操作系统大赛用户信息.csv b/public/操作系统大赛用户信息.csv new file mode 100644 index 000000000..7365072b2 --- /dev/null +++ b/public/操作系统大赛用户信息.csv @@ -0,0 +1,2 @@ +用户名,邮箱,密码,手机号,昵称 +123456789,yystopf1@163.com,9b653a7d,15386415122,何慧