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

This commit is contained in:
xxq250 2024-05-08 17:19:19 +08:00
commit e96d4e3d05
89 changed files with 1100 additions and 279 deletions

View File

@ -141,4 +141,4 @@ gem 'doorkeeper'
gem 'doorkeeper-jwt'
gem 'gitea-client', '~> 1.4.3'
gem 'gitea-client', '~> 1.4.6'

View File

@ -5,7 +5,7 @@ class Admins::ProjectsController < Admins::BaseController
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
search = params[:search].to_s.strip
projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
projects = Project.where("name like ? OR identifier LIKE ?", "%#{search}%", "%#{search}%").order("#{sort_by} #{sort_direction}")
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
end

View File

@ -55,6 +55,11 @@ class Api::V1::BaseController < ApplicationController
return render_forbidden if !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
end
def require_member_above
@project = load_project
return render_forbidden if !current_user.admin? && !@project.member?(current_user)
end
# 具有对仓库的访问权限
def require_public_and_member_above
@project = load_project

View File

@ -0,0 +1,10 @@
class Api::V1::ProjectDatasetsController < Api::V1::BaseController
def index
return render_error("请输入正确的项目id字符串") unless params[:ids].present?
ids = params[:ids].split(",")
@project_datasets = ProjectDataset.where(project_id: ids).includes(:license, :project)
@project_datasets = kaminari_unlimit_paginate(@project_datasets)
end
end

View File

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

View File

@ -0,0 +1,4 @@
class Api::V1::Projects::Actions::BaseController < Api::V1::BaseController
before_action :require_public_and_member_above
end

View File

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

View File

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

View File

@ -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,11 @@ 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
hash = Api::V1::Projects::Commits::RecentService.call(@project, {keyword: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
@result_object = hash[:result]
@object_detail = hash[:detail]
puts @object_detail
end
end

View File

@ -0,0 +1,51 @@
class Api::V1::Projects::DatasetsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:show]
before_action :require_member_above, only: [:create, :update]
before_action :find_dataset, only: [:update, :show]
before_action :check_menu_authorize
def create
::Projects::Datasets::CreateForm.new(dataset_params).validate!
return render_error('该项目下已存在数据集!') if @project.project_dataset.present?
@project_dataset = ProjectDataset.new(dataset_params.merge!(project_id: @project.id))
if @project_dataset.save!
render_ok
else
render_error('创建数据集失败!')
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def update
::Projects::Datasets::CreateForm.new(dataset_params).validate!
@project_dataset.attributes = dataset_params
if @project_dataset.save!
render_ok
else
render_error("更新数据集失败!")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def show
@attachments = kaminari_paginate(@project_dataset.attachments.includes(:author))
end
private
def dataset_params
params.permit(:title, :description, :license_id, :paper_content)
end
def find_dataset
@project_dataset = @project.project_dataset
return render_not_found unless @project_dataset.present?
end
def check_menu_authorize
return render_not_found unless @project.has_menu_permission("dataset")
end
end

View File

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

View File

@ -95,6 +95,9 @@ class AttachmentsController < ApplicationController
@attachment.disk_directory = month_folder
@attachment.cloud_url = remote_path
@attachment.uuid = SecureRandom.uuid
@attachment.description = params[:description]
@attachment.container_id = params[:container_id]
@attachment.container_type = params[:container_type]
@attachment.save!
else
logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}"
@ -124,7 +127,7 @@ class AttachmentsController < ApplicationController
# 附件为视频时,点击播放
def preview_attachment
attachment = Attachment.find_by(id: params[:id])
attachment = Attachment.where_id_or_uuid(params[:id]).first
dir_path = "#{Rails.root}/public/preview"
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
if params[:status] == "preview"

View File

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

View File

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

View File

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

View File

@ -67,7 +67,18 @@ class Organizations::TeamsController < Organizations::BaseController
tip_exception("组织团队不允许被删除") if @team.owner?
ActiveRecord::Base.transaction do
Gitea::Organization::Team::DeleteService.call(@organization.gitea_token, @team.gtid)
other_user_ids = @organization.team_users.where.not(team_id: @team.id).pluck(:user_id)
team_user_ids = @team.team_users.pluck(:user_id)
# 当前删除团队中成员在其他组织其他团队不存在的成员需清除组织
remove_user_ids = team_user_ids - other_user_ids
Rails.logger.info "remove_user_ids ===========> #{remove_user_ids}"
@team.destroy!
if remove_user_ids.present?
User.where(id: remove_user_ids).each do |user|
@organization.organization_users.find_by(user_id: user.id).destroy!
Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, user.login)
end
end
end
render_ok
rescue Exception => e

View File

@ -21,6 +21,7 @@ class ProjectsController < ApplicationController
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
menu.append(menu_hash_by_name("dataset")) if @project.has_menu_permission("dataset") && @project.forge?
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
menu.append(menu_hash_by_name("services")) if @project.has_menu_permission("services") && @project.forge? && (current_user.admin? || @project.member?(current_user.id))
@ -42,7 +43,8 @@ class ProjectsController < ApplicationController
@total_count =
if category_id.blank? && params[:search].blank? && params[:topic_id].blank?
# 默认查询时count性能问题处理
ProjectCategory.sum("projects_count") - Project.visible.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id").where("organization_extensions.visibility =2").count
not_category_count = Project.where(project_category_id: nil).count
ProjectCategory.sum("projects_count") - Project.visible.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id").where("organization_extensions.visibility =2").count + not_category_count
elsif params[:search].present? || params[:topic_id].present?
@projects.total_count
else
@ -58,7 +60,10 @@ class ProjectsController < ApplicationController
OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(@project&.id, current_user.id)
UpdateProjectTopicJob.perform_later(@project.id) if @project.id.present?
end
rescue Exception => e
rescue Gitea::Api::ServerError => ex
uid_logger_error(ex.message)
tip_exception(ex.http_code, ex.message)
rescue ApplicationService::Error => e
uid_logger_error(e.message)
tip_exception(e.message)
end
@ -193,13 +198,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 +358,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

View File

@ -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, "请选择合并方式")

View File

@ -64,6 +64,7 @@ class RepositoriesController < ApplicationController
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
else
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
return render_not_found if @entries.is_a?(Array) && @entries.blank?
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
end

View File

@ -1,4 +1,5 @@
class VersionReleasesController < ApplicationController
include ApplicationHelper
before_action :load_repository
before_action :set_user
before_action :require_login, except: [:index, :show]
@ -126,6 +127,16 @@ class VersionReleasesController < ApplicationController
end
end
def download
tip_exception(404, '您访问的页面不存在或已被删除') if params["tag_name"].blank? || params["filename"].blank?
version = @repository.version_releases.find_by(tag_name: params["tag_name"])
attachment = version.attachments.find_by(filename: params["filename"])
tip_exception(404, '您访问的页面不存在或已被删除') if attachment.blank?
send_file(absolute_path(local_path(attachment)), filename: attachment.title, stream: false, type: attachment.content_type.presence || 'application/octet-stream')
update_downloads(attachment)
# redirect_to "/api/attachments/#{attachment.uuid}"
end
private
def set_user

View File

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

View File

@ -0,0 +1,15 @@
class Projects::Datasets::CreateForm < BaseForm
attr_accessor :title, :description, :license_id, :paper_content
validates :title, presence: true, length: { maximum: 100 }
validates :description, presence: true, length: { maximum: 500 }
validates :paper_content, length: { maximum: 500 }
validate :check_license
def check_license
raise "license_id值无效. " if license_id && License.find_by(id: license_id).blank?
end
end

View File

@ -67,6 +67,7 @@ module ProjectsHelper
jianmu_devops_url: jianmu_devops_url,
cloud_ide_saas_url: cloud_ide_saas_url(user),
open_blockchain: Site.has_blockchain? && project.use_blockchain,
has_dataset: project.project_dataset.present?,
ignore_id: project.ignore_id
}).compact

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ module CustomRegexp
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
# REPOSITORY_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9\-\_\.]+[a-zA-Z0-9]$/ #只含有数字、字母、下划线不能以下划线开头和结尾
REPOSITORY_NAME_REGEX = /^[a-zA-Z0-9\-\_\.]+[a-zA-Z0-9]$/ #只含有数字、字母、下划线不能以下划线开头和结尾
MD_REGEX = /^.+(\.[m|M][d|D])$/

View File

@ -1,45 +1,45 @@
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# memo_image :boolean default("0")
# extra_type :integer default("0")
# uuid :string(255)
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# memo_image :boolean default("0")
# extra_type :integer default("0")
# uuid :string(255)
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#
@ -72,7 +72,7 @@ class Attachment < ApplicationRecord
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
scope :where_id_or_uuid, -> (id) { (Float(id) rescue nil).present? ? where(id: id) : where(uuid: id) }
validates_length_of :description, maximum: 100, message: "不能超过100个字符"
validates_length_of :description, maximum: 255, message: "不能超过255个字符"
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)

View File

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

View File

@ -52,6 +52,8 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{name}</b>', 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: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
self.create(type: 'MessageTemplate::ProjectMilestoneEarlyExpired', sys_notice: '您创建的里程碑 <b>{name}</b> 已临近截止日期,请尽快处理.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
self.create(type: 'MessageTemplate::ProjectMilestoneExpired', sys_notice: '您创建的里程碑 <b>{name}</b> 已逾期,请及时更新进度或联系项目团队.', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 <b>{repository}</b> 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops')
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")

View File

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

View File

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

View File

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

View File

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

View File

@ -28,7 +28,7 @@ class Page < ApplicationRecord
belongs_to :project
# language_frame 前端语言框架
enum language_frame: { hugo: 0, jekyll: 1, hexo: 2}
enum language_frame: { hugo: 0, jekyll: 1, hexo: 2, files: 3}
after_create do
PageService.genernate_user(user_id)

View File

@ -13,7 +13,7 @@
#
class PageTheme < ApplicationRecord
enum language_frame: { hugo: 0, jeklly: 1, hexo: 2}
enum language_frame: { hugo: 0, jeklly: 1, hexo: 2, files:3}
validates :name, presence: {message: "主题名不能为空"}, uniqueness: {message: "主题名已存在",scope: :language_frame},length: {maximum: 255}
def image

View File

@ -90,6 +90,8 @@ class Project < ApplicationRecord
include ProjectOperable
include Dcodes
default_scope {where.not(id: 0)}
# common:开源托管项目
# mirror:普通镜像项目,没有定时同步功能
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
@ -137,6 +139,7 @@ class Project < ApplicationRecord
has_many :project_topics, through: :project_topic_ralates
has_many :commit_logs, dependent: :destroy
has_many :daily_project_statistics, dependent: :destroy
has_one :project_dataset, dependent: :destroy
after_create :incre_user_statistic, :incre_platform_statistic
after_save :check_project_members
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data

View File

@ -0,0 +1,26 @@
# == Schema Information
#
# Table name: project_datasets
#
# id :integer not null, primary key
# title :string(255)
# description :text(65535)
# project_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# license_id :integer
# paper_content :text(65535)
#
# Indexes
#
# index_project_datasets_on_license_id (license_id)
# index_project_datasets_on_project_id (project_id)
#
class ProjectDataset < ApplicationRecord
belongs_to :project
belongs_to :license, optional: true
has_many :attachments, as: :container, dependent: :destroy
end

View File

@ -17,7 +17,7 @@ class ProjectUnit < ApplicationRecord
belongs_to :project
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8, dataset: 9}
validates :unit_type, uniqueness: { scope: :project_id}

View File

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

View File

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

View File

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

View File

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

View File

@ -135,7 +135,7 @@ class Api::V1::Issues::UpdateService < ApplicationService
end
def build_previous_issue_changes
@previous_issue_changes.merge!(@updated_issue.previous_changes.slice("status_id", "priority_id", "fixed_version_id", "issue_tags_value", "branch_name", "subject", "description").symbolize_keys)
@previous_issue_changes.merge!(@updated_issue.previous_changes.slice("status_id", "priority_id", "fixed_version_id", "issue_tags_value", "branch_name", "subject").symbolize_keys)
if @updated_issue.previous_changes[:start_date].present?
@previous_issue_changes.merge!(start_date: [@updated_issue.previous_changes[:start_date][0].to_s, @updated_issue.previous_changes[:start_date][1].to_s])
end

View File

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

View File

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

View File

@ -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, '删除分支失败!'

View File

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

View File

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

View File

@ -0,0 +1,44 @@
class Api::V1::Projects::Commits::RecentService < ApplicationService
attr_reader :project, :page, :limit, :keyword, :owner, :repo, :token
attr_accessor :gitea_data, :gitea_repo_detail
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
load_gitea_repo_detail
{result: gitea_data, detail:gitea_repo_detail}
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
def load_gitea_repo_detail
@gitea_repo_detail = $gitea_client.get_repos_by_owner_repo(owner, repo, {query: {access_token: token}})
raise Error, "获取项目详情失败" unless @gitea_repo_detail.is_a?(Hash)
end
end

View File

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

View File

@ -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, '删除标签失败!'

View File

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

View File

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

View File

@ -47,7 +47,7 @@ class PageService
repo_link = project.repository.url
repo = project.repository.identifier
branch = branch
script_path =page.build_script_path
script_path = branch == "gh-pages" ? "files_build" : page.build_script_path
if script_path.present?
uri = URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=#{script_path}&project_dir=#{project_dir}&repo=#{repo}&repo_link=#{repo_link}&branch=#{branch}&owner=#{owner}")
response = Net::HTTP.get_response(uri)

View File

@ -26,9 +26,6 @@ class Projects::CreateService < ApplicationService
end
end
@project
rescue => e
puts "create project service error: #{e.message}"
raise Error, e.message
end
private

View File

@ -33,18 +33,17 @@ class Repositories::CreateService < ApplicationService
end
repository
end
rescue => e
puts "create repository service error: #{e.message}"
raise Error, e.message
end
private
def create_gitea_repository
if project.owner.is_a?(User)
@gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call
# @gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call
@gitea_repository = $gitea_client.post_user_repos({query: {token: user.gitea_token}, body: gitea_repository_params.to_json})
elsif project.owner.is_a?(Organization)
@gitea_repository = Gitea::Organization::Repository::CreateService.call(user.gitea_token, project.owner.login, gitea_repository_params)
# @gitea_repository = Gitea::Organization::Repository::CreateService.call(user.gitea_token, project.owner.login, gitea_repository_params)
@gitea_repository = $gitea_client.post_orgs_repos_by_org(project.owner.login, {query: {token: user.gitea_token}, body: gitea_repository_params.to_json})
end
end
@ -67,7 +66,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

View File

@ -14,7 +14,7 @@
<label>
建站工具 <span class="ml10 color-orange mr20">*</span>
</label>
<% state_options = [['hugo', "hugo"], ['jeklly', "jeklly"],['hexo',"hexo"]] %>
<% state_options = [['hugo', "hugo"], ['jeklly', "jeklly"],['hexo',"hexo"],['files',"files"]] %>
<%= select_tag('page_theme[language_frame]', options_for_select(state_options), class: 'form-control') %>
</div>
<% end%>

View File

@ -6,7 +6,7 @@
<%= form_tag(admins_page_themes_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-2">
<label for="language_frame">建站工具:</label>
<% state_options = [['全部',nil], ['hugo', 0], ['jeklly', 1],['hexo',2]] %>
<% state_options = [['全部',nil], ['hugo', 0], ['jeklly', 1],['hexo',2],['files',3]] %>
<%= select_tag(:language_frame, options_for_select(state_options), class: 'form-control') %>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>

View File

@ -4,7 +4,7 @@
<div class="box search-form-container project-list-form">
<%= form_tag(admins_projects_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '项目名称检索') %>
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '项目名称/标识检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
<% end %>

View File

@ -0,0 +1,11 @@
json.id attachment.uuid
json.title attachment.title
json.description attachment.description
json.filesize number_to_human_size(attachment.filesize)
json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)
json.created_on attachment.created_on.strftime("%Y-%m-%d %H:%M:%S")
json.content_type attachment.content_type
json.creator do
json.partial! "api/v1/users/simple_user", locals: {user: attachment.author}
end

View File

@ -1,7 +1,8 @@
json.id attachment.id
json.id attachment.uuid
json.title attachment.title
json.description attachment.description
json.filesize number_to_human_size(attachment.filesize)
json.is_pdf attachment.is_pdf?
json.url attachment.is_pdf? ? download_url(attachment,disposition:"inline") : download_url(attachment)
json.created_on attachment.created_on.strftime("%Y-%m-%d %H:%M")
json.created_on attachment.created_on.strftime("%Y-%m-%d %H:%M:%S")
json.content_type attachment.content_type

View File

@ -0,0 +1,14 @@
json.total_count @project_datasets.total_count
json.project_datasets @project_datasets.each do |dataset|
json.(dataset, :id, :title, :description, :paper_content)
json.project do
json.partial! "api/v1/projects/simple_detail", project: dataset.project
end
if dataset.license.present?
json.license do
json.(dataset.license, :name, :content)
end
else
json.license nil
end
end

View File

@ -1,7 +1,7 @@
if project.present?
json.type project.project_type
json.(project,
:description, :forked_count, :forked_from_project_id, :identifier,
:id, :description, :forked_count, :forked_from_project_id, :identifier,
:issues_count, :pull_requests_count, :invite_code, :website, :platform,
:name, :open_devops, :praises_count, :is_public, :status, :watchers_count,
:ignore_id, :license_id, :project_category_id, :project_language_id)

View File

@ -0,0 +1,4 @@
json.total_count @data.size
json.files @data.each do |file|
json.name file["Name"]
end

View File

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

View File

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

View File

@ -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'])
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

View File

@ -0,0 +1,16 @@
json.total_count @result_object[:total_data].to_i
json.ssh_url @object_detail['ssh_url']
json.clone_url @object_detail['clone_url']
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

View File

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

View File

@ -0,0 +1,6 @@
json.(@project_dataset, :id, :title, :description, :license_id, :paper_content)
json.license_name @project_dataset&.license&.name
json.attachment_total_count @attachments.total_count
json.attachments @attachments do |at|
json.partial! "api/v1/attachments/detail", locals: {attachment: at}
end

View File

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

View File

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

View File

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

View File

@ -17,6 +17,7 @@ json.projects @projects do |project|
json.forked_from_project_id project.forked_from_project_id
json.open_devops project.open_devops?
json.platform project.platform
json.has_dataset project.has_menu_permission("dataset") && project.project_dataset.present?
json.author do
if project.educoder?
project_educoder = project.project_educoder

View File

@ -1,3 +1,4 @@
json.empty @result[:repo]["empty"]
json.content @project.content
json.website @project.website
json.lesson_url @project.lesson_url

View File

@ -36,7 +36,8 @@ json.setting do
json.subject_banner_url default_setting.subject_banner_url&.[](1..-1)
json.course_banner_url default_setting.course_banner_url&.[](1..-1)
json.competition_banner_url default_setting.competition_banner_url&.[](1..-1)
json.competition_banner_url EduSetting.get("competition_banner_url").to_s
json.competition_banner_href EduSetting.get("competition_banner_href").to_s
json.moop_cases_banner_url default_setting.moop_cases_banner_url&.[](1..-1)
json.oj_banner_url default_setting.oj_banner_url&.[](1..-1)

View File

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

View File

@ -16,6 +16,12 @@ json.user_login user&.login
json.image_url user.present? ? url_to_avatar(user) : ""
json.attachments do
json.array! version.try(:attachments) do |attachment|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
# json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
json.id attachment.id
json.title attachment.title
json.filesize number_to_human_size attachment.filesize
json.description attachment.description
json.is_pdf attachment.is_pdf?
json.url "/#{@owner.login}/#{@repository.identifier}/releases/download/#{version&.tag_name}/#{attachment.filename}"
end
end

View File

@ -19,11 +19,13 @@ Rails.application.routes.draw do
get 'attachments/entries/get_file', to: 'attachments#get_file'
get 'attachments/download/:id', to: 'attachments#show'
get 'attachments/download/:id/:filename', to: 'attachments#show'
get ':owner/:repo/releases/download/:tag_name/:filename', to: 'version_releases#download', constraints: { repo: /[^\/]+/, tag_name: /[^\/]+/, filename: /[^\/]+/ }
get 'check_pr_url',to: "settings#check_url"
# 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'

View File

@ -78,6 +78,16 @@ defaults format: :json do
# projects文件夹下的
scope module: :projects do
resource :dataset, only: [:create, :update, :show]
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 +108,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 +118,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
@ -130,7 +145,7 @@ defaults format: :json do
resources :projects, only: [:index]
resources :project_topics, only: [:index, :create, :destroy]
resources :project_datasets, only: [:index]
end
end

View File

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

View File

@ -0,0 +1,11 @@
class CreateProjectDatasets < ActiveRecord::Migration[5.2]
def change
create_table :project_datasets do |t|
t.string :title
t.text :description
t.references :project
t.timestamps
end
end
end

View File

@ -0,0 +1,6 @@
class AddLicenseAndPaperContentToProjectDataset < ActiveRecord::Migration[5.2]
def change
add_reference :project_datasets, :license
add_column :project_datasets, :paper_content, :text
end
end

View File

@ -0,0 +1 @@
lvSp9mqhewuv8zRT

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
用户名,邮箱,密码,手机号,昵称
123456789,yystopf1@163.com,9b653a7d,15386415122,何慧
1 用户名 邮箱 密码 手机号 昵称
2 123456789 yystopf1@163.com 9b653a7d 15386415122 何慧