forked from Gitlink/forgeplus
Merge branch 'develop'
This commit is contained in:
commit
196d1d74af
6
Gemfile
6
Gemfile
|
@ -118,6 +118,10 @@ gem 'deep_cloneable', '~> 3.0.0'
|
|||
# oauth2
|
||||
gem 'omniauth', '~> 1.9.0'
|
||||
gem 'omniauth-oauth2', '~> 1.6.0'
|
||||
gem "omniauth-github"
|
||||
gem "omniauth-rails_csrf_protection"
|
||||
gem 'omniauth-gitee', '~> 1.0.0'
|
||||
gem "omniauth-wechat-oauth2"
|
||||
|
||||
# global var
|
||||
gem 'request_store'
|
||||
|
@ -135,4 +139,4 @@ gem 'doorkeeper'
|
|||
|
||||
gem 'doorkeeper-jwt'
|
||||
|
||||
gem 'gitea-client', '~> 0.10.5'
|
||||
gem 'gitea-client', '~> 0.11.1'
|
|
@ -141,6 +141,7 @@ class AccountsController < ApplicationController
|
|||
Register::Form.new(register_params).validate!
|
||||
|
||||
user = Users::RegisterService.call(register_params)
|
||||
user.mail = "#{user.login}@example.org" if user.mail.blank?
|
||||
password = register_params[:password].strip
|
||||
|
||||
# gitea用户注册, email, username, password
|
||||
|
@ -152,6 +153,10 @@ class AccountsController < ApplicationController
|
|||
user.gitea_uid = gitea_user[:body]['id']
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
# 绑定授权账号
|
||||
if ["qq", "wechat", "gitee", "github", "educoder"].include?(params[:type].to_s) && session[:unionid].present?
|
||||
"OpenUsers::#{params[:type].to_s.capitalize}".constantize.create!(user: user, uid: session[:unionid])
|
||||
end
|
||||
successful_authentication(user)
|
||||
render_ok
|
||||
end
|
||||
|
@ -393,7 +398,7 @@ class AccountsController < ApplicationController
|
|||
end
|
||||
|
||||
def register_params
|
||||
params.permit(:login, :namespace, :password, :password_confirmation, :code)
|
||||
params.permit(:login, :namespace, :password, :password_confirmation, :code, :type)
|
||||
end
|
||||
|
||||
def reset_password_params
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
class Admins::FeedbacksController < Admins::BaseController
|
||||
before_action :get_feedback, only: [:new_history, :create_history, :destroy]
|
||||
|
||||
def index
|
||||
sort_by = Feedback.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
feedbacks = Feedback.order("#{sort_by} #{sort_direction}")
|
||||
@feedbacks = paginate(feedbacks)
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @feedback.destroy
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:success] = "反馈意见删除成功"
|
||||
else
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:danger] = "反馈意见删除失败"
|
||||
end
|
||||
end
|
||||
|
||||
def new_history
|
||||
@feedback_message_history = FeedbackMessageHistory.new
|
||||
end
|
||||
|
||||
def create_history
|
||||
@feedback_message_history = @feedback.feedback_message_histories.new(feedback_message_history_params)
|
||||
@feedback_message_history.user = current_user
|
||||
if @feedback_message_history.save
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:success] = "发送通知成功"
|
||||
else
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:danger] = @feedback_message_history.errors.full_messages.join(", ")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def feedback_params
|
||||
params.require(:feedback).permit!
|
||||
end
|
||||
|
||||
def feedback_message_history_params
|
||||
params.require(:feedback_message_history).permit(:title, :content)
|
||||
end
|
||||
|
||||
def get_feedback
|
||||
@feedback = Feedback.find_by_id(params[:id])
|
||||
end
|
||||
end
|
|
@ -53,6 +53,6 @@ class Admins::Topic::BannersController < Admins::Topic::BaseController
|
|||
end
|
||||
|
||||
def banner_params
|
||||
params.require(:topic_banner).permit(:title, :order_index)
|
||||
params.require(:topic_banner).permit(:title, :order_index, :url)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class Api::V1::Projects::CodeStatsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: params[:ref]}, current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
class Api::V1::Users::FeedbacksController < Api::V1::BaseController
|
||||
|
||||
before_action :load_observe_user
|
||||
before_action :check_auth_for_observe_user
|
||||
|
||||
def create
|
||||
@result = Api::V1::Users::Feedbacks::CreateService.call(@observe_user, feedback_params)
|
||||
return render_error("反馈意见创建失败.") if @result.nil?
|
||||
return render_ok
|
||||
end
|
||||
|
||||
private
|
||||
def feedback_params
|
||||
params.permit(:content)
|
||||
end
|
||||
end
|
|
@ -70,6 +70,21 @@ class Api::V1::UsersController < Api::V1::BaseController
|
|||
render_ok
|
||||
end
|
||||
|
||||
def check_phone_verify_code
|
||||
code = strip(params[:code])
|
||||
phone = strip(params[:phone])
|
||||
code_type = params[:code_type]
|
||||
|
||||
return tip_exception(-2, "手机号格式有误") unless phone =~ CustomRegexp::PHONE
|
||||
|
||||
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: code_type).last
|
||||
return render_ok if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||
|
||||
return tip_exception(-6, "验证码不正确") if verifi_code&.code != code
|
||||
return tip_exception(-6, "验证码已失效") if !verifi_code&.effective?
|
||||
render_ok
|
||||
end
|
||||
|
||||
def update_email
|
||||
@result_object = Api::V1::Users::UpdateEmailService.call(@observe_user, params, current_user.gitea_token)
|
||||
if @result_object
|
||||
|
@ -78,4 +93,13 @@ class Api::V1::UsersController < Api::V1::BaseController
|
|||
return render_error('更改邮箱失败!')
|
||||
end
|
||||
end
|
||||
|
||||
def update_phone
|
||||
@result_object = Api::V1::Users::UpdatePhoneService.call(@observe_user, params)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('更改手机号失败!')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -79,8 +79,7 @@ class ApplicationController < ActionController::Base
|
|||
# 判断用户的邮箱或者手机是否可用
|
||||
# params[:type] 1: 注册;2:忘记密码;3:绑定
|
||||
def check_mail_and_phone_valid login, type
|
||||
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/ ||
|
||||
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
|
||||
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/
|
||||
tip_exception(-2, "请输入正确的手机号或邮箱")
|
||||
end
|
||||
|
||||
|
@ -103,8 +102,10 @@ class ApplicationController < ActionController::Base
|
|||
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 = 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}
|
||||
|
@ -116,8 +117,13 @@ class ApplicationController < ActionController::Base
|
|||
send_email_control = LimitForbidControl::SendEmailCode.new(value)
|
||||
tip_exception(-1, '邮件发送太频繁,请稍后再试') if send_email_control.forbid?
|
||||
begin
|
||||
UserMailer.register_email(value, code).deliver_now
|
||||
|
||||
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)
|
||||
|
@ -149,6 +155,27 @@ class ApplicationController < ActionController::Base
|
|||
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
|
||||
|
@ -638,7 +665,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def kaminari_paginate(relation)
|
||||
limit = params[:limit] || params[:per_page]
|
||||
limit = (limit.to_i.zero? || limit.to_i > 25) ? 25 : limit.to_i
|
||||
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)
|
||||
|
|
|
@ -32,7 +32,7 @@ class AttachmentsController < ApplicationController
|
|||
def get_file
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = base_url.starts_with?("https:") ? URI.encode(params[:download_url].to_s.gsub("http:", "https:")) : URI.encode(params[:download_url].to_s)
|
||||
if url.starts_with?(base_url)
|
||||
if url.starts_with?(base_url) && !url.starts_with?("#{base_url}/repo")
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
url = ("/repos"+url.split(base_url + "/api")[1]).gsub('?filepath=', '/').gsub('&', '?')
|
||||
|
@ -213,20 +213,17 @@ class AttachmentsController < ApplicationController
|
|||
def attachment_candown
|
||||
unless current_user.admin? || current_user.business?
|
||||
candown = true
|
||||
unless params[:type] == 'history'
|
||||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user) || course.is_public
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user) || course.is_public
|
||||
else
|
||||
course = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
||||
if @file.container
|
||||
if @file.container.is_a?(Issue)
|
||||
project = @file.container.project
|
||||
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||
elsif @file.container.is_a?(Journal)
|
||||
project = @file.container.issue.project
|
||||
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||
else
|
||||
project = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if project.present? && !candown
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,35 +1,19 @@
|
|||
class BindUsersController < ApplicationController
|
||||
# before_action :require_login
|
||||
|
||||
def create
|
||||
# user = CreateBindUserService.call(create_params)
|
||||
#
|
||||
if params[:type] == "qq"
|
||||
begin
|
||||
user = CreateBindUserService.call(current_user, create_params)
|
||||
successful_authentication(user) if user.id != current_user.id
|
||||
Rails.logger.debug "--------------开始绑定用户------------"
|
||||
Rails.logger.debug "--------------params: #{params.to_unsafe_h}"
|
||||
tip_exception '系统错误' if session[:unionid].blank?
|
||||
|
||||
render_ok
|
||||
rescue ApplicationService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
else
|
||||
begin
|
||||
tip_exception '系统错误' if session[:unionid].blank?
|
||||
bind_user = User.try_to_login(params[:username], params[:password])
|
||||
tip_exception '用户名或者密码错误' if bind_user.blank?
|
||||
tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s)
|
||||
tip_exception '参数错误' unless ["qq", "wechat", "gitee", "github", "educoder"].include?(params[:type].to_s)
|
||||
tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
|
||||
|
||||
bind_user = User.try_to_login(params[:username], params[:password])
|
||||
tip_exception '用户名或者密码错误' if bind_user.blank?
|
||||
tip_exception '用户名或者密码错误' unless bind_user.check_password?(params[:password].to_s)
|
||||
tip_exception '该账号已被绑定,请更换其他账号进行绑定' if bind_user.bind_open_user?(params[:type].to_s)
|
||||
|
||||
OpenUsers::Wechat.create!(user: bind_user, uid: session[:unionid])
|
||||
successful_authentication(bind_user)
|
||||
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
render_error(e.message)
|
||||
end
|
||||
end
|
||||
"OpenUsers::#{params[:type].to_s.capitalize}".constantize.create!(user: bind_user, uid: session[:unionid])
|
||||
successful_authentication(bind_user)
|
||||
@user = bind_user
|
||||
end
|
||||
|
||||
def new_user
|
||||
|
|
|
@ -11,7 +11,7 @@ module LoginHelper
|
|||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
sync_user_token_to_trustie(user.login, token.value)
|
||||
# sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
|
||||
cookie_options = {
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
module RegisterHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def autologin_register(username, email, password, platform= 'forge', need_edit_info = false)
|
||||
def autologin_register(username, email, password, platform = 'forge', phone = nil, nickname =nil, need_edit_info = false)
|
||||
result = {message: nil, user: nil}
|
||||
email = email.blank? ? "#{username}@example.org" : email
|
||||
|
||||
user = User.new(admin: false, login: username, mail: email, type: "User")
|
||||
user.password = password
|
||||
user.platform = platform
|
||||
user.phone = phone if phone.present?
|
||||
user.nickname = nickname if nickname.present?
|
||||
if need_edit_info
|
||||
user.need_edit_info
|
||||
else
|
||||
else
|
||||
user.activate
|
||||
end
|
||||
|
||||
|
||||
return unless user.valid?
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
||||
|
@ -67,7 +70,7 @@ module RegisterHelper
|
|||
user.password = params[:password]
|
||||
user.mail = params[:email]
|
||||
|
||||
if user.save!
|
||||
if user.save!
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: params[:email],
|
||||
|
@ -75,9 +78,9 @@ module RegisterHelper
|
|||
new_name: params[:username],
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||
if interactor.success?
|
||||
if interactor.success?
|
||||
result[:user] = user
|
||||
else
|
||||
result[:message] = '用户同步Gitea失败!'
|
||||
|
|
|
@ -7,7 +7,7 @@ class IssueTagsController < ApplicationController
|
|||
|
||||
|
||||
def index
|
||||
issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}")
|
||||
issue_tags = @project.issue_tags.includes(:issues).reorder("issue_tags.#{order_name} #{order_type}")
|
||||
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
|
|
|
@ -3,6 +3,7 @@ class Oauth::BaseController < ActionController::Base
|
|||
include LoginHelper
|
||||
include ControllerRescueHandler
|
||||
include LoggerHelper
|
||||
include RegisterHelper
|
||||
# include LaboratoryHelper
|
||||
|
||||
skip_before_action :verify_authenticity_token
|
||||
|
@ -13,13 +14,13 @@ class Oauth::BaseController < ActionController::Base
|
|||
|
||||
private
|
||||
def tip_exception(status = -1, message)
|
||||
raise Educoder::TipException.new(status, message)
|
||||
raise Gitlink::TipException.new(status, message)
|
||||
end
|
||||
|
||||
|
||||
def tip_show_exception(status = -2, message)
|
||||
raise Educoder::TipException.new(status, message)
|
||||
raise Gitlink::TipException.new(status, message)
|
||||
end
|
||||
|
||||
|
||||
def tip_show(exception)
|
||||
uid_logger("Tip show status is #{exception.status}, message is #{exception.message}")
|
||||
render json: exception.tip_json
|
||||
|
@ -35,7 +36,7 @@ class Oauth::BaseController < ActionController::Base
|
|||
end
|
||||
|
||||
def auth_hash
|
||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
# Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
request.env['omniauth.auth']
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
class Oauth::CallbacksController < Oauth::BaseController
|
||||
def create
|
||||
process_callback_new
|
||||
rescue Exception => e
|
||||
Rails.logger.info "授权失败:#{e}"
|
||||
tip_exception("授权失败")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def config_providers
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth").keys
|
||||
end
|
||||
|
||||
# QQ: {"ret":0,"msg":"","is_lost":0,"nickname":"颜值不算太高","gender":"男","gender_type":1,"province":"","city":"","year":"2013","constellation":"","figureurl":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/30","figureurl_1":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/50","figureurl_2":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/100","figureurl_qq_1":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=40\u0026t=1568887757","figureurl_qq_2":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=100\u0026t=1568887757","figureurl_qq":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=140\u0026t=1568887757","figureurl_type":"1","is_yellow_vip":"0","vip":"0","yellow_vip_level":"0","level":"0","is_yellow_year_vip":"0"}
|
||||
def process_callback
|
||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
if auth_hash.blank?
|
||||
redirect_to("/login") && return
|
||||
end
|
||||
|
||||
new_user = false
|
||||
platform = auth_hash[:provider]
|
||||
uid = auth_hash[:uid]
|
||||
mail = auth_hash.info.email || nil
|
||||
nickname = ["gitee", "github"].include?(platform) ? auth_hash.info.name : auth_hash.info.nickname
|
||||
|
||||
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid)
|
||||
if open_user.present? && open_user.user.present?
|
||||
successful_authentication(open_user.user)
|
||||
else
|
||||
if current_user.blank? || !current_user.logged?
|
||||
has_user = User.find_by(mail: mail)
|
||||
if has_user.present?
|
||||
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: has_user.id, uid: uid, extra: auth_hash.extra)
|
||||
successful_authentication(has_user)
|
||||
else
|
||||
new_user = true
|
||||
login = build_login_name(platform, auth_hash.info.nickname)
|
||||
mail = "#{login}@example.org" if mail.blank?
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
rand_password = code.sample(10).join
|
||||
reg_result = autologin_register(login, mail, rand_password, platform, nil, nickname)
|
||||
Rails.logger.info("[OAuth2] omniauth.auth [reg_result] #{reg_result} ")
|
||||
if reg_result[:message].blank?
|
||||
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: reg_result[:user][:id], uid: uid, extra: auth_hash.extra)
|
||||
successful_authentication(open_user.user)
|
||||
else
|
||||
tip_exception(reg_result.present? ? reg_result[:message] : "授权失败")
|
||||
end
|
||||
end
|
||||
else
|
||||
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: login, extra: auth_hash.extra)
|
||||
end
|
||||
end
|
||||
redirect_to root_path(new_user: new_user)
|
||||
end
|
||||
|
||||
def process_callback_new
|
||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
if auth_hash.blank?
|
||||
redirect_to("/login") && return
|
||||
end
|
||||
platform = auth_hash[:provider]
|
||||
uid = auth_hash[:uid]
|
||||
uid = auth_hash.info.unionid if platform == "wechat"
|
||||
|
||||
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid)
|
||||
if open_user.present? && open_user.user.present?
|
||||
successful_authentication(open_user.user)
|
||||
redirect_to root_path(new_user: false)
|
||||
return
|
||||
else
|
||||
if current_user.blank? || !current_user.logged?
|
||||
session[:unionid] = uid
|
||||
else
|
||||
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: uid)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("[OAuth2] session[:unionid] -> #{session[:unionid]}")
|
||||
redirect_to "/bindlogin/#{platform}"
|
||||
end
|
||||
|
||||
# gitee,github nickname=login,如果系统未占用保留原用户名
|
||||
def build_login_name(provider, nickname)
|
||||
if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank?
|
||||
nickname
|
||||
else
|
||||
User.generate_user_login('p')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -46,6 +46,12 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||
@organization.save!
|
||||
sync_organization_extension!
|
||||
# 更改组织可见性为私有,则需将该组织下的所有仓库同步更改为私有仓库
|
||||
if organization_extension_params[:visibility] == "privacy"
|
||||
Project.where(user_id: @organization.id).where(is_public: true).each do |project|
|
||||
update_project_private(project)
|
||||
end
|
||||
end
|
||||
|
||||
Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
|
@ -123,5 +129,20 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
def sync_organization_extension!
|
||||
@organization.organization_extension.update_attributes!(organization_extension_params)
|
||||
end
|
||||
|
||||
def update_project_private(project)
|
||||
project.update_attributes!(is_public: false)
|
||||
project.forked_projects.update_all(is_public: project.is_public)
|
||||
gitea_params = {
|
||||
private: true,
|
||||
default_branch: project.default_branch,
|
||||
website: project.website,
|
||||
name: project.identifier
|
||||
}
|
||||
gitea_repo = Gitea::Repository::UpdateService.call(@organization, project&.repository&.identifier, gitea_params)
|
||||
project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
||||
# 更新对应所属分类下的项目数量(私有)
|
||||
project.project_category.decrement!(:private_projects_count, 1) if project.project_category.present?
|
||||
end
|
||||
|
||||
end
|
|
@ -10,7 +10,7 @@ class ProjectCategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def group_list
|
||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
||||
@project_categories = ProjectCategory.select("id, name, projects_count, private_projects_count, (projects_count - private_projects_count) as public_projects_count").having('public_projects_count > 0').order(public_projects_count: :desc)
|
||||
# projects = Project.no_anomory_projects.visible
|
||||
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
|
||||
end
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
class ProjectRankController < ApplicationController
|
||||
# 根据时间获取热门项目
|
||||
def index
|
||||
$redis_cache.zunionstore("recent-days-project-rank", get_timeable_key_names)
|
||||
$redis_cache.zunionstore("recent-days-project-rank-#{time}", get_timeable_key_names)
|
||||
deleted_data = $redis_cache.smembers("v2-project-rank-deleted")
|
||||
$redis_cache.zrem("recent-days-project-rank", deleted_data) unless deleted_data.blank?
|
||||
@project_rank = $redis_cache.zrevrange("recent-days-project-rank", 0, 4, withscores: true)
|
||||
$redis_cache.zrem("recent-days-project-rank-#{time}", deleted_data) unless deleted_data.blank?
|
||||
@project_rank = $redis_cache.zrevrange("recent-days-project-rank-#{time}", 0, 9, withscores: true)
|
||||
rescue Exception => e
|
||||
@project_rank = []
|
||||
end
|
||||
|
|
|
@ -40,8 +40,9 @@ class ProjectsController < ApplicationController
|
|||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
if category_id.blank?
|
||||
ps = ProjectStatistic.first
|
||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
# ps = ProjectStatistic.first
|
||||
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
@projects.total_count
|
||||
else
|
||||
cate = ProjectCategory.find_by(id: category_id)
|
||||
cate&.projects_count || 0
|
||||
|
@ -52,7 +53,7 @@ class ProjectsController < ApplicationController
|
|||
ActiveRecord::Base.transaction do
|
||||
Projects::CreateForm.new(project_params).validate!
|
||||
@project = Projects::CreateService.new(current_user, project_params).call
|
||||
|
||||
OpenProjectDevOpsJob.perform_later(@project&.id, current_user.id)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
@ -154,6 +155,15 @@ class ProjectsController < ApplicationController
|
|||
}
|
||||
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
|
||||
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
||||
# 更新对应所属分类下的项目数量(私有)
|
||||
before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public
|
||||
after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public
|
||||
before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id
|
||||
after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id
|
||||
before_pc = ProjectCategory.find_by_id(before_pc_id)
|
||||
after_pc = ProjectCategory.find_by_id(after_pc_id)
|
||||
before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public
|
||||
after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public
|
||||
end
|
||||
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
|
||||
end
|
||||
|
@ -171,6 +181,8 @@ class ProjectsController < ApplicationController
|
|||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
||||
@project.destroy!
|
||||
@project.forked_projects.update_all(forked_from_project_id: nil)
|
||||
# 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量
|
||||
@project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
|
|
|
@ -100,20 +100,6 @@ class PullRequestsController < ApplicationController
|
|||
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
merge_params
|
||||
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||
return normal_status(-1, "最多只能创建一个标记。")
|
||||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
return normal_status(-1, "请输入正确的标记。")
|
||||
end
|
||||
end
|
||||
|
||||
reviewers = User.where(id: params[:reviewer_ids])
|
||||
@pull_request.reviewers = reviewers
|
||||
|
||||
|
@ -165,6 +151,8 @@ class PullRequestsController < ApplicationController
|
|||
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
||||
if colsed === true
|
||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
|
||||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
normal_status(1, "已拒绝")
|
||||
else
|
||||
|
@ -210,6 +198,8 @@ class PullRequestsController < ApplicationController
|
|||
# @pull_request.project_trend_status!
|
||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
|
||||
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
||||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
normal_status(1, "合并成功")
|
||||
else
|
||||
|
|
|
@ -7,6 +7,7 @@ class SettingsController < ApplicationController
|
|||
get_sub_competitions
|
||||
get_personal_menu
|
||||
get_third_party
|
||||
get_third_party_new
|
||||
get_top_system_notification
|
||||
end
|
||||
|
||||
|
@ -67,6 +68,24 @@ class SettingsController < ApplicationController
|
|||
url: EducoderOauth.oauth_url
|
||||
}
|
||||
end
|
||||
|
||||
def get_third_party_new
|
||||
@third_party_new = []
|
||||
@third_party_new << {
|
||||
name: 'educoder',
|
||||
url: EducoderOauth.oauth_url,
|
||||
method: 'get'
|
||||
}
|
||||
platform_url = Rails.application.config_for(:configuration)['platform_url']
|
||||
config = Rails.application.config_for(:configuration)
|
||||
(config.dig("oauth").keys - ["educoder", "wechat"]).each do |provider|
|
||||
@third_party_new << {
|
||||
name: provider,
|
||||
url: "#{platform_url}/auth/#{provider}",
|
||||
method: 'get'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def get_top_system_notification
|
||||
@top_system_notification = SystemNotification.is_top.first
|
||||
|
|
|
@ -2,24 +2,24 @@ class StatisticController < ApplicationController
|
|||
|
||||
# 平台概况
|
||||
def platform_profile
|
||||
@platform_user_query = Statistic::PlatformUserQuery.new(params).call
|
||||
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call
|
||||
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call
|
||||
@platform_user_query = Statistic::PlatformUserQuery.new(params).call rescue [0, 0, 0]
|
||||
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call rescue [0, 0, 0]
|
||||
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call rescue [0, 0, 0]
|
||||
end
|
||||
|
||||
# 平台代码提交数据
|
||||
def platform_code
|
||||
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call
|
||||
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call
|
||||
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call rescue [0, 0]
|
||||
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call rescue [0, 0]
|
||||
end
|
||||
|
||||
# 项目案例活跃度排行榜
|
||||
def active_project_rank
|
||||
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call
|
||||
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call rescue []
|
||||
end
|
||||
|
||||
# 开发者活跃度排行榜
|
||||
def active_developer_rank
|
||||
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call
|
||||
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call rescue []
|
||||
end
|
||||
end
|
|
@ -57,6 +57,13 @@ class UsersController < ApplicationController
|
|||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def action
|
||||
if params[:action_id].present? && params[:action_type].present?
|
||||
UserAction.create(:action_id => params[:action_id], :action_type => "#{params[:action_type]}", :user_id => User.current.id, :ip => request.remote_ip)
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||
if params[:search].present?
|
||||
|
|
|
@ -6,7 +6,7 @@ module Admins::ProjectsHelper
|
|||
if owner.is_a?(User)
|
||||
link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank')
|
||||
elsif owner.is_a?(Organization)
|
||||
link_to(project.owner&.real_name, "/organize/#{project&.owner&.login}", target: '_blank')
|
||||
link_to(project.owner&.real_name, "/#{project&.owner&.login}", target: '_blank')
|
||||
else
|
||||
""
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ module RepositoriesHelper
|
|||
end
|
||||
|
||||
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 apk)
|
||||
default_type = %w(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 apk xlsx xls)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
|
@ -91,7 +91,7 @@ module RepositoriesHelper
|
|||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,7 +62,7 @@ module Gitea
|
|||
file_params = {}
|
||||
file_params = file_params.merge(branch: @params[:branch]) unless @params[:branch].blank?
|
||||
file_params = file_params.merge(new_branch: @params[:new_branch]) unless @params[:new_branch].blank?
|
||||
file_params = file_params.merge(content: Base64.encode64(@params[:content] || ""))
|
||||
file_params = file_params.merge(content: @params[:content] || "")
|
||||
file_params = file_params.merge(message: @params[:message]) unless @params[:message].blank?
|
||||
file_params = file_params.merge(committer: @params[:committer])
|
||||
file_params
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class MigrateRemoteRepositoryJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(repo_id, token, params)
|
||||
def perform(repo_id, token, user_id, params)
|
||||
repo = Repository.find_by(id: repo_id)
|
||||
return if repo.blank?
|
||||
|
||||
|
@ -12,6 +12,10 @@ class MigrateRemoteRepositoryJob < ApplicationJob
|
|||
if gitea_repository[0]==201
|
||||
repo&.project&.update_columns(gpid: gitea_repository[2]["id"])
|
||||
repo&.mirror&.succeeded!
|
||||
## open jianmu devops
|
||||
project_id = repo&.project&.id
|
||||
puts "############ mirror project_id,user_id: #{project_id},#{user_id} ############"
|
||||
OpenProjectDevOpsJob.perform_later(project_id, user_id) if project_id.present? && user_id.present?
|
||||
puts "############ mirror status: #{repo.mirror.status} ############"
|
||||
else
|
||||
repo&.mirror&.failed!
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
class OpenProjectDevOpsJob < ApplicationJob
|
||||
include ProjectsHelper
|
||||
|
||||
queue_as :message
|
||||
|
||||
def perform(project_id, user_id)
|
||||
project = Project.find_by(id: project_id)
|
||||
user = User.find_by(id: user_id)
|
||||
code = jianmu_devops_code(project, user)
|
||||
uri = URI.parse("#{jianmu_devops_url}/activate?code=#{URI.encode_www_form_component(code)}")
|
||||
response = Net::HTTP.get_response(uri)
|
||||
puts "jianmu_devops_url response.code ===== #{response.code}"
|
||||
SendTemplateMessageJob.perform_later('ProjectOpenDevOps', user_id, project_id)
|
||||
end
|
||||
|
||||
end
|
|
@ -217,6 +217,14 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers = project&.all_managers.where.not(id: operator&.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectPraised.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectOpenDevOps'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
return unless operator.present? && project.present?
|
||||
receivers = User.where(id: operator.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectOpenDevOps.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectPullRequest'
|
||||
operator_id, pull_request_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
|
@ -15,7 +15,7 @@ module EducoderOauth::Service
|
|||
|
||||
result
|
||||
rescue Exception => e
|
||||
raise Educoder::TipException.new(e.message)
|
||||
raise Gitlink::TipException.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -27,7 +27,7 @@ module EducoderOauth::Service
|
|||
result = client.auth_code.get_token(code, redirect_uri: EducoderOauth.redirect_uri).to_hash
|
||||
return result
|
||||
rescue Exception => e
|
||||
raise Educoder::TipException.new(e.message)
|
||||
raise Gitlink::TipException.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
class UserMailer < ApplicationMailer
|
||||
# 注意:这个地方一定要和你的邮箱服务域名一致
|
||||
# default from: 'notification@trustie.org'
|
||||
default from: 'noreply@gitlink.org.cn'
|
||||
# default from: 'noreply@gitlink.org.cn'
|
||||
default from: 'GitLink <noreply@gitlink.org.cn>'
|
||||
|
||||
# 用户注册验证码
|
||||
def register_email(mail, code)
|
||||
|
@ -9,8 +10,24 @@ class UserMailer < ApplicationMailer
|
|||
mail(to: mail, subject: 'Gitink | 注册验证码')
|
||||
end
|
||||
|
||||
# 用户找回密码
|
||||
def find_password(mail, code)
|
||||
@code = code
|
||||
mail(to: mail, subject: 'Gitink | 找回密码验证码')
|
||||
end
|
||||
|
||||
# 用户绑定邮箱
|
||||
def bind_email(mail, code)
|
||||
@code = code
|
||||
mail(to: mail, subject: 'Gitink | 绑定邮箱验证码')
|
||||
end
|
||||
|
||||
def update_email(mail, code)
|
||||
@code = code
|
||||
mail(to: mail, subject: 'Gitink | 更改邮箱验证码')
|
||||
end
|
||||
|
||||
def feedback_email(mail, title, content)
|
||||
mail(to: mail, subject: title, content_type: "text/html", body: content)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: feedbacks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_feedbacks_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Feedback < ApplicationRecord
|
||||
|
||||
belongs_to :user
|
||||
has_many :feedback_message_histories, dependent: :destroy
|
||||
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: feedback_message_histories
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# feedback_id :integer
|
||||
# user_id :integer
|
||||
# title :string(255)
|
||||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_feedback_message_histories_on_feedback_id (feedback_id)
|
||||
# index_feedback_message_histories_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class FeedbackMessageHistory < ApplicationRecord
|
||||
|
||||
belongs_to :feedback
|
||||
belongs_to :user
|
||||
|
||||
before_validation :send_meessage_email, on: :create
|
||||
|
||||
private
|
||||
|
||||
def send_meessage_email
|
||||
unless UserMailer.feedback_email(feedback&.user&.mail, title, content).deliver_now
|
||||
errors[:title] << '邮件发送失败!'
|
||||
end
|
||||
rescue
|
||||
errors[:title] << '邮件发送失败!'
|
||||
end
|
||||
|
||||
end
|
|
@ -52,6 +52,7 @@ class MessageTemplate < ApplicationRecord
|
|||
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectOpenDevOps', sys_notice: '您的仓库 <b>{repository}</b> 已成功开通引擎服务,可通过简单的节点编排完成自动化集成与部署。欢迎体验!', notification_url: '{baseurl}/{owner}/{identifier}/devops')
|
||||
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
|
||||
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求")
|
||||
email_html = File.read("#{email_template_html_dir}/project_role.html")
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# == 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::ProjectOpenDevOps < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectOpenDevOps.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers, user, project)
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{repository}', project&.name)
|
||||
url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectOpenDevOps.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: open_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# type :string(255)
|
||||
# uid :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# extra :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_open_users_on_type_and_uid (type,uid) UNIQUE
|
||||
# index_open_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OpenUsers::Gitee < OpenUser
|
||||
def nickname
|
||||
extra&.[]('nickname')
|
||||
end
|
||||
|
||||
def en_type
|
||||
'gitee'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: open_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# type :string(255)
|
||||
# uid :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# extra :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_open_users_on_type_and_uid (type,uid) UNIQUE
|
||||
# index_open_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OpenUsers::Github < OpenUser
|
||||
def nickname
|
||||
extra&.[]('name')
|
||||
end
|
||||
|
||||
def en_type
|
||||
'github'
|
||||
end
|
||||
end
|
|
@ -16,7 +16,7 @@
|
|||
# index_open_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class OpenUsers::QQ < OpenUser
|
||||
class OpenUsers::Qq < OpenUser
|
||||
def nickname
|
||||
extra&.[]('nickname')
|
||||
end
|
||||
|
|
|
@ -68,4 +68,9 @@ class Owner < ApplicationRecord
|
|||
has_many :repositories, foreign_key: :user_id, dependent: :destroy
|
||||
has_many :applied_transfer_projects, dependent: :destroy
|
||||
|
||||
scope :like, lambda { |keywords|
|
||||
sql = "CONCAT(lastname, firstname) LIKE :search OR nickname LIKE :search OR login LIKE :search "
|
||||
where(sql, :search => "%#{keywords.strip}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
end
|
||||
|
|
|
@ -175,6 +175,9 @@ class Project < ApplicationRecord
|
|||
$redis_cache.srem("v2-project-rank-deleted", self.id)
|
||||
end
|
||||
end
|
||||
if !self.common?
|
||||
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
|
||||
end
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
#
|
||||
# Table name: project_categories
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# position :integer
|
||||
# projects_count :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ancestry :string(255)
|
||||
# pinned_index :integer default("0")
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# position :integer
|
||||
# projects_count :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ancestry :string(255)
|
||||
# pinned_index :integer default("0")
|
||||
# private_projects_count :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
@ -114,13 +114,13 @@ class User < Owner
|
|||
# trustie: 来自Trustie平台
|
||||
# forge: 平台本身注册的用户
|
||||
# military: 军科的用户
|
||||
enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow
|
||||
enumerize :platform, in: [:forge, :educoder, :trustie, :military, :github, :gitee, :qq, :wechat], default: :forge, scope: :shallow
|
||||
|
||||
belongs_to :laboratory, optional: true
|
||||
has_one :user_extension, dependent: :destroy
|
||||
has_many :open_users, dependent: :destroy
|
||||
has_one :wechat_open_user, class_name: 'OpenUsers::Wechat'
|
||||
has_one :qq_open_user, class_name: 'OpenUsers::QQ'
|
||||
has_one :qq_open_user, class_name: 'OpenUsers::Qq'
|
||||
accepts_nested_attributes_for :user_extension, update_only: true
|
||||
has_many :fork_users, dependent: :destroy
|
||||
|
||||
|
@ -177,6 +177,7 @@ class User < Owner
|
|||
has_one :trace_user, dependent: :destroy
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
|
||||
has_many :feedbacks, dependent: :destroy
|
||||
# Groups and active users
|
||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||
scope :like, lambda { |keywords|
|
||||
|
@ -192,7 +193,8 @@ class User < Owner
|
|||
:show_email, :show_location, :show_department, :super_description, :show_super_description,
|
||||
:technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true
|
||||
|
||||
before_save :update_hashed_password, :set_lastname
|
||||
# before_save :update_hashed_password, :set_lastname
|
||||
before_save :update_hashed_password
|
||||
after_save :reset_cache_data
|
||||
after_create do
|
||||
SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie?
|
||||
|
@ -558,17 +560,19 @@ class User < Owner
|
|||
def full_name
|
||||
return '游客' unless logged?
|
||||
|
||||
name = show_realname? ? lastname + firstname : nickname
|
||||
name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
# name = show_realname? ? lastname + firstname : nickname
|
||||
# name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
nickname.blank? ? login : nickname
|
||||
end
|
||||
|
||||
# 用户的真实姓名(不考虑用户是否隐藏了真实姓名,课堂模块都用真实姓名)
|
||||
def real_name
|
||||
return '游客' unless logged?
|
||||
name = lastname + firstname
|
||||
name = name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
# name = lastname + firstname
|
||||
# name = name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
# name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
name.strip
|
||||
# name.strip
|
||||
nickname.blank? ? login : nickname
|
||||
end
|
||||
|
||||
def only_real_name
|
||||
|
@ -701,12 +705,13 @@ class User < Owner
|
|||
end
|
||||
|
||||
def show_real_name
|
||||
name = lastname + firstname
|
||||
if name.blank?
|
||||
nickname.blank? ? login : nickname
|
||||
else
|
||||
name
|
||||
end
|
||||
# name = lastname + firstname
|
||||
# if name.blank?
|
||||
# nickname.blank? ? login : nickname
|
||||
# else
|
||||
# name
|
||||
# end
|
||||
nickname.blank? ? login : nickname
|
||||
end
|
||||
|
||||
def update_hashed_password
|
||||
|
@ -787,6 +792,15 @@ class User < Owner
|
|||
login
|
||||
end
|
||||
|
||||
# 生成数字账号
|
||||
CODES = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
def self.generate_user_login type
|
||||
code = CODES.sample(8).join
|
||||
code = type + code.to_s
|
||||
return User.generate_user_login(type) if User.where(login: code).present?
|
||||
code
|
||||
end
|
||||
|
||||
def bind_open_user?(type)
|
||||
case type
|
||||
when 'wechat' then wechat_open_user.present?
|
||||
|
|
|
@ -12,11 +12,16 @@ class Projects::ListQuery < ApplicationQuery
|
|||
|
||||
def call
|
||||
collection = Project.visible
|
||||
# 增加私有组织中项目过滤
|
||||
collection = collection.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id")
|
||||
.where("organization_extensions.visibility is null or organization_extensions.visibility in (0,1)")
|
||||
.where("projects.user_id > 0")
|
||||
collection = filter_projects(collection)
|
||||
|
||||
sort = params[:sort_by] || "updated_on"
|
||||
sort_direction = params[:sort_direction] || "desc"
|
||||
|
||||
collection = optimize_sorting(collection, sort) if params[:category_id].present?
|
||||
custom_sort(collection, sort, sort_direction)
|
||||
|
||||
# scope = scope.reorder("projects.#{sort} #{sort_direction}")
|
||||
|
@ -36,10 +41,11 @@ class Projects::ListQuery < ApplicationQuery
|
|||
ids = Projects::ElasticsearchService.call(params[:search])
|
||||
items = items.where(platform: 'forge')
|
||||
if ids.present?
|
||||
items.where(id: ids).by_name_or_identifier(params[:search])
|
||||
items = items.where(id: ids).by_name_or_identifier(params[:search])
|
||||
else
|
||||
items.by_name_or_identifier(params[:search])
|
||||
items = items.by_name_or_identifier(params[:search])
|
||||
end
|
||||
items.or(items.where(user_id: Owner.like(params[:search]).pluck(:id)))
|
||||
end
|
||||
|
||||
def by_project_type(items)
|
||||
|
@ -57,5 +63,20 @@ class Projects::ListQuery < ApplicationQuery
|
|||
def by_pinned(items)
|
||||
(params[:pinned].present? && params[:category_id].present?) ? items.pinned : items
|
||||
end
|
||||
|
||||
# 优化排序
|
||||
def optimize_sorting(relations, sort_by)
|
||||
if sort_by == "updated_on"
|
||||
relations.where("projects.updated_on>'2010-01-01'")
|
||||
elsif sort_by == "created_on"
|
||||
relations.where("projects.created_on>'2010-01-01'")
|
||||
elsif sort_by == "forked_count"
|
||||
relations.where("projects.forked_count>=0")
|
||||
elsif sort_by == "praises_count"
|
||||
relations.where("projects.praises_count>=0")
|
||||
else
|
||||
relations
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -15,13 +15,14 @@ class Admins::UpdateUserService < ApplicationService
|
|||
user.firstname = ''
|
||||
user.password = params[:password] if params[:password].present?
|
||||
|
||||
user.user_extension.assign_attributes(user_extension_attributes)
|
||||
user.user_extension.assign_attributes(user_extension_attributes) if user.user_extension.present?
|
||||
|
||||
old_login = user.login
|
||||
ActiveRecord::Base.transaction do
|
||||
user.save!
|
||||
user.user_extension.save!
|
||||
user.user_extension.save! if user.user_extension.present?
|
||||
update_gitea_user(old_login)
|
||||
update_gitea_user_email(user.previous_changes[:mail])
|
||||
end
|
||||
|
||||
user
|
||||
|
@ -65,4 +66,14 @@ class Admins::UpdateUserService < ApplicationService
|
|||
Util.logger_error(ex)
|
||||
raise Error, '保存失败'
|
||||
end
|
||||
|
||||
def update_gitea_user_email(change_options)
|
||||
return if change_options.blank?
|
||||
return if user.gitea_uid.blank? || user.gitea_token.blank?
|
||||
$gitea_client.delete_user_emails({body: {emails: [change_options[0]]}.to_json, query: {access_token: user.gitea_token}})
|
||||
$gitea_client.post_user_emails({body: {emails: [change_options[1]]}.to_json, query: {access_token: user.gitea_token}})
|
||||
rescue Exception => ex
|
||||
Util.logger_error(ex)
|
||||
raise Error, '保存失败'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
class Api::V1::Projects::CodeStats::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :ref, :owner, :repo, :token
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@ref = params[:ref]
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
load_gitea_data
|
||||
|
||||
gitea_data
|
||||
end
|
||||
|
||||
private
|
||||
def request_params
|
||||
param = {
|
||||
access_token: token
|
||||
}
|
||||
param.merge!(ref: ref) if ref.present?
|
||||
|
||||
param
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_code_stats_by_owner_repo(owner, repo, {query: request_params}) rescue nil
|
||||
raise Error, '获取贡献者贡献度失败!' unless @gitea_data.is_a?(Hash)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
class Api::V1::Users::Feedbacks::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :user, :content
|
||||
attr_accessor :feedback
|
||||
|
||||
validates :content, presence: true
|
||||
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
@content = params[:content]
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
|
||||
begin
|
||||
@feedback = Feedback.new(user: user, content: content)
|
||||
@feedback.save!
|
||||
|
||||
return @feedback.valid? ? @feedback : nil
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,7 +14,7 @@ class Api::V1::Users::UpdateEmailService < ApplicationService
|
|||
@mail = params[:email]
|
||||
@old_mail = user.mail
|
||||
@code = params[:code]
|
||||
@verify_code = VerificationCode.where(email: @mail, code: @code, code_type: 10).last
|
||||
@verify_code = VerificationCode.where(email: @mail, code_type: 10).last
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
class Api::V1::Users::UpdatePhoneService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :user, :password, :phone, :code, :verify_code
|
||||
|
||||
validates :password, :code, presence: true
|
||||
validates :phone, presence: true, format: { with: CustomRegexp::PHONE }
|
||||
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
@password = params[:password]
|
||||
@phone = params[:phone]
|
||||
@code = params[:code]
|
||||
@verify_code = VerificationCode.where(phone: @phone, code_type: 4).last
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
raise Error, "密码不正确." unless @user.check_password?(@password)
|
||||
exist_owner = Owner.find_by(phone: @phone)
|
||||
raise Error, "手机号已被使用." if exist_owner
|
||||
is_debug = @code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||
raise Error, "验证码不正确." if @verify_code&.code != @code && !is_debug
|
||||
raise Error, "验证码已失效." if !@verify_code&.effective? && !is_debug
|
||||
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
@user.update_attributes!({phone: @phone})
|
||||
end
|
||||
return true
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -56,7 +56,7 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
|
|||
when 403 then error("你没有权限操作!")
|
||||
when 404 then error("你操作的链接不存在!")
|
||||
when 422
|
||||
if @body[:new_branch].include?('/') || @body[:new_branch].include?('\'') || @body[:new_branch].include?('^') || @body[:new_branch].include?('*')
|
||||
if @body[:new_branch].present? && (@body[:new_branch].include?('/') || @body[:new_branch].include?('\'') || @body[:new_branch].include?('^') || @body[:new_branch].include?('*'))
|
||||
error("不合法的分支名称!")
|
||||
else
|
||||
error("#{filepath}文件已存在,不能重复创建!")
|
||||
|
|
|
@ -17,7 +17,11 @@ class Issues::ListQueryService < ApplicationService
|
|||
issues = all_issues.issue_index_includes
|
||||
issues = issues.includes(pull_request: :reviewers)
|
||||
if status_type.to_s == "2" #表示关闭中的
|
||||
issues = issues.where(status_id: 5)
|
||||
if(select_type == "Issue")
|
||||
issues = issues.where(status_id: 5)
|
||||
else
|
||||
issues = issues.joins(:pull_request).where(pull_requests: {status: 2})
|
||||
end
|
||||
elsif status_type.to_s == "1"
|
||||
if(select_type == "Issue")
|
||||
issues = issues.where.not(status_id: 5) #默认显示开启中的
|
||||
|
|
|
@ -10,7 +10,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
|
|||
def call
|
||||
new_user = false
|
||||
# 存在该用户
|
||||
open_user = OpenUsers::QQ.find_by(uid: params['uid'])
|
||||
open_user = OpenUsers::Qq.find_by(uid: params['uid'])
|
||||
return [open_user.user, new_user] if open_user.present?
|
||||
|
||||
if user.blank? || !user.logged?
|
||||
|
@ -32,7 +32,7 @@ class Oauth::CreateOrFindQqAccountService < ApplicationService
|
|||
Util.download_file(params.dig('info', 'image'), avatar_path)
|
||||
end
|
||||
|
||||
new_open_user = OpenUsers::QQ.create!(user: user, uid: params['uid'])
|
||||
new_open_user = OpenUsers::Qq.create!(user: user, uid: params['uid'])
|
||||
|
||||
Rails.cache.write(new_open_user.can_bind_cache_key, 1, expires_in: 1.hours) if new_user # 方便后面进行账号绑定
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class Projects::CreateService < ApplicationService
|
|||
Project.update_common_projects_count!
|
||||
ProjectUnit.init_types(@project.id)
|
||||
Repositories::CreateService.new(user, @project, repository_params).call
|
||||
upgrade_project_category_private_projects_count
|
||||
else
|
||||
Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}")
|
||||
end
|
||||
|
@ -28,6 +29,14 @@ class Projects::CreateService < ApplicationService
|
|||
|
||||
private
|
||||
|
||||
def upgrade_project_category_private_projects_count
|
||||
# 如果为空或者项目为公有项目直接返回
|
||||
return unless params[:project_category_id].present?
|
||||
return if repo_is_public
|
||||
project_category = ProjectCategory.find_by_id(params[:project_category_id])
|
||||
project_category.increment!(:private_projects_count, 1)
|
||||
end
|
||||
|
||||
def authroize_user_id_success
|
||||
(user.id == params[:user_id].to_i) || (user.organizations.find_by_id(params[:user_id]).present?)
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ class Repositories::MigrateService < ApplicationService
|
|||
@repository = Repository.new(repository_params)
|
||||
if @repository.save!
|
||||
@repository.set_mirror!
|
||||
MigrateRemoteRepositoryJob.perform_later(@repository.id, user.gitea_token, gitea_repository_params)
|
||||
MigrateRemoteRepositoryJob.perform_later(@repository.id, user.gitea_token, user.id, gitea_repository_params)
|
||||
end
|
||||
@repository
|
||||
rescue => e
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
class Sms::UcloudService < ApplicationService
|
||||
attr_reader :phone, :code, :send_type
|
||||
|
||||
def initialize(phone, code, send_type)
|
||||
@phone = phone
|
||||
@code = code
|
||||
@send_type = send_type
|
||||
end
|
||||
|
||||
def call
|
||||
public_key = EduSetting.get("ucloud_public_key") || "4Z7QYDY0SumplMtmNmd9PERgPPFiMpR1R"
|
||||
private_key = EduSetting.get("ucloud_private_key") || "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtm2d"
|
||||
|
||||
project_id = "org-3ozbh2"
|
||||
sign_params = {
|
||||
"Action" => "SendUSMSMessage",
|
||||
"ProjectId" => project_id,
|
||||
"TemplateId" => get_template_id(@send_type),
|
||||
"PublicKey" => public_key,
|
||||
"PhoneNumbers.0" => @phone,
|
||||
"TemplateParams.0" => "#{@code}",
|
||||
"SigContent" => "GitLink确实开源"
|
||||
}
|
||||
sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('')
|
||||
# Rails.logger.info("create_signature=========#{sequence}#{private_key}")
|
||||
req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}"))
|
||||
uri = URI("https://api.ucloud.cn")
|
||||
uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&')
|
||||
# Rails.logger.info("uri.query=========#{uri.query}")
|
||||
|
||||
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
||||
req = Net::HTTP::Get.new uri.request_uri
|
||||
|
||||
response = http.request(req)
|
||||
# Rails.logger.info("ucloud sms response.body=========#{response.body}")
|
||||
result = ActiveSupport::JSON.decode(response.body)
|
||||
result['RetCode']
|
||||
end
|
||||
end
|
||||
|
||||
def send_by_params(opt={})
|
||||
public_key = "4Z7QYDY0SumplMtmNmd9PERgPPFiMpRR"
|
||||
private_key = "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtmd"
|
||||
|
||||
project_id = "org-3ozbh2"
|
||||
sign_params = {
|
||||
"Action" => "SendUSMSMessage",
|
||||
"ProjectId" => project_id,
|
||||
"TemplateId" => "#{opt[:TemplateId]}",
|
||||
"PublicKey" => public_key,
|
||||
"PhoneNumbers.0" => "#{opt[:PhoneNumbers]}",
|
||||
"TemplateParams.0" => "#{opt[:TemplateParams]}",
|
||||
"SigContent" => "GitLink确实开源"
|
||||
}
|
||||
sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('')
|
||||
# Rails.logger.info("create_signature=========#{sequence}#{private_key}")
|
||||
req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}"))
|
||||
uri = URI("https://api.ucloud.cn")
|
||||
uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&')
|
||||
# Rails.logger.info("uri.query=========#{uri.query}")
|
||||
|
||||
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
||||
req = Net::HTTP::Get.new uri.request_uri
|
||||
|
||||
response = http.request(req)
|
||||
# Rails.logger.info("ucloud sms response.body=========#{response.body}")
|
||||
ActiveSupport::JSON.decode(response.body)
|
||||
end
|
||||
end
|
||||
|
||||
def send_sms(template_id)
|
||||
|
||||
end
|
||||
|
||||
def GetProjectList
|
||||
public_key = "4Z7QYDY0SumplMtmNmd9PERgPPFiMpRR"
|
||||
private_key = "7wxMoGoaQ1DtcQjDxgJrOGOXnIiZq4amEWvmi7eBtmd"
|
||||
|
||||
sign_params = {
|
||||
"Action" => "GetProjectList",
|
||||
"PublicKey" => public_key
|
||||
}
|
||||
sequence = sign_params.sort.map { |k, v| "#{k}#{v}" }.join('')
|
||||
Rails.logger.info("create_signature=========#{sequence}#{private_key}")
|
||||
req_params = sign_params.merge("Signature" => Digest::SHA1.hexdigest("#{sequence}#{private_key}"))
|
||||
uri = URI("https://api.ucloud.cn")
|
||||
uri.query = req_params.map { |k, v| "#{k}=#{URI.escape(v.to_s)}" }.join('&')
|
||||
Rails.logger.info("uri.query=========#{uri.query}")
|
||||
|
||||
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
||||
req = Net::HTTP::Get.new uri.request_uri
|
||||
|
||||
response = http.request(req)
|
||||
Rails.logger.info("ucloud sms response.body=========#{response.body}")
|
||||
response.body
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# 1:注册手机验证码 2:找回密码手机验证码 4:绑定手机 9:验证手机号有效
|
||||
def get_template_id(send_type)
|
||||
case send_type
|
||||
when 1, 2, 9
|
||||
"UTA221114S2MGTY"
|
||||
when 4
|
||||
"UTA22112486FXLZ"
|
||||
else
|
||||
"UTA221114S2MGTY"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
<div class="modal fade feedback-history-change-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width: 800px">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">发送邮件给<%= @feedback&.user&.mail%></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<%= form_for @feedback_message_history, url: {controller: "feedbacks", action: "create_history"} do |p| %>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
邮件标题 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :title,class: "form-control input-lg", placeholder: "邮件标题", value: "您提交的意见反馈有新回复",required: true, maxlength: 64, readonly: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<span class="color-grey-6 pt10">
|
||||
邮件正文
|
||||
<span class="ml10 color-orange mr20">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mt-10">
|
||||
<div class="pl-0 my-3 setting-item-body" id="feedback-history-email-editor">
|
||||
<%= p.text_area :content, class:"form-control", style: 'display: none;', rows: "10", cols: "20", placeholer: "请输入邮件正文" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,46 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="5%">序号</th>
|
||||
<th width="10%">用户名</th>
|
||||
<th width="20%">用户邮箱</th>
|
||||
<th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_feedbacks_path) %></th>
|
||||
<th width="25%">反馈意见</th>
|
||||
<th width="15%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if feedbacks.present? %>
|
||||
<% feedbacks.each_with_index do |feedback, index| %>
|
||||
<tr class="feedback-item-<%= feedback.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= feedback&.user&.login%></td>
|
||||
<td><%= feedback&.user&.mail%></td>
|
||||
<td><%= feedback.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td>
|
||||
<span class="d-inline-block" tabindex="0" data-toggle="tooltip" data-placement="left" title="<%= feedback.content%>">
|
||||
<a href="javascript:">
|
||||
<%= feedback.content.truncate(20) %>
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
<td class="action-container">
|
||||
<%= link_to "发送邮件", new_history_admins_feedback_path(feedback), remote: true, class: "action" %>
|
||||
<%#= link_to "删除", admins_feedback_path(feedback), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: feedbacks } %>
|
||||
|
||||
<style>
|
||||
.tooltip-inner {
|
||||
max-width: 800px;
|
||||
/* width: inherit; will take up least amount of space */
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,9 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('反馈意见') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box admin-list-container feedback-list-container" style="min-height: 400px">
|
||||
<%= render partial: 'admins/feedbacks/list', locals: { feedbacks: @feedbacks } %>
|
||||
</div>
|
||||
<div id="feedback-modals">
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
$('.feedback-list-container').html("<%= j( render partial: 'admins/feedbacks/list', locals: { feedbacks: @feedbacks } ) %>");
|
|
@ -0,0 +1,3 @@
|
|||
$("#feedback-modals").html("<%= j render(partial: 'admins/feedbacks/history_form_modal', locals: {type: 'new_history'}) %>")
|
||||
$(".feedback-history-change-modal").modal('show');
|
||||
createMDEditor('feedback-history-email-editor', {width: 750, height: 300, placeholder: '请输入邮件正文',watch: false, imageUpload: false });
|
|
@ -4,7 +4,8 @@
|
|||
<th width="5%">序号</th>
|
||||
<th width="30%">名称</th>
|
||||
<th width="20%"><%= sort_tag('精选', name: 'pinned_index', path: admins_project_categories_path) %></th>
|
||||
<th width="20%"><%= sort_tag('项目数', name: 'projects_count', path: admins_project_categories_path) %></th>
|
||||
<th width="10%"><%= sort_tag('项目数', name: 'projects_count', path: admins_project_categories_path) %></th>
|
||||
<th width="10%"><%= sort_tag('私有项目数', name: 'private_projects_count', path: admins_project_categories_path) %></th>
|
||||
<th width="20%">精选项目数</th>
|
||||
<th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_project_categories_path) %></th>
|
||||
<th width="25%">操作</th>
|
||||
|
@ -20,6 +21,7 @@
|
|||
</td>
|
||||
<td><%= project_category.pinned_index == 0 ? "" : "√" %></td>
|
||||
<td><%= project_category.projects_count %></td>
|
||||
<td><%= project_category.private_projects_count %></td>
|
||||
<td><%= project_category.projects.select(:id).where(is_pinned: true).size %></td>
|
||||
<td><%= project_category.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td class="action-container">
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<th width="6%">ID</th>
|
||||
<th width="20%" class="text-left">项目名称</th>
|
||||
<th width="5%">公开</th>
|
||||
<th width="5%">精选</th>
|
||||
<th width="5%">推荐</th>
|
||||
<th width="5%">Issues</th>
|
||||
<th width="5%">资源</th>
|
||||
|
@ -27,7 +26,6 @@
|
|||
<%= link_to(project.name, "/#{project&.owner&.login}/#{project.identifier}", target: '_blank') %>
|
||||
</td>
|
||||
<td><%= project.is_public ? '√' : '' %></td>
|
||||
<td><%= project.is_pinned ? '√' : '' %></td>
|
||||
<td><%= project.recommend ? '√' : '' %></td>
|
||||
<td><%= project.issues.size %></td>
|
||||
<td><%= project.attachments.size %></td>
|
||||
|
@ -40,8 +38,6 @@
|
|||
<td><%= project.created_on&.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td class="action-container">
|
||||
<% if project.is_public %>
|
||||
<%= javascript_void_link '精选', class: 'action pinned-action', data: { id: project.id }, style: project.is_pinned ? 'display: none;' : '' %>
|
||||
<%= javascript_void_link '取消精选', class: 'action unpinned-action', data: { id: project.id }, style: project.is_pinned ? '' : 'display: none;' %>
|
||||
<%= javascript_void_link '推荐', class: 'action recommend-action', data: { id: project.id }, style: project.recommend ? 'display: none;' : '' %>
|
||||
<%= javascript_void_link '取消推荐', class: 'action unrecommend-action', data: { id: project.id }, style: project.recommend ? '' : 'display: none;' %>
|
||||
<%= link_to "设置推荐等级", edit_admins_project_path(project.id), remote: true, class: "action edit-recommend-action", style: project.recommend ? '' : 'display: none;' %>
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
||||
<li><%= sidebar_item(admins_nps_path, 'NPS用户调研', icon: 'question-circle', controller: 'admins-nps') %></li>
|
||||
<li><%= sidebar_item(admins_feedbacks_path, '用户反馈', icon: 'question-circle', controller: 'admins-feedbacks') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
</label>
|
||||
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
跳转URL
|
||||
</label>
|
||||
<%= p.text_field :url, class: "form-control",placeholder: ""%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
排序等级
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
<th width="5%">序号</th>
|
||||
<th width="20%">标题</th>
|
||||
<th width="20%">图片</th>
|
||||
<th width="20%">排序等级</th>
|
||||
<th width="25%">操作</th>
|
||||
<th width="25%">跳转URL</th>
|
||||
<th width="10%">排序等级</th>
|
||||
<th width="20%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -15,6 +16,7 @@
|
|||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= banner.title %></td>
|
||||
<td><img style="width:150px" src="<%= banner.image %>" /></td>
|
||||
<td><a href="<%= banner.url %>" target="_blank"><%= banner.url %></a> </td>
|
||||
<td><%= banner.order_index %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to "编辑", edit_admins_topic_banner_path(banner), remote: true, class: "action" %>
|
||||
|
|
|
@ -68,12 +68,12 @@
|
|||
<%= f.label :identity, label: '职业' %>
|
||||
<%= select_tag('user[identity]', [], class: 'form-control identity-select optional', 'data-value': @user.user_extension&.identity, 'data-first-title': '请选择') %>
|
||||
</div>
|
||||
<div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user.user_extension.student? ? 'display:none;' : '' %>">
|
||||
<div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user&.user_extension&.student? ? 'display:none;' : '' %>">
|
||||
<%= f.label :technical_title, label: '职称' %>
|
||||
<%= select_tag('user[technical_title]', [], class: 'form-control technical-title-select optional', 'data-value': @user.technical_title) %>
|
||||
</div>
|
||||
|
||||
<%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user.user_extension.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %>
|
||||
<%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user&.user_extension&.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<td><%= user.identity %></td>
|
||||
<td><%= display_text(user.created_on&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= display_text(user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %></td>
|
||||
<td><%= link_to user.projects_count, "/users/#{user.login}/projects", target: "_blank" %></td>
|
||||
<td><%= link_to user.projects_count, "/#{user.login}/projects", target: "_blank" %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to '编辑', edit_admins_user_path(user), class: 'action' %>
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
json.author_count @result_object["author_count"]
|
||||
json.commit_count @result_object["commit_count"]
|
||||
json.change_files @result_object["change_files"]
|
||||
json.additions @result_object["additions"]
|
||||
json.deletions @result_object["deletions"]
|
||||
json.commit_count_in_all_branches @result_object["commit_count_in_all_branches"]
|
||||
json.authors @result_object["authors"].each do |author|
|
||||
json.author do
|
||||
json.partial! 'api/v1/users/commit_user_email', locals: { user: render_cache_commit_author(author), name: author['name'], email: author['email'] }
|
||||
end
|
||||
json.commits author["commits"]
|
||||
json.additions author["additions"]
|
||||
json.deletions author["deletions"]
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
if user.present?
|
||||
if user.is_a?(Hash)
|
||||
json.id user["id"]
|
||||
json.login user["login"]
|
||||
json.name user["name"]
|
||||
json.type user["type"]
|
||||
json.image_url user["avatar_url"]
|
||||
else
|
||||
json.id user.id
|
||||
json.login user.login
|
||||
json.name user.real_name
|
||||
json.type user&.type
|
||||
json.image_url url_to_avatar(user)
|
||||
end
|
||||
else
|
||||
json.id nil
|
||||
json.login name
|
||||
json.name name
|
||||
json.email email
|
||||
json.type nil
|
||||
json.image_url User::Avatar.get_letter_avatar_url(name)
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
json.status 0
|
||||
json.username @user.full_name
|
||||
json.real_name @user.real_name
|
||||
json.login @user.login
|
||||
json.user_id @user.id
|
||||
json.image_url url_to_avatar(@user)
|
||||
json.admin @user.admin?
|
||||
json.user_identity @user.identity
|
||||
json.is_watch current_user&.watched?(@user)
|
|
@ -4,6 +4,7 @@ json.user_admin_or_member @user_admin_or_member
|
|||
json.issue_tags do
|
||||
|
||||
json.array! @issue_tags.each.to_a do |tag|
|
||||
json.extract! tag, :id, :name, :description, :color, :issues_count, :project_id, :gid, :gitea_url
|
||||
json.extract! tag, :id, :name, :description, :color, :project_id, :gid, :gitea_url
|
||||
json.issues_count tag.issues_count - tag.issues.closed.size
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
json.total_count @organization_users.total_count
|
||||
json.organization_users @organization_users do |org_user|
|
||||
next if org_user.user.blank?
|
||||
json.partial! "detail", org_user: org_user, organization: @organization
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
json.array! @project_categories do |category|
|
||||
json.id category.id
|
||||
json.name category.name
|
||||
json.projects_count category.projects_count
|
||||
json.projects_count category.public_projects_count
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
json.total_count @projects.total_count
|
||||
json.total_count @total_count
|
||||
json.projects @projects do |project|
|
||||
# json.partial! "/projects/project_detail", project: project
|
||||
json.id project.id
|
||||
|
@ -22,7 +22,7 @@ json.projects @projects do |project|
|
|||
project_educoder = project.project_educoder
|
||||
json.name project_educoder&.owner
|
||||
json.login project_educoder&.repo_name.split('/')[0]
|
||||
json.image_url render_educoder_avatar_url(project.project_educoder)
|
||||
# json.image_url render_educoder_avatar_url(project.project_educoder)
|
||||
else
|
||||
user = project.owner
|
||||
json.type user.type
|
||||
|
|
|
@ -2,7 +2,7 @@ if @project.forge?
|
|||
is_dir = @sub_entries.is_a?(Array)
|
||||
file_name = entry['name']
|
||||
file_type = File.extname(file_name.to_s)[1..-1]
|
||||
direct_download = download_type(file_type)
|
||||
direct_download = file_name.to_s.downcase != "Makefile".downcase && download_type(file_type)
|
||||
image_type = image_type?(file_type)
|
||||
json.name file_name
|
||||
json.sha entry['sha']
|
||||
|
|
|
@ -61,6 +61,7 @@ json.setting do
|
|||
|
||||
json.common @common
|
||||
json.third_party @third_party
|
||||
json.third_party_new @third_party_new
|
||||
|
||||
if @top_system_notification.present?
|
||||
json.system_notification do
|
||||
|
|
|
@ -1 +1 @@
|
|||
json.(banner, :id, :title, :image)
|
||||
json.(banner, :id, :title, :image, :url)
|
|
@ -0,0 +1,62 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>GitLink-验证码发送</title>
|
||||
<style type="text/css">
|
||||
/* 验证链接页面 */
|
||||
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
|
||||
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;}
|
||||
div,img,tr,td,table{ border:0;}
|
||||
table,tr,td{border:0;}
|
||||
ol,ul,li{ list-style-type:none}
|
||||
.new_content{ background:#fff; width: 100%;}
|
||||
.email-page-link{ }
|
||||
.email-link-top{ }
|
||||
.c_white{ color:#fff;}
|
||||
.email-link-con{ }
|
||||
.email-link-line{ }
|
||||
.email-link-footer{ padding:15px; color:#333; line-height: 1.9; }
|
||||
.c_grey02{ color: #888;}
|
||||
.fb{ font-weight: normal;}
|
||||
.f14{ }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body style="background:#fff;">
|
||||
<div class="new_content">
|
||||
<div style="width: 598px; background:#fff; margin:20px auto; font-size:14px; ">
|
||||
<div style="height:50px; width: 578px; background:#46484c; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
|
||||
<a href="https://www.gitlink.org.cn">
|
||||
<img width="100" style="float:left; margin-top: 8px;" src="https:///www.gitlink.org.cn/images/email_logo.png" alt="确实开源">
|
||||
</a>
|
||||
<div style="clear:both; overflow:hidden;"></div>
|
||||
</div>
|
||||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:30px 20px; color:#333; line-height: 1.9;">
|
||||
<p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold">
|
||||
您好!
|
||||
</p>
|
||||
<p style="color:#333;">
|
||||
您正在GitLink绑定邮箱,请在10分钟内输入此验证码,并进行下一步操作。
|
||||
如非你本人操作,请忽略此邮件。
|
||||
</p>
|
||||
<div style="text-align: center;">
|
||||
<div style="display:block; height: 45px; line-height:45px;padding:0 30px; width:100px; font-size: 20px; font-weight: bold; background:#ffd9d9; color:#e72c37; margin:30px auto;">
|
||||
<p><%= @code %></p>
|
||||
</div>
|
||||
<span style="font-weight: normal;color:#666;">
|
||||
此邮件为系统所发,请勿直接回复。<br/>
|
||||
要解决问题或了解您的帐户详情,您可以访问 <a href="https:///www.gitlink.org.cn/forums/1168/detail" style="font-weight: normal; color:#ff7500;">帮助中心</a>。
|
||||
</span>
|
||||
</div>
|
||||
<p style="color:#666; margin-top:30px;">
|
||||
如果您并未发过此请求,则可能是因为其他用户误输了您的邮件地址,而使您收到了这封邮件,那么您可以放心的忽略此邮件,无需进一步采取任何操作。
|
||||
</p>
|
||||
</div>
|
||||
<div style="padding:20px; color:#333; line-height: 1.9;background:#46484c;border:1px solid #ddd; border-top:none; width: 558px;">
|
||||
<a href="https:///www.gitlink.org.cn" style="font-weight: normal; color:#fff;">www.gitlink.org.cn</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,62 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>GitLink-验证码发送</title>
|
||||
<style type="text/css">
|
||||
/* 验证链接页面 */
|
||||
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
|
||||
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;}
|
||||
div,img,tr,td,table{ border:0;}
|
||||
table,tr,td{border:0;}
|
||||
ol,ul,li{ list-style-type:none}
|
||||
.new_content{ background:#fff; width: 100%;}
|
||||
.email-page-link{ }
|
||||
.email-link-top{ }
|
||||
.c_white{ color:#fff;}
|
||||
.email-link-con{ }
|
||||
.email-link-line{ }
|
||||
.email-link-footer{ padding:15px; color:#333; line-height: 1.9; }
|
||||
.c_grey02{ color: #888;}
|
||||
.fb{ font-weight: normal;}
|
||||
.f14{ }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body style="background:#fff;">
|
||||
<div class="new_content">
|
||||
<div style="width: 598px; background:#fff; margin:20px auto; font-size:14px; ">
|
||||
<div style="height:50px; width: 578px; background:#46484c; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
|
||||
<a href="https://www.gitlink.org.cn">
|
||||
<img width="100" style="float:left; margin-top: 8px;" src="https:///www.gitlink.org.cn/images/email_logo.png" alt="确实开源">
|
||||
</a>
|
||||
<div style="clear:both; overflow:hidden;"></div>
|
||||
</div>
|
||||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:30px 20px; color:#333; line-height: 1.9;">
|
||||
<p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold">
|
||||
您好!
|
||||
</p>
|
||||
<p style="color:#333;">
|
||||
您正在GitLink找回密码,请在10分钟内输入此验证码,并进行下一步操作。
|
||||
如非你本人操作,请忽略此邮件。
|
||||
</p>
|
||||
<div style="text-align: center;">
|
||||
<div style="display:block; height: 45px; line-height:45px;padding:0 30px; width:100px; font-size: 20px; font-weight: bold; background:#ffd9d9; color:#e72c37; margin:30px auto;">
|
||||
<p><%= @code %></p>
|
||||
</div>
|
||||
<span style="font-weight: normal;color:#666;">
|
||||
此邮件为系统所发,请勿直接回复。<br/>
|
||||
要解决问题或了解您的帐户详情,您可以访问 <a href="https:///www.gitlink.org.cn/forums/1168/detail" style="font-weight: normal; color:#ff7500;">帮助中心</a>。
|
||||
</span>
|
||||
</div>
|
||||
<p style="color:#666; margin-top:30px;">
|
||||
如果您并未发过此请求,则可能是因为其他用户误输了您的邮件地址,而使您收到了这封邮件,那么您可以放心的忽略此邮件,无需进一步采取任何操作。
|
||||
</p>
|
||||
</div>
|
||||
<div style="padding:20px; color:#333; line-height: 1.9;background:#46484c;border:1px solid #ddd; border-top:none; width: 558px;">
|
||||
<a href="https:///www.gitlink.org.cn" style="font-weight: normal; color:#fff;">www.gitlink.org.cn</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -11,7 +11,7 @@ json.user_identity @user.identity
|
|||
json.tidding_count 0
|
||||
json.user_phone_binded @user.phone.present?
|
||||
json.need_edit_info @user.need_edit_info?
|
||||
# json.phone @user.phone
|
||||
json.phone @user.phone
|
||||
# json.email @user.mail
|
||||
json.profile_completed @user.profile_is_completed?
|
||||
json.professional_certification @user.professional_certification
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
OmniAuth.config.add_camelization 'qq', 'QQ'
|
||||
config = Rails.application.config_for(:configuration)
|
||||
|
||||
OmniAuth.config.add_camelization 'qq', 'QQ' if config.dig("oauth", "qq")
|
||||
# OmniAuth.config.add_camelization 'github', 'GitHub' if config.dig("oauth", "github")
|
||||
# OmniAuth.config.add_camelization 'gitee', 'Gitee' if config.dig("oauth", "gitee")
|
||||
# OmniAuth.config.add_camelization 'wechat', 'Wechat' if config.dig("oauth", "wechat")
|
||||
OmniAuth.config.logger = Rails.logger
|
||||
OmniAuth.config.allowed_request_methods = %i[get post]
|
||||
OmniAuth.config.before_request_phase = nil
|
||||
OmniAuth.config.before_callback_phase = nil
|
||||
OmniAuth.config.on_failure = Proc.new { |env|
|
||||
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
|
||||
}
|
||||
|
||||
oauth_config = {}
|
||||
begin
|
||||
config = Rails.application.config_for(:configuration)
|
||||
oauth_config = config.dig('oauth', 'qq')
|
||||
raise 'oauth qq config missing' if oauth_config.blank?
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] qq oauth config or configuration.yml missing,
|
||||
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
|
||||
end
|
||||
|
||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
provider :qq, oauth_config['appid'], oauth_config['secret'], { provider_ignores_state: true }
|
||||
if config.dig("oauth", "qq")
|
||||
provider :qq, config.dig("oauth", "qq", "appid"), config.dig("oauth", "qq", "secret"), { provider_ignores_state: true }
|
||||
end
|
||||
if config.dig("oauth", "github").present?
|
||||
provider :github, config.dig("oauth", "github", "appid"), config.dig("oauth", "github", "secret"), { provider_ignores_state: true, scope: "user:email" }
|
||||
end
|
||||
if config.dig("oauth", "gitee").present?
|
||||
provider :gitee, config.dig("oauth", "gitee", "appid"), config.dig("oauth", "gitee", "secret"), { provider_ignores_state: true, scope: "user_info emails" }
|
||||
end
|
||||
if config.dig("oauth", "wechat").present?
|
||||
provider :wechat, config.dig("oauth", "wechat", "appid"), config.dig("oauth", "wechat", "secret"), { provider_ignores_state: true, scope: "snsapi_login" }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Enable per-form CSRF tokens.
|
||||
# Rails.application.config.action_controller.per_form_csrf_tokens = true
|
||||
# Rails.application.config.action_controller.forgery_protection_origin_check = true
|
|
@ -0,0 +1,5 @@
|
|||
'zh-CN':
|
||||
activemodel:
|
||||
attributes:
|
||||
api/v1/users/feedbacks/create_service:
|
||||
content: "反馈意见"
|
|
@ -231,6 +231,8 @@ zh-CN:
|
|||
ignore:
|
||||
name: 'git忽略文件名称'
|
||||
content: 'git忽略文件内容'
|
||||
feedback_message_history:
|
||||
title: ''
|
||||
close_pr: 合并请求
|
||||
roles:
|
||||
Developer: 开发者
|
||||
|
|
|
@ -20,9 +20,10 @@ Rails.application.routes.draw do
|
|||
get 'attachments/download/:id', to: 'attachments#show'
|
||||
get 'attachments/download/:id/:filename', to: 'attachments#show'
|
||||
|
||||
get 'auth/qq/callback', to: 'oauth/qq#create'
|
||||
# get 'auth/qq/callback', to: 'oauth/qq#create'
|
||||
get 'auth/failure', to: 'oauth/base#auth_failure'
|
||||
get 'auth/cas/callback', to: 'oauth/cas#create'
|
||||
get 'auth/:provider/callback', to: 'oauth/callbacks#create'
|
||||
|
||||
get 'oauth/bind', to: 'oauth/educoder#bind'
|
||||
get 'oauth/register', to: 'oauth#register'
|
||||
|
@ -267,6 +268,7 @@ Rails.application.routes.draw do
|
|||
get :trustie_related_projects
|
||||
post :sync_user_info
|
||||
get :email_search
|
||||
post :action
|
||||
|
||||
scope '/ci', module: :ci do
|
||||
scope do
|
||||
|
@ -942,6 +944,10 @@ Rails.application.routes.draw do
|
|||
resources :nps do
|
||||
post :switch_change, on: :collection
|
||||
end
|
||||
resources :feedbacks, only: [:index, :destroy] do
|
||||
get :new_history, on: :member
|
||||
post :create_history, on: :member
|
||||
end
|
||||
resources :laboratories, only: [:index, :create, :destroy, :update] do
|
||||
member do
|
||||
get :shixuns_for_select
|
||||
|
|
|
@ -8,11 +8,14 @@ defaults format: :json do
|
|||
post :check_password
|
||||
post :check_email
|
||||
post :check_email_verify_code
|
||||
post :check_phone_verify_code
|
||||
patch :update_email
|
||||
patch :update_phone
|
||||
end
|
||||
end
|
||||
scope module: :users do
|
||||
resources :projects, only: [:index]
|
||||
resources :feedbacks, only: [:create]
|
||||
end
|
||||
|
||||
scope ':repo' do
|
||||
|
@ -51,6 +54,7 @@ defaults format: :json do
|
|||
end
|
||||
end
|
||||
resources :commits, only: [:index]
|
||||
resources :code_stats, only: [:index]
|
||||
get '/commits/:sha/diff', to: 'commits#diff'
|
||||
get '/git/blobs/:sha', to: 'git#blobs'
|
||||
get '/git/trees/:sha', to: 'git#trees'
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
class CreateFeedbacks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :feedbacks do |t|
|
||||
t.references :user
|
||||
t.text :content
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class CreateFeedbackMessageHistories < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :feedback_message_histories do |t|
|
||||
t.references :feedback
|
||||
t.references :user
|
||||
t.string :title
|
||||
t.text :content
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddPrivateProjectsCountToProjectCategory < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :project_categories, :private_projects_count, :integer, default: 0
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
class UpdateUserNickName < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
execute("ALTER TABLE `users` MODIFY `nickname` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `open_users` MODIFY `extra` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `issues` MODIFY `subject` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `issues` MODIFY `description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `projects` MODIFY `description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `project_details` MODIFY `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `journals` MODIFY `notes` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `journal_details` MODIFY `old_value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `journal_details` MODIFY `value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `claims` MODIFY `note` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `commit_logs` MODIFY `message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
execute("ALTER TABLE `user_extensions` MODIFY `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
class UpdatePullRequestUtfName < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
execute("ALTER TABLE `projects` MODIFY `name` VARCHAR(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `pull_requests` MODIFY `title` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `pull_requests` MODIFY `body` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `organization_extensions` MODIFY `description` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `version_releases` MODIFY `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `version_releases` MODIFY `body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `version_releases` MODIFY `tag_name` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `versions` MODIFY `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `versions` MODIFY `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `issue_tags` MODIFY `name` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `issue_tags` MODIFY `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
execute("ALTER TABLE `projects_activity` MODIFY `project_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class UpdateUserSuper < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
execute("ALTER TABLE `user_extensions` MODIFY `super_description` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue