forgeplus/app/controllers/application_controller.rb

1188 lines
37 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'oauth2'
# require 'openssl'
# require 'jwt'
class ApplicationController < ActionController::Base
include CodeExample
include RenderExpand
include RenderHelper
include ControllerRescueHandler
include LaboratoryHelper
include GitHelper
include LoggerHelper
include LoginHelper
include RegisterHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? }
before_action :check_sign
before_action :user_setup
#before_action :check_account
# TODO
# check sql query time
before_action do
# if request.subdomain === 'testforgeplus' || request.subdomain === "profiler"
# Rack::MiniProfiler.authorize_request
# end
end
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
OPENKEY = Rails.application.config_for(:configuration)['sign_key'] || "79e33abd4b6588941ab7622aed1e67e8"
helper_method :current_user, :base_url
# 所有请求必须合法签名
def check_sign
# if !Rails.env.development?
# Rails.logger.info("66666 #{params}")
# # suffix = request.url.split(".").last.split("?").first
# # suffix_arr = ["xls", "xlsx", "pdf", "zip"] # excel文件先注释
# # unless suffix_arr.include?(suffix)
# if params[:client_key].present?
# randomcode = params[:randomcode]
# # tip_exception(501, "请求不合理") unless (Time.now.to_i - randomcode.to_i).between?(0,5)
#
# sign = Digest::MD5.hexdigest("#{OPENKEY}#{randomcode}")
# Rails.logger.info("2222 #{sign}")
# tip_exception(501, "请求不合理") if sign != params[:client_key]
# else
# tip_exception(501, "请求不合理")
# end
# # end
# end
end
# 全局配置参数
# 返回name对应的value
def edu_setting(name)
EduSetting.get(name)
end
# 平台身份权限判断(学生用户无权限)
def identity_auth
ue = current_user.user_extension
tip_exception(403, "..") unless current_user.admin_or_business? || ue.teacher? || ue.professional?
end
# 平台已认证身份判断(已认证的老师和专业人士)
def certi_identity_auth
ue = current_user.user_extension
tip_exception(403, "..") unless current_user.admin_or_business? ||
(current_user.professional_certification && (ue.teacher? || ue.professional?))
end
def admin_or_business?
User.current.admin? || User.current.business?
end
def admin_or_glcc_admin?
User.current.admin? || User.current.glcc_admin?
end
# 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码3绑定
def check_mail_and_phone_valid login, type
unless login =~ /\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 =~ /^1\d{10}$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end
user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
if user_exist && type.to_i == 1
tip_exception(-2, "该手机号码或邮箱已被注册")
elsif type.to_i == 2 && !user_exist
tip_exception(-2, "该手机号码或邮箱未注册")
elsif type.to_i == 3 && user_exist
tip_exception(-2, "该手机号码或邮箱已绑定")
end
render_ok
end
# 发送及记录激活码
# 发送验证码type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱
# 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 9验证手机号有效
def check_verification_code(code, send_type, value)
case send_type
when 1, 2, 4, 9
# 手机类型的发送
sigle_para = {phone: value}
# status = Gitlink::Sms.send(mobile: value, code: code)
# tip_exception(-2, code_msg(status)) if status != 0
status = Sms::UcloudService.call(value, code, send_type)
tip_exception(-2, ucloud_code_msg(status)) if status != 0
when 8, 3, 5
# 邮箱类型的发送
sigle_para = {email: value}
# 60s内不能重复发送
# send_email_limit_cache_key = "send_email_60_second_limit:#{value}"
# tip_exception(-1, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key)
# # 短时间内不能大量发送
# send_email_control = LimitForbidControl::SendEmailCode.new(value)
# tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid?
begin
if send_type == 3
UserMailer.find_password(value, code).deliver_now
elsif send_type == 5
UserMailer.bind_email(value, code).deliver_now
else
UserMailer.register_email(value, code).deliver_now
end
# Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute)
# send_email_control.increment!
# Mailer.run.email_register(code, value)
rescue Exception => e
logger_error(e)
tip_exception(-2,"邮件发送失败,请稍后重试")
end
end
ver_params = {code_type: send_type, code: code}.merge(sigle_para)
VerificationCode.create!(ver_params)
end
def code_msg status
case status
when 0
"验证码已经发送到您的手机,请注意查收"
when 8
"同一手机号30秒内重复提交相同的内容"
when 9
"同一手机号5分钟内重复提交相同的内容超过3次"
when 22
"1小时内同一手机号发送次数超过限制"
when 33
"验证码发送次数超过频率"
when 43
"一天内同一手机号发送次数超过限制"
when 53
"手机号接收超过频率限制"
end
end
def ucloud_code_msg status
case status
when 0
"验证码已经发送到您的手机,请注意查收"
when 171
"API签名错误"
when 18014
"无效手机号码"
when 18017
"无效模板"
when 18018
"短信模板参数与短信模板不匹配"
when 18023
"短信内容中含有运营商拦截的关键词"
when 18033
"变量内容不符合规范"
else
"错误码#{status}"
end
end
def validate_type(object_type)
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def set_pagination
@page = params[:page] || 1
@page_size = params[:page_size] || 15
end
def require_admin
normal_status(403, "") unless User.current.admin?
end
def require_business
normal_status(403, "") unless admin_or_business?
end
def require_glcc_admin
normal_status(403, "") unless admin_or_glcc_admin?
end
# 前端会捕捉401,弹登录弹框
# 未授权的捕捉407弹试用申请弹框
def require_login
#6.13 -hs
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
def require_login_or_token
if params[:token].present?
user = User.try_to_autologin(params[:token])
User.current = user
end
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
def require_login_cloud_ide_saas
if params[:sign].present? && params[:email].present?
sign = Digest::MD5.hexdigest("#{OPENKEY}#{params[:email]}")
if params[:sign].to_s == sign
user = User.find_by(mail: params[:email])
User.current = user
end
end
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
def require_profile_completed
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
end
def require_user_profile_completed(user)
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
end
# 异常提醒
def tip_exception(status = -1, message)
raise Gitlink::TipException.new(status, message)
end
def missing_template
tip_exception(404, "...")
end
# 弹框提醒
def tip_show_exception(status = -2, message)
raise Gitlink::TipException.new(status, message)
end
def normal_status(status = 0, message)
case status
when 403
message = "您没有权限进行该操作"
when 404
message = "您访问的页面不存在或已被删除"
end
render :json => { status: status, message: message }
end
# 资料是否完善
def check_account
if !current_user. profile_is_completed?
#info_url = '/account/profile'
tip_exception(402, nil)
end
end
# 系统全局认证(暂时隐藏试用申请的判断)
def check_auth
# day_cer = UserDayCertification.find_by(user_id: current_user.id)
# # 如果注册超过24小时则需要完善资料及授权
# if (Time.now.to_i - day_cer.try(:created_at).to_i) > 86400
# if !current_user.profile_completed?
# info_url = '/account/profile'
# tip_exception(402, info_url)
# elsif current_user.certification != 1
# if current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
# tip_exception(408, "您的试用申请正在审核中,请耐心等待")
# end
# tip_exception(407, "系统未授权")
# end
# end
# if current_user.certification != 1 && current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
# tip_exception(408, "您的试用申请正在审核中,请耐心等待")
# elsif (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
# if !current_user.profile_completed?
# info_url = '/account/profile'
# tip_exception(402, info_url)
# elsif current_user.certification != 1
# day_cer = UserDayCertification.find_by(user_id: current_user.id)
# tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
# end
# end
end
def user_setup
# # reacct静态资源加载不需要走这一步
#return if params[:controller] == "main"
# Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
if !valid_doorkeeper_token?
header = request.authorization
pattern = /^Bearer /i
token = header.gsub(pattern, "")
User.current, message = Bot.decode_jwt_token(token)
tip_exception(401, message) if message.present?
else
if @doorkeeper_token.present?
# client方法对接需要一直带着用户标识uid
if @doorkeeper_token.resource_owner_id.blank?
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
User.current = User.find(params[:uid])
else
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
end
end
end
else
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
# 开放课程通过链接访问的用户
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
user = open_class_user
if user
start_user_session(user)
set_autologin_cookie(user)
end
User.current = user
end
end
if !User.current.logged? && Rails.env.development?
user = User.find 1
User.current = user
start_user_session(user)
end
# 测试版前端需求
logger.info("subdomain:#{request.subdomain}")
if request.subdomain != "www"
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 81403
elsif params[:debug] == 'student'
User.current = User.find 8686
elsif params[:debug] == 'admin'
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
user = User.find 36480
User.current = user
cookies.signed[:user_id] = user.id
end
end
end
# User.current = User.find 81403
end
# Returns the current user or nil if no user is logged in
# and starts a session if needed
def find_current_user
uid_logger("user setup start: session[:user_id] is #{session[:user_id]}")
uid_logger("0000000000000user setup start: default_yun_session is #{default_yun_session}, session[:current_user_id] is #{session[:"#{default_yun_session}"]}")
current_domain_session = session[:"#{default_yun_session}"]
if current_domain_session
# existing session
User.current = (User.active.find(current_domain_session) rescue nil)
elsif autologin_user = try_to_autologin
autologin_user
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session
User.find_by_rss_key(params[:key])
end
end
def try_to_autologin
if cookies[autologin_cookie_name]
# auto-login feature starts a new session
user = nil
Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
user = User.try_to_autologin(cookies[autologin_cookie_name])
# start_user_session(user) if user # TODO 解决sso退出不同步的问题
user
end
end
def api_request?
%w(xml json).include? params[:format]
end
def current_user
User.current
end
## 默认输出json
def render_json
respond_to do |format|
format.json
end
end
## 输出错误信息
def error_status(message = nil)
@status = -1
@message = message
end
def repo_url(repo_path)
"#{edu_setting('git_address_domain')}/#{repo_path}"
end
# 通关后,把最后一次成功的代码存到数据库
# type 0 创始内容, 1 最新内容
# def game_passed_code(path, myshixun, game_id)
# # 如果代码窗口是隐藏的,则不用保存代码
# return if myshixun.shixun.hide_code || myshixun.shixun.vnc
# file_content = git_fle_content myshixun.repo_path, path
# #unless file_content.present?
# # raise("获取文件代码异常")
# #end
# logger.info("#######game_id:#{game_id}, file_content:#{file_content}")
# game_code = GameCode.where(:game_id => game_id, :path => path).first
# if game_code.nil?
# GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path)
# else
# game_code.update_attributes!(:new_code => file_content)
# end
# end
# Post请求
def uri_post(uri, params)
begin
uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.post_form(uri, params).body
uid_logger_dubug("--uri_exec: .....res is #{res}")
JSON.parse(res)
rescue Exception => e
uid_logger_error("--uri_exec: exception #{e.message}")
raise Gitlink::TipException.new("实训平台繁忙繁忙等级84")
end
end
# 处理返回非0就报错的请求
def interface_post(uri, params, status, message)
begin
uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.post_form(uri, params).body
uid_logger_dubug("--uri_exec: .....res is #{res}")
res = JSON.parse(res)
if (res && res['code'] != 0)
tip_exception(status, message)
else
res
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Gitlink::TipException.new(message)
end
end
# json格式请求
def interface_json_post(uri, params, status, message)
begin
uid_logger_dubug("--uri_exec: params is #{params}, url is #{uri}")
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.start(uri.host, uri.port) do |http|
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = params.to_json
http.request(req)
end
uid_logger_dubug("--uri_exec: .....res is #{res.body}")
res = JSON.parse(res.body)
if (res && res['code'] != 0)
tip_exception(status, message)
else
res
end
rescue Exception => e
uid_logger("--uri_exec: exception #{e.message}")
raise Gitlink::TipException.new("服务器繁忙")
end
end
# 适用与已经用url_safe编码后回调字符串形式
def tran_base64_decode64(str)
s_size = str.size % 4
if s_size != 0
str += "=" * (4 - s_size)
end
if str.blank?
str
else
Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8")
end
end
def sucess_status(message = 'success')
render :json => { status: 1, message: message }
end
# 随机生成字符
def generate_identifier(container, num, pre='')
code = DCODES.sample(num).join
if container == User
while container.exists?(login: pre+code) do
code = DCODES.sample(num).join
end
else
while container.exists?(identifier: code) do
code = DCODES.sample(num).join
end
end
code
end
# 实训主类别列表,自带描述
def shixun_main_type
list = []
mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_main_mirror
mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name, description: mirror.try(:description), mirror_name: mirror.name}
end
list
end
# 小类别列表
def shixun_small_type
list = []
mirrors = MirrorRepository.select([:id, :type_name, :description, :name]).published_small_mirror
mirrors.try(:each) do |mirror|
list << {id: mirror.id, type_name: mirror.type_name, description: mirror.description, mirror_name: mirror.name}
end
list
end
def container_limit(mirror_repositories)
container = []
mirror_repositories.each do |mr|
if mr.name.present?
container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 实训中间层pod配置
def shixun_container_limit shixun
container = []
shixun.shixun_service_configs.each do |config|
mirror = config.mirror_repository
if mirror.name.present?
# 资源限制没有就传默认值。
cpu_limit = config.cpu_limit.presence || 1
cpu_request = config.lower_cpu_limit.presence || 0.1
memory_limit = config.memory_limit.presence || 1024
request_limit = config.request_limit.presence || 10
resource_limit = config.resource_limit.presence || 10000
container << {:image => mirror.name,
:cpuLimit => cpu_limit,
:cpuRequest => cpu_request,
:memoryLimit => "#{memory_limit}M",
:memoryRequest => "#{request_limit}M",
:resourceLimit => "#{resource_limit}K",
:type => mirror.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 毕设任务列表的赛选
def course_work(task, **option)
logger.info("#############{option}")
course = task.course
work_list = task.graduation_works.includes(user: [:user_extension])
# 教师评阅搜索 0: 未评, 1 已评
if option[:teacher_comment]
graduation_work_ids = GraduationWorkScore.where(graduation_work_id: work_list.map(&:id)).pluck(:graduation_work_id)
if option[:teacher_comment].zero?
work_list = work_list.where.not(id: graduation_work_ids)
elsif option[:teacher_comment] == 1
work_list = work_list.where(id: graduation_work_ids).where.not(work_status: 0)
end
end
# 作品状态 0 未提交, 1 按时提交, 2 延迟提交
if option[:task_status]
work_list = work_list.where(work_status: option[:task_status])
end
# 分班情况
if option[:course_group]
group_user_ids = course.course_members.where(course_group_id: option[:course_group]).pluck(:user_id)
# 有分组只可能是老师身份查看列表
work_list = work_list.where(user_id: group_user_ids)
end
# 只看我的交叉评阅
if option[:cross_comment]
graduation_work_id = task.graduation_work_comment_assignations.where(:user_id => current_user.id)
.pluck(:graduation_work_id).uniq if task.graduation_work_comment_assignations
work_list = work_list.where(id: graduation_work_id)
end
# 输入姓名和学号搜索
# TODO user_extension 如果修改 请调整
if option[:search]
work_list = work_list.joins(user: :user_extension).where("concat(lastname, firstname) like ?
or student_id like ?", "%#{option[:search]}%", "%#{option[:search]}%")
end
# 排序
rorder = UserExtension.column_names.include?(option[:order]) ? option[:order] : "updated_at"
b_order = %w(desc asc).include?(option[:b_order]) ? option[:b_order] : "desc"
if rorder == "created_at" || rorder == "work_score"
work_list = work_list.order("graduation_works.#{rorder} #{b_order}")
elsif rorder == "student_id"
work_list = work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end
work_list
end
def strip_html(text, len=0, endss="...")
ss = ""
if !text.nil? && text.length>0
ss=text.gsub(/<\/?.*?>/, '').strip
ss = ss.gsub(/&nbsp;*/, '')
ss = ss.gsub(/\r\n/,'') #新增
ss = ss.gsub(/\n/,'') #新增
if len > 0 && ss.length > len
ss = ss[0, len] + endss
elsif len > 0 && ss.length <= len
ss = ss
#ss = truncate(ss, :length => len)
end
end
ss
end
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name
end
def format_time(time)
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M")
end
# 获取Oauth Client
def get_client(site)
client_id = Rails.configuration.Gitlink['client_id']
client_secret = Rails.configuration.Gitlink['client_secret']
OAuth2::Client.new(client_id, client_secret, site: site)
end
def paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
offset = (page - 1) * limit
if relation.is_a?(Array)
relation[offset, limit]
else
relation.limit(limit).offset(offset)
end
end
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 50) ? 50 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
end
def kaminari_unlimit_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 9999) ? 9999 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
end
def kaminari_array_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
Kaminari.paginate_array(relation).page(page).per(limit)
end
def strf_time(time)
time.blank? ? '' : time.strftime("%Y-%m-%d %H:%M:%S")
end
def strf_date(date)
date.blank? ? '' : date.to_date.strftime("%Y-%m-%d")
end
def logger_error(error)
Rails.logger.error(error.message)
error.backtrace.each { |msg| Rails.logger.error(msg) }
end
def find_user
@user = User.find_by_login params[:login]
render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
end
def find_user_with_id
@user = User.find_by(type: 'User', id: params[:user_id])
# render_not_found("未找到’#{params[:login]}’相关的用户") unless @user
render_error("未找到相关的用户") unless @user
end
def find_repository
@repo = @user.repositories.find_by_identifier params[:repo_identifier]
render_not_found("未找到’#{params[:repo_identifier]}’相关的项目") unless @repo
end
def find_repository_by_id
@repo = Repository.find params[:id]
end
def find_project
project_id = params[:project_id] ? params[:project_id] : params[:id]
project = Project.where(identifier: project_id)
if project.exists?
@project = project.first
else
@project = Project.find project_id
end
render_not_found("未找到’#{project}’相关的项目") unless @project
end
def find_project_with_id
@project = Project.find(params[:project_id] || params[:id])
rescue Exception => e
logger_error(e.message)
tip_exception(e.message)
end
def render_response(interactor)
interactor.success? ? render_ok : render_error(interactor.error)
end
# projects
def load_project
namespace = params[:owner]
id = params[:repo] || params[:id]
@project, @owner = Project.find_with_namespace(namespace, id)
if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
logger.info "########### has project and can read project"
@project
# elsif @project && current_user.is_a?(AnonymousUser)
# logger.info "###########This is AnonymousUser"
# @project = nil if !@project.is_public?
# render_forbidden and return
else
if @project.present?
logger.info "########### has project and but can't read project"
@project = nil
render_forbidden and return
else
logger.info "###########project not found"
@project = nil
render_not_found and return
end
end
@project
end
def load_repository
@repository ||= load_project&.repository
end
def base_url
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
end
def image_type?(str)
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
default_type.include?(str&.downcase)
end
def convert_image!
@image = params[:image]
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
return unless @image.present?
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
if @image.class == ActionDispatch::Http::UploadedFile
return render_error('请上传文件') if @image.size.zero?
return render_error('文件大小超过限制') if @image.size > max_size.to_i
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
else
image = @image.to_s.strip
return render_error('请上传正确的图片') if image.blank?
@image = Util.convert_base64_image(image, max_size: max_size.to_i)
end
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
def avatar_path(object)
ApplicationController.helpers.disk_filename(object.class, object.id)
end
private
def object_not_found
uid_logger("Missing template or cant't find record, responding with 404")
render json: {message: "您访问的页面不存在或已被删除", status: 404}
false
end
def tip_show(exception)
uid_logger("Tip show status is #{exception.status}, message is #{exception.message}")
render json: exception.tip_json
end
def set_export_cookies
cookies[:fileDownload] = true
end
# 记录热门搜索关键字
def record_search_keyword
keyword = params[:keyword].to_s.strip
return if keyword.blank? || keyword.size <= 1
return unless HotSearchKeyword.available?
HotSearchKeyword.add(keyword)
end
# author: zxh
# blockchain相关项目活动调用函数
# return true: 表示上链操作成功; return false: 表示上链操作失败
def push_activity_2_blockchain(activity_type, model)
if activity_type == "issue_create"
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
id = model['id']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
identifier = project['identifier']
author_id = project['user_id']
author = User.find(author_id)
username = author['login']
action = 'opened'
title = model['subject']
content = model['description']
created_at = model['created_on']
updated_at = model['updated_on']
# 调用区块链接口
params = {
"request-type": "upload issue info",
"issue_id": "gitlink-" + id.to_s,
"repo_id": "gitlink-" + project_id.to_s,
"issue_number": 0, # 暂时不需要改字段
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"title": title,
"content": content,
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "issue_comment_create"
issue_comment_id = model['id']
issue_id = model['journalized_id']
parent_id = model['parent_id'].nil? ? "" : model['parent_id']
issue = Issue.find(issue_id)
issue_classify = issue['issue_classify'] # issue或pull_request
project_id = issue['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
action = 'created'
content = model['notes']
created_at = model['created_on']
if issue_classify == "issue"
params = {
"request-type": "upload issue comment info",
"issue_comment_id": "gitlink-" + issue_comment_id.to_s,
"issue_comment_number": 0, # 暂时不需要
"issue_number": 0, # 暂时不需要
"issue_id": "gitlink-" + issue_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"parent_id": parent_id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
elsif issue_classify == "pull_request"
params = {
"request-type": "upload pull request comment info",
"pull_request_comment_id": "gitlink-" + issue_comment_id.to_s,
"pull_request_comment_number": 0, # 不考虑该字段
"pull_request_number": 0, # 不考虑该字段
"pull_request_id": "gitlink-" + issue_id.to_s,
"parent_id": parent_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
end
# 调用区块链接口
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_create"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'opened'
title = model['title']
content = model['body']
source_branch = model['head']
source_repo_id = model['fork_project_id'].nil? ? project_id : model['fork_project_id']
target_branch = model['base']
target_repo_id = project_id
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
if commits.nil?
raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_merge"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'merged'
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'], current_user&.gitea_token)
if commits.nil?
raise ApplicationService::Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
# 将commit相关信息写入链上
commit_shas.each do |commit_sha|
commit_diff = Gitea::Commit::DiffService.call(ownername, identifier, commit_sha, owner['gitea_token'])
commit = Gitea::Commit::InfoService.call(ownername, identifier, commit_sha, owner['gitea_token'])
params = {
"request-type": "upload commit info",
"commit_hash": commit_sha,
"repo_id": "gitlink-" + project_id.to_s,
"author": commit['commit']['author']['name'],
"author_email": commit['commit']['author']['email'],
"committer": commit['commit']['committer']['name'],
"committer_email": commit['commit']['committer']['email'],
"author_time": commit['commit']['author']['date'],
"committer_time": commit['commit']['committer']['date'],
"content": commit['commit']['message'],
"commit_diff": commit_diff.present? ? commit_diff['Files'].to_s : ""
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 7
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
end
elsif activity_type == "pull_request_refuse"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'refused'
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise ApplicationService::Error, resp_body['message']
elsif resp_body['status'] != 0
raise ApplicationService::Error, "区块链接口请求失败."
end
end
end
def find_atme_receivers
@atme_receivers = User.where(login: params[:receivers_login])
end
# 接口限流,请求量大有性能问题
def request_limit
record_count = Rails.cache.read("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H%M')}/#{request.remote_ip}")
if record_count.present?
record_count = record_count + 1
else
record_count = 1
end
tip_exception("请求太快,请稍后再试。") if record_count > 100
Rails.cache.write("request/#{controller_name}/#{Time.now.strftime('%Y%m%d%H%M')}/#{request.remote_ip}", record_count, expires_in: 1.minute)
end
end