Merge pull request '20220608版本' (#306) from Trustie/forgeplus:trustie_server into develop
This commit is contained in:
commit
507d63e98c
|
@ -84,4 +84,5 @@ redis_data/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
dump.rdb
|
dump.rdb
|
||||||
.tags*
|
.tags*
|
||||||
ceshi_user.xlsx
|
ceshi_user.xlsx
|
||||||
|
public/trace_task_results
|
|
@ -1,6 +1,25 @@
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
|
before_action :require_login, only: [:login_check, :simple_update]
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
|
#skip_before_action :check_account, :only => [:logout]
|
||||||
|
|
||||||
|
def simple_update
|
||||||
|
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, ""))
|
||||||
|
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
|
||||||
|
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, ""))
|
||||||
|
Register::RemoteForm.new(simple_update_params).validate!
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
result = auto_update(current_user, simple_update_params)
|
||||||
|
if result[:message].blank?
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
render_error(result[:message])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render json: session
|
render json: session
|
||||||
end
|
end
|
||||||
|
@ -315,6 +334,11 @@ class AccountsController < ApplicationController
|
||||||
Register::CheckColumnsForm.new(check_params).validate!
|
Register::CheckColumnsForm.new(check_params).validate!
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def login_check
|
||||||
|
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
@ -383,4 +407,7 @@ class AccountsController < ApplicationController
|
||||||
params.permit(:username, :email, :password, :platform)
|
params.permit(:username, :email, :password, :platform)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def simple_update_params
|
||||||
|
params.permit(:username, :email, :password, :platform)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
|
||||||
def create
|
def create
|
||||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
result = Admins::ImportUserService.call(params[:file].to_io)
|
result = Admins::ImportUserFromExcelService.call(params[:file].to_io)
|
||||||
render_ok(result)
|
render_ok(result)
|
||||||
rescue Admins::ImportUserService::Error => ex
|
rescue Admins::ImportUserService::Error => ex
|
||||||
render_error(ex)
|
render_error(ex)
|
||||||
|
|
|
@ -2,8 +2,24 @@ class Admins::MessageTemplatesController < Admins::BaseController
|
||||||
before_action :get_template, only: [:edit, :update, :destroy]
|
before_action :get_template, only: [:edit, :update, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
message_templates = MessageTemplate.group(:type).count.keys
|
message_templates = MessageTemplate.ransack(sys_notice_or_email_or_email_title_cont: params[:search]).result
|
||||||
@message_templates = kaminari_array_paginate(message_templates)
|
@message_templates = kaminari_paginate(message_templates)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@message_template = MessageTemplate::CustomTip.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@message_template = MessageTemplate::CustomTip.new(ignore_params)
|
||||||
|
|
||||||
|
if @message_template.save!
|
||||||
|
redirect_to admins_message_templates_path
|
||||||
|
flash[:success] = "创建消息模板成功"
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
flash[:danger] = "创建消息模板失败"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
|
|
@ -14,12 +14,12 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
flag, msg = check_bind_cloud_account!
|
flag, msg = check_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = bind_account!
|
@cloud_account = bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
|
@ -27,17 +27,17 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate
|
def activate
|
||||||
return render_error('请先认证') unless current_user.ci_certification?
|
return tip_exception('请先认证') unless current_user.ci_certification?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@cloud_account = Ci::CloudAccount.find params[:id]
|
@cloud_account = Ci::CloudAccount.find params[:id]
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
if @repo
|
if @repo
|
||||||
return render_error('该项目已经激活') if @repo.repo_active?
|
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||||
@repo.activate!(@project)
|
@repo.activate!(@project)
|
||||||
else
|
else
|
||||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||||
|
@ -50,7 +50,7 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,39 +59,39 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
|
|
||||||
def bind
|
def bind
|
||||||
flag, msg = check_bind_cloud_account!
|
flag, msg = check_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = bind_account!
|
@cloud_account = bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def trustie_bind
|
def trustie_bind
|
||||||
account = params[:account].to_s
|
account = params[:account].to_s
|
||||||
return render_error("account不能为空.") if account.blank?
|
return tip_exception("account不能为空.") if account.blank?
|
||||||
|
|
||||||
flag, msg = check_trustie_bind_cloud_account!
|
flag, msg = check_trustie_bind_cloud_account!
|
||||||
return render_error(msg) if flag === true
|
return tip_exception(msg) if flag === true
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@cloud_account = trustie_bind_account!
|
@cloud_account = trustie_bind_account!
|
||||||
if @cloud_account.blank?
|
if @cloud_account.blank?
|
||||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
else
|
else
|
||||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unbind
|
def unbind
|
||||||
|
@ -107,18 +107,18 @@ class Ci::CloudAccountsController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def oauth_grant
|
def oauth_grant
|
||||||
password = params[:password].to_s
|
password = params[:password].to_s
|
||||||
return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
|
return tip_exception('你输入的密码不正确.') unless current_user.check_password?(password)
|
||||||
|
|
||||||
oauth = current_user.oauths.last
|
oauth = current_user.oauths.last
|
||||||
return render_error("服务器出小差了.") if oauth.blank?
|
return tip_exception("服务器出小差了.") if oauth.blank?
|
||||||
|
|
||||||
result = gitea_oauth_grant!(password, oauth)
|
result = gitea_oauth_grant!(password, oauth)
|
||||||
return render_error('授权失败.') unless result === true
|
return tip_exception('授权失败.') unless result === true
|
||||||
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
|
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
|
||||||
if size > 0
|
if size > 0
|
||||||
render_error("#{params[:branch]}分支已经存在流水线!")
|
tip_exception("#{params[:branch]}分支已经存在流水线!")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
|
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
|
||||||
|
@ -53,7 +53,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok({id: pipeline.id})
|
render_ok({id: pipeline.id})
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 在代码库创建文件
|
# 在代码库创建文件
|
||||||
|
@ -81,6 +81,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
repo_branch: pipeline.branch,
|
repo_branch: pipeline.branch,
|
||||||
repo_config: pipeline.file_name
|
repo_config: pipeline.file_name
|
||||||
}
|
}
|
||||||
|
Rails.logger.info("########create_params===#{create_params.to_json}")
|
||||||
repo = Ci::Repo.create_repo(create_params)
|
repo = Ci::Repo.create_repo(create_params)
|
||||||
repo
|
repo
|
||||||
end
|
end
|
||||||
|
@ -118,7 +119,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -132,7 +133,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def content
|
def content
|
||||||
|
@ -182,7 +183,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage
|
def update_stage
|
||||||
|
@ -192,7 +193,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_stage
|
def delete_stage
|
||||||
|
@ -205,7 +206,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage_index(pipeline_id, show_index, diff)
|
def update_stage_index(pipeline_id, show_index, diff)
|
||||||
|
@ -229,7 +230,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
unless steps.empty?
|
unless steps.empty?
|
||||||
steps.each do |step|
|
steps.each do |step|
|
||||||
unless step[:template_id]
|
unless step[:template_id]
|
||||||
render_error('请选择模板!')
|
tip_exception('请选择模板!')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if !step[:id]
|
if !step[:id]
|
||||||
|
@ -246,7 +247,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_stage_step
|
def create_stage_step
|
||||||
|
@ -262,7 +263,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_stage_step
|
def update_stage_step
|
||||||
|
@ -279,7 +280,7 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_stage_step
|
def delete_stage_step
|
||||||
|
@ -289,6 +290,6 @@ class Ci::PipelinesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,19 +30,19 @@ class Ci::ProjectsController < Ci::BaseController
|
||||||
@file = interactor.result
|
@file = interactor.result
|
||||||
render_result(1, "更新成功")
|
render_result(1, "更新成功")
|
||||||
else
|
else
|
||||||
render_error(interactor.error)
|
tip_exception(interactor.error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate
|
def activate
|
||||||
return render_error('你还未认证') unless current_user.ci_certification?
|
return tip_exception('你还未认证') unless current_user.ci_certification?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
if @repo
|
if @repo
|
||||||
return render_error('该项目已经激活') if @repo.repo_active?
|
@repo.destroy! if @repo&.repo_user_id == 0
|
||||||
|
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||||
@repo.activate!(@project)
|
@repo.activate!(@project)
|
||||||
return render_ok
|
|
||||||
else
|
else
|
||||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||||
@ci_user.update_column(:user_syncing, false)
|
@ci_user.update_column(:user_syncing, false)
|
||||||
|
@ -55,12 +55,12 @@ class Ci::ProjectsController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deactivate
|
def deactivate
|
||||||
return render_error('该项目已经取消激活') if !@repo.repo_active?
|
return tip_exception('该项目已经取消激活') if !@repo.repo_active?
|
||||||
|
|
||||||
@project.update_column(:open_devops, false)
|
@project.update_column(:open_devops, false)
|
||||||
@repo.deactivate_repos!
|
@repo.deactivate_repos!
|
||||||
|
|
|
@ -20,14 +20,14 @@ class Ci::SecretsController < Ci::BaseController
|
||||||
if result["id"]
|
if result["id"]
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error(result["message"])
|
tip_exception(result["message"])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
||||||
if result["id"]
|
if result["id"]
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error(result["message"])
|
tip_exception(result["message"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -39,7 +39,7 @@ class Ci::SecretsController < Ci::BaseController
|
||||||
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
||||||
render_ok
|
render_ok
|
||||||
else
|
else
|
||||||
render_error("参数名不能为空")
|
tip_exception("参数名不能为空")
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_ok
|
render_ok
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -63,7 +63,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
)
|
)
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -73,7 +73,7 @@ class Ci::TemplatesController < Ci::BaseController
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
render_error(ex.message)
|
tip_exception(ex.message)
|
||||||
end
|
end
|
||||||
|
|
||||||
#======流水线模板查询=====#
|
#======流水线模板查询=====#
|
||||||
|
|
|
@ -160,9 +160,9 @@ module Ci::CloudAccountManageable
|
||||||
state = SecureRandom.hex(8)
|
state = SecureRandom.hex(8)
|
||||||
# redirect_uri eg:
|
# redirect_uri eg:
|
||||||
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
||||||
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
# redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
||||||
clientId = client_id(oauth)
|
# clientId = client_id(oauth)
|
||||||
grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{clientId}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
|
grant_url = "#{@cloud_account.drone_url}/login"
|
||||||
logger.info "[gitea] grant_url: #{grant_url}"
|
logger.info "[gitea] grant_url: #{grant_url}"
|
||||||
|
|
||||||
conn = Faraday.new(url: grant_url) do |req|
|
conn = Faraday.new(url: grant_url) do |req|
|
||||||
|
@ -179,7 +179,7 @@ module Ci::CloudAccountManageable
|
||||||
|
|
||||||
def drone_oauth_user!(url, state)
|
def drone_oauth_user!(url, state)
|
||||||
logger.info "[drone] drone_oauth_user url: #{url}"
|
logger.info "[drone] drone_oauth_user url: #{url}"
|
||||||
conn = Faraday.new(url: "#{Gitea.gitea_config[:domain]}#{url}") do |req|
|
conn = Faraday.new(url: url) do |req|
|
||||||
req.request :url_encoded
|
req.request :url_encoded
|
||||||
req.adapter Faraday.default_adapter
|
req.adapter Faraday.default_adapter
|
||||||
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
||||||
|
@ -188,8 +188,8 @@ module Ci::CloudAccountManageable
|
||||||
response = conn.get
|
response = conn.get
|
||||||
logger.info "[drone] response headers: #{response.headers}"
|
logger.info "[drone] response headers: #{response.headers}"
|
||||||
|
|
||||||
true
|
# true
|
||||||
# response.headers['location'].include?('error') ? false : true
|
response.headers['location'].include?('error') ? false : true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -58,4 +58,32 @@ module RegisterHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def auto_update(user, params={})
|
||||||
|
return if params.blank?
|
||||||
|
result = {message: nil, user: nil}
|
||||||
|
before_login = user.login
|
||||||
|
user.login = params[:username]
|
||||||
|
user.password = params[:password]
|
||||||
|
user.mail = params[:email]
|
||||||
|
|
||||||
|
if user.save!
|
||||||
|
sync_params = {
|
||||||
|
password: params[:password].to_s,
|
||||||
|
email: params[:email],
|
||||||
|
login_name: params[:username],
|
||||||
|
new_name: params[:username],
|
||||||
|
source_id: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||||
|
if interactor.success?
|
||||||
|
result[:user] = user
|
||||||
|
else
|
||||||
|
result[:message] = '用户同步Gitea失败!'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result[:message] = user.errors.full_messages.join(",")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module RenderHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_error(message = '')
|
def render_error(message = '')
|
||||||
render json: { status: -1, message: message }
|
render json: { status: status, message: message }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_not_acceptable(message = '请求已拒绝')
|
def render_not_acceptable(message = '请求已拒绝')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class NoticesController < ApplicationController
|
class NoticesController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
tip_exception("参数有误") if params["source"].blank?
|
return tip_exception("参数有误") if params["source"].blank?
|
||||||
user_id = params[:user_id]
|
user_id = params[:user_id]
|
||||||
|
|
||||||
if params["source"] == "CompetitionBegin"
|
if params["source"] == "CompetitionBegin"
|
||||||
|
@ -13,9 +13,21 @@ class NoticesController < ApplicationController
|
||||||
elsif params["source"] == "CompetitionReview"
|
elsif params["source"] == "CompetitionReview"
|
||||||
competition_id = params[:competition_id]
|
competition_id = params[:competition_id]
|
||||||
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
|
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
|
||||||
|
elsif params["source"] == "CustomTip"
|
||||||
|
users_id = params[:users_id]
|
||||||
|
props = params[:props].to_unsafe_hash
|
||||||
|
return tip_exception("参数有误") unless props.is_a?(Hash) && users_id.is_a?(Array)
|
||||||
|
template_id = params[:template_id]
|
||||||
|
SendTemplateMessageJob.perform_later('CustomTip', users_id, template_id, props)
|
||||||
else
|
else
|
||||||
tip_exception("#{params["source"]}未配置")
|
tip_exception("#{params["source"]}未配置")
|
||||||
end
|
end
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
def params_props
|
||||||
|
params.require(:notice).permit(:props)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ class OwnersController < ApplicationController
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
|
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
|
||||||
return render_ok(type: 'User') unless @owner.present?
|
return render_not_found unless @owner.present?
|
||||||
# 组织
|
# 组织
|
||||||
if @owner.is_a?(Organization)
|
if @owner.is_a?(Organization)
|
||||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||||
|
|
|
@ -22,6 +22,7 @@ class ProjectsController < ApplicationController
|
||||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
||||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
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("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))
|
||||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||||
menu.append(menu_hash_by_name("activity"))
|
menu.append(menu_hash_by_name("activity"))
|
||||||
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
||||||
|
|
|
@ -225,7 +225,8 @@ class RepositoriesController < ApplicationController
|
||||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||||
@readme = result[:status] === :success ? result[:body] : nil
|
@readme = result[:status] === :success ? result[:body] : nil
|
||||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||||
|
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
|
||||||
rescue
|
rescue
|
||||||
render json: nil
|
render json: nil
|
||||||
end
|
end
|
||||||
|
@ -387,4 +388,4 @@ class RepositoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
class Traces::BaseController < ApplicationController
|
||||||
|
|
||||||
|
helper_method :observed_logged_user?, :observed_user
|
||||||
|
|
||||||
|
|
||||||
|
def observed_user
|
||||||
|
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||||
|
end
|
||||||
|
|
||||||
|
def observed_logged_user?
|
||||||
|
observed_user.id == User.current&.id
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def check_auth
|
||||||
|
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,83 @@
|
||||||
|
class Traces::ProjectsController < Traces::BaseController
|
||||||
|
include OperateProjectAbilityAble
|
||||||
|
|
||||||
|
before_action :require_login
|
||||||
|
before_action :load_project
|
||||||
|
before_action :authorizate_user_can_edit_project!, except: [:task_results]
|
||||||
|
|
||||||
|
def tasks
|
||||||
|
branch_name = params[:branch_name]
|
||||||
|
return render_error("无可用检测次数") if @project.user_trace_tasks.size >= 5
|
||||||
|
return render_error("分支名不能为空!") if branch_name.blank?
|
||||||
|
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||||
|
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||||
|
code, data, error = Trace::CheckService.call(current_user.trace_token, @project, "1", branch_name)
|
||||||
|
if code == 200
|
||||||
|
UserTraceTask.create!(
|
||||||
|
user_id: current_user.id,
|
||||||
|
project_id: @project.id,
|
||||||
|
branch_tag: branch_name,
|
||||||
|
task_id: data["task_id"]
|
||||||
|
)
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
render_error("检测失败 Error:#{error}")
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def task_results
|
||||||
|
limit = params[:limit] || params[:per_page]
|
||||||
|
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
|
||||||
|
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||||
|
return render :json => {left_tasks_count: 5, data: []} if current_user.trace_user.nil?
|
||||||
|
code, data, error = Trace::CheckResultService.call(current_user.trace_token, @project, nil, page, limit)
|
||||||
|
if code == 200
|
||||||
|
render :json => {left_tasks_count: 5 - @project.user_trace_tasks.size, data: data}
|
||||||
|
else
|
||||||
|
render_error("获取检测记录失败 Error:#{error}")
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reload_task
|
||||||
|
return render_error("project_id错误") if params[:project_id].blank?
|
||||||
|
branch_name = params[:branch_name]
|
||||||
|
return render_error("分支名不能为空!") if branch_name.blank?
|
||||||
|
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||||
|
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||||
|
code, data, error = Trace::ReloadCheckService.call(current_user.trace_token, params[:project_id])
|
||||||
|
if code == 200
|
||||||
|
UserTraceTask.create!(
|
||||||
|
user_id: current_user.id,
|
||||||
|
project_id: @project.id,
|
||||||
|
branch_tag: branch_name,
|
||||||
|
task_id: data["task_id"]
|
||||||
|
)
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
render_error("重新检测失败 Error:#{error}")
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def task_pdf
|
||||||
|
return render_error("task_id错误") if params[:task_id].blank?
|
||||||
|
result = Trace::PdfReportService.call(current_user.trace_token, params[:task_id])
|
||||||
|
if result.is_a?(Hash) && result[:code] == 200
|
||||||
|
redirect_to result[:download_url]
|
||||||
|
else
|
||||||
|
render_error("下载报告失败!")
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
class Traces::TraceUsersController < Traces::BaseController
|
||||||
|
before_action :require_login
|
||||||
|
|
||||||
|
def create
|
||||||
|
if current_user.trace_token.present?
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
render_error(-1, "代码溯源用户初始化失败")
|
||||||
|
end
|
||||||
|
rescue Exception => exception
|
||||||
|
puts exception.message
|
||||||
|
normal_status(-1, exception.message)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,332 +1,399 @@
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include Ci::DbConnectable
|
include Ci::DbConnectable
|
||||||
|
|
||||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||||
before_action :require_login, only: %i[me sync_user_info]
|
before_action :require_login, only: %i[me sync_user_info]
|
||||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||||
before_action :convert_image!, only: [:update, :update_image]
|
before_action :convert_image!, only: [:update, :update_image]
|
||||||
skip_before_action :check_sign, only: [:attachment_show]
|
skip_before_action :check_sign, only: [:attachment_show]
|
||||||
|
before_action :sso_login, only: [:get_user_info]
|
||||||
def connect_to_ci_db(options={})
|
|
||||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
def connect_to_ci_db(options={})
|
||||||
return
|
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||||
end
|
return
|
||||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
end
|
||||||
connect_to_trustie_ci_database(options)
|
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||||
else
|
connect_to_trustie_ci_database(options)
|
||||||
connect_to_ci_database(options)
|
else
|
||||||
end
|
connect_to_ci_database(options)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def list
|
|
||||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
def list
|
||||||
@total_count = scope.size
|
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||||
@users = paginate(scope)
|
@total_count = scope.size
|
||||||
end
|
@users = paginate(scope)
|
||||||
|
end
|
||||||
def show
|
|
||||||
#待办事项,现在未做
|
def show
|
||||||
if User.current.admin? || User.current.login == @user.login
|
#待办事项,现在未做
|
||||||
@waiting_applied_messages = @user.applied_messages.waiting
|
if User.current.admin? || User.current.login == @user.login
|
||||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
@waiting_applied_messages = @user.applied_messages.waiting
|
||||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||||
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||||
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||||
else
|
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||||
@waiting_applied_messages = AppliedMessage.none
|
else
|
||||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
@waiting_applied_messages = AppliedMessage.none
|
||||||
@common_applied_projects = AppliedProject.none
|
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||||
@undo_events = 0
|
@common_applied_projects = AppliedProject.none
|
||||||
end
|
@undo_events = 0
|
||||||
#用户的组织数量
|
end
|
||||||
# @user_composes_count = @user.composes.size
|
#用户的组织数量
|
||||||
@user_composes_count = 0
|
# @user_composes_count = @user.composes.size
|
||||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
@user_composes_count = 0
|
||||||
@user_org_count = user_organizations.size
|
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||||
normal_projects = Project.members_projects(@user.id).to_sql
|
@user_org_count = user_organizations.size
|
||||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
normal_projects = Project.members_projects(@user.id).to_sql
|
||||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||||
@projects_common_count = user_projects.common.size
|
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||||
@projects_mirrior_count = user_projects.mirror.size
|
@projects_common_count = user_projects.common.size
|
||||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
@projects_mirrior_count = user_projects.mirror.size
|
||||||
# 为了缓存活跃用户的基本信息,后续删除
|
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
# 为了缓存活跃用户的基本信息,后续删除
|
||||||
end
|
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||||
|
end
|
||||||
def watch_users
|
|
||||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
def watch_users
|
||||||
if params[:search].present?
|
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
if params[:search].present?
|
||||||
watchers = watchers.where(watchable_id: search_user_ids)
|
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||||
end
|
watchers = watchers.where(watchable_id: search_user_ids)
|
||||||
@watchers_count = watchers.size
|
end
|
||||||
@watchers = paginate(watchers)
|
@watchers_count = watchers.size
|
||||||
end
|
@watchers = paginate(watchers)
|
||||||
|
end
|
||||||
def fan_users
|
|
||||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
def fan_users
|
||||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||||
@watchers_count = watchers.size
|
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||||
@watchers = paginate(watchers)
|
@watchers_count = watchers.size
|
||||||
end
|
@watchers = paginate(watchers)
|
||||||
|
end
|
||||||
def hovercard
|
|
||||||
end
|
def hovercard
|
||||||
|
end
|
||||||
def update
|
|
||||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
def update
|
||||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
@user.attributes = user_params.except(:image)
|
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||||
unless @user.save
|
@user.attributes = user_params.except(:image)
|
||||||
render_error(-1, @user.errors.full_messages.join(", "))
|
unless @user.save
|
||||||
end
|
render_error(-1, @user.errors.full_messages.join(", "))
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def update_image
|
|
||||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
def update_image
|
||||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
Util.write_file(@image, avatar_path(@user))
|
|
||||||
return render_ok({message: '头像修改成功'})
|
Util.write_file(@image, avatar_path(@user))
|
||||||
rescue Exception => e
|
return render_ok({message: '头像修改成功'})
|
||||||
uid_logger_error(e.message)
|
rescue Exception => e
|
||||||
render_error(-1, '头像修改失败!')
|
uid_logger_error(e.message)
|
||||||
end
|
render_error(-1, '头像修改失败!')
|
||||||
|
end
|
||||||
def get_image
|
|
||||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
def get_image
|
||||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||||
|
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
|
||||||
end
|
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||||
|
end
|
||||||
def me
|
|
||||||
@user = current_user
|
def me
|
||||||
end
|
@user = current_user
|
||||||
|
end
|
||||||
# 贴吧获取用户信接口
|
|
||||||
def get_user_info
|
# 贴吧获取用户信接口
|
||||||
begin
|
def get_user_info
|
||||||
@user = current_user
|
begin
|
||||||
begin
|
@user = current_user
|
||||||
result = Notice::Read::CountService.call(current_user.id)
|
begin
|
||||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
result = Notice::Read::CountService.call(current_user.id)
|
||||||
rescue
|
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||||
@message_unread_total = 0
|
rescue
|
||||||
end
|
@message_unread_total = 0
|
||||||
# TODO 等消息上线再打开注释
|
end
|
||||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
# TODO 等消息上线再打开注释
|
||||||
rescue Exception => e
|
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||||
uid_logger_error(e.message)
|
rescue Exception => e
|
||||||
missing_template
|
uid_logger_error(e.message)
|
||||||
end
|
missing_template
|
||||||
|
end
|
||||||
end
|
|
||||||
|
end
|
||||||
def attachment_show
|
|
||||||
file_name = params[:file_name]
|
def attachment_show
|
||||||
path = params[:path] || file_storage_directory
|
file_name = params[:file_name]
|
||||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
path = params[:path] || file_storage_directory
|
||||||
:type => 'game',
|
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||||
:disposition => 'attachment' #inline can open in browser
|
:type => 'game',
|
||||||
end
|
:disposition => 'attachment' #inline can open in browser
|
||||||
|
end
|
||||||
def html_show
|
|
||||||
@contents = File.read("#{params[:path]}")
|
def html_show
|
||||||
respond_to do |format|
|
@contents = File.read("#{params[:path]}")
|
||||||
format.html {render :layout => false}
|
respond_to do |format|
|
||||||
end
|
format.html {render :layout => false}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
# Redo: 消息总数缓存
|
|
||||||
def get_navigation_info
|
# Redo: 消息总数缓存
|
||||||
# @old_domain = edu_setting('old_edu_host')
|
def get_navigation_info
|
||||||
# @user = current_user
|
# @old_domain = edu_setting('old_edu_host')
|
||||||
# # 新消息数
|
# @user = current_user
|
||||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
# # 新消息数
|
||||||
#
|
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||||
# @user_url = "/users/#{@user.login}"
|
#
|
||||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
# @user_url = "/users/#{@user.login}"
|
||||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||||
end
|
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||||
|
end
|
||||||
# 用户回复功能
|
|
||||||
def reply_message
|
# 用户回复功能
|
||||||
message = JournalsForMessage.new(reply_message_params)
|
def reply_message
|
||||||
message.user_id = current_user.id
|
message = JournalsForMessage.new(reply_message_params)
|
||||||
message.save!
|
message.user_id = current_user.id
|
||||||
|
message.save!
|
||||||
render_ok(id: message.id)
|
|
||||||
end
|
render_ok(id: message.id)
|
||||||
|
end
|
||||||
# 搜索用户具有管理员角色的项目
|
|
||||||
def search_user_projects
|
# 搜索用户具有管理员角色的项目
|
||||||
projects = Project.where.not(status: 9)
|
def search_user_projects
|
||||||
|
projects = Project.where.not(status: 9)
|
||||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
|
||||||
projects = projects.where(members: { user_id: current_user.id })
|
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||||
|
projects = projects.where(members: { user_id: current_user.id })
|
||||||
search = params[:search].to_s.strip
|
|
||||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
search = params[:search].to_s.strip
|
||||||
|
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||||
@projects = projects.select(:id, :name)
|
|
||||||
end
|
@projects = projects.select(:id, :name)
|
||||||
|
end
|
||||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
|
||||||
def homepage_info
|
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||||
#待办事项,现在未做
|
def homepage_info
|
||||||
@undo_events = 10
|
#待办事项,现在未做
|
||||||
#用户的组织数量
|
@undo_events = 10
|
||||||
# @user_composes_count = @user.composes.size
|
#用户的组织数量
|
||||||
@user_composes_count = 10
|
# @user_composes_count = @user.composes.size
|
||||||
end
|
@user_composes_count = 10
|
||||||
|
end
|
||||||
def brief_introduction
|
|
||||||
content = params[:content].to_s.strip
|
def brief_introduction
|
||||||
|
content = params[:content].to_s.strip
|
||||||
current_user.user_extension.update!(brief_introduction: content)
|
|
||||||
|
current_user.user_extension.update!(brief_introduction: content)
|
||||||
render_ok
|
|
||||||
end
|
render_ok
|
||||||
|
end
|
||||||
def attendance
|
|
||||||
attendance = Users::AttendanceService.call(current_user)
|
def attendance
|
||||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
attendance = Users::AttendanceService.call(current_user)
|
||||||
rescue Users::AttendanceService::Error => ex
|
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||||
render_error(ex.message)
|
rescue Users::AttendanceService::Error => ex
|
||||||
end
|
render_error(ex.message)
|
||||||
|
end
|
||||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
|
||||||
def sync_token
|
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||||
return render_error('未找相关用户!') unless @user
|
def sync_token
|
||||||
|
return render_error('未找相关用户!') unless @user
|
||||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
|
||||||
token.update_column(:value, params[:token])
|
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||||
render_ok
|
token.update_column(:value, params[:token])
|
||||||
end
|
render_ok
|
||||||
|
end
|
||||||
def trustie_related_projects
|
|
||||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
def trustie_related_projects
|
||||||
projects_json = []
|
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||||
domain_url = EduSetting.get('host_name')
|
projects_json = []
|
||||||
if projects.present?
|
domain_url = EduSetting.get('host_name')
|
||||||
projects.each do |p|
|
if projects.present?
|
||||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
projects.each do |p|
|
||||||
pj = {
|
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||||
id: p.id,
|
pj = {
|
||||||
name: p.name,
|
id: p.id,
|
||||||
is_public: p.is_public,
|
name: p.name,
|
||||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
is_public: p.is_public,
|
||||||
status: p.status,
|
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||||
is_member: p.member?(current_user.try(:id)),
|
status: p.status,
|
||||||
owner: {
|
is_member: p.member?(current_user.try(:id)),
|
||||||
name: p.owner.try(:show_real_name),
|
owner: {
|
||||||
login: p.owner.login
|
name: p.owner.try(:show_real_name),
|
||||||
},
|
login: p.owner.login
|
||||||
members_count: p&.members.size,
|
},
|
||||||
issues_count: p.issues_count - p.pull_requests_count,
|
members_count: p&.members.size,
|
||||||
commits_count: p&.project_score&.changeset_num.to_i,
|
issues_count: p.issues_count - p.pull_requests_count,
|
||||||
http_url: domain_url + project_url,
|
commits_count: p&.project_score&.changeset_num.to_i,
|
||||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
http_url: domain_url + project_url,
|
||||||
http_issues_url: domain_url + project_url + "/issues",
|
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||||
http_commits_url: domain_url + project_url + "/commits",
|
http_issues_url: domain_url + project_url + "/issues",
|
||||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
http_commits_url: domain_url + project_url + "/commits",
|
||||||
}
|
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||||
projects_json.push(pj)
|
}
|
||||||
end
|
projects_json.push(pj)
|
||||||
end
|
end
|
||||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
end
|
||||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||||
end
|
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||||
|
end
|
||||||
def trustie_projects
|
|
||||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
def trustie_projects
|
||||||
projects = Project.visible
|
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||||
|
projects = Project.visible
|
||||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
|
||||||
|
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||||
search = params[:search].to_s.strip
|
|
||||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
search = params[:search].to_s.strip
|
||||||
|
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||||
projects = projects.select(:id, :name).limit(10).as_json
|
|
||||||
render json: { projects: projects }
|
projects = projects.select(:id, :name).limit(10).as_json
|
||||||
end
|
render json: { projects: projects }
|
||||||
|
end
|
||||||
def projects
|
|
||||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
def projects
|
||||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||||
@total_count = scope.size
|
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||||
@projects = paginate(scope)
|
@total_count = scope.size
|
||||||
end
|
@projects = paginate(scope)
|
||||||
|
end
|
||||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
|
||||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||||
def sync_gitea_pwd
|
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||||
return render_error("未找到相关的用户") if @user.blank?
|
def sync_gitea_pwd
|
||||||
|
return render_error("未找到相关的用户") if @user.blank?
|
||||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
|
||||||
flag ? render_ok : render_error('同步失败!')
|
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||||
end
|
flag ? render_ok : render_error('同步失败!')
|
||||||
|
end
|
||||||
# TODO
|
|
||||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
# TODO
|
||||||
def sync_salt
|
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||||
user = User.find_by_login params[:login]
|
def sync_salt
|
||||||
return if user.blank?
|
user = User.find_by_login params[:login]
|
||||||
user.update_column(:salt, params[:salt])
|
return if user.blank?
|
||||||
render_ok
|
user.update_column(:salt, params[:salt])
|
||||||
end
|
render_ok
|
||||||
|
end
|
||||||
def sync_user_info
|
|
||||||
user = User.find_by_login params[:login]
|
def sync_user_info
|
||||||
return render_forbidden unless user === current_user
|
user = User.find_by_login params[:login]
|
||||||
|
return render_forbidden unless user === current_user
|
||||||
sync_params = {
|
|
||||||
email: params[:email],
|
sync_params = {
|
||||||
password: params[:password]
|
email: params[:email],
|
||||||
}
|
password: params[:password]
|
||||||
|
}
|
||||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
|
||||||
|
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
|
||||||
if interactor.success?
|
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
if interactor.success?
|
||||||
render_ok
|
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
||||||
else
|
render_ok
|
||||||
render_error(interactor.error)
|
else
|
||||||
end
|
render_error(interactor.error)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
private
|
|
||||||
def load_user
|
def email_search
|
||||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
return render_error('请输入email') if params[:email].blank?
|
||||||
end
|
@user = User.find_by(mail: params[:email])
|
||||||
|
end
|
||||||
def user_params
|
|
||||||
params.require(:user).permit(:nickname, :image,
|
private
|
||||||
user_extension_attributes: [
|
def load_user
|
||||||
:gender, :location, :location_city,
|
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||||
:occupation, :technical_title,
|
end
|
||||||
:school_id, :department_id, :province, :city,
|
|
||||||
:custom_department, :identity, :student_id, :description,
|
def user_params
|
||||||
:show_super_description, :super_description,
|
params.require(:user).permit(:nickname, :image,
|
||||||
:show_email, :show_location, :show_department]
|
user_extension_attributes: [
|
||||||
)
|
:gender, :location, :location_city,
|
||||||
end
|
:occupation, :technical_title,
|
||||||
|
:school_id, :department_id, :province, :city,
|
||||||
def reply_message_params
|
:custom_department, :identity, :student_id, :description,
|
||||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
:show_super_description, :super_description,
|
||||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
:show_email, :show_location, :show_department]
|
||||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_user_exist
|
def reply_message_params
|
||||||
return if @user.present?
|
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||||
render_not_found
|
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||||
end
|
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||||
|
end
|
||||||
end
|
|
||||||
|
def check_user_exist
|
||||||
|
return if @user.present?
|
||||||
|
render_not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
def sso_login
|
||||||
|
if params[:login].present? && !current_user.logged? && params[:websiteName].present?
|
||||||
|
user = User.where("login = ?", "#{params[:login].presence}").first
|
||||||
|
# 已同步注册,直接登录
|
||||||
|
if user.present?
|
||||||
|
successful_authentication(user)
|
||||||
|
else
|
||||||
|
autologin_register_by_educoder(params[:login].presence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 通过login参数查询头歌账号信息,注册并登录
|
||||||
|
def autologin_register_by_educoder(edu_login)
|
||||||
|
req_params = { "login" => "#{edu_login}", "private_token" => "hriEn3UwXfJs3PmyXnSH" }
|
||||||
|
api_url= "https://data.educoder.net"
|
||||||
|
client = Faraday.new(url: api_url)
|
||||||
|
response = client.public_send("get", "/api/sources/get_user_info_by_login", req_params)
|
||||||
|
result = JSON.parse(response.body)
|
||||||
|
#查询
|
||||||
|
return nil if result["status"].to_s != "0"
|
||||||
|
|
||||||
|
# login 邮箱 手机号 姓名 学校/单位
|
||||||
|
user_info = result["data"]
|
||||||
|
Rails.logger.info("user_info====== #{user_info}")
|
||||||
|
login = user_info["login"]
|
||||||
|
email = user_info["mail"]
|
||||||
|
phone = user_info["phone"]
|
||||||
|
real_name = user_info["username"]
|
||||||
|
department_name = user_info["school"]
|
||||||
|
password = "12345678"
|
||||||
|
|
||||||
|
# 没有用户时,新建用户并登录
|
||||||
|
user = User.where("login = ? or phone = ? or mail = ? ", "#{login}", phone, email).first
|
||||||
|
if user.present?
|
||||||
|
# 手机号先记录,后续用
|
||||||
|
user.update_column(:phone, "#{phone}") if phone.present?
|
||||||
|
else
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
email = "#{login}@gitlink.org.cn" if email.blank?
|
||||||
|
user_params = { status: 1, type: 'User', login: "#{login}", lastname: "#{real_name}", mail: "#{email}",
|
||||||
|
nickname: "#{real_name}", professional_certification: 0, certification: 0, grade: 0,
|
||||||
|
password: "#{password}", phone: "#{phone}", profile_completed: 1 }
|
||||||
|
user = User.create!(user_params)
|
||||||
|
UserExtension.create!(user_id: user.id, gender: 1, custom_department: "#{department_name}")
|
||||||
|
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: password})
|
||||||
|
if interactor.success?
|
||||||
|
gitea_user = interactor.result
|
||||||
|
Rails.logger.info("Gitea::RegisterInteractor.call result====== #{gitea_user}")
|
||||||
|
result = Gitea::User::GenerateTokenService.call(login, password)
|
||||||
|
user.gitea_token = result['sha1']
|
||||||
|
user.gitea_uid = gitea_user[:body]['id']
|
||||||
|
user.save!
|
||||||
|
else
|
||||||
|
Rails.logger.info("Gitea::RegisterInteractor.call error====== #{interactor.error}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
successful_authentication(user) if user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -16,6 +16,7 @@ includes:
|
||||||
- users
|
- users
|
||||||
- projects
|
- projects
|
||||||
- repositories
|
- repositories
|
||||||
|
- traces
|
||||||
- pulls
|
- pulls
|
||||||
- issues
|
- issues
|
||||||
- organizations
|
- organizations
|
||||||
|
|
|
@ -280,7 +280,7 @@ repo |是| |string |项目标识identifier
|
||||||
### 返回字段说明
|
### 返回字段说明
|
||||||
参数 | 类型 | 字段说明
|
参数 | 类型 | 字段说明
|
||||||
--------- | ----------- | -----------
|
--------- | ----------- | -----------
|
||||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,services:服务,activity:动态,setting:仓库设置
|
||||||
|
|
||||||
|
|
||||||
> 返回的JSON示例:
|
> 返回的JSON示例:
|
||||||
|
@ -408,7 +408,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
|
||||||
### 请求参数
|
### 请求参数
|
||||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
--------- | ------- | ------- | -------- | ----------
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,resources:资源库,services:服务 |
|
||||||
|
|
||||||
|
|
||||||
### 返回字段说明:
|
### 返回字段说明:
|
||||||
|
@ -849,4 +849,36 @@ await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.j
|
||||||
"created_at": "2021-04-26 09:54",
|
"created_at": "2021-04-26 09:54",
|
||||||
"time_ago": "1分钟前"
|
"time_ago": "1分钟前"
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 退出项目
|
||||||
|
供项目成员(开发者、报告者)退出项目用
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/quit.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/:owner/:repo/quit.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/:owner/:repo/quit.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
|owner |是| |string |用户登录名 |
|
||||||
|
|repo |是| |string |项目标识identifier |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
```
|
```
|
|
@ -0,0 +1,217 @@
|
||||||
|
# Traces
|
||||||
|
|
||||||
|
## 代码溯源初始化
|
||||||
|
用户同意协议后请求的接口,创建代码溯源的账号
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST \
|
||||||
|
http://localhost:3000/api/traces/trace_users.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/traces/trace_users.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST api/traces/trace_users.json`
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 代码分析结果列表
|
||||||
|
查询项目下代码分析的结果
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/task_results.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/traces/:owner/:repo/task_results.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET api/traces/:owner/:repo/task_results.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
owner|是|否|string | 项目所有者标识|
|
||||||
|
repo|是 | 否|string | 项目标识 |
|
||||||
|
page |否| 1 | int | 页码 |
|
||||||
|
limit |否| 15 | int | 每页数量 |
|
||||||
|
|
||||||
|
### 返回字段说明(暂缺)
|
||||||
|
<!-- 参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
total_count |int |总数 |
|
||||||
|
public_keys.id |int |ID|
|
||||||
|
public_keys.name |string|密钥标题|
|
||||||
|
public_keys.content |string|密钥内容|
|
||||||
|
public_keys.fingerprint |string|密钥标识|
|
||||||
|
public_keys.created_time |string|密钥创建时间| -->
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"accuracy": "20",
|
||||||
|
"code_type": "C",
|
||||||
|
"depth": "2",
|
||||||
|
"detect_flag": "快速-组件级",
|
||||||
|
"detect_rule": "快速-组件级,2,20,,开源软件,50,10",
|
||||||
|
"detect_startdate": "2022-05-10 15:59:46 ",
|
||||||
|
"detect_status": "fail",
|
||||||
|
"detectflag": "快速-组件级",
|
||||||
|
"fail_reason": "Invalid package type",
|
||||||
|
"file_name": "many_branch.zip",
|
||||||
|
"license_process": "100",
|
||||||
|
"licenseparam": "开源软件",
|
||||||
|
"package_type": "",
|
||||||
|
"product_name": "84727546110",
|
||||||
|
"project_id": "6dbc3e42-5857-4ca4-a54d-58fd9dbf6dc5",
|
||||||
|
"sim_process": "100",
|
||||||
|
"similarity_process": "2",
|
||||||
|
"task_id": "15139171-091b-4316-98b1-6068970efa44",
|
||||||
|
"totalsize": 5,
|
||||||
|
"uid": "78",
|
||||||
|
"vuln_process": "",
|
||||||
|
"vulnlevel": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 新建分析
|
||||||
|
用户选择仓库分支进行代码分析的接口
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST \
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/tasks.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('POST /api/traces/:owner/:repo/tasks.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST api/traces/:owner/:repo/tasks.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
owner |是 | 否 | string | 项目所有者标识 |
|
||||||
|
repo |是 | 否 | string | 项目标识 |
|
||||||
|
branch_name|是 | 否| string | 分支名称 |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
## 重新扫描
|
||||||
|
对代码分析结果进行再次分析
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/reload_task.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/traces/:owner/:repo/reload_task.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET api/traces/:owner/:repo/reload_task.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
owner |是 | 否 | string | 项目所有者标识 |
|
||||||
|
repo |是 | 否 | string | 项目标识 |
|
||||||
|
project_id|是 | 否| string | 代码分析结果里的project_id |
|
||||||
|
branch_name|是 | 否| string | 分支名称 |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
|
||||||
|
## 下载报告
|
||||||
|
把代码分析的结果下载到本地
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X GET \
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/task_pdf.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/traces/:owner/:repo/task_pdf.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`GET api/traces/:owner/:repo/task_pdf.json`
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||||
|
--------- | ------- | ------- | -------- | ----------
|
||||||
|
owner |是 | 否 | string | 项目所有者标识 |
|
||||||
|
repo |是 | 否 | string | 项目标识 |
|
||||||
|
task_id|是 | 否| string | 代码分析结果里的task_id |
|
||||||
|
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
|
@ -4,7 +4,7 @@ class Gitea::User::UpdateForm
|
||||||
|
|
||||||
attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local,
|
attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local,
|
||||||
:full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login,
|
:full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login,
|
||||||
:source_id, :website
|
:source_id, :website, :new_name
|
||||||
|
|
||||||
validates :username, presence: true
|
validates :username, presence: true
|
||||||
validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true }
|
validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true }
|
||||||
|
|
|
@ -3,28 +3,40 @@ module Register
|
||||||
include ActiveModel::Model
|
include ActiveModel::Model
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_login(login)
|
def check_login(login, user=nil)
|
||||||
login = strip(login)
|
login = strip(login)
|
||||||
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
||||||
|
|
||||||
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
||||||
raise LoginError, '登录名已被使用' if login_exist
|
if user.present?
|
||||||
|
raise LoginError, '登录名已被使用' if login_exist && login != user&.login
|
||||||
|
else
|
||||||
|
raise LoginError, '登录名已被使用' if login_exist
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_mail(mail)
|
def check_mail(mail, user=nil)
|
||||||
mail = strip(mail)
|
mail = strip(mail)
|
||||||
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
||||||
|
|
||||||
mail_exist = Owner.exists?(mail: mail)
|
mail_exist = Owner.exists?(mail: mail)
|
||||||
raise EmailError, '邮箱已被使用' if mail_exist
|
if user.present?
|
||||||
|
raise EmailError, '邮箱已被使用' if mail_exist && mail != user&.mail
|
||||||
|
else
|
||||||
|
raise EmailError, '邮箱已被使用' if mail_exist
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_phone(phone)
|
def check_phone(phone, user=nil)
|
||||||
phone = strip(phone)
|
phone = strip(phone)
|
||||||
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
||||||
|
|
||||||
phone_exist = Owner.exists?(phone: phone)
|
phone_exist = Owner.exists?(phone: phone)
|
||||||
raise PhoneError, '手机号已被使用' if phone_exist
|
if user.present?
|
||||||
|
raise PhoneError, '手机号已被使用' if phone_exist && phone != user&.phone
|
||||||
|
else
|
||||||
|
raise PhoneError, '手机号已被使用' if phone_exist
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Register
|
||||||
|
class LoginCheckColumnsForm < Register::BaseForm
|
||||||
|
attr_accessor :type, :value, :user
|
||||||
|
|
||||||
|
validates :type, presence: true, numericality: true
|
||||||
|
validates :value, presence: true
|
||||||
|
validate :check!
|
||||||
|
|
||||||
|
def check!
|
||||||
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
|
case strip(type).to_i
|
||||||
|
when 1 then check_login(strip(value), user)
|
||||||
|
when 2 then check_mail(strip(value), user)
|
||||||
|
when 3 then check_phone(strip(value), user)
|
||||||
|
else raise("type值无效")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,486 +1,486 @@
|
||||||
# 所有的方法请按首字母的顺序依次列出
|
# 所有的方法请按首字母的顺序依次列出
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
include Gitlink::I18n
|
include Gitlink::I18n
|
||||||
include GitHelper
|
include GitHelper
|
||||||
|
|
||||||
ONE_MINUTE = 60 * 1000
|
ONE_MINUTE = 60 * 1000
|
||||||
ONE_HOUR = 60 * ONE_MINUTE
|
ONE_HOUR = 60 * ONE_MINUTE
|
||||||
ONE_DAY = 24 * ONE_HOUR
|
ONE_DAY = 24 * ONE_HOUR
|
||||||
ONE_MONTH = 30 * ONE_DAY
|
ONE_MONTH = 30 * ONE_DAY
|
||||||
|
|
||||||
ONE_YEAR = 12 * ONE_MONTH
|
ONE_YEAR = 12 * ONE_MONTH
|
||||||
|
|
||||||
# 全局参数配置
|
# 全局参数配置
|
||||||
def edu_setting name
|
def edu_setting name
|
||||||
EduSetting.get(name)
|
EduSetting.get(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# xss共计问题
|
# xss共计问题
|
||||||
def content_safe content
|
def content_safe content
|
||||||
tags = %w(
|
tags = %w(
|
||||||
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
||||||
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
||||||
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
||||||
tfoot th thead time tr u ul var wbr div span
|
tfoot th thead time tr u ul var wbr div span
|
||||||
)
|
)
|
||||||
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
||||||
sanitize content, tags: tags, attributes: attributes
|
sanitize content, tags: tags, attributes: attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
def graduation_navigation graduation
|
def graduation_navigation graduation
|
||||||
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
||||||
end
|
end
|
||||||
|
|
||||||
def graduation_navigation_id course
|
def graduation_navigation_id course
|
||||||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
# git用户
|
# git用户
|
||||||
# git用户命名规则:login+"@educoder.net"
|
# git用户命名规则:login+"@educoder.net"
|
||||||
def git_username(email)
|
def git_username(email)
|
||||||
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 不同的类型扩展不同的目录
|
# 不同的类型扩展不同的目录
|
||||||
def relative_path
|
def relative_path
|
||||||
"avatars"
|
"avatars"
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace_bytes_to_b(size_string)
|
def replace_bytes_to_b(size_string)
|
||||||
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
||||||
end
|
end
|
||||||
|
|
||||||
def storage_path
|
def storage_path
|
||||||
File.join(Rails.root, "public", "images", relative_path)
|
File.join(Rails.root, "public", "images", relative_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 推荐实训
|
# 推荐实训
|
||||||
def recommend_shixun(shixun)
|
def recommend_shixun(shixun)
|
||||||
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
||||||
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
||||||
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
||||||
|
|
||||||
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
||||||
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
||||||
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# shixun开启挑战对应的行为名及url
|
# shixun开启挑战对应的行为名及url
|
||||||
def task_operation_url current_myshixun, shixun
|
def task_operation_url current_myshixun, shixun
|
||||||
if current_myshixun.blank?
|
if current_myshixun.blank?
|
||||||
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
||||||
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
||||||
else
|
else
|
||||||
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
||||||
if current_myshixun.status == 1
|
if current_myshixun.status == 1
|
||||||
name = "查看实战"
|
name = "查看实战"
|
||||||
else
|
else
|
||||||
name = "继续挑战"
|
name = "继续挑战"
|
||||||
end
|
end
|
||||||
url = identifier
|
url = identifier
|
||||||
end
|
end
|
||||||
[name, url]
|
[name, url]
|
||||||
end
|
end
|
||||||
|
|
||||||
# 获取当前时间
|
# 获取当前时间
|
||||||
def time_from_now(time)
|
def time_from_now(time)
|
||||||
if String === time
|
if String === time
|
||||||
time = Time.parse(time)
|
time = Time.parse(time)
|
||||||
end
|
end
|
||||||
|
|
||||||
lastUpdateTime = time.to_i*1000
|
lastUpdateTime = time.to_i*1000
|
||||||
|
|
||||||
currentTime = Time.now.to_i*1000
|
currentTime = Time.now.to_i*1000
|
||||||
timePassed = currentTime - lastUpdateTime
|
timePassed = currentTime - lastUpdateTime
|
||||||
timeIntoFormat = 0
|
timeIntoFormat = 0
|
||||||
updateAtValue = ""
|
updateAtValue = ""
|
||||||
if timePassed < 0
|
if timePassed < 0
|
||||||
updateAtValue = "刚刚"
|
updateAtValue = "刚刚"
|
||||||
elsif timePassed < ONE_MINUTE
|
elsif timePassed < ONE_MINUTE
|
||||||
updateAtValue = "1分钟前"
|
updateAtValue = "1分钟前"
|
||||||
elsif timePassed < ONE_HOUR
|
elsif timePassed < ONE_HOUR
|
||||||
timeIntoFormat = timePassed / ONE_MINUTE
|
timeIntoFormat = timePassed / ONE_MINUTE
|
||||||
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
||||||
elsif (timePassed < ONE_DAY)
|
elsif (timePassed < ONE_DAY)
|
||||||
timeIntoFormat = timePassed / ONE_HOUR
|
timeIntoFormat = (timePassed.to_f / ONE_HOUR).ceil
|
||||||
updateAtValue = timeIntoFormat.to_s + "小时前"
|
updateAtValue = timeIntoFormat.to_s + "小时前"
|
||||||
elsif (timePassed < ONE_MONTH)
|
elsif (timePassed < ONE_MONTH)
|
||||||
timeIntoFormat = timePassed / ONE_DAY
|
timeIntoFormat = (timePassed.to_f / ONE_DAY).ceil
|
||||||
updateAtValue = timeIntoFormat.to_s + "天前"
|
updateAtValue = timeIntoFormat.to_s + "天前"
|
||||||
elsif (timePassed < ONE_YEAR)
|
elsif (timePassed < ONE_YEAR)
|
||||||
timeIntoFormat = timePassed / ONE_MONTH
|
timeIntoFormat = (timePassed.to_f / ONE_MONTH).ceil
|
||||||
updateAtValue = timeIntoFormat.to_s + "个月前"
|
updateAtValue = timeIntoFormat.to_s + "个月前"
|
||||||
else
|
else
|
||||||
timeIntoFormat = timePassed / ONE_YEAR
|
timeIntoFormat = timePassed / ONE_YEAR
|
||||||
updateAtValue = timeIntoFormat.to_s + "年前"
|
updateAtValue = timeIntoFormat.to_s + "年前"
|
||||||
end
|
end
|
||||||
updateAtValue
|
updateAtValue
|
||||||
end
|
end
|
||||||
|
|
||||||
# 计算到结束还有多长时间 **天**小时**分
|
# 计算到结束还有多长时间 **天**小时**分
|
||||||
def how_much_time(time)
|
def how_much_time(time)
|
||||||
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
||||||
''
|
''
|
||||||
else
|
else
|
||||||
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
||||||
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
||||||
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_time(time)
|
def format_time(time)
|
||||||
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
||||||
end
|
end
|
||||||
|
|
||||||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||||
def url_to_avatar(source)
|
def url_to_avatar(source)
|
||||||
if File.exist?(disk_filename(source&.class, source&.id))
|
if File.exist?(disk_filename(source&.class, source&.id))
|
||||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||||
if %w(User Organization).include?(source.class.to_s)
|
if %w(User Organization).include?(source.class.to_s)
|
||||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||||
else
|
else
|
||||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||||
end
|
end
|
||||||
elsif source.class.to_s == 'User'
|
elsif source.class.to_s == 'User'
|
||||||
source.get_letter_avatar_url
|
source.get_letter_avatar_url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def url_to_avatar_with_platform_url(source)
|
def url_to_avatar_with_platform_url(source)
|
||||||
platform_url = Rails.application.config_for(:configuration)['platform_url']
|
platform_url = Rails.application.config_for(:configuration)['platform_url']
|
||||||
if platform_url
|
if platform_url
|
||||||
return Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(source).to_s
|
return Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(source).to_s
|
||||||
else
|
else
|
||||||
return url_to_avatar(source).to_s
|
return url_to_avatar(source).to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 主页banner图
|
# 主页banner图
|
||||||
def banner_img(source_type)
|
def banner_img(source_type)
|
||||||
if File.exist?(disk_filename(source_type, "banner"))
|
if File.exist?(disk_filename(source_type, "banner"))
|
||||||
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
||||||
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def disk_filename(source_type,source_id,image_file=nil)
|
def disk_filename(source_type,source_id,image_file=nil)
|
||||||
File.join(storage_path, "#{source_type}", "#{source_id}")
|
File.join(storage_path, "#{source_type}", "#{source_id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def disk_auth_filename(source_type, source_id, type)
|
def disk_auth_filename(source_type, source_id, type)
|
||||||
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def disk_real_name_auth_filename(source_id)
|
def disk_real_name_auth_filename(source_id)
|
||||||
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
||||||
end
|
end
|
||||||
|
|
||||||
def auth_file_url(source_type, source_id, type)
|
def auth_file_url(source_type, source_id, type)
|
||||||
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def real_name_auth_file_url(source_id)
|
def real_name_auth_file_url(source_id)
|
||||||
auth_file_url('UserAuthentication', source_id, 'ID')
|
auth_file_url('UserAuthentication', source_id, 'ID')
|
||||||
end
|
end
|
||||||
|
|
||||||
def disk_professional_auth_filename(source_id)
|
def disk_professional_auth_filename(source_id)
|
||||||
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
||||||
end
|
end
|
||||||
|
|
||||||
def professional_auth_file_url(source_id)
|
def professional_auth_file_url(source_id)
|
||||||
auth_file_url('UserAuthentication', source_id, 'PRO')
|
auth_file_url('UserAuthentication', source_id, 'PRO')
|
||||||
end
|
end
|
||||||
|
|
||||||
def shixun_url_to_avatar(shixun)
|
def shixun_url_to_avatar(shixun)
|
||||||
if File.exist?(disk_filename(shixun.class, shixun.id))
|
if File.exist?(disk_filename(shixun.class, shixun.id))
|
||||||
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
||||||
else
|
else
|
||||||
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 选用实训的学校情况
|
# 选用实训的学校情况
|
||||||
def school_user_detail shixun
|
def school_user_detail shixun
|
||||||
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
||||||
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
||||||
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
||||||
school_size = school_ids.size
|
school_size = school_ids.size
|
||||||
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
||||||
end
|
end
|
||||||
|
|
||||||
# 普通/分组 作业作品状态数组
|
# 普通/分组 作业作品状态数组
|
||||||
def student_work_status homework, user_id, course, work
|
def student_work_status homework, user_id, course, work
|
||||||
status = []
|
status = []
|
||||||
homework_setting = homework.homework_group_setting user_id, true
|
homework_setting = homework.homework_group_setting user_id, true
|
||||||
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
||||||
late_time = homework.late_time || course.end_date
|
late_time = homework.late_time || course.end_date
|
||||||
|
|
||||||
if course.is_end && work && work.work_status > 0
|
if course.is_end && work && work.work_status > 0
|
||||||
status << "查看作品"
|
status << "查看作品"
|
||||||
elsif !course.is_end
|
elsif !course.is_end
|
||||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
||||||
# 作业未截止时
|
# 作业未截止时
|
||||||
if homework_setting.end_time > Time.now
|
if homework_setting.end_time > Time.now
|
||||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||||
if work.project_id.nil? || work.project_id == 0
|
if work.project_id.nil? || work.project_id == 0
|
||||||
status << "创建项目"
|
status << "创建项目"
|
||||||
status << "关联项目"
|
status << "关联项目"
|
||||||
elsif work.work_status == 0
|
elsif work.work_status == 0
|
||||||
status << "取消关联"
|
status << "取消关联"
|
||||||
status << "提交作品"
|
status << "提交作品"
|
||||||
else
|
else
|
||||||
status << "修改作品"
|
status << "修改作品"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if work.work_status == 0
|
if work.work_status == 0
|
||||||
status << "提交作品"
|
status << "提交作品"
|
||||||
else
|
else
|
||||||
status << "修改作品"
|
status << "修改作品"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 补交阶段
|
# 补交阶段
|
||||||
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
||||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||||
if work.project_id.nil? || work.project_id == 0
|
if work.project_id.nil? || work.project_id == 0
|
||||||
status << "创建项目"
|
status << "创建项目"
|
||||||
status << "关联项目"
|
status << "关联项目"
|
||||||
elsif work.work_status == 0
|
elsif work.work_status == 0
|
||||||
status << "取消关联"
|
status << "取消关联"
|
||||||
status << "补交作品"
|
status << "补交作品"
|
||||||
else
|
else
|
||||||
status << "补交附件"
|
status << "补交附件"
|
||||||
status << "查看作品"
|
status << "查看作品"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if work.work_status == 0
|
if work.work_status == 0
|
||||||
status << "补交作品"
|
status << "补交作品"
|
||||||
else
|
else
|
||||||
status << "补交附件"
|
status << "补交附件"
|
||||||
status << "查看作品"
|
status << "查看作品"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 匿评阶段
|
# 匿评阶段
|
||||||
elsif work.work_status != 0
|
elsif work.work_status != 0
|
||||||
if homework.homework_detail_manual.comment_status == 3
|
if homework.homework_detail_manual.comment_status == 3
|
||||||
work_ids = homework.student_works.has_committed.pluck(:id)
|
work_ids = homework.student_works.has_committed.pluck(:id)
|
||||||
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
||||||
status << "匿评作品"
|
status << "匿评作品"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
status << "查看作品"
|
status << "查看作品"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit_des_status work, homework
|
def commit_des_status work, homework
|
||||||
status = []
|
status = []
|
||||||
homework_setting = homework.homework_group_setting work.user_id
|
homework_setting = homework.homework_group_setting work.user_id
|
||||||
|
|
||||||
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
||||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
||||||
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
||||||
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
||||||
work.description.present? ? status << "修改总结" : status << "提交总结"
|
work.description.present? ? status << "修改总结" : status << "提交总结"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_url attachment,options={}
|
def download_url attachment,options={}
|
||||||
attachment_path(attachment,options)
|
attachment_path(attachment,options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 耗时:天、小时、分、秒
|
# 耗时:天、小时、分、秒
|
||||||
# 小于1分钟则不显示
|
# 小于1分钟则不显示
|
||||||
def game_spend_time time
|
def game_spend_time time
|
||||||
day = time / 86400
|
day = time / 86400
|
||||||
hour = time % (24*60*60) / (60*60)
|
hour = time % (24*60*60) / (60*60)
|
||||||
min = time % (24*60*60) % (60*60) / 60
|
min = time % (24*60*60) % (60*60) / 60
|
||||||
sec = time % (24*60*60) % (60*60) % 60
|
sec = time % (24*60*60) % (60*60) % 60
|
||||||
if day < 1
|
if day < 1
|
||||||
if hour < 1
|
if hour < 1
|
||||||
if min < 1
|
if min < 1
|
||||||
if sec < 1
|
if sec < 1
|
||||||
time = "--"
|
time = "--"
|
||||||
else
|
else
|
||||||
time = "#{sec}秒"
|
time = "#{sec}秒"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
time = "#{min}分钟 #{sec}秒"
|
time = "#{min}分钟 #{sec}秒"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
||||||
end
|
end
|
||||||
return time
|
return time
|
||||||
end
|
end
|
||||||
|
|
||||||
def absolute_path(file_path)
|
def absolute_path(file_path)
|
||||||
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_root_directory
|
def file_root_directory
|
||||||
Rails.root.to_s
|
Rails.root.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_storage_directory
|
def file_storage_directory
|
||||||
file_root_directory + edu_setting('attachment_folder')
|
file_root_directory + edu_setting('attachment_folder')
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_path(file)
|
def local_path(file)
|
||||||
File.join(file.disk_directory, file.disk_filename)
|
File.join(file.disk_directory, file.disk_filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_downloads(file)
|
def update_downloads(file)
|
||||||
file.update_attributes(:downloads => file.downloads + 1)
|
file.update_attributes(:downloads => file.downloads + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 项目信息,
|
# 项目信息,
|
||||||
def project_info work, current_user, course_identity
|
def project_info work, current_user, course_identity
|
||||||
project = work.project
|
project = work.project
|
||||||
if project
|
if project
|
||||||
if project.status == 9
|
if project.status == 9
|
||||||
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
||||||
else
|
else
|
||||||
project_score = project.project_score
|
project_score = project.project_score
|
||||||
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
||||||
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
||||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||||
else
|
else
|
||||||
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
||||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{id: -1, name: "--", title: "--"}
|
{id: -1, name: "--", title: "--"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def message_content(content)
|
def message_content(content)
|
||||||
content = (strip_html content).strip
|
content = (strip_html content).strip
|
||||||
content = content.gsub(/\s+/, " ")
|
content = content.gsub(/\s+/, " ")
|
||||||
if content.gsub(" ", "") == ""
|
if content.gsub(" ", "") == ""
|
||||||
content = "[非文本消息]"
|
content = "[非文本消息]"
|
||||||
end
|
end
|
||||||
content
|
content
|
||||||
end
|
end
|
||||||
|
|
||||||
def strip_html(text, len=0, endss="...")
|
def strip_html(text, len=0, endss="...")
|
||||||
ss = ""
|
ss = ""
|
||||||
if !text.nil? && text.length>0
|
if !text.nil? && text.length>0
|
||||||
ss=text.gsub(/<\/?.*?>/, '').strip
|
ss=text.gsub(/<\/?.*?>/, '').strip
|
||||||
ss = ss.gsub(/ */, '')
|
ss = ss.gsub(/ */, '')
|
||||||
ss = ss.gsub(/\r\n/,'') #新增
|
ss = ss.gsub(/\r\n/,'') #新增
|
||||||
ss = ss.gsub(/\n/,'') #新增
|
ss = ss.gsub(/\n/,'') #新增
|
||||||
if len > 0 && ss.length > len
|
if len > 0 && ss.length > len
|
||||||
ss = ss[0, len] + endss
|
ss = ss[0, len] + endss
|
||||||
elsif len > 0 && ss.length <= len
|
elsif len > 0 && ss.length <= len
|
||||||
ss = ss
|
ss = ss
|
||||||
#ss = truncate(ss, :length => len)
|
#ss = truncate(ss, :length => len)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ss
|
ss
|
||||||
end
|
end
|
||||||
|
|
||||||
def strip_export_title(content)
|
def strip_export_title(content)
|
||||||
con_ = ""
|
con_ = ""
|
||||||
if content.length > 0
|
if content.length > 0
|
||||||
con_ = strip_tags(content)
|
con_ = strip_tags(content)
|
||||||
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
||||||
end
|
end
|
||||||
con_
|
con_
|
||||||
end
|
end
|
||||||
|
|
||||||
def pdf_load_sources(*arg)
|
def pdf_load_sources(*arg)
|
||||||
arr = arg.map do |path|
|
arr = arg.map do |path|
|
||||||
content_tag(:script) do
|
content_tag(:script) do
|
||||||
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raw arr.join('')
|
raw arr.join('')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 导出pdf时,转化markdown为html
|
# 导出pdf时,转化markdown为html
|
||||||
def to_markdown(text,origin_url)
|
def to_markdown(text,origin_url)
|
||||||
return nil if text.blank?
|
return nil if text.blank?
|
||||||
options = {
|
options = {
|
||||||
:autolink => true,
|
:autolink => true,
|
||||||
:no_intra_emphasis => true,
|
:no_intra_emphasis => true,
|
||||||
:fenced_code_blocks => true,
|
:fenced_code_blocks => true,
|
||||||
:lax_html_blocks => true,
|
:lax_html_blocks => true,
|
||||||
:strikethrough => true,
|
:strikethrough => true,
|
||||||
:superscript => false,
|
:superscript => false,
|
||||||
:tables => true
|
:tables => true
|
||||||
}
|
}
|
||||||
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
||||||
m_t = markdown.render(text)
|
m_t = markdown.render(text)
|
||||||
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
||||||
end
|
end
|
||||||
|
|
||||||
def shixun_status_class(shixun)
|
def shixun_status_class(shixun)
|
||||||
case shixun.status
|
case shixun.status
|
||||||
when 0 then 'text-info'
|
when 0 then 'text-info'
|
||||||
when 1 then 'text-warning'
|
when 1 then 'text-warning'
|
||||||
when 2 then 'text-success'
|
when 2 then 'text-success'
|
||||||
when 3 then 'text-secondary'
|
when 3 then 'text-secondary'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_unix_time(date)
|
def render_unix_time(date)
|
||||||
date.to_time.to_i
|
date.to_time.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_user_by_login(login)
|
def find_user_by_login(login)
|
||||||
User.find_by_login login
|
User.find_by_login login
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_user_by_login_and_mail(login, mail)
|
def find_user_by_login_and_mail(login, mail)
|
||||||
User.find_by(login: login, mail: mail)
|
User.find_by(login: login, mail: mail)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_user_by_gitea_uid(gitea_uid)
|
def find_user_by_gitea_uid(gitea_uid)
|
||||||
User.find_by(gitea_uid: gitea_uid)
|
User.find_by(gitea_uid: gitea_uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_user_in_redis_cache(login, email)
|
def find_user_in_redis_cache(login, email)
|
||||||
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_user_in_redis_cache_by_id(id)
|
def find_user_in_redis_cache_by_id(id)
|
||||||
$redis_cache.hgetall("v2-owner-common:#{id}")
|
$redis_cache.hgetall("v2-owner-common:#{id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_base64_decoded(str)
|
def render_base64_decoded(str)
|
||||||
return nil if str.blank?
|
return nil if str.blank?
|
||||||
Base64.decode64 str
|
Base64.decode64 str
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_admin_statistics_item
|
def render_admin_statistics_item
|
||||||
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
||||||
|
|
||||||
return if url.blank?
|
return if url.blank?
|
||||||
content_tag(:li) do
|
content_tag(:li) do
|
||||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 1 手机类型;0 邮箱类型
|
# 1 手机类型;0 邮箱类型
|
||||||
# 注意新版的login是自动名生成的
|
# 注意新版的login是自动名生成的
|
||||||
def phone_mail_type value
|
def phone_mail_type value
|
||||||
value =~ /^1\d{10}$/ ? 1 : 0
|
value =~ /^1\d{10}$/ ? 1 : 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def strip(str)
|
def strip(str)
|
||||||
str.to_s.strip.presence
|
str.to_s.strip.presence
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,169 +1,218 @@
|
||||||
module RepositoriesHelper
|
module RepositoriesHelper
|
||||||
def render_permission(user, project)
|
def render_permission(user, project)
|
||||||
return "Admin" if user&.admin?
|
return "Admin" if user&.admin?
|
||||||
project.get_premission(user)
|
project.get_premission(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_decode64_content(str)
|
def render_decode64_content(str)
|
||||||
return nil if str.blank?
|
return nil if str.blank?
|
||||||
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_type(str)
|
def download_type(str)
|
||||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||||
default_type.include?(str&.downcase) || str.blank?
|
default_type.include?(str&.downcase) || str.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_type?(str)
|
def image_type?(str)
|
||||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||||
default_type.include?(str&.downcase)
|
default_type.include?(str&.downcase)
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_readme?(type, str)
|
def is_readme?(type, str)
|
||||||
return false if type != 'file' || str.blank?
|
return false if type != 'file' || str.blank?
|
||||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||||
readme_types.include?(str.to_s.downcase)
|
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_commit_author(author_json)
|
def render_commit_author(author_json)
|
||||||
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
||||||
if author_json["id"].present?
|
if author_json["id"].present?
|
||||||
return find_user_by_gitea_uid author_json['id']
|
return find_user_by_gitea_uid author_json['id']
|
||||||
end
|
end
|
||||||
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
||||||
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_cache_commit_author(author_json)
|
def render_cache_commit_author(author_json)
|
||||||
if author_json["name"].present? && author_json["email"].present?
|
if author_json["name"].present? && author_json["email"].present?
|
||||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||||
end
|
end
|
||||||
if author_json["Name"].present? && author_json["Email"].present?
|
if author_json["Name"].present? && author_json["Email"].present?
|
||||||
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||||
return nil if str.blank?
|
return nil if str.blank?
|
||||||
begin
|
begin
|
||||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||||
|
|
||||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||||
src_regex = /src=\"(.*?)\"/
|
src_regex = /src=\"(.*?)\"/
|
||||||
src2_regex = /src='(.*?)'/
|
src2_regex = /src='(.*?)'/
|
||||||
ss = content.to_s.scan(c_regex)
|
ss = content.to_s.scan(c_regex)
|
||||||
ss_src = content.scan(src_regex)
|
ss_src = content.scan(src_regex)
|
||||||
ss_src2 = content.scan(src2_regex)
|
ss_src2 = content.scan(src2_regex)
|
||||||
total_images = ss + ss_src + ss_src2
|
total_images = ss + ss_src + ss_src2
|
||||||
if total_images.length > 0
|
if total_images.length > 0
|
||||||
total_images.each do |s|
|
total_images.each do |s|
|
||||||
begin
|
begin
|
||||||
image_title = /\"(.*?)\"/
|
image_title = /\"(.*?)\"/
|
||||||
r_content = s[0]
|
r_content = s[0]
|
||||||
remove_title = r_content.to_s.scan(image_title)
|
remove_title = r_content.to_s.scan(image_title)
|
||||||
# if remove_title.length > 0
|
# if remove_title.length > 0
|
||||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||||
# end
|
# end
|
||||||
path_last = r_content
|
path_last = r_content
|
||||||
path_current = ""
|
path_current = ""
|
||||||
# 相对路径处理
|
# 相对路径处理
|
||||||
if r_content.start_with?("../")
|
if r_content.start_with?("../")
|
||||||
relative_path_length = r_content.split("../").size - 1
|
relative_path_length = r_content.split("../").size - 1
|
||||||
path_pre = path.split("/").size - 1 - relative_path_length
|
path_pre = path.split("/").size - 1 - relative_path_length
|
||||||
path_pre = 0 if path_pre < 0
|
path_pre = 0 if path_pre < 0
|
||||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||||
path_last = r_content.split("../").last
|
path_last = r_content.split("../").last
|
||||||
elsif r_content.start_with?("/") # 根路径处理
|
elsif r_content.start_with?("/") # 根路径处理
|
||||||
path_last = r_content[1..r_content.size]
|
path_last = r_content[1..r_content.size]
|
||||||
else
|
else
|
||||||
path_current = path
|
path_current = path
|
||||||
end
|
end
|
||||||
# if r_content.include?("?")
|
# if r_content.include?("?")
|
||||||
# new_r_content = r_content + "&raw=true"
|
# new_r_content = r_content + "&raw=true"
|
||||||
# else
|
# else
|
||||||
# new_r_content = r_content + "?raw=true"
|
# new_r_content = r_content + "?raw=true"
|
||||||
# end
|
# end
|
||||||
new_r_content = r_content
|
new_r_content = r_content
|
||||||
|
|
||||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||||
# new_r_content = "#{path}" + new_r_content
|
# new_r_content = "#{path}" + new_r_content
|
||||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||||
end
|
end
|
||||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||||
rescue
|
rescue
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return content
|
return content
|
||||||
rescue
|
rescue
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# unix_time values for example: 1604382982
|
# author hui.he
|
||||||
def render_format_time_with_unix(unix_time)
|
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||||
end
|
return nil if str.blank?
|
||||||
|
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||||
# date for example: 2020-11-01T19:57:27+08:00
|
s_regex = /\[.*?\]\((.*?)\)/
|
||||||
def render_format_time_with_date(date)
|
src_regex = /src=\"(.*?)\"/
|
||||||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
ss = content.to_s.scan(s_regex)
|
||||||
end
|
ss_src = content.to_s.scan(src_regex)
|
||||||
|
total_sources = ss + ss_src
|
||||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
total_sources.uniq!
|
||||||
if is_readme?(entry['type'], entry['name'])
|
total_sources.each do |s|
|
||||||
# content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
begin
|
||||||
content = entry['content']
|
s_content = s[0]
|
||||||
path = URI.escape(entry['path']).to_s.downcase.gsub("/readme.md","")
|
# 链接直接跳过不做替换
|
||||||
readme_render_decode64_content(content, owner, repo, ref, path)
|
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||||
else
|
ext = File.extname(s_content)[1..-1]
|
||||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
|
||||||
if image_type?(file_type)
|
if image_type?(ext) || download_type(ext)
|
||||||
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
s_content = File.expand_path(s_content, file_path)
|
||||||
end
|
s_content = s_content.split("#{Rails.root}/")[1]
|
||||||
if download_type(file_type)
|
# content = content.gsub(s[0], "/#{s_content}")
|
||||||
return entry['content']
|
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||||
end
|
content = content.gsub(s[0], s_content)
|
||||||
render_decode64_content(entry['content'])
|
else
|
||||||
end
|
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||||
end
|
s_content = File.expand_path(s_content, path)
|
||||||
|
s_content = s_content.split("#{Rails.root}/")[1]
|
||||||
def base64_to_image(path, content)
|
content = content.gsub(s[0], "/#{s_content}")
|
||||||
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
end
|
||||||
content = Base64.decode64(content)
|
rescue
|
||||||
File.open(path, 'wb') { |f| f.write(content) }
|
next
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def render_download_image_url(dir_path, file_path, content)
|
|
||||||
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
return content
|
||||||
file_name = full_path.split("/")[-1]
|
rescue
|
||||||
# 用户名/项目标识/文件路径
|
return str
|
||||||
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
end
|
||||||
|
|
||||||
file_path = [dir_path, file_name].join('/')
|
# unix_time values for example: 1604382982
|
||||||
|
def render_format_time_with_unix(unix_time)
|
||||||
puts "##### render_download_image_url file_path: #{file_path}"
|
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||||
base64_to_image(file_path, content)
|
end
|
||||||
file_path = file_path[6..-1]
|
|
||||||
File.join(base_url, file_path)
|
# date for example: 2020-11-01T19:57:27+08:00
|
||||||
end
|
def render_format_time_with_date(date)
|
||||||
|
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||||
def generate_dir_path(dir_path)
|
end
|
||||||
# tmp_dir_path
|
|
||||||
# eg: jasder/forgeplus/raw/branch/ref
|
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||||
dir_path = ["public", tmp_dir, dir_path].join('/')
|
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||||
puts "#### dir_path: #{dir_path}"
|
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||||
unless Dir.exists?(dir_path)
|
Rails.logger.info("content===#{content}")
|
||||||
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
# readme_render_decode64_content(content, owner, repo, ref)
|
||||||
end
|
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||||
dir_path
|
end
|
||||||
end
|
|
||||||
|
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||||
def tmp_dir
|
if is_readme?(entry['type'], entry['name'])
|
||||||
"repo"
|
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||||
end
|
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||||
|
Rails.logger.info("content===#{content}")
|
||||||
end
|
# readme_render_decode64_content(content, owner, repo, ref)
|
||||||
|
return Base64.decode64(content).force_encoding('UTF-8')
|
||||||
|
else
|
||||||
|
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||||
|
if image_type?(file_type)
|
||||||
|
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
||||||
|
end
|
||||||
|
if download_type(file_type)
|
||||||
|
return entry['content']
|
||||||
|
end
|
||||||
|
render_decode64_content(entry['content'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def base64_to_image(path, content)
|
||||||
|
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
||||||
|
content = Base64.decode64(content)
|
||||||
|
File.open(path, 'wb') { |f| f.write(content) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_download_image_url(dir_path, file_path, content)
|
||||||
|
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
||||||
|
file_name = full_path.split("/")[-1]
|
||||||
|
# 用户名/项目标识/文件路径
|
||||||
|
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
||||||
|
|
||||||
|
file_path = [dir_path, file_name].join('/')
|
||||||
|
|
||||||
|
puts "##### render_download_image_url file_path: #{file_path}"
|
||||||
|
base64_to_image(file_path, content)
|
||||||
|
file_path = file_path[6..-1]
|
||||||
|
File.join(base_url, file_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_dir_path(dir_path)
|
||||||
|
# tmp_dir_path
|
||||||
|
# eg: jasder/forgeplus/raw/branch/ref
|
||||||
|
dir_path = ["public", tmp_dir, dir_path].join('/')
|
||||||
|
puts "#### dir_path: #{dir_path}"
|
||||||
|
unless Dir.exists?(dir_path)
|
||||||
|
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
||||||
|
end
|
||||||
|
dir_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def tmp_dir
|
||||||
|
"repo"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Admins::NewImportUserFromExcel < BaseImportXlsx
|
||||||
|
UserData = Struct.new(:login, :email, :password, :nickname)
|
||||||
|
|
||||||
|
def read_each(&block)
|
||||||
|
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||||
|
data = row.map(&method(:cell_value))[0..3]
|
||||||
|
block.call UserData.new(*data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def cell_value(obj)
|
||||||
|
obj&.cell_value
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,7 +13,7 @@ module Gitea
|
||||||
end
|
end
|
||||||
|
|
||||||
def success?
|
def success?
|
||||||
@error.nil?
|
@error.nil? && @result[:status].to_s == "success"
|
||||||
end
|
end
|
||||||
|
|
||||||
def result
|
def result
|
||||||
|
|
|
@ -4,6 +4,24 @@ class SendTemplateMessageJob < ApplicationJob
|
||||||
def perform(source, *args)
|
def perform(source, *args)
|
||||||
Rails.logger.info "SendTemplateMessageJob [args] #{args}"
|
Rails.logger.info "SendTemplateMessageJob [args] #{args}"
|
||||||
case source
|
case source
|
||||||
|
when 'CustomTip'
|
||||||
|
receivers_id, template_id, props = args[0], args[1], args[2]
|
||||||
|
template = MessageTemplate.find_by_id(template_id)
|
||||||
|
return unless template.present?
|
||||||
|
receivers = User.where(id: receivers_id).or(User.where(mail: receivers_id))
|
||||||
|
not_exists_receivers = receivers_id - receivers.pluck(:id) - receivers.pluck(:mail)
|
||||||
|
receivers_string, content, notification_url = MessageTemplate::CustomTip.get_message_content(receivers, template, props)
|
||||||
|
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {receivers_id: receivers_id, template_id: template_id, props: props})
|
||||||
|
receivers.find_each do |receiver|
|
||||||
|
receivers_email_string, email_title, email_content = MessageTemplate::CustomTip.get_email_message_content(receiver, template, props)
|
||||||
|
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||||
|
end
|
||||||
|
not_exists_receivers.each do |mail|
|
||||||
|
valid_email_regex = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/i
|
||||||
|
next unless (mail =~ valid_email_regex)
|
||||||
|
email_title, email_content = MessageTemplate::CustomTip.get_email_content(template, props)
|
||||||
|
Notice::Write::EmailCreateService.call(mail, email_title, email_content)
|
||||||
|
end
|
||||||
when 'FollowTip'
|
when 'FollowTip'
|
||||||
watcher_id = args[0]
|
watcher_id = args[0]
|
||||||
watcher = Watcher.find_by_id(watcher_id)
|
watcher = Watcher.find_by_id(watcher_id)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module CustomRegexp
|
module CustomRegexp
|
||||||
PHONE = /1\d{10}/
|
PHONE = /1\d{10}/
|
||||||
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
||||||
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||||
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
||||||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||||
|
@ -11,5 +11,5 @@ module CustomRegexp
|
||||||
|
|
||||||
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})(?!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
|
||||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||||
|
MD_REGEX = /^.+(\.[m|M][d|D])$/
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,8 +16,7 @@ class MessageTemplate < ApplicationRecord
|
||||||
PLATFORM = 'GitLink'
|
PLATFORM = 'GitLink'
|
||||||
|
|
||||||
def self.build_init_data
|
def self.build_init_data
|
||||||
MessageTemplate::IssueAssignerExpire.destroy_all
|
MessageTemplate.where.not(type: 'MessageTemplate::CustomTip').destroy_all
|
||||||
MessageTemplate::IssueCreatorExpire.destroy_all
|
|
||||||
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
|
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
|
||||||
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
|
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
|
||||||
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修")
|
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修")
|
||||||
|
|
|
@ -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::CustomTip < MessageTemplate
|
||||||
|
|
||||||
|
# MessageTemplate::CustomTip.get_message_content(User.where(login: 'yystopf'), "hahah")
|
||||||
|
def self.get_message_content(receivers, template, props={})
|
||||||
|
return '', '', '' if receivers.blank? || template.blank?
|
||||||
|
content = template.sys_notice
|
||||||
|
notification_url = template.notification_url
|
||||||
|
props.each do |k, v|
|
||||||
|
content.gsub!("{#{k}}", v)
|
||||||
|
notification_url.gsub!("{#{k}}", v)
|
||||||
|
end
|
||||||
|
notification_url.gsub!('{baseurl}', base_url)
|
||||||
|
return receivers_string(receivers), content, notification_url
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.info("MessageTemplate::CustomTip.get_message_content [ERROR] #{e}")
|
||||||
|
return '', '', ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_email_message_content(receiver, template, props={})
|
||||||
|
return '', '', '' if receiver.blank? || template.blank?
|
||||||
|
title = template.email_title
|
||||||
|
content = template.email
|
||||||
|
props.each do |k, v|
|
||||||
|
title.gsub!("{#{k}}", v)
|
||||||
|
content.gsub!("{#{k}}", v)
|
||||||
|
end
|
||||||
|
content.gsub!('{receiver}', receiver&.real_name)
|
||||||
|
title.gsub!('{platform}', PLATFORM)
|
||||||
|
content.gsub!('{platform}', PLATFORM)
|
||||||
|
content.gsub!('{baseurl}', base_url)
|
||||||
|
|
||||||
|
return receiver&.mail, title, content
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.info("MessageTemplate::CustomTip.get_email_message_content [ERROR] #{e}")
|
||||||
|
return '', '', ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_email_content(template, props = {})
|
||||||
|
return '', '', '' if template.blank?
|
||||||
|
title = template.email_title
|
||||||
|
content = template.email
|
||||||
|
props.each do |k, v|
|
||||||
|
title.gsub!("{#{k}}", v)
|
||||||
|
content.gsub!("{#{k}}", v)
|
||||||
|
end
|
||||||
|
title.gsub!('{platform}', PLATFORM)
|
||||||
|
content.gsub!('{platform}', PLATFORM)
|
||||||
|
|
||||||
|
return title, content
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.info("MessageTemplate::CustomTip.get_email_content [ERROR] #{e}")
|
||||||
|
return '', ''
|
||||||
|
end
|
||||||
|
end
|
|
@ -141,6 +141,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
||||||
navbar.gsub!('devops', '工作流')
|
navbar.gsub!('devops', '工作流')
|
||||||
navbar.gsub!('versions', '里程碑')
|
navbar.gsub!('versions', '里程碑')
|
||||||
navbar.gsub!('resources', '资源库')
|
navbar.gsub!('resources', '资源库')
|
||||||
|
navbar.gsub!('services', '服务')
|
||||||
if change_count > 1
|
if change_count > 1
|
||||||
content.sub!('{ifnavbar}', '<br/>')
|
content.sub!('{ifnavbar}', '<br/>')
|
||||||
else
|
else
|
||||||
|
@ -290,6 +291,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
||||||
navbar.gsub!('devops', '工作流')
|
navbar.gsub!('devops', '工作流')
|
||||||
navbar.gsub!('versions', '里程碑')
|
navbar.gsub!('versions', '里程碑')
|
||||||
navbar.gsub!('resources', '资源库')
|
navbar.gsub!('resources', '资源库')
|
||||||
|
navbar.gsub!('services', '服务')
|
||||||
if change_count > 1
|
if change_count > 1
|
||||||
content.sub!('{ifnavbar}', '<br/>')
|
content.sub!('{ifnavbar}', '<br/>')
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,411 +1,420 @@
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
#
|
#
|
||||||
# Table name: projects
|
# Table name: projects
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# name :string(255) default(""), not null
|
# name :string(255) default(""), not null
|
||||||
# description :text(4294967295)
|
# description :text(4294967295)
|
||||||
# homepage :string(255) default("")
|
# homepage :string(255) default("")
|
||||||
# is_public :boolean default("1"), not null
|
# is_public :boolean default("1"), not null
|
||||||
# parent_id :integer
|
# parent_id :integer
|
||||||
# created_on :datetime
|
# created_on :datetime
|
||||||
# updated_on :datetime
|
# updated_on :datetime
|
||||||
# identifier :string(255)
|
# identifier :string(255)
|
||||||
# status :integer default("1"), not null
|
# status :integer default("1"), not null
|
||||||
# lft :integer
|
# lft :integer
|
||||||
# rgt :integer
|
# rgt :integer
|
||||||
# inherit_members :boolean default("0"), not null
|
# inherit_members :boolean default("0"), not null
|
||||||
# project_type :integer default("0")
|
# project_type :integer default("0")
|
||||||
# hidden_repo :boolean default("0"), not null
|
# hidden_repo :boolean default("0"), not null
|
||||||
# attachmenttype :integer default("1")
|
# attachmenttype :integer default("1")
|
||||||
# user_id :integer
|
# user_id :integer
|
||||||
# dts_test :integer default("0")
|
# dts_test :integer default("0")
|
||||||
# enterprise_name :string(255)
|
# enterprise_name :string(255)
|
||||||
# organization_id :integer
|
# organization_id :integer
|
||||||
# project_new_type :integer
|
# project_new_type :integer
|
||||||
# gpid :integer
|
# gpid :integer
|
||||||
# forked_from_project_id :integer
|
# forked_from_project_id :integer
|
||||||
# forked_count :integer default("0")
|
# forked_count :integer default("0")
|
||||||
# publish_resource :integer default("0")
|
# publish_resource :integer default("0")
|
||||||
# visits :integer default("0")
|
# visits :integer default("0")
|
||||||
# hot :integer default("0")
|
# hot :integer default("0")
|
||||||
# invite_code :string(255)
|
# invite_code :string(255)
|
||||||
# qrcode :string(255)
|
# qrcode :string(255)
|
||||||
# qrcode_expiretime :integer default("0")
|
# qrcode_expiretime :integer default("0")
|
||||||
# script :text(65535)
|
# script :text(65535)
|
||||||
# training_status :integer default("0")
|
# training_status :integer default("0")
|
||||||
# rep_identifier :string(255)
|
# rep_identifier :string(255)
|
||||||
# project_category_id :integer
|
# project_category_id :integer
|
||||||
# project_language_id :integer
|
# project_language_id :integer
|
||||||
# praises_count :integer default("0")
|
# license_id :integer
|
||||||
# watchers_count :integer default("0")
|
# ignore_id :integer
|
||||||
# issues_count :integer default("0")
|
# praises_count :integer default("0")
|
||||||
# pull_requests_count :integer default("0")
|
# watchers_count :integer default("0")
|
||||||
# language :string(255)
|
# issues_count :integer default("0")
|
||||||
# versions_count :integer default("0")
|
# pull_requests_count :integer default("0")
|
||||||
# issue_tags_count :integer default("0")
|
# language :string(255)
|
||||||
# closed_issues_count :integer default("0")
|
# versions_count :integer default("0")
|
||||||
# open_devops :boolean default("0")
|
# issue_tags_count :integer default("0")
|
||||||
# gitea_webhook_id :integer
|
# closed_issues_count :integer default("0")
|
||||||
# open_devops_count :integer default("0")
|
# open_devops :boolean default("0")
|
||||||
# recommend :boolean default("0")
|
# gitea_webhook_id :integer
|
||||||
# platform :integer default("0")
|
# open_devops_count :integer default("0")
|
||||||
# license_id :integer
|
# recommend :boolean default("0")
|
||||||
# ignore_id :integer
|
# platform :integer default("0")
|
||||||
# default_branch :string(255) default("master")
|
# default_branch :string(255) default("master")
|
||||||
# website :string(255)
|
# website :string(255)
|
||||||
# lesson_url :string(255)
|
# lesson_url :string(255)
|
||||||
# is_pinned :boolean default("0")
|
# is_pinned :boolean default("0")
|
||||||
# recommend_index :integer default("0")
|
# recommend_index :integer default("0")
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
||||||
# index_projects_on_identifier (identifier)
|
# index_projects_on_identifier (identifier)
|
||||||
# index_projects_on_invite_code (invite_code)
|
# index_projects_on_invite_code (invite_code)
|
||||||
# index_projects_on_is_public (is_public)
|
# index_projects_on_is_public (is_public)
|
||||||
# index_projects_on_lft (lft)
|
# index_projects_on_lft (lft)
|
||||||
# index_projects_on_license_id (license_id)
|
# index_projects_on_license_id (license_id)
|
||||||
# index_projects_on_name (name)
|
# index_projects_on_name (name)
|
||||||
# index_projects_on_platform (platform)
|
# index_projects_on_platform (platform)
|
||||||
# index_projects_on_project_category_id (project_category_id)
|
# index_projects_on_project_category_id (project_category_id)
|
||||||
# index_projects_on_project_language_id (project_language_id)
|
# index_projects_on_project_language_id (project_language_id)
|
||||||
# index_projects_on_project_type (project_type)
|
# index_projects_on_project_type (project_type)
|
||||||
# index_projects_on_recommend (recommend)
|
# index_projects_on_recommend (recommend)
|
||||||
# index_projects_on_rgt (rgt)
|
# index_projects_on_rgt (rgt)
|
||||||
# index_projects_on_status (status)
|
# index_projects_on_status (status)
|
||||||
# index_projects_on_updated_on (updated_on)
|
# index_projects_on_updated_on (updated_on)
|
||||||
#
|
#
|
||||||
|
|
||||||
class Project < ApplicationRecord
|
class Project < ApplicationRecord
|
||||||
include Matchable
|
include Matchable
|
||||||
include Publicable
|
include Publicable
|
||||||
include Watchable
|
include Watchable
|
||||||
include ProjectOperable
|
include ProjectOperable
|
||||||
include Dcodes
|
include Dcodes
|
||||||
|
|
||||||
# common:开源托管项目
|
# common:开源托管项目
|
||||||
# mirror:普通镜像项目,没有定时同步功能
|
# mirror:普通镜像项目,没有定时同步功能
|
||||||
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
|
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
|
||||||
#
|
#
|
||||||
enum project_type: { sync_mirror: 2, mirror: 1, common: 0 }
|
enum project_type: { sync_mirror: 2, mirror: 1, common: 0 }
|
||||||
|
|
||||||
# forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台
|
# forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台
|
||||||
enum platform: { forge: 0, educoder: 1 }
|
enum platform: { forge: 0, educoder: 1 }
|
||||||
|
|
||||||
belongs_to :ignore, optional: true
|
belongs_to :ignore, optional: true
|
||||||
belongs_to :license, optional: true
|
belongs_to :license, optional: true
|
||||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
||||||
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
|
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
|
||||||
belongs_to :project_category, optional: true , :counter_cache => true
|
belongs_to :project_category, optional: true , :counter_cache => true
|
||||||
belongs_to :project_language, optional: true , :counter_cache => true
|
belongs_to :project_language, optional: true , :counter_cache => true
|
||||||
belongs_to :forked_from_project, class_name: 'Project', optional: true, foreign_key: :forked_from_project_id
|
belongs_to :forked_from_project, class_name: 'Project', optional: true, foreign_key: :forked_from_project_id
|
||||||
has_many :project_trends, dependent: :destroy
|
has_many :project_trends, dependent: :destroy
|
||||||
has_many :watchers, as: :watchable, dependent: :destroy
|
has_many :watchers, as: :watchable, dependent: :destroy
|
||||||
has_many :fork_users, dependent: :destroy
|
has_many :fork_users, dependent: :destroy
|
||||||
has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy
|
has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy
|
||||||
has_many :forked_projects, class_name: 'Project', foreign_key: :forked_from_project_id
|
has_many :forked_projects, class_name: 'Project', foreign_key: :forked_from_project_id
|
||||||
has_one :project_educoder, dependent: :destroy
|
has_one :project_educoder, dependent: :destroy
|
||||||
|
|
||||||
has_one :project_score, dependent: :destroy
|
has_one :project_score, dependent: :destroy
|
||||||
has_one :repository, dependent: :destroy
|
has_one :repository, dependent: :destroy
|
||||||
has_many :pull_requests, dependent: :destroy
|
has_many :pull_requests, dependent: :destroy
|
||||||
has_many :issue_tags, -> { order("issue_tags.created_at DESC") }, dependent: :destroy
|
has_many :issue_tags, -> { order("issue_tags.created_at DESC") }, dependent: :destroy
|
||||||
has_many :issues, dependent: :destroy
|
has_many :issues, dependent: :destroy
|
||||||
# has_many :user_grades, dependent: :destroy
|
# has_many :user_grades, dependent: :destroy
|
||||||
has_many :attachments, as: :container, dependent: :destroy
|
has_many :attachments, as: :container, dependent: :destroy
|
||||||
has_one :project_score, dependent: :destroy
|
has_one :project_score, dependent: :destroy
|
||||||
has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy
|
has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy
|
||||||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||||
has_one :project_detail, dependent: :destroy
|
has_one :project_detail, dependent: :destroy
|
||||||
has_many :project_units, dependent: :destroy
|
has_many :project_units, dependent: :destroy
|
||||||
has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy
|
has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy
|
||||||
has_many :pinned_projects, dependent: :destroy
|
has_many :pinned_projects, dependent: :destroy
|
||||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||||
after_create :incre_user_statistic, :incre_platform_statistic
|
has_many :user_trace_tasks, dependent: :destroy
|
||||||
after_save :check_project_members
|
after_create :incre_user_statistic, :incre_platform_statistic
|
||||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
after_save :check_project_members
|
||||||
before_destroy :decre_project_common, :decre_forked_from_project_count
|
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||||
after_destroy :decre_user_statistic, :decre_platform_statistic
|
before_destroy :decre_project_common, :decre_forked_from_project_count
|
||||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :description, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
after_destroy :decre_user_statistic, :decre_platform_statistic
|
||||||
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :description, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
||||||
scope :pinned, -> {where(is_pinned: true)}
|
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||||
|
scope :pinned, -> {where(is_pinned: true)}
|
||||||
delegate :content, to: :project_detail, allow_nil: true
|
|
||||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
delegate :content, to: :project_detail, allow_nil: true
|
||||||
|
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||||
def self.all_visible(user_id=nil)
|
|
||||||
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
|
validate :validate_sensitive_string
|
||||||
org_public_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'common'})).to_sql
|
|
||||||
if user_id.present?
|
def self.all_visible(user_id=nil)
|
||||||
org_limit_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'limited'})).to_sql
|
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
|
||||||
org_privacy_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension, :organization_users).where(organization_extensions: {visibility: 'privacy'}, organization_users: {user_id: user_id})).to_sql
|
org_public_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'common'})).to_sql
|
||||||
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } UNION #{ org_limit_projects_sql } UNION #{org_privacy_projects_sql} ) AS projects").visible
|
if user_id.present?
|
||||||
else
|
org_limit_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension).where(organization_extensions: {visibility: 'limited'})).to_sql
|
||||||
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } ) AS projects").visible
|
org_privacy_projects_sql = Project.joins(:owner).merge(Organization.joins(:organization_extension, :organization_users).where(organization_extensions: {visibility: 'privacy'}, organization_users: {user_id: user_id})).to_sql
|
||||||
end
|
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } UNION #{ org_limit_projects_sql } UNION #{org_privacy_projects_sql} ) AS projects").visible
|
||||||
end
|
else
|
||||||
|
return Project.from("( #{ user_projects_sql } UNION #{ org_public_projects_sql } ) AS projects").visible
|
||||||
def reset_cache_data
|
end
|
||||||
CacheAsyncResetJob.set(wait: 5.seconds).perform_later("project_common_service", self.id)
|
end
|
||||||
if changes[:user_id].present?
|
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1}, changes[:user_id].first)
|
def reset_cache_data
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1}, changes[:user_id].last)
|
CacheAsyncResetJob.set(wait: 5.seconds).perform_later("project_common_service", self.id)
|
||||||
end
|
if changes[:user_id].present?
|
||||||
if changes[:project_language_id].present?
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1}, changes[:user_id].first)
|
||||||
first_language = ProjectLanguage.find_by_id(changes[:project_language_id].first)
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1}, changes[:user_id].last)
|
||||||
last_language = ProjectLanguage.find_by_id(changes[:project_language_id].last)
|
end
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1}, self.user_id)
|
if changes[:project_language_id].present?
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1}, self.user_id)
|
first_language = ProjectLanguage.find_by_id(changes[:project_language_id].first)
|
||||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1})
|
last_language = ProjectLanguage.find_by_id(changes[:project_language_id].last)
|
||||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1})
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1}, self.user_id)
|
||||||
end
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1}, self.user_id)
|
||||||
if changes[:is_public].present?
|
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1})
|
||||||
if changes[:is_public][0] && !changes[:is_public][1]
|
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1})
|
||||||
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
|
end
|
||||||
end
|
if changes[:is_public].present?
|
||||||
if !changes[:is_public][0] && changes[:is_public][1]
|
if changes[:is_public][0] && !changes[:is_public][1]
|
||||||
$redis_cache.srem("v2-project-rank-deleted", self.id)
|
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
|
||||||
end
|
end
|
||||||
end
|
if !changes[:is_public][0] && changes[:is_public][1]
|
||||||
end
|
$redis_cache.srem("v2-project-rank-deleted", self.id)
|
||||||
|
end
|
||||||
def decre_project_common
|
end
|
||||||
CacheAsyncClearJob.perform_later('project_common_service', self.id)
|
end
|
||||||
end
|
|
||||||
|
def decre_project_common
|
||||||
def decre_forked_from_project_count
|
CacheAsyncClearJob.perform_later('project_common_service', self.id)
|
||||||
forked_project = self.forked_from_project
|
end
|
||||||
if forked_project.present?
|
|
||||||
forked_project.decrement(:forked_count, 1)
|
def decre_forked_from_project_count
|
||||||
forked_project.save
|
forked_project = self.forked_from_project
|
||||||
end
|
if forked_project.present?
|
||||||
end
|
forked_project.decrement(:forked_count, 1)
|
||||||
|
forked_project.save
|
||||||
def incre_user_statistic
|
end
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1, project_language_count_key: self.project_language&.name, project_language_count: 1}, self.user_id)
|
end
|
||||||
end
|
|
||||||
|
def incre_user_statistic
|
||||||
def decre_user_statistic
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1, project_language_count_key: self.project_language&.name, project_language_count: 1}, self.user_id)
|
||||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1, project_language_count_key: self.project_language&.name, project_language_count: -1}, self.user_id)
|
end
|
||||||
end
|
|
||||||
|
def decre_user_statistic
|
||||||
def incre_platform_statistic
|
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1, project_language_count_key: self.project_language&.name, project_language_count: -1}, self.user_id)
|
||||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_count: 1, project_language_count_key: self.project_language&.name, project_language_count: 1})
|
end
|
||||||
end
|
|
||||||
|
def incre_platform_statistic
|
||||||
def decre_platform_statistic
|
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_count: 1, project_language_count_key: self.project_language&.name, project_language_count: 1})
|
||||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_count: -1, project_language_count_key: self.project_language&.name, project_language_count: -1})
|
end
|
||||||
end
|
|
||||||
|
def decre_platform_statistic
|
||||||
def is_full_public
|
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_count: -1, project_language_count_key: self.project_language&.name, project_language_count: -1})
|
||||||
owner = self.owner
|
end
|
||||||
if owner.is_a?(Organization)
|
|
||||||
return self.is_public && owner&.visibility == "common"
|
def is_full_public
|
||||||
else
|
owner = self.owner
|
||||||
return self.is_public
|
if owner.is_a?(Organization)
|
||||||
end
|
return self.is_public && owner&.visibility == "common"
|
||||||
end
|
else
|
||||||
|
return self.is_public
|
||||||
def reset_unmember_followed
|
end
|
||||||
if changes[:is_public].present? && changes[:is_public] == [true, false]
|
end
|
||||||
self.watchers.where.not(user_id: self.all_collaborators).destroy_all
|
|
||||||
end
|
def reset_unmember_followed
|
||||||
end
|
if changes[:is_public].present? && changes[:is_public] == [true, false]
|
||||||
|
self.watchers.where.not(user_id: self.all_collaborators).destroy_all
|
||||||
def set_invite_code
|
end
|
||||||
if self.invite_code.nil?
|
end
|
||||||
self.invite_code= self.generate_dcode('invite_code', 6)
|
|
||||||
end
|
def set_invite_code
|
||||||
end
|
if self.invite_code.nil?
|
||||||
|
self.invite_code= self.generate_dcode('invite_code', 6)
|
||||||
def set_recommend_and_is_pinned
|
end
|
||||||
self.recommend = self.recommend_index.zero? ? false : true
|
end
|
||||||
# 私有项目不允许设置精选和推荐
|
|
||||||
unless self.is_public
|
def set_recommend_and_is_pinned
|
||||||
self.recommend = false
|
self.recommend = self.recommend_index.zero? ? false : true
|
||||||
self.recommend_index = 0
|
# 私有项目不允许设置精选和推荐
|
||||||
self.is_pinned = false
|
unless self.is_public
|
||||||
end
|
self.recommend = false
|
||||||
end
|
self.recommend_index = 0
|
||||||
|
self.is_pinned = false
|
||||||
def self.search_project(search)
|
end
|
||||||
ransack(name_or_identifier_cont: search)
|
end
|
||||||
end
|
|
||||||
# 创建者
|
def self.search_project(search)
|
||||||
def creator
|
ransack(name_or_identifier_cont: search)
|
||||||
User.find(user_id).full_name
|
end
|
||||||
end
|
# 创建者
|
||||||
|
def creator
|
||||||
def members_user_infos
|
User.find(user_id).full_name
|
||||||
members.joins(:roles).where("roles.name in ('Manager', 'Developer', 'Reporter')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User")
|
end
|
||||||
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")
|
|
||||||
# .pluck("users.id", "users.login","users.lastname", "users.firstname")
|
def members_user_infos
|
||||||
end
|
members.joins(:roles).where("roles.name in ('Manager', 'Developer', 'Reporter')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User")
|
||||||
|
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")
|
||||||
def to_param
|
# .pluck("users.id", "users.login","users.lastname", "users.firstname")
|
||||||
self.identifier.parameterize
|
end
|
||||||
end
|
|
||||||
|
def to_param
|
||||||
def get_issues_count(status_id)
|
self.identifier.parameterize
|
||||||
if status_id.present?
|
end
|
||||||
self&.issues.issue_issue.select(:id, :status_id).where(status_id: status_id)&.pluck(:id).size
|
|
||||||
else
|
def get_issues_count(status_id)
|
||||||
self&.issues.issue_issue.select(:id)&.pluck(:id).size
|
if status_id.present?
|
||||||
end
|
self&.issues.issue_issue.select(:id, :status_id).where(status_id: status_id)&.pluck(:id).size
|
||||||
end
|
else
|
||||||
|
self&.issues.issue_issue.select(:id)&.pluck(:id).size
|
||||||
def get_pull_requests_count(status_id)
|
end
|
||||||
if status_id.present?
|
end
|
||||||
self&.pull_requests.select(:id, :status).where(status: status_id)&.pluck(:id).size
|
|
||||||
else
|
def get_pull_requests_count(status_id)
|
||||||
self&.pull_requests.select(:id)&.pluck(:id).size
|
if status_id.present?
|
||||||
end
|
self&.pull_requests.select(:id, :status).where(status: status_id)&.pluck(:id).size
|
||||||
end
|
else
|
||||||
|
self&.pull_requests.select(:id)&.pluck(:id).size
|
||||||
#创建项目管理员
|
end
|
||||||
def check_project_members
|
end
|
||||||
return if owner.is_a?(Organization)
|
|
||||||
unless members.present? && members.exists?(user_id: self.user_id)
|
#创建项目管理员
|
||||||
member_params = {
|
def check_project_members
|
||||||
user_id: self.user_id,
|
return if owner.is_a?(Organization)
|
||||||
project_id: self.id
|
unless members.present? && members.exists?(user_id: self.user_id)
|
||||||
}
|
member_params = {
|
||||||
user_member = Member.new(member_params)
|
user_id: self.user_id,
|
||||||
if user_member.save
|
project_id: self.id
|
||||||
role_id = Role.select(:id,:position).where(position: 3)&.first&.id
|
}
|
||||||
MemberRole.create!(member_id: user_member.id ,role_id: role_id)
|
user_member = Member.new(member_params)
|
||||||
end
|
if user_member.save
|
||||||
end
|
role_id = Role.select(:id,:position).where(position: 3)&.first&.id
|
||||||
end
|
MemberRole.create!(member_id: user_member.id ,role_id: role_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
def self.init_bluck_repository
|
end
|
||||||
Project.includes(:repository).find_each do |project|
|
|
||||||
puts project.id
|
|
||||||
next if project.owner.blank?
|
def self.init_bluck_repository
|
||||||
if project.repository.blank?
|
Project.includes(:repository).find_each do |project|
|
||||||
puts "########### start create repositoy #############"
|
puts project.id
|
||||||
Repository.create!(project_id: project.id, identifier: Project.generate_identifier, user_id: project&.owner&.id)
|
next if project.owner.blank?
|
||||||
end
|
if project.repository.blank?
|
||||||
end
|
puts "########### start create repositoy #############"
|
||||||
end
|
Repository.create!(project_id: project.id, identifier: Project.generate_identifier, user_id: project&.owner&.id)
|
||||||
|
end
|
||||||
def self.generate_identifier
|
end
|
||||||
str_arr = (("a".."z").to_a + ("A".."Z").to_a)
|
end
|
||||||
|
|
||||||
str = str_arr.shuffle[0..8].join
|
def self.generate_identifier
|
||||||
while Repository.exists?(identifier: str)
|
str_arr = (("a".."z").to_a + ("A".."Z").to_a)
|
||||||
str = str_arr.shuffle[0..8].join
|
|
||||||
end
|
str = str_arr.shuffle[0..8].join
|
||||||
str
|
while Repository.exists?(identifier: str)
|
||||||
end
|
str = str_arr.shuffle[0..8].join
|
||||||
|
end
|
||||||
def self.list_user_projects(user_id)
|
str
|
||||||
projects = Project.is_private.select(:id,:user_id)
|
end
|
||||||
user_not_show_1 = projects.where("user_id != ?",user_id).pluck(:id).uniq
|
|
||||||
|
def self.list_user_projects(user_id)
|
||||||
user_show_2 = projects.joins(:members).where("members.user_id = ?", user_id).pluck(:id).uniq
|
projects = Project.is_private.select(:id,:user_id)
|
||||||
Project.where.not(id: (user_not_show_1 - user_show_2).uniq)
|
user_not_show_1 = projects.where("user_id != ?",user_id).pluck(:id).uniq
|
||||||
end
|
|
||||||
|
user_show_2 = projects.joins(:members).where("members.user_id = ?", user_id).pluck(:id).uniq
|
||||||
def members_count
|
Project.where.not(id: (user_not_show_1 - user_show_2).uniq)
|
||||||
members.select(:id).size
|
end
|
||||||
end
|
|
||||||
|
def members_count
|
||||||
|
members.select(:id).size
|
||||||
def can_visited?
|
end
|
||||||
is_public? || User.current.admin? || member?(User.current)
|
|
||||||
end
|
|
||||||
|
def can_visited?
|
||||||
def releases_size(current_user_id, type)
|
is_public? || User.current.admin? || member?(User.current)
|
||||||
if current_user_id == self.user_id && type.to_s == "all"
|
end
|
||||||
self.repository.version_releases_count
|
|
||||||
else
|
def releases_size(current_user_id, type)
|
||||||
self.repository.version_releases.releases_size
|
if current_user_id == self.user_id && type.to_s == "all"
|
||||||
end
|
self.repository.version_releases_count
|
||||||
end
|
else
|
||||||
|
self.repository.version_releases.releases_size
|
||||||
def contributor_users
|
end
|
||||||
self.pull_requests.select(:user_id).pluck(:user_id).uniq.size
|
end
|
||||||
end
|
|
||||||
|
def contributor_users
|
||||||
def open_issues_count
|
self.pull_requests.select(:user_id).pluck(:user_id).uniq.size
|
||||||
issues_count - closed_issues_count
|
end
|
||||||
end
|
|
||||||
|
def open_issues_count
|
||||||
def numerical_for_project_type
|
issues_count - closed_issues_count
|
||||||
self.class.name.constantize.project_types["#{self.project_type}"]
|
end
|
||||||
end
|
|
||||||
|
def numerical_for_project_type
|
||||||
def watched_by? user
|
self.class.name.constantize.project_types["#{self.project_type}"]
|
||||||
watchers.pluck(:user_id).include? user&.id
|
end
|
||||||
end
|
|
||||||
|
def watched_by? user
|
||||||
def praised_by? user
|
watchers.pluck(:user_id).include? user&.id
|
||||||
praise_treads.pluck(:user_id).include? user&.id
|
end
|
||||||
end
|
|
||||||
|
def praised_by? user
|
||||||
def get_premission user
|
praise_treads.pluck(:user_id).include? user&.id
|
||||||
return "Owner" if owner?(user)
|
end
|
||||||
return "Manager" if manager?(user)
|
|
||||||
return "Developer" if develper?(user)
|
def get_premission user
|
||||||
return "Reporter" if reporter?(user)
|
return "Owner" if owner?(user)
|
||||||
|
return "Manager" if manager?(user)
|
||||||
return ""
|
return "Developer" if develper?(user)
|
||||||
end
|
return "Reporter" if reporter?(user)
|
||||||
|
|
||||||
def fork_project
|
return ""
|
||||||
Project.find_by(id: self.forked_from_project_id)
|
end
|
||||||
end
|
|
||||||
|
def fork_project
|
||||||
def self.members_projects(member_user_id)
|
Project.find_by(id: self.forked_from_project_id)
|
||||||
joins(:members).where(members: { user_id: member_user_id})
|
end
|
||||||
end
|
|
||||||
|
def self.members_projects(member_user_id)
|
||||||
def self.find_with_namespace(namespace_path, identifier)
|
joins(:members).where(members: { user_id: member_user_id})
|
||||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
end
|
||||||
|
|
||||||
user = Owner.find_by_login namespace_path
|
def self.find_with_namespace(namespace_path, identifier)
|
||||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||||
return nil if project.blank?
|
|
||||||
|
user = Owner.find_by_login namespace_path
|
||||||
[project, user]
|
user = Owner.new(login: namespace_path) if user.nil?
|
||||||
end
|
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||||
|
return nil if project.blank?
|
||||||
def ci_reactivate?
|
|
||||||
open_devops_count > 0
|
[project, user]
|
||||||
end
|
end
|
||||||
|
|
||||||
def ci_reactivate!(ci_repo)
|
def ci_reactivate?
|
||||||
ci_repo.update_column(:repo_active, 1)
|
open_devops_count > 0
|
||||||
update_column(:open_devops, true)
|
end
|
||||||
increment!(:open_devops_count)
|
|
||||||
end
|
def ci_reactivate!(ci_repo)
|
||||||
|
ci_repo.update_column(:repo_active, 1)
|
||||||
def self.sync_educoder_shixun(url, private_token, page, per_page)
|
update_column(:open_devops, true)
|
||||||
SyncEducoderShixunJob.perform_later(url, private_token, page, per_page)
|
increment!(:open_devops_count)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.update_common_projects_count!
|
def self.sync_educoder_shixun(url, private_token, page, per_page)
|
||||||
ps = ProjectStatistic.first
|
SyncEducoderShixunJob.perform_later(url, private_token, page, per_page)
|
||||||
ps.increment!(:common_projects_count) unless ps.blank?
|
end
|
||||||
end
|
|
||||||
|
def self.update_common_projects_count!
|
||||||
def self.update_mirror_projects_count!
|
ps = ProjectStatistic.first
|
||||||
ps = ProjectStatistic.first
|
ps.increment!(:common_projects_count) unless ps.blank?
|
||||||
ps.increment!(:mirror_projects_count) unless ps.blank?
|
end
|
||||||
end
|
|
||||||
|
def self.update_mirror_projects_count!
|
||||||
def set_updated_on(time)
|
ps = ProjectStatistic.first
|
||||||
return if time.blank?
|
ps.increment!(:mirror_projects_count) unless ps.blank?
|
||||||
update_column(:updated_on, time)
|
end
|
||||||
end
|
|
||||||
|
def set_updated_on(time)
|
||||||
def is_transfering
|
return if time.blank?
|
||||||
applied_transfer_project&.common? ? true : false
|
update_column(:updated_on, time)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
def is_transfering
|
||||||
|
applied_transfer_project&.common? ? true : false
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_sensitive_string
|
||||||
|
raise("项目名称包含敏感词汇,请重新输入") if name && !HarmoniousDictionary.clean?(name)
|
||||||
|
raise("项目描述包含敏感词汇,请重新输入") if description && !HarmoniousDictionary.clean?(description)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
class ProjectUnit < ApplicationRecord
|
class ProjectUnit < ApplicationRecord
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
|
|
||||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7}
|
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
|
||||||
|
|
||||||
validates :unit_type, uniqueness: { scope: :project_id}
|
validates :unit_type, uniqueness: { scope: :project_id}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,10 @@ class Repository < ApplicationRecord
|
||||||
self.identifier.parameterize
|
self.identifier.parameterize
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
self['url'].blank? ? "#{Rails.application.config_for(:configuration)['platform_url']}/#{self.owner&.login}/#{self.identifier}.git" : self['url']
|
||||||
|
end
|
||||||
|
|
||||||
# with repository is mirror
|
# with repository is mirror
|
||||||
def set_mirror!
|
def set_mirror!
|
||||||
self.build_mirror(status: Mirror.statuses[:waiting]).save
|
self.build_mirror(status: Mirror.statuses[:waiting]).save
|
||||||
|
|
|
@ -175,6 +175,7 @@ class User < Owner
|
||||||
has_many :system_notification_histories
|
has_many :system_notification_histories
|
||||||
has_many :system_notifications, through: :system_notification_histories
|
has_many :system_notifications, through: :system_notification_histories
|
||||||
has_one :trace_user, dependent: :destroy
|
has_one :trace_user, dependent: :destroy
|
||||||
|
has_many :user_trace_tasks, dependent: :destroy
|
||||||
|
|
||||||
# Groups and active users
|
# Groups and active users
|
||||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: user_trace_tasks
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# user_id :integer
|
||||||
|
# project_id :integer
|
||||||
|
# branch_tag :string(255)
|
||||||
|
# task_id :string(255)
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_user_trace_tasks_on_project_id (project_id)
|
||||||
|
# index_user_trace_tasks_on_user_id (user_id)
|
||||||
|
#
|
||||||
|
|
||||||
|
class UserTraceTask < ApplicationRecord
|
||||||
|
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :project
|
||||||
|
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,71 @@
|
||||||
|
class Admins::ImportUserFromExcelService < ApplicationService
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
|
attr_reader :file, :result
|
||||||
|
|
||||||
|
def initialize(file)
|
||||||
|
@file = file
|
||||||
|
@result = { success: 0, fail: [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, '文件不存在' if file.blank?
|
||||||
|
excel = Admins::NewImportUserFromExcel.new(file)
|
||||||
|
|
||||||
|
excel.read_each(&method(:save_user))
|
||||||
|
result
|
||||||
|
rescue ApplicationImport::Error => ex
|
||||||
|
raise Error, ex.message
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def save_user(data)
|
||||||
|
user = find_user(data)
|
||||||
|
if user.blank?
|
||||||
|
create_user(data)
|
||||||
|
result[:success] +=1
|
||||||
|
else
|
||||||
|
fail_data = data.as_json
|
||||||
|
fail_data[:data] = fail_data.values.join(",")
|
||||||
|
fail_data[:message] = '用户已存在'
|
||||||
|
result[:fail] << fail_data
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue Exception => ex
|
||||||
|
fail_data = data.as_json
|
||||||
|
fail_data[:data] = fail_data.values.join(",")
|
||||||
|
fail_data[:message] = ex.message
|
||||||
|
result[:fail] << fail_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_user(data)
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
username = data.login&.gsub(/\s+/, "")
|
||||||
|
email = data.email&.gsub(/\s+/, "")
|
||||||
|
password = data.password
|
||||||
|
nickname = data.nickname&.gsub(/\s+/, "")
|
||||||
|
raise Error, "无法使用以下关键词:#{username},请重新命名" if ReversedKeyword.check_exists?(data.login)
|
||||||
|
Register::RemoteForm.new({username: username, email: email, password: password, platform: 'forge'}).validate!
|
||||||
|
user = User.new(admin: false, login: username, mail: email, nickname: nickname, platform: 'forge' , type: "User")
|
||||||
|
user.password = password
|
||||||
|
user.activate
|
||||||
|
raise Error, user.errors.full_messages.join(",") unless user.valid?
|
||||||
|
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
||||||
|
if interactor.success?
|
||||||
|
gitea_user = interactor.result
|
||||||
|
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||||
|
user.gitea_token = result['sha1']
|
||||||
|
user.gitea_uid = gitea_user[:body]['id']
|
||||||
|
UserExtension.create!(user_id: user.id) if user.save!
|
||||||
|
else
|
||||||
|
raise interactor.error, 'gitea user create error'
|
||||||
|
end
|
||||||
|
|
||||||
|
user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_user(data)
|
||||||
|
User.find_by(login: data.login)
|
||||||
|
end
|
||||||
|
end
|
|
@ -24,7 +24,8 @@ class Projects::TransferService < ApplicationService
|
||||||
|
|
||||||
private
|
private
|
||||||
def update_owner
|
def update_owner
|
||||||
project.members.map{|m| m.destroy! if m.user_id == owner.id || (new_owner.is_a?(Organization) && new_owner.is_member?(m.user_id)) }
|
project.members.map{|m| m.destroy! if m.user_id == owner.id || project.member(new_owner.id) || (new_owner.is_a?(Organization) && new_owner.is_member?(m.user_id)) }
|
||||||
|
project.set_owner_permission(new_owner)
|
||||||
project.update!(user_id: new_owner.id)
|
project.update!(user_id: new_owner.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# 代码溯源 查询检测结果
|
# 代码溯源 查询检测结果
|
||||||
class Trace::CheckResultService < Trace::ClientService
|
class Trace::CheckResultService < Trace::ClientService
|
||||||
|
|
||||||
attr_accessor :token, :project_name, :file_name, :page_num, :page_size
|
attr_accessor :token, :project, :file_name, :page_num, :page_size
|
||||||
|
|
||||||
def initialize(token, project_name=nil, file_name=nil, page_num=1, page_size=15)
|
def initialize(token, project, file_name=nil, page_num=1, page_size=15)
|
||||||
@token = token
|
@token = token
|
||||||
@project_name = project_name
|
@project = project
|
||||||
@file_name = file_name
|
@file_name = file_name
|
||||||
@page_num = page_num
|
@page_num = page_num
|
||||||
@page_size = page_size
|
@page_size = page_size
|
||||||
|
@ -19,7 +19,7 @@ class Trace::CheckResultService < Trace::ClientService
|
||||||
private
|
private
|
||||||
def request_params
|
def request_params
|
||||||
{
|
{
|
||||||
product_name: project_name,
|
product_name: Digest::MD5.hexdigest(project&.id.to_s)[0...20],
|
||||||
file_name: file_name,
|
file_name: file_name,
|
||||||
pageNum: page_num,
|
pageNum: page_num,
|
||||||
pageSize: page_size,
|
pageSize: page_size,
|
||||||
|
|
|
@ -11,26 +11,25 @@ class Trace::CheckService < Trace::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
result = authed_post(token, url, {data: request_params})
|
result = http_authed_post(token, url, {data: request_params})
|
||||||
reponse = render_response(result)
|
reponse = render_response(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def request_params
|
def request_params
|
||||||
repo = Gitea::Repository::GetService.call(project&.owner&.login, project&.identifier)
|
repo = Gitea::Repository::GetService.call(project&.owner, project&.identifier)
|
||||||
{
|
{
|
||||||
product_name: project&.name,
|
product_name: Digest::MD5.hexdigest(project&.id.to_s)[0...20],
|
||||||
product_type: project&.category&.name,
|
product_type: project&.project_category&.name || '其他',
|
||||||
code_type: project&.language&.name,
|
code_type: project&.project_language&.name || '其他',
|
||||||
product_desc: project&.description,
|
product_desc: project&.description,
|
||||||
git_url: repo['clone_url'],
|
git_url: repo['clone_url'],
|
||||||
if_branch: if_branch,
|
if_branch: if_branch,
|
||||||
branch_tag: branch_tag
|
branch_tag: branch_tag
|
||||||
}
|
}.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
"/user/check".freeze
|
"/user/check".freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,19 @@ class Trace::ClientService < ApplicationService
|
||||||
conn.post(full_url(url), params[:data])
|
conn.post(full_url(url), params[:data])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def http_authed_post(token, url, params={})
|
||||||
|
puts "[trace][POST] request params: #{params}"
|
||||||
|
puts "[trace][POST] request token: #{token}"
|
||||||
|
url = URI("#{full_url(url)}")
|
||||||
|
http = Net::HTTP.new(url.host, url.port)
|
||||||
|
http.read_timeout = 1200
|
||||||
|
request = Net::HTTP::Post.new(url)
|
||||||
|
request["Authorization"] = token
|
||||||
|
form_data = params[:data].stringify_keys.to_a
|
||||||
|
request.set_form form_data, 'multipart/form-data'
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
|
||||||
def get(url, params={})
|
def get(url, params={})
|
||||||
puts "[trace][GET] request params: #{params}"
|
puts "[trace][GET] request params: #{params}"
|
||||||
conn.get do |req|
|
conn.get do |req|
|
||||||
|
@ -100,11 +113,22 @@ class Trace::ClientService < ApplicationService
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_response(response)
|
def render_response(response)
|
||||||
status = response.status
|
if response.is_a?(Faraday::Response)
|
||||||
body = JSON.parse(response&.body)
|
status = response.status
|
||||||
|
body = JSON.parse(response&.body)
|
||||||
|
|
||||||
log_error(status, body)
|
log_error(status, body)
|
||||||
|
|
||||||
return [body["code"], body["data"], body["error"]]
|
return [body["code"], body["data"], body["error"]]
|
||||||
|
end
|
||||||
|
|
||||||
|
if response.is_a?(Net::HTTPOK)
|
||||||
|
status = 200
|
||||||
|
body = JSON.parse(response&.body)
|
||||||
|
|
||||||
|
log_error(status, body)
|
||||||
|
|
||||||
|
return [body["code"], body["data"], body["error"]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,4 +1,7 @@
|
||||||
# 代码溯源 导出pdf
|
# 代码溯源 导出pdf
|
||||||
|
require 'open-uri'
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
class Trace::PdfReportService < Trace::ClientService
|
class Trace::PdfReportService < Trace::ClientService
|
||||||
|
|
||||||
attr_accessor :token, :task_id
|
attr_accessor :token, :task_id
|
||||||
|
@ -9,15 +12,23 @@ class Trace::PdfReportService < Trace::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
result = authed_get(token, url, request_params)
|
content = open("#{domain}#{base_url}#{url}?task_id=#{task_id}", "Authorization" => token)
|
||||||
response = render_response(result)
|
if content.is_a?(Tempfile)
|
||||||
|
check_file_path
|
||||||
|
IO.copy_stream(content, "#{save_path}/#{task_id}.pdf")
|
||||||
|
return {code: 200, download_url: "/trace_task_results/#{task_id}.pdf"}
|
||||||
|
else
|
||||||
|
return {code: 404}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def request_params
|
def check_file_path
|
||||||
{
|
FileUtils.mkdir_p save_path
|
||||||
task_id: task_id
|
end
|
||||||
}
|
|
||||||
|
def save_path
|
||||||
|
"public/trace_task_results"
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% if message_templates.present? %>
|
<% if message_templates.present? %>
|
||||||
<% message_templates.each_with_index do |message_template_type, index| %>
|
<% message_templates.each_with_index do |message_template, index| %>
|
||||||
<% message_template = message_template_type.constantize.last%>
|
<%# message_template = message_template_type.constantize.last%>
|
||||||
<tr class="project-language-item-<%= message_template.id %>">
|
<tr class="project-language-item-<%= message_template.id %>">
|
||||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
<td><%= message_template.simple_type %></td>
|
<td><%= message_template.simple_type %></td>
|
||||||
|
|
|
@ -3,7 +3,13 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<div id="admins-message-templates-content">
|
<div id="admins-message-templates-content">
|
||||||
<div class="box search-form-container project-list-form">
|
<div class="box search-form-container project-list-form">
|
||||||
<%= link_to "初始化数据", init_data_admins_message_templates_path, class: "btn btn-primary pull-right", "data-disabled-with":"...初始化数据" %>
|
<%= form_tag(admins_message_templates_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: '名称检索') %>
|
||||||
|
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "初始化数据", init_data_admins_message_templates_path, class: "btn btn-primary mr-3 pull-right", "data-disabled-with":"...初始化数据" %>
|
||||||
|
<%= link_to "新增", new_admins_message_template_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
</div>
|
</div>
|
||||||
<div class="box admin-list-container message-templates-list-container">
|
<div class="box admin-list-container message-templates-list-container">
|
||||||
<%= render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } %>
|
<%= render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } %>
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
$("#admins-message-templates-content").html("<%= j render partial: 'admins/message_templates/form', locals:{type: 'create'} %>")
|
||||||
|
createMDEditor('message-template-email-editor', { height: 500, placeholder: '请输入邮件模版' });
|
|
@ -31,7 +31,9 @@
|
||||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %>
|
<%= link_to '下载导入模板', "/导入用户模板.xlsx", class: 'btn btn-secondary mr-3' %>
|
||||||
|
|
||||||
|
<%= javascript_void_link '导入用户', class: 'btn btn-secondary', data: { toggle: 'modal', target: '.admin-import-user-modal'} %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
json.total_count @projects.total_count
|
json.total_count @projects.total_count
|
||||||
json.projects @projects.each do |project|
|
json.projects @projects.each do |project|
|
||||||
json.(project, :id, :name, :identifier, :description, :forked_count, :praises_count, :forked_from_project_id)
|
json.(project, :id, :name, :identifier, :description, :forked_count, :praises_count, :forked_from_project_id, :is_public)
|
||||||
json.mirror_url project.repository&.mirror_url
|
json.mirror_url project.repository&.mirror_url
|
||||||
json.type project.numerical_for_project_type
|
json.type project.numerical_for_project_type
|
||||||
json.praised project.praised_by?(current_user)
|
json.praised project.praised_by?(current_user)
|
||||||
|
|
|
@ -9,7 +9,7 @@ json.num_projects team.num_projects
|
||||||
json.num_users team.num_users
|
json.num_users team.num_users
|
||||||
json.units team.team_units.pluck(:unit_type)
|
json.units team.team_units.pluck(:unit_type)
|
||||||
json.users team.team_users.each do |user|
|
json.users team.team_users.each do |user|
|
||||||
json.partial! "organizations/user_detail", user: user&.user
|
json.partial! "organizations/user_detail", user: user&.user if user&.user
|
||||||
end
|
end
|
||||||
json.is_admin @is_admin
|
json.is_admin @is_admin
|
||||||
json.is_member team.is_member?(current_user.id)
|
json.is_member team.is_member?(current_user.id)
|
||||||
|
|
|
@ -9,7 +9,10 @@ if @project.forge?
|
||||||
json.path entry['path']
|
json.path entry['path']
|
||||||
json.type entry['type']
|
json.type entry['type']
|
||||||
json.size entry['size']
|
json.size entry['size']
|
||||||
|
is_readme = is_readme?(entry['type'], entry['name'])
|
||||||
|
if is_readme
|
||||||
|
json.replace_content readme_decode64_content(entry, @owner, @repository, @ref, @path)
|
||||||
|
end
|
||||||
json.content (direct_download || image_type || is_dir) ? nil : decode64_content(entry, @owner, @repository, @ref, @path)
|
json.content (direct_download || image_type || is_dir) ? nil : decode64_content(entry, @owner, @repository, @ref, @path)
|
||||||
json.target entry['target']
|
json.target entry['target']
|
||||||
|
|
||||||
|
@ -25,7 +28,7 @@ if @project.forge?
|
||||||
|
|
||||||
json.direct_download direct_download
|
json.direct_download direct_download
|
||||||
json.image_type image_type
|
json.image_type image_type
|
||||||
json.is_readme_file is_readme?(entry['type'], entry['name'])
|
json.is_readme_file is_readme
|
||||||
json.commit do
|
json.commit do
|
||||||
json.partial! 'last_commit', latest_commit: entry['latest_commit']
|
json.partial! 'last_commit', latest_commit: entry['latest_commit']
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
if @user.present?
|
||||||
|
json.partial! 'users/user', locals: { user: @user }
|
||||||
|
else
|
||||||
|
json.null
|
||||||
|
end
|
|
@ -1,27 +1,29 @@
|
||||||
json.username @user.full_name
|
json.username @user.full_name
|
||||||
json.real_name @user.real_name
|
json.real_name @user.real_name
|
||||||
json.nickname @user.nickname
|
json.nickname @user.nickname
|
||||||
json.gender @user.gender
|
json.gender @user.gender
|
||||||
json.login @user.login
|
json.login @user.login
|
||||||
json.user_id @user.id
|
json.user_id @user.id
|
||||||
json.image_url url_to_avatar(@user)
|
json.image_url url_to_avatar(@user)
|
||||||
json.admin @user.admin?
|
json.admin @user.admin?
|
||||||
json.is_teacher @user.user_extension&.teacher?
|
json.is_teacher @user.user_extension&.teacher?
|
||||||
json.user_identity @user.identity
|
json.user_identity @user.identity
|
||||||
json.tidding_count 0
|
json.tidding_count 0
|
||||||
json.user_phone_binded @user.phone.present?
|
json.user_phone_binded @user.phone.present?
|
||||||
json.need_edit_info @user.need_edit_info?
|
json.need_edit_info @user.need_edit_info?
|
||||||
# json.phone @user.phone
|
# json.phone @user.phone
|
||||||
# json.email @user.mail
|
# json.email @user.mail
|
||||||
json.profile_completed @user.profile_is_completed?
|
json.profile_completed @user.profile_is_completed?
|
||||||
json.professional_certification @user.professional_certification
|
json.professional_certification @user.professional_certification
|
||||||
json.devops_step @user.devops_step
|
json.devops_step @user.devops_step
|
||||||
json.ci_certification @user.ci_certification?
|
json.ci_certification @user.ci_certification?
|
||||||
json.email @user.mail
|
json.email @user.mail
|
||||||
json.province @user.province
|
json.province @user.province
|
||||||
json.city @user.city
|
json.city @user.city
|
||||||
json.custom_department @user.custom_department
|
json.custom_department @user.custom_department
|
||||||
json.description @user.description
|
json.description @user.description
|
||||||
json.super_description @user.super_description
|
json.super_description @user.super_description
|
||||||
json.(@user, :show_email, :show_department, :show_location, :show_super_description)
|
json.(@user, :show_email, :show_department, :show_location, :show_super_description)
|
||||||
json.message_unread_total @message_unread_total
|
json.message_unread_total @message_unread_total
|
||||||
|
json.has_trace_user @user.trace_user.present?
|
||||||
|
json.is_new @user.login.present? && params[:login].to_s.include?("#{@user.login}")
|
|
@ -214,6 +214,8 @@ Rails.application.routes.draw do
|
||||||
post :remote_password
|
post :remote_password
|
||||||
post :change_password
|
post :change_password
|
||||||
post :check
|
post :check
|
||||||
|
post :login_check
|
||||||
|
post :simple_update
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -247,6 +249,7 @@ Rails.application.routes.draw do
|
||||||
get :trustie_projects
|
get :trustie_projects
|
||||||
get :trustie_related_projects
|
get :trustie_related_projects
|
||||||
post :sync_user_info
|
post :sync_user_info
|
||||||
|
get :email_search
|
||||||
|
|
||||||
scope '/ci', module: :ci do
|
scope '/ci', module: :ci do
|
||||||
scope do
|
scope do
|
||||||
|
@ -427,6 +430,20 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :traces do
|
||||||
|
resources :trace_users, only: [:create]
|
||||||
|
scope "/:owner/:repo" do
|
||||||
|
resource :projects, path: '/', only: [:index] do
|
||||||
|
member do
|
||||||
|
post :tasks
|
||||||
|
get :task_results
|
||||||
|
get :reload_task
|
||||||
|
get :task_pdf
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Project Area START
|
# Project Area START
|
||||||
scope "/:owner/:repo" do
|
scope "/:owner/:repo" do
|
||||||
scope do
|
scope do
|
||||||
|
@ -712,7 +729,7 @@ Rails.application.routes.draw do
|
||||||
get :history
|
get :history
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :message_templates, only: [:index, :edit, :update] do
|
resources :message_templates, only: [:index, :new, :create, :edit, :update] do
|
||||||
collection do
|
collection do
|
||||||
get :init_data
|
get :init_data
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
class CreateUserTraceTasks < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :user_trace_tasks do |t|
|
||||||
|
t.references :user
|
||||||
|
t.references :project
|
||||||
|
t.string :branch_tag
|
||||||
|
t.string :task_id
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,35 @@
|
||||||
|
namespace :sync_outer_repo do
|
||||||
|
desc "sync outer repository to gitlink"
|
||||||
|
task done: :environment do
|
||||||
|
file = ENV['file'] || "rcore-os_repo.xlsx"
|
||||||
|
user_type = ENV['type'] || "User"
|
||||||
|
doc = SimpleXlsxReader.open("#{Rails.root}/public/#{file}")
|
||||||
|
data = doc.sheets.first.rows
|
||||||
|
data.each_with_index do |row, index|
|
||||||
|
next if index == 0
|
||||||
|
begin
|
||||||
|
user = (user_type == "User" ? User.find_by(login: row[1]) : Owner.find_by(login: row[1]))
|
||||||
|
project = user.projects.find_by(identifier: row[4])
|
||||||
|
unless project.present?
|
||||||
|
p_category = ProjectCategory.find_or_create_by(name: row[6])
|
||||||
|
p_language = ProjectLanguage.find_or_create_by(name: row[7].to_s.split("/")[0]) if row[7]
|
||||||
|
p_license = License.find_by(name: row[8])
|
||||||
|
|
||||||
|
mirror_params = {
|
||||||
|
user_id: user.id,
|
||||||
|
name: row[5],
|
||||||
|
description: row[9],
|
||||||
|
repository_name: row[4],
|
||||||
|
project_category_id: p_category.id,
|
||||||
|
project_language_id: p_language&.id,
|
||||||
|
clone_addr: row[10]
|
||||||
|
}
|
||||||
|
Projects::MigrateService.call(user, mirror_params)
|
||||||
|
end
|
||||||
|
puts "sync outer repository to gitlink Success repo: #{row[5]} username: #{row[0]}"
|
||||||
|
rescue Exception => e
|
||||||
|
puts "sync outer repository to gitlink Error repo: #{row[5]} username: #{row[0]}, error:#{e}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -467,6 +467,9 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="#4f8579f6bd" class="toc-h2 toc-link" data-title="取消迁移项目">取消迁移项目</a>
|
<a href="#4f8579f6bd" class="toc-h2 toc-link" data-title="取消迁移项目">取消迁移项目</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#88c0b2e25f" class="toc-h2 toc-link" data-title="退出项目">退出项目</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -543,6 +546,26 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#traces" class="toc-h1 toc-link" data-title="Traces">Traces</a>
|
||||||
|
<ul class="toc-list-h2">
|
||||||
|
<li>
|
||||||
|
<a href="#ca438fc3ca" class="toc-h2 toc-link" data-title="代码溯源初始化">代码溯源初始化</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#bb16c601f1" class="toc-h2 toc-link" data-title="代码分析结果列表">代码分析结果列表</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#32497859e0" class="toc-h2 toc-link" data-title="新建分析">新建分析</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#7b3a48e274" class="toc-h2 toc-link" data-title="重新扫描">重新扫描</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#87775b1430" class="toc-h2 toc-link" data-title="下载报告">下载报告</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#pulls" class="toc-h1 toc-link" data-title="Pulls">Pulls</a>
|
<a href="#pulls" class="toc-h1 toc-link" data-title="Pulls">Pulls</a>
|
||||||
<ul class="toc-list-h2">
|
<ul class="toc-list-h2">
|
||||||
|
@ -4968,7 +4991,7 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq
|
||||||
<tr>
|
<tr>
|
||||||
<td>menu_name</td>
|
<td>menu_name</td>
|
||||||
<td>string</td>
|
<td>string</td>
|
||||||
<td>导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置</td>
|
<td>导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,services:服务,activity:动态,setting:仓库设置</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
|
|
||||||
|
@ -5131,7 +5154,7 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json
|
||||||
<td>是</td>
|
<td>是</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>array</td>
|
<td>array</td>
|
||||||
<td>项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑</td>
|
<td>项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,resources:资源库,services:服务</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
<h3 id='7447e4874e-2'>返回字段说明:</h3>
|
<h3 id='7447e4874e-2'>返回字段说明:</h3>
|
||||||
|
@ -6026,6 +6049,49 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
|
||||||
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-04-26 09:54"</span><span class="p">,</span><span class="w">
|
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-04-26 09:54"</span><span class="p">,</span><span class="w">
|
||||||
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1分钟前"</span><span class="w">
|
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1分钟前"</span><span class="w">
|
||||||
</span><span class="p">}</span><span class="w">
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div><h2 id='88c0b2e25f'>退出项目</h2>
|
||||||
|
<p>供项目成员(开发者、报告者)退出项目用</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/ceshi1/ceshi_repo1/quit.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/:owner/:repo/quit.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http-15'>HTTP 请求</h3>
|
||||||
|
<p><code>POST /api/:owner/:repo/quit.json</code></p>
|
||||||
|
<h3 id='1f9ac54b15-13'>请求参数</h3>
|
||||||
|
<table><thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>必选</th>
|
||||||
|
<th>默认</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>字段说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
<tr>
|
||||||
|
<td>owner</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td></td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>用户登录名</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>repo</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td></td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目标识identifier</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
</span></code></pre></div><h1 id='repositories'>Repositories</h1><h2 id='0a366f0c25'>仓库详情</h2>
|
</span></code></pre></div><h1 id='repositories'>Repositories</h1><h2 id='0a366f0c25'>仓库详情</h2>
|
||||||
<p>仓库详情</p>
|
<p>仓库详情</p>
|
||||||
|
|
||||||
|
@ -9302,6 +9368,289 @@ http://localhost:3000/api/yystopf/ceshi/webhooks/3/test.json
|
||||||
<aside class="success">
|
<aside class="success">
|
||||||
Success Data.
|
Success Data.
|
||||||
</aside>
|
</aside>
|
||||||
|
<h1 id='traces'>Traces</h1><h2 id='ca438fc3ca'>代码溯源初始化</h2>
|
||||||
|
<p>用户同意协议后请求的接口,创建代码溯源的账号</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST <span class="se">\</span>
|
||||||
|
http://localhost:3000/api/traces/trace_users.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/traces/trace_users.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http'>HTTP 请求</h3>
|
||||||
|
<p><code>POST api/traces/trace_users.json</code></p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div>
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
<h2 id='bb16c601f1'>代码分析结果列表</h2>
|
||||||
|
<p>查询项目下代码分析的结果</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/task_results.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/traces/:owner/:repo/task_results.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http-2'>HTTP 请求</h3>
|
||||||
|
<p><code>GET api/traces/:owner/:repo/task_results.json</code></p>
|
||||||
|
<h3 id='1f9ac54b15'>请求参数</h3>
|
||||||
|
<table><thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>必选</th>
|
||||||
|
<th>默认</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>字段说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
<tr>
|
||||||
|
<td>owner</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目所有者标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>repo</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>page</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>页码</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>limit</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>15</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>每页数量</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
<h3 id='90889036d2'>返回字段说明(暂缺)</h3>
|
||||||
|
<!-- 参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
total_count |int |总数 |
|
||||||
|
public_keys.id |int |ID|
|
||||||
|
public_keys.name |string|密钥标题|
|
||||||
|
public_keys.content |string|密钥内容|
|
||||||
|
public_keys.fingerprint |string|密钥标识|
|
||||||
|
public_keys.created_time |string|密钥创建时间| -->
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"data"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
||||||
|
</span><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"accuracy"</span><span class="p">:</span><span class="w"> </span><span class="s2">"20"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"code_type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"depth"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"detect_flag"</span><span class="p">:</span><span class="w"> </span><span class="s2">"快速-组件级"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"detect_rule"</span><span class="p">:</span><span class="w"> </span><span class="s2">"快速-组件级,2,20,,开源软件,50,10"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"detect_startdate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-05-10 15:59:46 "</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"detect_status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"fail"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"detectflag"</span><span class="p">:</span><span class="w"> </span><span class="s2">"快速-组件级"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"fail_reason"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Invalid package type"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"file_name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"many_branch.zip"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"license_process"</span><span class="p">:</span><span class="w"> </span><span class="s2">"100"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"licenseparam"</span><span class="p">:</span><span class="w"> </span><span class="s2">"开源软件"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"package_type"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"product_name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"84727546110"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"project_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"6dbc3e42-5857-4ca4-a54d-58fd9dbf6dc5"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"sim_process"</span><span class="p">:</span><span class="w"> </span><span class="s2">"100"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"similarity_process"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"task_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"15139171-091b-4316-98b1-6068970efa44"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"totalsize"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"uid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"78"</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"vuln_process"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"vulnlevel"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span><span class="p">]</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div>
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
<h2 id='32497859e0'>新建分析</h2>
|
||||||
|
<p>用户选择仓库分支进行代码分析的接口</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST <span class="se">\</span>
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/tasks.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/traces/:owner/:repo/tasks.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http-3'>HTTP 请求</h3>
|
||||||
|
<p><code>POST api/traces/:owner/:repo/tasks.json</code></p>
|
||||||
|
<h3 id='1f9ac54b15-2'>请求参数</h3>
|
||||||
|
<table><thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>必选</th>
|
||||||
|
<th>默认</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>字段说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
<tr>
|
||||||
|
<td>owner</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目所有者标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>repo</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>branch_name</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>分支名称</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div>
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
<h2 id='7b3a48e274'>重新扫描</h2>
|
||||||
|
<p>对代码分析结果进行再次分析</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/reload_task.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/traces/:owner/:repo/reload_task.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http-4'>HTTP 请求</h3>
|
||||||
|
<p><code>GET api/traces/:owner/:repo/reload_task.json</code></p>
|
||||||
|
<h3 id='1f9ac54b15-3'>请求参数</h3>
|
||||||
|
<table><thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>必选</th>
|
||||||
|
<th>默认</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>字段说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
<tr>
|
||||||
|
<td>owner</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目所有者标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>repo</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>project_id</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>代码分析结果里的project_id</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div>
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
|
<h2 id='87775b1430'>下载报告</h2>
|
||||||
|
<p>把代码分析的结果下载到本地</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
|
||||||
|
http://localhost:3000/api/traces/yystopf/many_branch/task_pdf.json
|
||||||
|
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/traces/:owner/:repo/task_pdf.json</span><span class="dl">'</span><span class="p">)</span>
|
||||||
|
</code></pre></div><h3 id='http-5'>HTTP 请求</h3>
|
||||||
|
<p><code>GET api/traces/:owner/:repo/task_pdf.json</code></p>
|
||||||
|
<h3 id='1f9ac54b15-4'>请求参数</h3>
|
||||||
|
<table><thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>必选</th>
|
||||||
|
<th>默认</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>字段说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
<tr>
|
||||||
|
<td>owner</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目所有者标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>repo</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>项目标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>task_id</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>string</td>
|
||||||
|
<td>代码分析结果里的task_id</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>返回的JSON示例:</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
|
||||||
|
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
|
||||||
|
</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w">
|
||||||
|
</span><span class="p">}</span><span class="w">
|
||||||
|
</span></code></pre></div>
|
||||||
|
<aside class="success">
|
||||||
|
Success — a happy kitten is an authenticated kitten!
|
||||||
|
</aside>
|
||||||
<h1 id='pulls'>Pulls</h1><h2 id='get-a-pull-request'>Get a pull request</h2>
|
<h1 id='pulls'>Pulls</h1><h2 id='get-a-pull-request'>Get a pull request</h2>
|
||||||
<p>获取合并请求详情接口</p>
|
<p>获取合并请求详情接口</p>
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe UserTraceTask, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
Loading…
Reference in New Issue