forked from Trustie/forgeplus
Merge branch 'trustie_server' into standalone
This commit is contained in:
commit
97d0d09497
|
@ -23,7 +23,7 @@
|
|||
* Fix 版本库中附件下载400(#51625)
|
||||
* Fix loading页面优化(#51588)
|
||||
* Fix 提交详情页面优化(#51577)
|
||||
* Fix 修复易修复制功能(#51569)
|
||||
* Fix 修复疑修复制功能(#51569)
|
||||
* Fix 修复新建发行版用户信息显示错误的问题(#51665)
|
||||
* Fix 修复查看文件详细信息报错的问题(#51561)
|
||||
* Fix 修复提交记录中时间显示格式问题(#51526)
|
||||
|
@ -62,7 +62,7 @@
|
|||
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
|
||||
|
||||
* BUGFIXES
|
||||
* Fix 解决易修标题过长导致的排版问题(45469)
|
||||
* Fix 解决疑修标题过长导致的排版问题(45469)
|
||||
* Fix 解决合并请求详情页面排版错误的问题(45457)
|
||||
* FIX 解决转移仓库界面专有名词描述错误的问题(45455)
|
||||
* Fix 解决markdown格式文件自动生成数字排序的问题(45454)
|
||||
|
|
|
@ -1,379 +1,384 @@
|
|||
class AccountsController < ApplicationController
|
||||
include ApplicationHelper
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
||||
# 其他平台同步注册的用户
|
||||
def remote_register
|
||||
username = params[:username]&.gsub(/\s+/, "")
|
||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
password = params[:password]
|
||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = autologin_register(username, email, password, platform)
|
||||
if result[:message].blank?
|
||||
render_ok({user: result[:user]})
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台修改用户的信息,这边同步修改
|
||||
def remote_update
|
||||
ActiveRecord::Base.transaction do
|
||||
user_params = params[:user_params]
|
||||
user_extension_params = params[:user_extension_params]
|
||||
|
||||
u = User.find_by(login: params[:old_user_login])
|
||||
user_mail = u.try(:mail)
|
||||
|
||||
if u.present?
|
||||
ue = u.user_extension
|
||||
u.login = user_params["login"] if user_params["login"]
|
||||
u.mail = user_params["mail"] if user_params["mail"]
|
||||
u.lastname = user_params["lastname"] if user_params["lastname"]
|
||||
|
||||
ue.gender = user_extension_params["gender"]
|
||||
ue.school_id = user_extension_params["school_id"]
|
||||
ue.location = user_extension_params["location"]
|
||||
ue.location_city = user_extension_params["location_city"]
|
||||
ue.identity = user_extension_params["identity"]
|
||||
ue.technical_title = user_extension_params["technical_title"]
|
||||
ue.student_id = user_extension_params["student_id"]
|
||||
ue.description = user_extension_params["description"]
|
||||
ue.save!
|
||||
u.save!
|
||||
|
||||
sync_params = {}
|
||||
|
||||
if (user_params["mail"] && user_params["mail"] != user_mail)
|
||||
sync_params = sync_params.merge(email: user_params["mail"])
|
||||
end
|
||||
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
||||
if interactor.success?
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台同步登录
|
||||
def remote_login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
if @user
|
||||
successful_authentication(@user)
|
||||
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
||||
else
|
||||
render_error("用户不存在")
|
||||
end
|
||||
end
|
||||
|
||||
#修改密码
|
||||
def remote_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 用户注册
|
||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||
# params[:login] 邮箱或者手机号
|
||||
# params[:namespace] 登录名
|
||||
# params[:code] 验证码
|
||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||
# 本地forge注册入口需要重新更改逻辑
|
||||
def register
|
||||
# type只可能是1或者8
|
||||
user = nil
|
||||
begin
|
||||
Register::Form.new(register_params).validate!
|
||||
|
||||
user = Users::RegisterService.call(register_params)
|
||||
password = register_params[:password].strip
|
||||
|
||||
# gitea用户注册, email, username, password
|
||||
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
successful_authentication(user)
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
rescue Register::BaseForm::EmailError => e
|
||||
render_result(-2, e.message)
|
||||
rescue Register::BaseForm::LoginError => e
|
||||
render_result(-3, e.message)
|
||||
rescue Register::BaseForm::PhoneError => e
|
||||
render_result(-4, e.message)
|
||||
rescue Register::BaseForm::PasswordFormatError => e
|
||||
render_result(-5, e.message)
|
||||
rescue Register::BaseForm::PasswordConfirmationError => e
|
||||
render_result(-7, e.message)
|
||||
rescue Register::BaseForm::VerifiCodeError => e
|
||||
render_result(-6, e.message)
|
||||
rescue Exception => e
|
||||
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
# 用户登录
|
||||
def login
|
||||
Users::LoginForm.new(login_params).validate!
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||
# user is already in local database
|
||||
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
||||
|
||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
||||
|
||||
password_ok = @user.check_password?(params[:password].to_s)
|
||||
unless password_ok
|
||||
if login_control.remain_times-1 == 0
|
||||
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
||||
else
|
||||
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
||||
end
|
||||
login_control.increment!
|
||||
return
|
||||
end
|
||||
|
||||
successful_authentication(@user)
|
||||
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
||||
|
||||
# session[:user_id] = @user.id
|
||||
end
|
||||
|
||||
def change_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
# 忘记密码
|
||||
def reset_password
|
||||
begin
|
||||
Accounts::ResetPasswordForm.new(reset_password_params).validate!
|
||||
|
||||
user = find_user
|
||||
return render_error('未找到相关账号') if user.blank?
|
||||
|
||||
user = Accounts::ResetPasswordService.call(user, reset_password_params)
|
||||
LimitForbidControl::UserLogin.new(user).clear if user.save!
|
||||
|
||||
render_ok
|
||||
rescue Register::BaseForm::EmailError => e
|
||||
render_result(-2, e.message)
|
||||
rescue Register::BaseForm::PhoneError => e
|
||||
render_result(-4, e.message)
|
||||
rescue Register::BaseForm::PasswordFormatError => e
|
||||
render_result(-5, e.message)
|
||||
rescue Register::BaseForm::PasswordConfirmationError => e
|
||||
render_result(-7, e.message)
|
||||
rescue Register::BaseForm::VerifiCodeError => e
|
||||
render_result(-6, e.message)
|
||||
rescue ActiveRecord::Rollback => e
|
||||
render_result(-1, "服务器异常")
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def successful_authentication(user)
|
||||
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
||||
# Valid user
|
||||
self.logged_user = user
|
||||
# generate a key and set cookie if autologin
|
||||
|
||||
set_autologin_cookie(user)
|
||||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||
user.update_column(:last_login_on, Time.now)
|
||||
session[:"#{default_yun_session}"] = user.id
|
||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||
# 注册完成后有一天的试用申请(先去掉)
|
||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
:path => '/',
|
||||
:secure => false,
|
||||
:httponly => true
|
||||
}
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||
end
|
||||
cookies[autologin_cookie_name] = cookie_options
|
||||
cookies.signed[:user_id] ||= user.id
|
||||
|
||||
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
||||
end
|
||||
|
||||
def logout
|
||||
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
||||
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
||||
logout_user
|
||||
render :json => {status: 1, message: "退出成功!"}
|
||||
end
|
||||
|
||||
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
||||
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
||||
def valid_email_and_phone
|
||||
check_mail_and_phone_valid(params[:login], params[:type])
|
||||
end
|
||||
|
||||
# 发送验证码
|
||||
# params[:login] 手机号或者邮箱号
|
||||
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||
def get_verification_code
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
value = params[:login]
|
||||
type = params[:type].strip.to_i
|
||||
login_type = phone_mail_type(value)
|
||||
send_type = verify_type(login_type, type)
|
||||
verification_code = code.sample(6).join
|
||||
|
||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||
|
||||
logger.info "########### 验证码:#{verification_code}"
|
||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||
|
||||
# 记录验证码
|
||||
check_verification_code(verification_code, send_type, value)
|
||||
render_ok
|
||||
end
|
||||
|
||||
# check user's login or email or phone is used
|
||||
# params[:value] 手机号或者邮箱号或者登录名
|
||||
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||
def check
|
||||
Register::CheckColumnsForm.new(check_params).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||
# login_type 1:手机类型 2:邮箱类型
|
||||
def verify_type login_type, type
|
||||
case type
|
||||
when 1
|
||||
login_type == 1 ? 1 : 8
|
||||
when 2
|
||||
login_type == 1 ? 2 : 3
|
||||
when 3
|
||||
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
||||
when 4
|
||||
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
||||
when 5
|
||||
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
|
||||
end
|
||||
end
|
||||
|
||||
def generate_login(login)
|
||||
type = phone_mail_type(login.strip)
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = login
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = login
|
||||
phone = nil
|
||||
end
|
||||
code = generate_identifier User, 8, pre
|
||||
|
||||
{ login: pre + code, email: email, phone: phone }
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
||||
def login_params
|
||||
params.require(:account).permit(:login, :password)
|
||||
end
|
||||
|
||||
def check_params
|
||||
params.permit(:type, :value)
|
||||
end
|
||||
|
||||
def register_params
|
||||
params.permit(:login, :namespace, :password, :password_confirmation, :code)
|
||||
end
|
||||
|
||||
def reset_password_params
|
||||
params.permit(:login, :password, :password_confirmation, :code)
|
||||
end
|
||||
|
||||
def find_user
|
||||
phone_or_mail = strip(reset_password_params[:login])
|
||||
User.where("phone = :search OR mail = :search", search: phone_or_mail).last
|
||||
end
|
||||
|
||||
end
|
||||
class AccountsController < ApplicationController
|
||||
include ApplicationHelper
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
||||
# 其他平台同步注册的用户
|
||||
def remote_register
|
||||
Register::RemoteForm.new(remote_register_params).validate!
|
||||
username = params[:username]&.gsub(/\s+/, "")
|
||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
password = params[:password]
|
||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = autologin_register(username, email, password, platform)
|
||||
if result[:message].blank?
|
||||
render_ok({user: result[:user]})
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台修改用户的信息,这边同步修改
|
||||
def remote_update
|
||||
ActiveRecord::Base.transaction do
|
||||
user_params = params[:user_params]
|
||||
user_extension_params = params[:user_extension_params]
|
||||
|
||||
u = User.find_by(login: params[:old_user_login])
|
||||
user_mail = u.try(:mail)
|
||||
|
||||
if u.present?
|
||||
ue = u.user_extension
|
||||
u.login = user_params["login"] if user_params["login"]
|
||||
u.mail = user_params["mail"] if user_params["mail"]
|
||||
u.lastname = user_params["lastname"] if user_params["lastname"]
|
||||
|
||||
ue.gender = user_extension_params["gender"]
|
||||
ue.school_id = user_extension_params["school_id"]
|
||||
ue.location = user_extension_params["location"]
|
||||
ue.location_city = user_extension_params["location_city"]
|
||||
ue.identity = user_extension_params["identity"]
|
||||
ue.technical_title = user_extension_params["technical_title"]
|
||||
ue.student_id = user_extension_params["student_id"]
|
||||
ue.description = user_extension_params["description"]
|
||||
ue.save!
|
||||
u.save!
|
||||
|
||||
sync_params = {}
|
||||
|
||||
if (user_params["mail"] && user_params["mail"] != user_mail)
|
||||
sync_params = sync_params.merge(email: user_params["mail"])
|
||||
end
|
||||
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
||||
if interactor.success?
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台同步登录
|
||||
def remote_login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
if @user
|
||||
successful_authentication(@user)
|
||||
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
||||
else
|
||||
render_error("用户不存在")
|
||||
end
|
||||
end
|
||||
|
||||
#修改密码
|
||||
def remote_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 用户注册
|
||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||
# params[:login] 邮箱或者手机号
|
||||
# params[:namespace] 登录名
|
||||
# params[:code] 验证码
|
||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||
# 本地forge注册入口需要重新更改逻辑
|
||||
def register
|
||||
# type只可能是1或者8
|
||||
user = nil
|
||||
begin
|
||||
Register::Form.new(register_params).validate!
|
||||
|
||||
user = Users::RegisterService.call(register_params)
|
||||
password = register_params[:password].strip
|
||||
|
||||
# gitea用户注册, email, username, password
|
||||
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
successful_authentication(user)
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
rescue Register::BaseForm::EmailError => e
|
||||
render_result(-2, e.message)
|
||||
rescue Register::BaseForm::LoginError => e
|
||||
render_result(-3, e.message)
|
||||
rescue Register::BaseForm::PhoneError => e
|
||||
render_result(-4, e.message)
|
||||
rescue Register::BaseForm::PasswordFormatError => e
|
||||
render_result(-5, e.message)
|
||||
rescue Register::BaseForm::PasswordConfirmationError => e
|
||||
render_result(-7, e.message)
|
||||
rescue Register::BaseForm::VerifiCodeError => e
|
||||
render_result(-6, e.message)
|
||||
rescue Exception => e
|
||||
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
# 用户登录
|
||||
def login
|
||||
Users::LoginForm.new(login_params).validate!
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||
# user is already in local database
|
||||
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
||||
|
||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
||||
|
||||
password_ok = @user.check_password?(params[:password].to_s)
|
||||
unless password_ok
|
||||
if login_control.remain_times-1 == 0
|
||||
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
||||
else
|
||||
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
||||
end
|
||||
login_control.increment!
|
||||
return
|
||||
end
|
||||
|
||||
successful_authentication(@user)
|
||||
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
||||
|
||||
# session[:user_id] = @user.id
|
||||
end
|
||||
|
||||
def change_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
return render_error("旧密码不正确") unless @user.check_password?(params[:old_password])
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
# 忘记密码
|
||||
def reset_password
|
||||
begin
|
||||
Accounts::ResetPasswordForm.new(reset_password_params).validate!
|
||||
|
||||
user = find_user
|
||||
return render_error('未找到相关账号') if user.blank?
|
||||
|
||||
user = Accounts::ResetPasswordService.call(user, reset_password_params)
|
||||
LimitForbidControl::UserLogin.new(user).clear if user.save!
|
||||
|
||||
render_ok
|
||||
rescue Register::BaseForm::EmailError => e
|
||||
render_result(-2, e.message)
|
||||
rescue Register::BaseForm::PhoneError => e
|
||||
render_result(-4, e.message)
|
||||
rescue Register::BaseForm::PasswordFormatError => e
|
||||
render_result(-5, e.message)
|
||||
rescue Register::BaseForm::PasswordConfirmationError => e
|
||||
render_result(-7, e.message)
|
||||
rescue Register::BaseForm::VerifiCodeError => e
|
||||
render_result(-6, e.message)
|
||||
rescue ActiveRecord::Rollback => e
|
||||
render_result(-1, "服务器异常")
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def successful_authentication(user)
|
||||
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
||||
# Valid user
|
||||
self.logged_user = user
|
||||
# generate a key and set cookie if autologin
|
||||
|
||||
set_autologin_cookie(user)
|
||||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||
user.update_column(:last_login_on, Time.now)
|
||||
session[:"#{default_yun_session}"] = user.id
|
||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||
# 注册完成后有一天的试用申请(先去掉)
|
||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
# sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
:path => '/',
|
||||
:secure => false,
|
||||
:httponly => true
|
||||
}
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||
end
|
||||
cookies[autologin_cookie_name] = cookie_options
|
||||
cookies.signed[:user_id] ||= user.id
|
||||
|
||||
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
||||
end
|
||||
|
||||
def logout
|
||||
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
||||
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
||||
logout_user
|
||||
render :json => {status: 1, message: "退出成功!"}
|
||||
end
|
||||
|
||||
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
||||
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
||||
def valid_email_and_phone
|
||||
check_mail_and_phone_valid(params[:login], params[:type])
|
||||
end
|
||||
|
||||
# 发送验证码
|
||||
# params[:login] 手机号或者邮箱号
|
||||
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||
def get_verification_code
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
value = params[:login]
|
||||
type = params[:type].strip.to_i
|
||||
login_type = phone_mail_type(value)
|
||||
send_type = verify_type(login_type, type)
|
||||
verification_code = code.sample(6).join
|
||||
|
||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||
|
||||
logger.info "########### 验证码:#{verification_code}"
|
||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||
|
||||
# 记录验证码
|
||||
check_verification_code(verification_code, send_type, value)
|
||||
render_ok
|
||||
end
|
||||
|
||||
# check user's login or email or phone is used
|
||||
# params[:value] 手机号或者邮箱号或者登录名
|
||||
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||
def check
|
||||
Register::CheckColumnsForm.new(check_params).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||
# login_type 1:手机类型 2:邮箱类型
|
||||
def verify_type login_type, type
|
||||
case type
|
||||
when 1
|
||||
login_type == 1 ? 1 : 8
|
||||
when 2
|
||||
login_type == 1 ? 2 : 3
|
||||
when 3
|
||||
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
||||
when 4
|
||||
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
||||
when 5
|
||||
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
|
||||
end
|
||||
end
|
||||
|
||||
def generate_login(login)
|
||||
type = phone_mail_type(login.strip)
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = login
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = login
|
||||
phone = nil
|
||||
end
|
||||
code = generate_identifier User, 8, pre
|
||||
|
||||
{ login: pre + code, email: email, phone: phone }
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
||||
def login_params
|
||||
params.require(:account).permit(:login, :password)
|
||||
end
|
||||
|
||||
def check_params
|
||||
params.permit(:type, :value)
|
||||
end
|
||||
|
||||
def register_params
|
||||
params.permit(:login, :namespace, :password, :password_confirmation, :code)
|
||||
end
|
||||
|
||||
def reset_password_params
|
||||
params.permit(:login, :password, :password_confirmation, :code)
|
||||
end
|
||||
|
||||
def find_user
|
||||
phone_or_mail = strip(reset_password_params[:login])
|
||||
User.where("phone = :search OR mail = :search", search: phone_or_mail).last
|
||||
end
|
||||
|
||||
def remote_register_params
|
||||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -272,18 +272,18 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
# 测试版前端需求
|
||||
logger.info("subdomain:#{request.subdomain}")
|
||||
# if request.subdomain != "www"
|
||||
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
# User.current = User.find 81403
|
||||
# elsif params[:debug] == 'student'
|
||||
# User.current = User.find 8686
|
||||
# elsif params[:debug] == 'admin'
|
||||
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
# user = User.find 36480
|
||||
# User.current = user
|
||||
# cookies.signed[:user_id] = user.id
|
||||
# end
|
||||
# end
|
||||
if request.subdomain != "www"
|
||||
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
User.current = User.find 81403
|
||||
elsif params[:debug] == 'student'
|
||||
User.current = User.find 8686
|
||||
elsif params[:debug] == 'admin'
|
||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
user = User.find 36480
|
||||
User.current = user
|
||||
cookies.signed[:user_id] = user.id
|
||||
end
|
||||
end
|
||||
# User.current = User.find 81403
|
||||
end
|
||||
|
||||
|
@ -704,14 +704,20 @@ class ApplicationController < ActionController::Base
|
|||
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def convert_image!
|
||||
@image = params[:image]
|
||||
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
|
||||
return unless @image.present?
|
||||
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
||||
if @image.class == ActionDispatch::Http::UploadedFile
|
||||
render_error('请上传文件') if @image.size.zero?
|
||||
render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||
return render_error('请上传文件') if @image.size.zero?
|
||||
return render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
|
||||
else
|
||||
image = @image.to_s.strip
|
||||
return render_error('请上传正确的图片') if image.blank?
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
#coding=utf-8
|
||||
class ClaimsController < ApplicationController
|
||||
# skip_before_action :verify_authenticity_token
|
||||
protect_from_forgery with: :null_session
|
||||
before_action :require_login, except: [:index]
|
||||
before_action :set_issue
|
||||
|
||||
def index
|
||||
@user_claimed = 0
|
||||
@claims = @issue.claims.claim_includes.order("created_at desc")
|
||||
|
||||
@claims.each do |claim|
|
||||
if claim.user_id == current_user.id
|
||||
@user_claimed = 1
|
||||
break
|
||||
end
|
||||
end
|
||||
render file: 'app/views/claims/list.json.jbuilder'
|
||||
end
|
||||
|
||||
def create
|
||||
@claim = Claim.find_by_sql(["select id from claims where issue_id=? and user_id=?",params[:issue_id], current_user.id])
|
||||
if @claim.present?
|
||||
return normal_status(-1,"您已经声明过该易修")
|
||||
end
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@claim = Claim.new(parse_issue_params(params))
|
||||
if @claim.save
|
||||
@claims = @issue.claims.claim_includes.order("created_at desc")
|
||||
@user_claimed = 1
|
||||
|
||||
journal_params = {
|
||||
journalized_id: params[:issue_id],
|
||||
journalized_type: "Issue",
|
||||
user_id: current_user.id ,
|
||||
notes: "新建声明: #{params[:claim_note]}",
|
||||
}
|
||||
|
||||
journal = Journal.new(journal_params)
|
||||
if journal.save
|
||||
render file: 'app/views/claims/list.json.jbuilder'
|
||||
else
|
||||
normal_status(-1,"新建声明关联评论操作失败")
|
||||
end
|
||||
|
||||
else
|
||||
normal_status(-1,"新建声明操作失败")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@claim = Claim.find_by_id(params[:claim_id])
|
||||
if @claim.blank?
|
||||
return normal_status(-1,"易修不存在")
|
||||
end
|
||||
|
||||
if @claim.user_id != current_user.id
|
||||
return normal_status(-1,"你不能更新别人的声明")
|
||||
end
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
if @claim.update_attribute(:note,params[:claim_note])
|
||||
@claims = @issue.claims.claim_includes.order("created_at desc")
|
||||
@user_claimed = 1
|
||||
|
||||
journal_params = {
|
||||
journalized_id: params[:issue_id],
|
||||
journalized_type: "Issue",
|
||||
user_id: current_user.id ,
|
||||
notes: "更新声明: #{params[:claim_note]}",
|
||||
}
|
||||
|
||||
journal = Journal.new(journal_params)
|
||||
if journal.save
|
||||
render file: 'app/views/claims/list.json.jbuilder'
|
||||
else
|
||||
normal_status(-1,"新建声明关联评论操作失败")
|
||||
end
|
||||
|
||||
else
|
||||
normal_status(-1,"声明更新操作失败")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@claim = Claim.find_by_sql(["select id from claims where issue_id=? and user_id=?",params[:issue_id], current_user.id])
|
||||
if @claim.blank?
|
||||
normal_status(-1,"您未曾声明过该易修")
|
||||
else
|
||||
@claim = @claim[0]
|
||||
# 判断current user是否是claimer
|
||||
ActiveRecord::Base.transaction do
|
||||
if @claim.destroy
|
||||
|
||||
@claims = @issue.claims.claim_includes.order("created_at desc")
|
||||
@user_claimed = 0
|
||||
|
||||
journal_params = {
|
||||
journalized_id: params[:issue_id],
|
||||
journalized_type: "Issue",
|
||||
user_id: current_user.id ,
|
||||
notes: "取消声明",
|
||||
}
|
||||
|
||||
journal = Journal.new(journal_params)
|
||||
if journal.save
|
||||
render file: 'app/views/claims/list.json.jbuilder'
|
||||
else
|
||||
normal_status(-1,"新建声明关联评论操作失败")
|
||||
end
|
||||
|
||||
else
|
||||
normal_status(-1,"取消声明操作失败")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def parse_issue_params(params)
|
||||
{
|
||||
issue_id: params[:issue_id],
|
||||
user_id: current_user.id,
|
||||
note: params[:claim_note],
|
||||
}
|
||||
end
|
||||
|
||||
def set_issue
|
||||
@issue = Issue.find_by_id(params[:issue_id])
|
||||
unless @issue.present?
|
||||
normal_status(-1, "易修不存在")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -42,12 +42,14 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def load_compare_params
|
||||
@base = Addressable::URI.unescape(params[:base])
|
||||
# @base = Addressable::URI.unescape(params[:base])
|
||||
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
|
||||
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
|
||||
|
||||
# @head = Addressable::URI.unescape(@head)
|
||||
@head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head)
|
||||
end
|
||||
|
||||
def gitea_compare(base, head)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -486,7 +486,8 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
def operate_issue_permission
|
||||
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
|
||||
@issue = Issue.find_by_id(params[:id]) unless @issue.present?
|
||||
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
|
||||
end
|
||||
|
||||
def export_issues(issues)
|
||||
|
|
|
@ -28,7 +28,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate!
|
||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
end
|
||||
|
@ -39,7 +39,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate!
|
||||
login = @organization.login
|
||||
@organization.login = organization_params[:name] if organization_params[:name].present?
|
||||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||
|
|
|
@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
|||
ActiveRecord::Base.transaction do
|
||||
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
||||
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
||||
SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
end
|
||||
rescue Exception => e
|
||||
|
@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
|||
ActiveRecord::Base.transaction do
|
||||
@team_user.destroy!
|
||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
|
||||
unless org_team_users.present?
|
||||
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!
|
||||
|
|
|
@ -4,15 +4,24 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
|
||||
|
||||
def index
|
||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
#else
|
||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
#end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
|
||||
@teams = kaminari_paginate(@teams)
|
||||
if params[:is_full].present?
|
||||
if can_edit_org?
|
||||
@teams = @organization.teams
|
||||
else
|
||||
@teams = []
|
||||
end
|
||||
else
|
||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
#else
|
||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
#end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
|
||||
@teams = kaminari_paginate(@teams)
|
||||
end
|
||||
end
|
||||
|
||||
def search
|
||||
|
@ -34,8 +43,12 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
if @organization.teams.count >= 50
|
||||
return render_forbidden("组织的团队数量已超过限制!")
|
||||
else
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
|
|||
before_action :check_project_public
|
||||
|
||||
def index
|
||||
project_trends = @project.project_trends.preload(:user, trend: :user)
|
||||
project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner)
|
||||
|
||||
check_time = params[:time] #时间的筛选
|
||||
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
||||
|
|
|
@ -16,13 +16,13 @@ class ProjectsController < ApplicationController
|
|||
menu.append(menu_hash_by_name("home"))
|
||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
|
||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki")
|
||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
|
||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
|
||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
|
||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||
menu.append(menu_hash_by_name("activity"))
|
||||
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
|
||||
menu.append(menu_hash_by_name("settings")) if (current_user.admin? || @project.manager?(current_user)) && @project.forge?
|
||||
|
||||
render json: menu
|
||||
end
|
||||
|
@ -82,8 +82,9 @@ class ProjectsController < ApplicationController
|
|||
def branches
|
||||
return @branches = [] unless @project.forge?
|
||||
|
||||
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier)
|
||||
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
|
||||
end
|
||||
|
||||
def branches_slice
|
||||
|
|
|
@ -56,7 +56,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
if @gitea_pull_request[:status] == :success
|
||||
|
@ -89,6 +89,7 @@ class PullRequestsController < ApplicationController
|
|||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
return normal_status(-1, "title不能超过255个字符") if params[:title].length > 255
|
||||
merge_params
|
||||
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
|
|
|
@ -1,368 +1,387 @@
|
|||
class RepositoriesController < ApplicationController
|
||||
include RepositoriesHelper
|
||||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include Repository::LanguagesPercentagable
|
||||
|
||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||
before_action :require_profile_completed, only: [:create_file]
|
||||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
def top_counts
|
||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = [{
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}]
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
end
|
||||
else
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits
|
||||
if @project.educoder?
|
||||
@hash_commit = nil
|
||||
else
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits_slice
|
||||
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner&.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def commit
|
||||
@sha = params[:sha]
|
||||
if @project.educoder?
|
||||
@commit = {}
|
||||
@commit_diff ={}
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def contributors
|
||||
if params[:filepath].present?
|
||||
@contributors = []
|
||||
else
|
||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
||||
end
|
||||
|
||||
def create_file
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# create_new_pr(params)
|
||||
#如果是更新流水线文件
|
||||
if params[:pipeline_id]
|
||||
update_pipeline(params[:pipeline_id])
|
||||
end
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def update_pipeline(pipeline_id)
|
||||
pipeline = Ci::Pipeline.find(pipeline_id)
|
||||
if pipeline
|
||||
pipeline.update!(sync: 1)
|
||||
end
|
||||
end
|
||||
|
||||
def update_file
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# TODO: 是否创建pr
|
||||
# create_new_pr(params)
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "文件删除成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def repo_hook
|
||||
|
||||
end
|
||||
|
||||
def sync_mirror
|
||||
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
||||
|
||||
@repository.sync_mirror!
|
||||
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def readme
|
||||
if params[:filepath].present?
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
end
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
||||
rescue
|
||||
render json: nil
|
||||
end
|
||||
|
||||
def languages
|
||||
render json: languages_precentagable
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
|
||||
file_path = [domain, api_url, url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden?
|
||||
|
||||
redirect_to URI.escape(file_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_project
|
||||
@project = Project.find params[:id]
|
||||
render_not_found("未找到相关的仓库") unless @project
|
||||
end
|
||||
|
||||
def find_project_with_includes
|
||||
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
||||
end
|
||||
|
||||
def authorizate!
|
||||
return if current_user && current_user.admin?
|
||||
if @project.repository.hidden? && !@project.member?(current_user)
|
||||
render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
# TODO 获取最新commit信息
|
||||
def project_commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
else
|
||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
@ref = params[:ref] || @project&.default_branch
|
||||
end
|
||||
|
||||
def get_latest_commit
|
||||
latest_commit = @project.educoder? ? nil : project_commits
|
||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||
end
|
||||
|
||||
def content_params
|
||||
{
|
||||
filepath: params[:filepath],
|
||||
branch: params[:branch],
|
||||
new_branch: params[:new_branch],
|
||||
content: params[:content],
|
||||
message: params[:message],
|
||||
committer: {
|
||||
email: current_user.mail,
|
||||
name: current_user.login
|
||||
},
|
||||
identifier: @project.identifier
|
||||
}
|
||||
end
|
||||
|
||||
def hook_params(hook_type, params)
|
||||
# if hook_type == "push"
|
||||
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
||||
# uploadPushInfo = {
|
||||
# "sha": params["commits"].present? ? params["commits"].last : "",
|
||||
# "branch": params["ref"].to_s.split("/").last,
|
||||
# "modification_lines": params["commits"].length
|
||||
# }
|
||||
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
||||
# uploadPushInfo = {
|
||||
# "branch": params["base"]["ref"].to_s.split("/").last,
|
||||
# "sha": params["pull_request"]["merge_base"],
|
||||
# "modification_lines": 1 #pull_request中没有commits数量
|
||||
# }
|
||||
# else
|
||||
# uploadPushInfo = {}
|
||||
# end
|
||||
|
||||
# uploadPushInfo
|
||||
end
|
||||
|
||||
def create_new_pr(params)
|
||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||
local_params = {
|
||||
title: params[:message], #标题
|
||||
body: params[:content], #内容
|
||||
head: params[:new_branch], #源分支
|
||||
base: params[:branch], #目标分支
|
||||
milestone: 0 #里程碑,未与本地的里程碑关联
|
||||
|
||||
}
|
||||
requests_params = local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
assignees: [],
|
||||
labels: [],
|
||||
due_date: Time.now
|
||||
})
|
||||
|
||||
issue_params = {
|
||||
author_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
subject: params[:message],
|
||||
description: params[:content],
|
||||
assigned_to_id: nil,
|
||||
fixed_version_id: nil,
|
||||
issue_tags_value: nil,
|
||||
issue_classify: "pull_request",
|
||||
issue_type: "1",
|
||||
tracker_id: 2,
|
||||
status_id: 1,
|
||||
priority_id: params[:priority_id] || "2"
|
||||
}
|
||||
@pull_issue = Issue.new(issue_params)
|
||||
if @pull_issue.save!
|
||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gitea_number: gitea_request["body"]["number"], gpid: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
class RepositoriesController < ApplicationController
|
||||
include RepositoriesHelper
|
||||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include Repository::LanguagesPercentagable
|
||||
|
||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||
before_action :require_profile_completed, only: [:create_file]
|
||||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
def top_counts
|
||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
begin
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
end
|
||||
rescue
|
||||
return render_error('该文件暂未开放,敬请期待.')
|
||||
end
|
||||
end
|
||||
else
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits
|
||||
if @project.educoder?
|
||||
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
|
||||
else
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits_slice
|
||||
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def commit
|
||||
@sha = params[:sha]
|
||||
if @project.educoder?
|
||||
return render_error('暂未开放,敬请期待.')
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def contributors
|
||||
if params[:filepath].present? || @project.educoder?
|
||||
@contributors = []
|
||||
else
|
||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
||||
end
|
||||
|
||||
def create_file
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# create_new_pr(params)
|
||||
#如果是更新流水线文件
|
||||
if params[:pipeline_id]
|
||||
update_pipeline(params[:pipeline_id])
|
||||
end
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def update_pipeline(pipeline_id)
|
||||
pipeline = Ci::Pipeline.find(pipeline_id)
|
||||
if pipeline
|
||||
pipeline.update!(sync: 1)
|
||||
end
|
||||
end
|
||||
|
||||
def update_file
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# TODO: 是否创建pr
|
||||
# create_new_pr(params)
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "文件删除成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def repo_hook
|
||||
|
||||
end
|
||||
|
||||
def sync_mirror
|
||||
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
||||
|
||||
@repository.sync_mirror!
|
||||
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def readme
|
||||
if params[:filepath].present?
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
end
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
||||
rescue
|
||||
render json: nil
|
||||
end
|
||||
|
||||
def languages
|
||||
if @project.educoder?
|
||||
render json: {}
|
||||
else
|
||||
render json: languages_precentagable
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_project
|
||||
@project = Project.find params[:id]
|
||||
render_not_found("未找到相关的仓库") unless @project
|
||||
end
|
||||
|
||||
def find_project_with_includes
|
||||
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
||||
end
|
||||
|
||||
def authorizate!
|
||||
return if current_user && current_user.admin?
|
||||
if @project.repository.hidden? && !@project.member?(current_user)
|
||||
render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
# TODO 获取最新commit信息
|
||||
def project_commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
else
|
||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
@ref = params[:ref] || @project&.default_branch
|
||||
end
|
||||
|
||||
def get_latest_commit
|
||||
latest_commit = @project.educoder? ? nil : project_commits
|
||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||
end
|
||||
|
||||
def content_params
|
||||
{
|
||||
filepath: params[:filepath],
|
||||
branch: params[:branch],
|
||||
new_branch: params[:new_branch],
|
||||
content: params[:content],
|
||||
message: params[:message],
|
||||
committer: {
|
||||
email: current_user.mail,
|
||||
name: current_user.login
|
||||
},
|
||||
identifier: @project.identifier
|
||||
}
|
||||
end
|
||||
|
||||
def hook_params(hook_type, params)
|
||||
# if hook_type == "push"
|
||||
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
||||
# uploadPushInfo = {
|
||||
# "sha": params["commits"].present? ? params["commits"].last : "",
|
||||
# "branch": params["ref"].to_s.split("/").last,
|
||||
# "modification_lines": params["commits"].length
|
||||
# }
|
||||
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
||||
# uploadPushInfo = {
|
||||
# "branch": params["base"]["ref"].to_s.split("/").last,
|
||||
# "sha": params["pull_request"]["merge_base"],
|
||||
# "modification_lines": 1 #pull_request中没有commits数量
|
||||
# }
|
||||
# else
|
||||
# uploadPushInfo = {}
|
||||
# end
|
||||
|
||||
# uploadPushInfo
|
||||
end
|
||||
|
||||
def create_new_pr(params)
|
||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||
local_params = {
|
||||
title: params[:message], #标题
|
||||
body: params[:content], #内容
|
||||
head: params[:new_branch], #源分支
|
||||
base: params[:branch], #目标分支
|
||||
milestone: 0 #里程碑,未与本地的里程碑关联
|
||||
|
||||
}
|
||||
requests_params = local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
assignees: [],
|
||||
labels: [],
|
||||
due_date: Time.now
|
||||
})
|
||||
|
||||
issue_params = {
|
||||
author_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
subject: params[:message],
|
||||
description: params[:content],
|
||||
assigned_to_id: nil,
|
||||
fixed_version_id: nil,
|
||||
issue_tags_value: nil,
|
||||
issue_classify: "pull_request",
|
||||
issue_type: "1",
|
||||
tracker_id: 2,
|
||||
status_id: 1,
|
||||
priority_id: params[:priority_id] || "2"
|
||||
}
|
||||
@pull_issue = Issue.new(issue_params)
|
||||
if @pull_issue.save!
|
||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ class UsersController < ApplicationController
|
|||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me list sync_user_info]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
before_action :convert_image!, only: [:update]
|
||||
before_action :convert_image!, only: [:update, :update_image]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
||||
def connect_to_ci_db(options={})
|
||||
|
@ -82,10 +82,21 @@ class UsersController < ApplicationController
|
|||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||
@user.attributes = user_params.except(:image)
|
||||
unless @user.save
|
||||
render_error(@user.errors.full_messages.join(", "))
|
||||
render_error(-1, @user.errors.full_messages.join(", "))
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
Util.write_file(@image, avatar_path(@user))
|
||||
return render_ok({message: '头像修改成功'})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
render_error(-1, '头像修改失败!')
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
|
|
@ -0,0 +1,852 @@
|
|||
# Projects
|
||||
|
||||
## 申请加入项目
|
||||
申请加入项目
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/applied_projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/appliedr_projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/applied_projects.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|applied_project.code |是| |string |邀请码 |
|
||||
|applied_project.role |否| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||
|
||||
> 请求的JSON示例
|
||||
|
||||
```json
|
||||
{
|
||||
"applied_project": {
|
||||
"code": "1una34",
|
||||
"role": "developer"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |申请id |
|
||||
|status |string |申请状态,canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |项目申请创建的时间 |
|
||||
|project.id |int |申请项目的id |
|
||||
|project.identifier |string |申请项目的标识 |
|
||||
|project.name |string |申请项目的名称 |
|
||||
|project.description |string |申请项目的描述 |
|
||||
|project.is_public |bool |申请项目是否公开 |
|
||||
|project.owner.id |bool |申请项目拥有者id |
|
||||
|project.owner.type |string |申请项目拥有者类型 |
|
||||
|project.owner.name |string |申请项目拥有者昵称 |
|
||||
|project.owner.login |string |申请项目拥有者标识 |
|
||||
|project.owner.image_url |string |申请项目拥有者头像 |
|
||||
|user.id |int |申请创建者的id |
|
||||
|user.type |string |申请创建者的类型 |
|
||||
|user.name |string |申请创建者的名称 |
|
||||
|user.login |string |申请创建者的标识 |
|
||||
|user.image_url |string |申请创建者头像 |
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 74,
|
||||
"identifier": "hehuisssjssjjsjs",
|
||||
"name": "hehuisssjssjjsjs",
|
||||
"description": "wwww",
|
||||
"is_public": false,
|
||||
"owner": {
|
||||
"id": 10,
|
||||
"type": "User",
|
||||
"name": "testforge1",
|
||||
"login": "testforge1",
|
||||
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "何慧",
|
||||
"login": "yystopf",
|
||||
"image_url": "images/avatars/User/6?t=1622513134"
|
||||
},
|
||||
"id": 7,
|
||||
"status": "common",
|
||||
"created_at": "2021-06-09 16:41",
|
||||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
||||
|
||||
## 获取项目列表
|
||||
获取项目列表,也可以更加相关条件过滤搜素
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
-d "page=1" \
|
||||
-d "limit=5" \
|
||||
http://localhost:3000/api/projects | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/projects')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/projects`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
page | false | 1 | string | 页数,第几页
|
||||
limit | false | 15 | string | 每页多少条数据,默认15条
|
||||
sort_by | false | | string | 排序类型, 取值:updated_on、created_on、forked_count、praises_count; updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序
|
||||
sort_direction| false | | string | 排序方式,取值为: desc、asc; desc: 降序排序, asc: 升序排序, 默认为:desc
|
||||
search | false | | string | 按照项目名称搜索
|
||||
category_id | false | | int | 项目类别id
|
||||
language_id | false | | int | 项目语言id
|
||||
project_type | false | | string | 项目类型, 取值为:common、mirror; common:开源托管项目, mirror:开源镜像项目
|
||||
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
total_count | int | 项目总条数
|
||||
id | string | 项目id
|
||||
name | string | 项目名称
|
||||
description | string | 项目简介
|
||||
visits | int | 流量数
|
||||
forked_count | int | 被fork的数量
|
||||
praises_count | int | star数量
|
||||
is_public | boolean | 是否公开, true:公开,false:未公开
|
||||
mirror_url | string | 镜像url
|
||||
last_update_time| int | 最后更新时间,为UNIX格式的时间戳
|
||||
author | object | 项目创建者
|
||||
-- name | string | 用户名,也是用户标识
|
||||
category | object | 项目类别
|
||||
-- id | int | 项目类型id
|
||||
-- name | string | 项目类型名称
|
||||
language | object | 项目语言
|
||||
-- id | int | 项目语言id
|
||||
-- name | string | 项目语言名称
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_count": 3096,
|
||||
"projects": [
|
||||
{
|
||||
"id": 1400794,
|
||||
"repo_id": 1402452,
|
||||
"identifier": "cscw_2021_sponsor",
|
||||
"name": "Sponsor机制下的开源贡献",
|
||||
"description": "CSCW 2021 sponsor机制研究",
|
||||
"visits": 5,
|
||||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"mirror_url": null,
|
||||
"type": 0,
|
||||
"last_update_time": 1611971671,
|
||||
"time_ago": "2天前",
|
||||
"forked_from_project_id": null,
|
||||
"open_devops": false,
|
||||
"platform": "forge",
|
||||
"author": {
|
||||
"name": "张迅晖",
|
||||
"login": "Nigel",
|
||||
"image_url": "images/avatars/User/3675?t=1611832880"
|
||||
},
|
||||
"category": {
|
||||
"id": 13,
|
||||
"name": "云计算和大数据"
|
||||
},
|
||||
"language": {
|
||||
"id": 34,
|
||||
"name": "Python3.6"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Remember — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
## 推荐项目
|
||||
获取推荐项目列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/projects/recommend | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/projects/recommend.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/projects/recommend`
|
||||
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
total_count |int |项目总条数
|
||||
id |string |项目id
|
||||
name |string|项目名称
|
||||
description |string|项目简介
|
||||
visits |int|流量数
|
||||
forked_count |int|被fork的数量
|
||||
praises_count |int|star数量
|
||||
is_public |boolean|是否公开, true:公开,false:未公开
|
||||
mirror_url |string|镜像url
|
||||
last_update_time|int|最后更新时间,为UNIX格式的时间戳
|
||||
author |object|项目创建者
|
||||
-- name |string|用户名,也是用户标识
|
||||
category |object|项目类别
|
||||
-- id |int|项目类型id
|
||||
-- name |string|项目类型名称
|
||||
language |object|项目语言
|
||||
-- id |int|项目语言id
|
||||
-- name |string|项目语言名称
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 20,
|
||||
"repo_id": 2,
|
||||
"identifier": "PNAekinmH",
|
||||
"name": "FNILL",
|
||||
"visits": 13567,
|
||||
"author": {
|
||||
"name": "王一达",
|
||||
"login": "wangyida",
|
||||
"image_url": "avatars/User/b"
|
||||
},
|
||||
"category": {
|
||||
"id": 8,
|
||||
"name": "其他"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
<aside class="success">
|
||||
Remember — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
## 项目导航
|
||||
获取项目导航信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/yystopf/ceshi/menu_list | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/menu_list')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/:owner/:repo/menu_list`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是| |string |用户登录名
|
||||
repo |是| |string |项目标识identifier
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"menu_name": "home"
|
||||
},
|
||||
{
|
||||
"menu_name": "code"
|
||||
},
|
||||
{
|
||||
"menu_name": "pulls"
|
||||
},
|
||||
{
|
||||
"menu_name": "activity"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## 项目主页
|
||||
获取项目主页信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/jasder/forgeplus/about | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/jasder/forgeplus/about')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/:owner/:repo/about`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是| |string |用户登录名
|
||||
repo |是| |string |项目标识identifier
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
identifier |string|project's identifier
|
||||
content |string|主页内容
|
||||
attachments |array|附件
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "",
|
||||
"identifier": "forgeplus",
|
||||
attachments: []
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Remember — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 项目模块信息
|
||||
项目模块信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/yystopf/ceshi/project_units.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/project_units')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/yystopf/ceshi/project_units`
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|type |string|模块名称 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "code"
|
||||
},
|
||||
{
|
||||
"type": "pulls"
|
||||
},
|
||||
{
|
||||
"type": "issues"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 更改项目模块展示
|
||||
更改项目模块展示
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
-H "accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \
|
||||
http://localhost:3000/api/yystopf/ceshi/project_units.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/ceshi/project_units')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/yystopf/ceshi/project_units`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|status |int|返回状态, 0: 表示操作成功 |
|
||||
|message |string|返回信息说明|
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
## 创建项目
|
||||
创建项目
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
-d "user_id=36401" \
|
||||
-d "name=hnfl_demo" \
|
||||
-d "description=my first project" \
|
||||
-d "repository_name=hnfl_demo" \
|
||||
-d "project_category_id=1" \
|
||||
-d "project_language_id=2" \
|
||||
-d "ignore_id=2" \
|
||||
-d "license_id=1" \
|
||||
http://localhost:3000/api/projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/projects`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|user_id |是| |int |用户id或者组织id |
|
||||
|name |是| |string |项目名称 |
|
||||
|description |是| |string |项目描述 |
|
||||
|repository_name |是| |string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
||||
|project_category_id|是| |int |项目类别id |
|
||||
|project_language_id|是| |int |项目语言id |
|
||||
|ignore_id |否| |int |gitignore相关id |
|
||||
|license_id |否| |int |开源许可证id |
|
||||
|private |否| |boolean|项目是否私有, true:为私有,false: 公开,默认为公开 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |id |
|
||||
|name |string|项目名称|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 3240,
|
||||
"name": "好项目"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 创建镜像项目
|
||||
创建镜像项目
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
-d "user_id=36408" \
|
||||
-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
|
||||
-d "name=golden_mirror1" \
|
||||
-d "description=golden_mirror" \
|
||||
-d "project_category_id=1" \
|
||||
-d "project_language_id=2" \
|
||||
http://localhost:3000/api/projects/migrate.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/projects/migrate.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/projects/migrate.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|user_id |是| |int |用户id或者组织id |
|
||||
|name |是| |string |项目名称 |
|
||||
|clone_addr |是| |string |镜像项目clone地址 |
|
||||
|description |否| |string |项目描述 |
|
||||
|repository_name |是| |string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|
||||
|project_category_id|是| |int |项目类别id |
|
||||
|project_language_id|是| |int |项目语言id |
|
||||
|is_mirror |否| |boolean|是否设置为镜像, true:是, false:否,默认为否 |
|
||||
|auth_username |否| |string|镜像源仓库的登录用户名 |
|
||||
|auth_password |否| |string|镜像源仓库的登录秘密 |
|
||||
|private |否| |boolean|项目是否私有, true:为私有,false: 非私有,默认为公开 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |id |
|
||||
|name |string|项目名称|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 3241,
|
||||
"name": "这是一个镜像项目"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 同步镜像
|
||||
手动同步镜像
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/repositories/1244/sync_mirror.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/repositories/:id/sync_mirror.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|id |是| |int |仓库id |
|
||||
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|status |int |状态码, 0:标识请求成功 |
|
||||
|message |string|服务端返回的信息说明|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Fork项目
|
||||
fork项目
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/jaser/jasder_test/forks.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/:owner/:repo/forks.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |项目id |
|
||||
|identifier |string|项目标识|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 3290,
|
||||
"identifier": "newadm"
|
||||
}
|
||||
```
|
||||
|
||||
## 用户管理的组织列表
|
||||
用户管理的组织列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/:owner/:repo/applied_transfer_projects/organizations')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/:owner/:repo/applied_transfer_projects/organizations`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是| |string |用户登录名
|
||||
repo |是| |string |项目标识identifier
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
name |string|组织标识
|
||||
nickname |string|组织名称
|
||||
description|string|组织描述
|
||||
avatar_url|string|组织头像
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_count": 3,
|
||||
"organizations": [
|
||||
{
|
||||
"id": 9,
|
||||
"name": "ceshi_org",
|
||||
"nickname": "测试组织",
|
||||
"description": "测试组织",
|
||||
"avatar_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"name": "ceshi",
|
||||
"nickname": "测试组织哈哈哈",
|
||||
"description": "23212312",
|
||||
"avatar_url": "images/avatars/Organization/51?t=1618800723"
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"name": "ceshi1",
|
||||
"nickname": "身份卡手动阀",
|
||||
"description": "1231手动阀是的",
|
||||
"avatar_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 迁移项目
|
||||
迁移项目,edit接口is_transfering为true表示正在迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/:owner/:repo/applied_transfer_projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/applied_transfer_projects.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|owner_name|是| |string |迁移对象标识 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |项目id |
|
||||
|status |string |项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |项目迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 9,
|
||||
"type": "Organization",
|
||||
"name": "测试组织",
|
||||
"login": "ceshi_org",
|
||||
"image_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
"id": 4,
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
||||
|
||||
## 取消迁移项目
|
||||
迁移项目,edit接口is_transfering为true表示正在迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/applied_transfer_projects/cancel.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |迁移id |
|
||||
|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 9,
|
||||
"type": "Organization",
|
||||
"name": "测试组织",
|
||||
"login": "ceshi_org",
|
||||
"image_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
"id": 4,
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
|
@ -1240,11 +1240,11 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
|
|||
|delete|分支或标签删除|
|
||||
|fork|仓库被fork|
|
||||
|push|git仓库推送|
|
||||
|issue|易修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|易修被指派|
|
||||
|issue_label|易修标签被更新或删除|
|
||||
|issue_milestone|易修被收入里程碑|
|
||||
|issue_comment|易修评论|
|
||||
|issue|疑修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|疑修被指派|
|
||||
|issue_label|疑修标签被更新或删除|
|
||||
|issue_milestone|疑修被收入里程碑|
|
||||
|issue_comment|疑修评论|
|
||||
|pull_request|合并请求|
|
||||
|pull_request_assign|合并请求被指派|
|
||||
|pull_request_label|合并请求被贴上标签|
|
||||
|
@ -1337,11 +1337,11 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
|
|||
|delete|分支或标签删除|
|
||||
|fork|仓库被fork|
|
||||
|push|git仓库推送|
|
||||
|issue|易修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|易修被指派|
|
||||
|issue_label|易修标签被更新或删除|
|
||||
|issue_milestone|易修被收入里程碑|
|
||||
|issue_comment|易修评论|
|
||||
|issue|疑修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|疑修被指派|
|
||||
|issue_label|疑修标签被更新或删除|
|
||||
|issue_milestone|疑修被收入里程碑|
|
||||
|issue_comment|疑修评论|
|
||||
|pull_request|合并请求|
|
||||
|pull_request_assign|合并请求被指派|
|
||||
|pull_request_label|合并请求被贴上标签|
|
||||
|
@ -1440,11 +1440,11 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|
|||
|delete|分支或标签删除|
|
||||
|fork|仓库被fork|
|
||||
|push|git仓库推送|
|
||||
|issue|易修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|易修被指派|
|
||||
|issue_label|易修标签被更新或删除|
|
||||
|issue_milestone|易修被收入里程碑|
|
||||
|issue_comment|易修评论|
|
||||
|issue|疑修已打开、已关闭、已重新打开或编辑|
|
||||
|issue_assign|疑修被指派|
|
||||
|issue_label|疑修标签被更新或删除|
|
||||
|issue_milestone|疑修被收入里程碑|
|
||||
|issue_comment|疑修评论|
|
||||
|pull_request|合并请求|
|
||||
|pull_request_assign|合并请求被指派|
|
||||
|pull_request_label|合并请求被贴上标签|
|
||||
|
|
|
@ -90,13 +90,13 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
#### 消息来源source字段说明
|
||||
类型|说明
|
||||
--------- | -----------
|
||||
|IssueAssigned | 有新指派给我的易修 |
|
||||
|IssueAssignerExpire | 我负责的易修截止日期到达最后一天 |
|
||||
|IssueAtme | 在易修中@我 |
|
||||
|IssueChanged | 我创建或负责的易修状态变更 |
|
||||
|IssueCreatorExpire | 我创建的易修截止日期到达最后一天 |
|
||||
|IssueDeleted | 我创建或负责的易修删除 |
|
||||
|IssueJournal | 我创建或负责的易修有新的评论 |
|
||||
|IssueAssigned | 有新指派给我的疑修 |
|
||||
|IssueAssignerExpire | 我负责的疑修截止日期到达最后一天 |
|
||||
|IssueAtme | 在疑修中@我 |
|
||||
|IssueChanged | 我创建或负责的疑修状态变更 |
|
||||
|IssueCreatorExpire | 我创建的疑修截止日期到达最后一天 |
|
||||
|IssueDeleted | 我创建或负责的疑修删除 |
|
||||
|IssueJournal | 我创建或负责的疑修有新的评论 |
|
||||
|LoginIpTip | 登录异常提示 |
|
||||
|OrganizationJoined | 账号被拉入组织 |
|
||||
|OrganizationLeft | 账号被移出组织 |
|
||||
|
@ -104,7 +104,7 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
|ProjectDeleted | 我关注的仓库被删除 |
|
||||
|ProjectFollowed | 我管理的仓库被关注 |
|
||||
|ProjectForked | 我管理的仓库被复刻 |
|
||||
|ProjectIssue | 我管理/关注的仓库有新的易修 |
|
||||
|ProjectIssue | 我管理/关注的仓库有新的疑修 |
|
||||
|ProjectJoined | 账号被拉入项目 |
|
||||
|ProjectLeft | 账号被移出项目 |
|
||||
|ProjectMemberJoined | 我管理的仓库有成员加入 |
|
||||
|
@ -250,7 +250,7 @@ await octokit.request('POST /api/users/:login/messages.json')
|
|||
--------- | ----------- | -----------
|
||||
|type | string | 消息类型 |
|
||||
|receivers_login | array | 需要发送消息的用户名数组|
|
||||
|atmeable_type | string | atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest |
|
||||
|atmeable_type | string | atme消息对象,是从哪里@我的,比如评论:Journal、疑修:Issue、合并请求:PullRequest |
|
||||
|atmeable_id | integer | atme消息对象id |
|
||||
|
||||
> 请求的JSON示例:
|
||||
|
@ -469,7 +469,7 @@ await octokit.request('GET /api/template_message_settings.json')
|
|||
"total_settings_count": 4,
|
||||
"settings": [
|
||||
{
|
||||
"name": "易修被指派",
|
||||
"name": "疑修被指派",
|
||||
"key": "IssueAssigned",
|
||||
"notification_disabled": true,
|
||||
"email_disabled": false
|
||||
|
@ -488,7 +488,7 @@ await octokit.request('GET /api/template_message_settings.json')
|
|||
"total_settings_count": 4,
|
||||
"settings": [
|
||||
{
|
||||
"name": "有新的易修",
|
||||
"name": "有新的疑修",
|
||||
"key": "Issue",
|
||||
"notification_disabled": true,
|
||||
"email_disabled": false
|
||||
|
@ -875,7 +875,7 @@ await octokit.request('GET /api/users/:login/statistics/activity.json')
|
|||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|dates |array |时间 |
|
||||
|issues_count |array |易修数量|
|
||||
|issues_count |array |疑修数量|
|
||||
|pull_requests_count |array |合并请求数量|
|
||||
|commtis_count |array |贡献数量|
|
||||
|
||||
|
@ -1084,7 +1084,7 @@ await octokit.request('GET /api/users/:login/project_trends.json')
|
|||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|total_count |int |所选时间内的总动态数 |
|
||||
|project_trends.trend_type |string|动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求|
|
||||
|project_trends.trend_type |string|动态类型,Issue:疑修,VersionRelease:版本发布,PullRequest:合并请求|
|
||||
|project_trends.action_type |string|操作类型|
|
||||
|project_trends.trend_id |integer|动态id|
|
||||
|project_trends.user_name |string|用户名称|
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Organizations::CreateForm < BaseForm
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname
|
||||
attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname, :original_name
|
||||
|
||||
validates :name, :nickname, :visibility, presence: true
|
||||
validates :name, :nickname, length: { maximum: 100 }
|
||||
|
@ -9,7 +9,7 @@ class Organizations::CreateForm < BaseForm
|
|||
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
validate do
|
||||
check_name(name) unless name.blank?
|
||||
check_name(name) unless name.blank? || name == original_name
|
||||
end
|
||||
|
||||
def check_name(name)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
module Register
|
||||
class RemoteForm < Register::BaseForm
|
||||
# login 登陆方式,支持邮箱、登陆、手机号等
|
||||
attr_accessor :username, :email, :password, :platform
|
||||
|
||||
validates :username, :email, :password, presence: true
|
||||
validate :check!
|
||||
|
||||
def check!
|
||||
Rails.logger.info "Register::RemoteForm params: username: #{username}; email: #{email}; password: #{password}; platform: #{platform}"
|
||||
check_login(username)
|
||||
check_mail(email)
|
||||
check_password(password)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,5 +4,5 @@ class Users::LoginForm
|
|||
attr_accessor :password, :login
|
||||
|
||||
validates :login, presence: true
|
||||
validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位,支持字母数字和符号" }
|
||||
validates :password, presence: true, length: { minimum: 6, maximum: 16 }, format: { with: CustomRegexp::LOGIN_PASSWORD, message: "6~16位,支持字母数字和符号" }
|
||||
end
|
|
@ -15,7 +15,7 @@ module RepositoriesHelper
|
|||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
|
@ -45,7 +45,7 @@ module RepositoriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, path)
|
||||
def readme_render_decode64_content(str, owner, repo, ref)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
@ -63,13 +63,16 @@ module RepositoriesHelper
|
|||
if remove_title.length > 0
|
||||
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
end
|
||||
if r_content.include?("?")
|
||||
new_r_content = r_content + "&raw=true"
|
||||
else
|
||||
new_r_content = r_content + "?raw=true"
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
new_r_content = "#{path}" + new_r_content
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/#{r_content}/, new_r_content)
|
||||
end
|
||||
|
@ -94,7 +97,7 @@ module RepositoriesHelper
|
|||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
readme_render_decode64_content(content, path)
|
||||
readme_render_decode64_content(content, owner, repo, ref)
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
|
|
|
@ -26,8 +26,13 @@ module TagChosenHelper
|
|||
end
|
||||
|
||||
def render_branches(project)
|
||||
branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier)
|
||||
branches.collect{|i| i["name"] if i.is_a?(Hash)}
|
||||
if project.educoder?
|
||||
return ['master']
|
||||
else
|
||||
branches = Gitea::Repository::Branches::ListNameService.call(project&.owner, project.identifier)
|
||||
return branches.collect{|i| i["name"] if i.is_a?(Hash)} if branches.is_a?(Array)
|
||||
return branches["branch_name"] if branches.is_a?(Hash)
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_trackers
|
||||
|
|
|
@ -6,7 +6,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob
|
|||
return if repo.blank?
|
||||
|
||||
puts "############ MigrateRemoteRepositoryJob starting ... ############"
|
||||
|
||||
params.except!(:auth_password, :auth_username) if params[:auth_username].nil?
|
||||
gitea_repository = Gitea::Repository::MigrateService.new(token, params).call
|
||||
puts "#gitea_repository#{gitea_repository}"
|
||||
if gitea_repository[0]==201
|
||||
|
|
|
@ -37,6 +37,7 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
issue = Issue.find_by_id(issue_id)
|
||||
return unless operator.present? && issue.present?
|
||||
# receivers = receivers.where.not(id: operator&.id)
|
||||
receivers = User.where(id: receivers)
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2, operator_id)
|
||||
when 'IssueChanged'
|
||||
|
@ -93,18 +94,6 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'OrganizationRole'
|
||||
user_id, organization_id, role = args[0], args[1], args[2]
|
||||
user = User.find_by_id(user_id)
|
||||
organization = Organization.find_by_id(organization_id)
|
||||
return unless user.present? && organization.present?
|
||||
receivers = User.where(id: user.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationRole.get_email_message_content(receiver, organization, role)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectIssue'
|
||||
operator_id, issue_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
@ -235,6 +224,7 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
pull_request = PullRequest.find_by_id(pull_request_id)
|
||||
return unless operator.present? && pull_request.present?
|
||||
# receivers = receivers.where.not(id: operator&.id)
|
||||
receivers = User.where(id: receivers)
|
||||
receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2, operator_id)
|
||||
when 'PullRequestChanged'
|
||||
|
@ -274,6 +264,32 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestMerged.get_email_message_content(receiver, operator, pull_request)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'TeamJoined'
|
||||
user_id, organization_id, team_id = args[0], args[1], args[2]
|
||||
user = User.find_by_id(user_id)
|
||||
organization = Organization.find_by_id(organization_id)
|
||||
team = Team.find_by_id(team_id)
|
||||
return unless user.present? && organization.present? && team.present?
|
||||
receivers = User.where(id: user.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::TeamJoined.get_message_content(receivers, organization, team)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::TeamJoined.get_email_message_content(receiver, organization, team)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'TeamLeft'
|
||||
user_id, organization_id, team_id = args[0], args[1], args[2]
|
||||
user = User.find_by_id(user_id)
|
||||
organization = Organization.find_by_id(organization_id)
|
||||
team = Team.find_by_id(team_id)
|
||||
return unless user.present? && organization.present? && team.present?
|
||||
receivers = User.where(id: user.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::TeamLeft.get_message_content(receivers, organization, team)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::TeamLeft.get_email_message_content(receiver, organization, team)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,6 +5,7 @@ module CustomRegexp
|
|||
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
||||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||
LOGIN_PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{6,16}\z/
|
||||
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
|
||||
IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ module Util
|
|||
file.write(io)
|
||||
end
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def download_file(url, save_path)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: claims
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# issue_id :integer
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# note :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_claims_on_issue_id (issue_id)
|
||||
# index_claims_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Claim < ApplicationRecord
|
||||
belongs_to :user, foreign_key: :user_id
|
||||
scope :claim_includes, ->{includes(:user)}
|
||||
end
|
|
@ -21,13 +21,37 @@ module ProjectOperable
|
|||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
member = members.create!(user_id: user_id)
|
||||
if self.owner.is_a?(Organization)
|
||||
case role_name
|
||||
when 'Manager'
|
||||
team = self.owner.teams.admin.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
when 'Developer'
|
||||
team = self.owner.teams.write.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
when 'Reporter'
|
||||
team = self.owner.teams.read.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
end
|
||||
end
|
||||
member = members.create!(user_id: user_id, team_user_id: team_user&.id)
|
||||
set_developer_role(member, role_name)
|
||||
end
|
||||
|
||||
def remove_member!(user_id)
|
||||
member = members.find_by(user_id: user_id)
|
||||
member.destroy! if member && self.user_id != user_id
|
||||
team_user = TeamUser.find_by_id(member&.team_user_id)
|
||||
team_user.destroy! if team_user
|
||||
end
|
||||
|
||||
def member?(user_id)
|
||||
|
@ -47,6 +71,28 @@ module ProjectOperable
|
|||
|
||||
def change_member_role!(user_id, role)
|
||||
member = self.member(user_id)
|
||||
if self.owner.is_a?(Organization) && member.team_user.present?
|
||||
case role&.name
|
||||
when 'Manager'
|
||||
team = self.owner.teams.admin.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = member.team_user.update(team_id: team&.id)
|
||||
when 'Developer'
|
||||
team = self.owner.teams.write.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = member.team_user.update(team_id: team&.id)
|
||||
when 'Reporter'
|
||||
team = self.owner.teams.read.take
|
||||
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
|
||||
TeamProject.build(self.user_id, team.id, self.id)
|
||||
OrganizationUser.build(self.user_id, user_id)
|
||||
team_user = member.team_user.update(team_id: team&.id)
|
||||
end
|
||||
end
|
||||
member.member_roles.last.update_attributes!(role: role)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
class Gitea::WebhookTask < Gitea::Base
|
||||
serialize :payload_content, JSON
|
||||
serialize :request_content, JSON
|
||||
serialize :response_content, JSON
|
||||
|
||||
self.inheritance_column = nil
|
||||
|
||||
|
@ -10,4 +9,10 @@ class Gitea::WebhookTask < Gitea::Base
|
|||
belongs_to :webhook, class_name: "Gitea::Webhook", foreign_key: :hook_id
|
||||
|
||||
enum type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9}
|
||||
|
||||
def response_content_json
|
||||
JSON.parse(response_content)
|
||||
rescue
|
||||
{}
|
||||
end
|
||||
end
|
|
@ -64,6 +64,7 @@ class Issue < ApplicationRecord
|
|||
# has_many :memos
|
||||
has_many :journals, :as => :journalized, :dependent => :destroy
|
||||
has_many :journal_details, through: :journals
|
||||
has_many :claims, :dependent => :destroy
|
||||
has_many :issue_tags_relates, dependent: :destroy
|
||||
has_many :issue_tags, through: :issue_tags_relates
|
||||
has_many :issue_times, dependent: :destroy
|
||||
|
@ -154,7 +155,7 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def is_collaborators?
|
||||
self.assigned_to_id.present? ? self.project.members.where(user_id: self.assigned_to_id).present? : false
|
||||
self.assigned_to_id.present? ? self.project.member?(self.assigned_to_id) : false
|
||||
end
|
||||
|
||||
def get_issue_tags_name
|
||||
|
|
|
@ -11,23 +11,26 @@
|
|||
# course_group_id :integer default("0")
|
||||
# is_collect :integer default("1")
|
||||
# graduation_group_id :integer default("0")
|
||||
# team_user_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_members_on_course_id (course_id)
|
||||
# index_members_on_project_id (project_id)
|
||||
# index_members_on_team_user_id (team_user_id)
|
||||
# index_members_on_user_id (user_id)
|
||||
# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE
|
||||
#
|
||||
|
||||
class Member < ApplicationRecord
|
||||
belongs_to :user
|
||||
# belongs_to :course, optional: true
|
||||
belongs_to :project, optional: true
|
||||
|
||||
has_many :member_roles, dependent: :destroy
|
||||
has_many :roles, through: :member_roles
|
||||
|
||||
validates :user_id, :project_id, presence: true
|
||||
|
||||
end
|
||||
class Member < ApplicationRecord
|
||||
belongs_to :user
|
||||
# belongs_to :course, optional: true
|
||||
belongs_to :project, optional: true
|
||||
belongs_to :team_user, optional: true
|
||||
|
||||
has_many :member_roles, dependent: :destroy
|
||||
has_many :roles, through: :member_roles
|
||||
|
||||
validates :user_id, :project_id, presence: true
|
||||
|
||||
end
|
||||
|
|
|
@ -17,27 +17,25 @@ class MessageTemplate < ApplicationRecord
|
|||
def self.build_init_data
|
||||
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
|
||||
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个易修')
|
||||
self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在易修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修')
|
||||
self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在疑修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_changed.html")
|
||||
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: 'GitLink: 易修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的疑修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: 'GitLink: 疑修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_deleted.html")
|
||||
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', email: email_html, email_title: 'GitLink: 易修 {title} 有状态变更', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论易修{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将疑修 <b>{title}</b> 删除', email: email_html, email_title: 'GitLink: 疑修 {title} 有状态变更', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论疑修{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '')
|
||||
email_html = File.read("#{email_template_html_dir}/organization_joined.html")
|
||||
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织')
|
||||
email_html = File.read("#{email_template_html_dir}/organization_left.html")
|
||||
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {organization} 组织')
|
||||
email_html = File.read("#{email_template_html_dir}/organization_role.html")
|
||||
self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_issue.html")
|
||||
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 新建了一个易修')
|
||||
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 新建了一个疑修')
|
||||
email_html = File.read("#{email_template_html_dir}/project_joined.html")
|
||||
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: 你已加入 {repository} 项目')
|
||||
email_html = File.read("#{email_template_html_dir}/project_left.html")
|
||||
|
@ -66,6 +64,10 @@ class MessageTemplate < ApplicationRecord
|
|||
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/team_joined.html")
|
||||
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/team_left.html")
|
||||
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
|
||||
end
|
||||
|
||||
def self.sys_notice
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 有新指派给我的易修
|
||||
# 有新指派给我的疑修
|
||||
class MessageTemplate::IssueAssigned < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我负责的易修截止日期到达最后一天
|
||||
# 我负责的疑修截止日期到达最后一天
|
||||
class MessageTemplate::IssueAssignerExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 在易修中@我
|
||||
# 在疑修中@我
|
||||
class MessageTemplate::IssueAtme < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我创建或负责的易修状态变更
|
||||
# 我创建或负责的疑修状态变更
|
||||
class MessageTemplate::IssueChanged < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueChanged.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last, {status_id: [1, 2], assigned_to_id: [nil, 203], tracker_id: [4, 3], priority_id: [2, 4], fixed_version_id: [nil, 5], due_date: ['', '2021-09-11'], done_ratio: [0, 40], issue_tags_value: ["", "7"], branch_name: ["", "master"]})
|
||||
|
@ -29,7 +29,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
|
||||
change_count = change_params.keys.size
|
||||
# 易修负责人修改
|
||||
# 疑修负责人修改
|
||||
if change_params[:assigned_to_id].present?
|
||||
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
|
||||
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
|
||||
|
@ -44,7 +44,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
|
||||
end
|
||||
# 易修状态修改
|
||||
# 疑修状态修改
|
||||
if change_params[:status_id].present?
|
||||
status1 = IssueStatus.find_by_id(change_params[:status_id][0])
|
||||
status2 = IssueStatus.find_by_id(change_params[:status_id][1])
|
||||
|
@ -59,7 +59,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
|
||||
end
|
||||
# 易修类型修改
|
||||
# 疑修类型修改
|
||||
if change_params[:tracker_id].present?
|
||||
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
|
||||
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
|
||||
|
@ -74,7 +74,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({iftracker})(.*)({endtracker})/, '')
|
||||
end
|
||||
# 易修里程碑修改
|
||||
# 疑修里程碑修改
|
||||
if change_params[:fixed_version_id].present?
|
||||
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
|
||||
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
|
||||
|
@ -89,7 +89,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
|
||||
end
|
||||
# 易修标记修改
|
||||
# 疑修标记修改
|
||||
if change_params[:issue_tags_value].present?
|
||||
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
|
||||
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
|
||||
|
@ -106,7 +106,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({iftag})(.*)({endtag})()/, '')
|
||||
end
|
||||
# 易修优先级修改
|
||||
# 疑修优先级修改
|
||||
if change_params[:priority_id].present?
|
||||
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
|
||||
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
|
||||
|
@ -121,7 +121,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
|
||||
end
|
||||
# 易修完成度修改
|
||||
# 疑修完成度修改
|
||||
if change_params[:done_ratio].present?
|
||||
doneratio1 = change_params[:done_ratio][0]
|
||||
doneratio2 = change_params[:done_ratio][1]
|
||||
|
@ -136,7 +136,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
|
||||
end
|
||||
# 易修指定分支修改
|
||||
# 疑修指定分支修改
|
||||
if change_params[:branch_name].present?
|
||||
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
|
||||
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
|
||||
|
@ -151,7 +151,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
|
||||
end
|
||||
# 易修开始日期修改
|
||||
# 疑修开始日期修改
|
||||
if change_params[:start_date].present?
|
||||
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
|
||||
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
|
||||
|
@ -166,7 +166,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
|
||||
end
|
||||
# 易修结束日期修改
|
||||
# 疑修结束日期修改
|
||||
if change_params[:due_date].present?
|
||||
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
|
||||
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
|
||||
|
@ -207,7 +207,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
change_count = change_params.keys.size
|
||||
# 易修负责人修改
|
||||
# 疑修负责人修改
|
||||
if change_params[:assigned_to_id].present?
|
||||
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
|
||||
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
|
||||
|
@ -222,7 +222,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
|
||||
end
|
||||
# 易修状态修改
|
||||
# 疑修状态修改
|
||||
if change_params[:status_id].present?
|
||||
status1 = IssueStatus.find_by_id(change_params[:status_id][0])
|
||||
status2 = IssueStatus.find_by_id(change_params[:status_id][1])
|
||||
|
@ -237,7 +237,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifstatus})(.*)({endstatus})/, '')
|
||||
end
|
||||
# 易修类型修改
|
||||
# 疑修类型修改
|
||||
if change_params[:tracker_id].present?
|
||||
tracker1 = Tracker.find_by_id(change_params[:tracker_id][0])
|
||||
tracker2 = Tracker.find_by_id(change_params[:tracker_id][1])
|
||||
|
@ -252,7 +252,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({iftracker})(.*)({endtracker})/, '')
|
||||
end
|
||||
# 易修里程碑修改
|
||||
# 疑修里程碑修改
|
||||
if change_params[:fixed_version_id].present?
|
||||
fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0])
|
||||
fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1])
|
||||
|
@ -267,7 +267,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '')
|
||||
end
|
||||
# 易修标记修改
|
||||
# 疑修标记修改
|
||||
if change_params[:issue_tags_value].present?
|
||||
issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct
|
||||
issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct
|
||||
|
@ -284,7 +284,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({iftag})(.*)({endtag})()/, '')
|
||||
end
|
||||
# 易修优先级修改
|
||||
# 疑修优先级修改
|
||||
if change_params[:priority_id].present?
|
||||
priority1 = IssuePriority.find_by_id(change_params[:priority_id][0])
|
||||
priority2 = IssuePriority.find_by_id(change_params[:priority_id][1])
|
||||
|
@ -299,7 +299,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifpriority})(.*)({endpriority})/, '')
|
||||
end
|
||||
# 易修完成度修改
|
||||
# 疑修完成度修改
|
||||
if change_params[:done_ratio].present?
|
||||
doneratio1 = change_params[:done_ratio][0]
|
||||
doneratio2 = change_params[:done_ratio][1]
|
||||
|
@ -314,7 +314,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '')
|
||||
end
|
||||
# 易修指定分支修改
|
||||
# 疑修指定分支修改
|
||||
if change_params[:branch_name].present?
|
||||
branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0]
|
||||
branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1]
|
||||
|
@ -329,7 +329,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifbranch})(.*)({endbranch})/, '')
|
||||
end
|
||||
# 易修开始日期修改
|
||||
# 疑修开始日期修改
|
||||
if change_params[:start_date].present?
|
||||
startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0]
|
||||
startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1]
|
||||
|
@ -344,7 +344,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '')
|
||||
end
|
||||
# 易修结束日期修改
|
||||
# 疑修结束日期修改
|
||||
if change_params[:due_date].present?
|
||||
duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0]
|
||||
duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我创建的易修截止日期到达最后一天
|
||||
# 我创建的疑修截止日期到达最后一天
|
||||
class MessageTemplate::IssueCreatorExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我创建或负责的易修删除
|
||||
# 我创建或负责的疑修删除
|
||||
class MessageTemplate::IssueDeleted < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah")
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我创建或负责的易修有新的评论
|
||||
# TODO 我创建或负责的疑修有新的评论
|
||||
class MessageTemplate::IssueJournal < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueJournal.get_message_content(User.where(login: 'yystopf'))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理/关注的仓库有新的易修
|
||||
# TODO 我管理/关注的仓库有新的疑修
|
||||
class MessageTemplate::ProjectIssue < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectIssue.get_message_content(User.where(login: 'yystopf'), User.where(login: 'forgetest1'), User.last, Issue.last)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# 我管理的仓库项目设置被更改
|
||||
class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectSettingChanged.get_message_content(User.where(login: 'yystopf'), User.last, Project.last, {description: '测试修改项目简介', category: '大数据', language: 'Ruby', permission: '公有', navbar: '易修, 合并请求'})
|
||||
# MessageTemplate::ProjectSettingChanged.get_message_content(User.where(login: 'yystopf'), User.last, Project.last, {description: '测试修改项目简介', category: '大数据', language: 'Ruby', permission: '公有', navbar: '疑修, 合并请求'})
|
||||
def self.get_message_content(receivers, operator, project, change_params)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
|
@ -135,7 +135,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
unit_types.unshift('主页')
|
||||
unit_types.append('动态')
|
||||
navbar = unit_types.join(',')
|
||||
navbar.gsub!('issues', '易修')
|
||||
navbar.gsub!('issues', '疑修')
|
||||
navbar.gsub!('pulls', '合并请求')
|
||||
navbar.gsub!('wiki', 'Wiki')
|
||||
navbar.gsub!('devops', '工作流')
|
||||
|
@ -284,7 +284,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
unit_types.unshift('主页')
|
||||
unit_types.append('动态')
|
||||
navbar = unit_types.join(',')
|
||||
navbar.gsub!('issues', '易修')
|
||||
navbar.gsub!('issues', '疑修')
|
||||
navbar.gsub!('pulls', '合并请求')
|
||||
navbar.gsub!('wiki', 'Wiki')
|
||||
navbar.gsub!('devops', '工作流')
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
# == 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::TeamJoined < MessageTemplate
|
||||
|
||||
# MessageTemplate::TeamJoined.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take)
|
||||
def self.get_message_content(receivers, organization, team)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name)
|
||||
url = notification_url.gsub('{login}', organization&.login)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::TeamJoined.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, organization, role)
|
||||
if receiver.user_template_message_setting.present?
|
||||
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
|
||||
title = email_title
|
||||
title.gsub!('{organization}', organization&.real_name)
|
||||
title.gsub!('{team}', team&.nickname)
|
||||
title.gsub!('{role}', team&.authorize_name)
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::TeamJoined.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
# == 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::TeamLeft < MessageTemplate
|
||||
|
||||
# MessageTemplate::TeamLeft.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take)
|
||||
def self.get_message_content(receivers, organization, team)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name)
|
||||
url = notification_url.gsub('{login}', organization&.login)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::TeamLeft.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, organization, team)
|
||||
if receiver.user_template_message_setting.present?
|
||||
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
|
||||
title = email_title
|
||||
title.gsub!('{organization}', organization&.real_name)
|
||||
title.gsub!('{team}', team&.nickname)
|
||||
title.gsub!('{role}', team&.authorize_name)
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::TeamLeft.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
|
@ -56,10 +56,10 @@ class Team < ApplicationRecord
|
|||
|
||||
def authorize_name
|
||||
case self.authorize
|
||||
when 'read' then '报告者'
|
||||
when 'write' then '开发者'
|
||||
when 'read' then '读取'
|
||||
when 'write' then '写入'
|
||||
when 'admin' then '管理员'
|
||||
when 'owner' then '拥有者'
|
||||
when 'owner' then '管理员'
|
||||
else
|
||||
''
|
||||
end
|
||||
|
|
|
@ -22,9 +22,17 @@ class TeamUser < ApplicationRecord
|
|||
belongs_to :team, counter_cache: :num_users
|
||||
belongs_to :user
|
||||
|
||||
has_one :member
|
||||
|
||||
validates :user_id, uniqueness: {scope: [:organization_id, :team_id]}
|
||||
|
||||
before_destroy :remove_project_member
|
||||
|
||||
def self.build(organization_id, user_id, team_id)
|
||||
self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id)
|
||||
end
|
||||
|
||||
def remove_project_member
|
||||
member.destroy if member.present?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,7 +25,7 @@ class TemplateMessageSetting::CreateOrAssign < TemplateMessageSetting
|
|||
end
|
||||
|
||||
def self.build_init_data
|
||||
self.find_or_create_by(name: "易修状态变更", key: "IssueChanged")
|
||||
self.find_or_create_by(name: "疑修状态变更", key: "IssueChanged")
|
||||
self.find_or_create_by(name: "合并请求状态变更", key: "PullRequestChanged")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,7 +25,7 @@ class TemplateMessageSetting::ManageProject < TemplateMessageSetting
|
|||
end
|
||||
|
||||
def self.build_init_data
|
||||
self.find_or_create_by(name: "有新的易修", key: "Issue")
|
||||
self.find_or_create_by(name: "有新的疑修", key: "Issue")
|
||||
self.find_or_create_by(name: "有新的合并请求", key: "PullRequest")
|
||||
self.find_or_create_by(name: "有成员变动", key: "Member")
|
||||
self.find_or_create_by(name: "仓库设置被更改", key: "SettingChanged")
|
||||
|
|
|
@ -27,7 +27,7 @@ class TemplateMessageSetting::Normal < TemplateMessageSetting
|
|||
self.find_or_create_by(name: "账号有权限变更", key: "Permission")
|
||||
self.find_or_create_by(name: "被拉入或移出组织", key: "Organization")
|
||||
self.find_or_create_by(name: "被拉入或移出项目", key: "Project")
|
||||
self.find_or_create_by(name: "有新的易修指派给我", key: "IssueAssigned")
|
||||
self.find_or_create_by(name: "有新的疑修指派给我", key: "IssueAssigned")
|
||||
self.find_or_create_by(name: "有新的合并请求指派给我", key: "PullRequestAssigned")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -786,7 +786,7 @@ class User < Owner
|
|||
end
|
||||
|
||||
def profile_is_completed?
|
||||
self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
|
||||
self.nickname.present? && self.mail.present?
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -32,6 +32,6 @@ class AtmeService < ApplicationService
|
|||
else
|
||||
return
|
||||
end
|
||||
SendTemplateMessageJob.perform_now(message_source, receivers, user.id, @atmeable.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later(message_source, receivers.pluck(:id), user.id, @atmeable.id) if Site.has_notice_menu?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class Gitea::Organization::UpdateService < Gitea::ClientService
|
|||
def request_params
|
||||
update_params = {
|
||||
name: org.login,
|
||||
full_name: org.nickname,
|
||||
description: org.description,
|
||||
location: org.location,
|
||||
repo_admin_change_team_access: org.repo_admin_change_team_access,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
class Gitea::Repository::Branches::ListNameService < Gitea::ClientService
|
||||
attr_reader :user, :repo
|
||||
|
||||
def initialize(user, repo)
|
||||
@user = user
|
||||
@repo = repo
|
||||
end
|
||||
|
||||
def call
|
||||
response = get(url, params)
|
||||
render_200_response(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: user.gitea_token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/#{user.login}/#{repo}/branch_name_set".freeze
|
||||
end
|
||||
end
|
|
@ -55,7 +55,12 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
|
|||
when 201 then success(json_parse!(body))
|
||||
when 403 then error("你没有权限操作!")
|
||||
when 404 then error("你操作的链接不存在!")
|
||||
when 422 then error("#{filepath}文件已存在,不能重复创建!")
|
||||
when 422
|
||||
if @body[:new_branch].include?('/') || @body[:new_branch].include?('\'') || @body[:new_branch].include?('^') || @body[:new_branch].include?('*')
|
||||
error("不合法的分支名称!")
|
||||
else
|
||||
error("#{filepath}文件已存在,不能重复创建!")
|
||||
end
|
||||
else error("系统错误!")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -59,6 +59,8 @@ class Notice::Write::ClientService < ApplicationService
|
|||
req.request :url_encoded
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.adapter Faraday.default_adapter
|
||||
req.options.timeout = 100 # open/read timeout in seconds
|
||||
req.options.open_timeout = 10 # connection open timeout in seconds
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -129,8 +129,10 @@ class PullRequests::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def merge_original_pull_params
|
||||
base_pull_params[:head] = CGI.escape(base_pull_params[:head])
|
||||
base_pull_params[:base] = CGI.escape(base_pull_params[:base])
|
||||
if pull_request.is_original && @params[:merge_user_login]
|
||||
base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{@params[:head]}")
|
||||
base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{base_pull_params[:head]}")
|
||||
else
|
||||
base_pull_params
|
||||
end
|
||||
|
@ -148,6 +150,7 @@ class PullRequests::CreateService < ApplicationService
|
|||
|
||||
def validate!
|
||||
raise "title参数不能为空" if @params[:title].blank?
|
||||
raise "title不能超过255个字符" if @params[:title].length > 255
|
||||
raise "head参数不能为空" if @params[:head].blank?
|
||||
raise "base参数不能为空" if @params[:base].blank?
|
||||
raise "fork_project_id参数错误" if is_original && !@project.forked_projects.pluck(:id).include?(@params[:fork_project_id].to_i)
|
||||
|
@ -159,7 +162,7 @@ class PullRequests::CreateService < ApplicationService
|
|||
|
||||
def compare_head_base!
|
||||
head = pull_request.is_original && @params[:merge_user_login] ? "#{@params[:merge_user_login]}/#{@project.identifier}:#{@params[:head]}" : @params[:head]
|
||||
compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, @params[:base], head, @current_user.gitea_token)
|
||||
compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(@params[:base]), CGI.escape(head), @current_user.gitea_token)
|
||||
raise '分支内容相同,无需创建合并请求' if compare_result["Commits"].blank? && compare_result["Diff"].blank?
|
||||
end
|
||||
|
||||
|
|
|
@ -10,20 +10,12 @@ class Repositories::DetailService < ApplicationService
|
|||
def call
|
||||
return {
|
||||
repo: repo_suitable,
|
||||
contributor: contributor_suitable,
|
||||
language: language_suitable,
|
||||
branch_tag_total_count: branch_tag_total_count
|
||||
}
|
||||
rescue
|
||||
return {
|
||||
repo: {},
|
||||
release: [],
|
||||
branch: [],
|
||||
branch_type: [],
|
||||
tag: [],
|
||||
contributor: [],
|
||||
language: {},
|
||||
readme: {}
|
||||
branch_tag_total_count: {}
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -35,14 +27,4 @@ class Repositories::DetailService < ApplicationService
|
|||
def repo_suitable
|
||||
Gitea::Repository::GetService.call(@owner, @repo.identifier)
|
||||
end
|
||||
|
||||
def contributor_suitable
|
||||
contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repo.identifier)
|
||||
contributors.is_a?(Hash) && contributors.key?(:status) ? [] : contributors
|
||||
end
|
||||
|
||||
def language_suitable
|
||||
result = Gitea::Repository::Languages::ListService.call(@owner.login, @repo.identifier, @user&.gitea_token)
|
||||
result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
json.user_name claimer.user.try(:show_real_name)
|
||||
json.user_login claimer.user.try(:login)
|
||||
json.user_picture url_to_avatar(claimer.user)
|
||||
json.created_at time_from_now(claimer.created_at)
|
||||
json.note_body claimer.note
|
||||
json.claim_id claimer.id
|
||||
json.visible false
|
|
@ -0,0 +1,7 @@
|
|||
json.partial! "commons/success"
|
||||
json.currentUserclaimed @user_claimed
|
||||
json.claimers do
|
||||
json.array! @claims do |claimer|
|
||||
json.partial! "claims/claim_item", claimer: claimer
|
||||
end
|
||||
end
|
|
@ -13,6 +13,7 @@ json.tracker @issue.tracker.try(:name)
|
|||
json.issue_status @issue.issue_status.try(:name)
|
||||
json.priority @issue.priority.try(:name)
|
||||
json.version @issue.version.try(:name)
|
||||
json.version_id @issue.version.try(:id)
|
||||
json.issue_tags @issue.get_issue_tags
|
||||
json.done_ratio @issue.done_ratio.to_s + "%"
|
||||
json.issue_type @issue.issue_type
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
json.id team.id
|
||||
json.name team.name
|
||||
json.nickname team.nickname.blank? ? team.name : team.nickname
|
|
@ -1,4 +1,8 @@
|
|||
json.total_count @teams.total_count
|
||||
json.total_count params[:is_full].present? ? @teams.count : @teams.total_count
|
||||
json.teams @teams do |team|
|
||||
json.partial! "detail", team: team, organization: @organization
|
||||
if params[:is_full].present?
|
||||
json.partial! "simple_detail", team: team, organization: @organization
|
||||
else
|
||||
json.partial! "detail", team: team, organization: @organization
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,15 +3,26 @@ owner_common = $redis_cache.hgetall("v2-owner-common:#{project_common["owner_id"
|
|||
json.id item[0]
|
||||
json.score item[1]
|
||||
json.name project_common["name"]
|
||||
json.identifier project_common["identifier"]
|
||||
json.description project_common["description"]
|
||||
json.owner do
|
||||
json.id project_common["owner_id"]
|
||||
json.type owner_common["type"]
|
||||
json.name owner_common["name"]
|
||||
json.login owner_common["login"]
|
||||
json.avatar_url owner_common["avatar_url"]
|
||||
if project_common['identifier'].include?("/")
|
||||
json.identifier project_common["identifier"].split('/')[1]
|
||||
json.owner do
|
||||
json.id nil
|
||||
json.type 'User'
|
||||
json.name project_common["identifier"].split('/')[0]
|
||||
json.login project_common["identifier"].split('/')[0]
|
||||
json.avatar_url User::Avatar.get_letter_avatar_url(project_common["identifier"].split('/')[0])
|
||||
end
|
||||
else
|
||||
json.identifier project_common["identifier"]
|
||||
json.owner do
|
||||
json.id project_common["owner_id"]
|
||||
json.type owner_common["type"]
|
||||
json.name owner_common["name"]
|
||||
json.login owner_common["login"]
|
||||
json.avatar_url owner_common["avatar_url"]
|
||||
end
|
||||
end
|
||||
json.description project_common["description"]
|
||||
json.visits project_common["visits"]
|
||||
json.forks project_common["forks"]
|
||||
json.watchers project_common["watchers"]
|
||||
|
|
|
@ -6,6 +6,13 @@ json.user_name trend.user.try(:show_real_name)
|
|||
json.user_login trend.user.login
|
||||
json.user_avatar url_to_avatar(trend.user)
|
||||
json.action_time time_from_now(trend.created_at)
|
||||
json.project do
|
||||
json.owner do
|
||||
json.partial! 'users/user_simple', locals: {user: trend&.project&.owner}
|
||||
end
|
||||
json.identifier trend&.project&.identifier
|
||||
json.description trend&.project&.description
|
||||
end
|
||||
|
||||
if trend.trend_type == "Issue"
|
||||
json.partial! "issues/simple_issue_item", locals: {issue: trend.trend}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
json.array! @branches do |branch|
|
||||
json.name branch['name']
|
||||
json.user_can_push branch['user_can_push']
|
||||
json.user_can_merge branch['user_can_merge']
|
||||
json.protected branch['protected']
|
||||
branch_name = branch.is_a?(Hash) ? branch['name'] : branch
|
||||
json.name branch_name
|
||||
# json.user_can_push branch['user_can_push']
|
||||
# json.user_can_merge branch['user_can_merge']
|
||||
# json.protected branch['protected']
|
||||
json.http_url render_http_url(@project)
|
||||
json.zip_url render_zip_url(@owner, @repository, branch['name'])
|
||||
json.tar_url render_tar_url(@owner, @repository, branch['name'])
|
||||
json.last_commit do
|
||||
json.sha branch['commit']['id']
|
||||
json.message branch['commit']['message']
|
||||
json.timestamp render_unix_time(branch['commit']['timestamp'])
|
||||
json.time_from_now time_from_now(branch['commit']['timestamp'])
|
||||
json.author do
|
||||
json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name']
|
||||
end
|
||||
json.committer do
|
||||
json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name']
|
||||
end
|
||||
end
|
||||
json.zip_url render_zip_url(@owner, @repository, branch_name)
|
||||
json.tar_url render_tar_url(@owner, @repository, branch_name)
|
||||
# json.last_commit do
|
||||
# json.sha branch['commit']['id']
|
||||
# json.message branch['commit']['message']
|
||||
# json.timestamp render_unix_time(branch['commit']['timestamp'])
|
||||
# json.time_from_now time_from_now(branch['commit']['timestamp'])
|
||||
# json.author do
|
||||
# json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['author']), name: branch['commit']['author']['name']
|
||||
# end
|
||||
# json.committer do
|
||||
# json.partial! 'repositories/commit_author', user: render_cache_commit_author(branch['commit']['committer']), name: branch['commit']['committer']['name']
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
json.(webhook, :id, :url, :http_method, :is_active)
|
||||
json.type webhook.hook_task_type
|
||||
json.type webhook.type
|
||||
json.last_status webhook.last_status
|
||||
json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")
|
|
@ -1,6 +1,6 @@
|
|||
json.id @webhook.id
|
||||
json.(@webhook, :id, :http_method, :content_type, :url, :secret, :last_status, :is_active)
|
||||
json.type @webhook.hook_task_type
|
||||
json.type @webhook.type
|
||||
json.create_time Time.at(@webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")
|
||||
event = @webhook.events
|
||||
json.branch_filter event["branch_filter"]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
json.total_count @tasks.total_count
|
||||
json.tasks @tasks.each do |task|
|
||||
json.(task, :id, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content, :response_content)
|
||||
json.(task, :id, :event_type, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content)
|
||||
json.response_content task.response_content_json
|
||||
json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S")
|
||||
end
|
|
@ -1,12 +1,27 @@
|
|||
json.author do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
|
||||
end
|
||||
if commit['Status'].present?
|
||||
json.author do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] }
|
||||
end
|
||||
json.timestamp render_unix_time(commit['Committer']['When'])
|
||||
json.time_from_now time_from_now(commit['Committer']['When'])
|
||||
json.created_at render_format_time_with_date(commit['Committer']['When'])
|
||||
json.message commit['CommitMessage']
|
||||
json.sha commit['Sha']
|
||||
else
|
||||
json.author do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] }
|
||||
end
|
||||
|
||||
json.committer do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] }
|
||||
end
|
||||
json.timestamp render_unix_time(commit['Committer']['When'])
|
||||
json.time_from_now time_from_now(commit['Committer']['When'])
|
||||
json.created_at render_format_time_with_date(commit['Committer']['When'])
|
||||
json.message commit['CommitMessage']
|
||||
json.sha commit['Sha']
|
||||
json.committer do
|
||||
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] }
|
||||
end
|
||||
json.timestamp render_unix_time(commit['commit']['committer']['date'])
|
||||
json.time_from_now time_from_now(commit['commit']['committer']['date'])
|
||||
json.created_at render_format_time_with_date(commit['commit']['committer']['date'])
|
||||
json.message commit['commit']['message']
|
||||
json.sha commit['sha']
|
||||
end
|
|
@ -7,11 +7,22 @@ if @project.educoder?
|
|||
json.timestamp 0
|
||||
json.time_from_now commit[0]['time']
|
||||
end
|
||||
json.author do
|
||||
{}
|
||||
# json.partial! '/projects/author', user: render_commit_author(commit['author'])
|
||||
end
|
||||
json.committer {}
|
||||
if commit[0]['author'].present?
|
||||
json.author do
|
||||
json.id nil
|
||||
json.login commit[0]['author']['username']
|
||||
json.name commit[0]['author']['username']
|
||||
json.type nil
|
||||
json.image_url commit[0]['author']['image_url']
|
||||
end
|
||||
json.committer do
|
||||
json.id nil
|
||||
json.login commit[0]['author']['username']
|
||||
json.name commit[0]['author']['username']
|
||||
json.type nil
|
||||
json.image_url commit[0]['author']['image_url']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if @project.forge?
|
||||
|
|
|
@ -32,6 +32,8 @@ end
|
|||
|
||||
if @project.educoder?
|
||||
file_path = params[:filepath].present? ? [params[:filepath], entry['name']].join('/') : entry['name']
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
image_type = image_type?(file_type)
|
||||
|
||||
json.name entry['name']
|
||||
json.sha nil
|
||||
|
@ -42,7 +44,7 @@ if @project.educoder?
|
|||
json.target nil
|
||||
json.download_url nil
|
||||
json.direct_download false
|
||||
json.image_type false
|
||||
json.image_type image_type
|
||||
json.is_readme_file false
|
||||
json.commit do
|
||||
json.message entry['title']
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
if @hash_commit.blank? #如果有状态值,则表示报错了
|
||||
if @hash_commit.blank? || @project.educoder? #如果有状态值,则表示报错了
|
||||
json.total_count 0
|
||||
json.commits []
|
||||
json.commits do
|
||||
json.array! @commits do |commit|
|
||||
json.sha commit['id']
|
||||
json.message commit['title']
|
||||
json.time_from_now commit['time']
|
||||
json.author do
|
||||
json.id nil
|
||||
json.login commit['author']['username']
|
||||
json.name commit['author']['username']
|
||||
json.type nil
|
||||
json.image_url commit['author']['image_url']
|
||||
end
|
||||
json.committer do
|
||||
json.id nil
|
||||
json.login commit['author']['username']
|
||||
json.name commit['author']['username']
|
||||
json.type nil
|
||||
json.image_url commit['author']['image_url']
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
json.total_count @hash_commit[:total_count]
|
||||
json.commits do
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
total_count = @contributors.size
|
||||
json.contributors @contributors.each do |contributor|
|
||||
json.list @contributors.each do |contributor|
|
||||
json.partial! 'contributor', locals: { contributor: contributor }
|
||||
end
|
||||
json.total_count total_count
|
||||
|
|
|
@ -44,7 +44,7 @@ end
|
|||
if @result[:repo]
|
||||
json.size replace_bytes_to_b(number_to_human_size(@result[:repo]['size'].to_i*1024))
|
||||
json.ssh_url @result[:repo]['ssh_url']
|
||||
json.clone_url @result[:repo]['clone_url']
|
||||
json.clone_url @project.educoder? ? "#{Rails.application.config_for(:configuration)['educoder']['git_site']}/#{@project&.project_educoder&.repo_name}.git" : @result[:repo]['clone_url']
|
||||
json.default_branch @project.educoder? ? "master" : @result[:repo]['default_branch']
|
||||
json.empty @result[:repo]['empty']
|
||||
json.full_name @result[:repo]['full_name']
|
||||
|
@ -53,13 +53,13 @@ end
|
|||
json.license_name @project.license_name
|
||||
json.branches_count @result[:branch_tag_total_count].present? ? (@result[:branch_tag_total_count]['branch_count'] || 0) : 0
|
||||
json.tags_count @result[:branch_tag_total_count].present? ? (@result[:branch_tag_total_count]['tag_count'] || 0) : 0
|
||||
json.contributors do
|
||||
total_count = @result[:contributor].size
|
||||
json.list @result[:contributor].each do |contributor|
|
||||
json.partial! 'contributor', locals: { contributor: contributor }
|
||||
end
|
||||
json.total_count total_count
|
||||
end
|
||||
json.languages @result[:language].blank? ? nil : @result[:language]
|
||||
# json.contributors do
|
||||
# total_count = @result[:contributor].size
|
||||
# json.list @result[:contributor].each do |contributor|
|
||||
# json.partial! 'contributor', locals: { contributor: contributor }
|
||||
# end
|
||||
# json.total_count total_count
|
||||
# end
|
||||
# json.languages @result[:language].blank? ? nil : @result[:language]
|
||||
|
||||
json.partial! 'author', locals: { user: @project.owner }
|
||||
|
|
|
@ -7,7 +7,7 @@ if @project.educoder?
|
|||
end
|
||||
end
|
||||
json.commits_count @entries['commit_count']
|
||||
json.zip_url @entries['git_url']
|
||||
json.zip_url ''
|
||||
json.tar_url ''
|
||||
json.entries do
|
||||
json.array! @entries['trees'] do |entry|
|
||||
|
|
|
@ -24,8 +24,12 @@ if @project.educoder?
|
|||
end
|
||||
end
|
||||
json.entries do
|
||||
json.array! @sub_entries['trees'] do |entry|
|
||||
json.partial! 'repositories/simple_entry', locals: { entry: entry }
|
||||
if @sub_entries['trees'].is_a?(Array)
|
||||
json.array! @sub_entries['trees'] do |entry|
|
||||
json.partial! 'repositories/simple_entry', locals: { entry: entry }
|
||||
end
|
||||
elsif @sub_entries['trees'].is_a?(Hash)
|
||||
json.partial! 'repositories/simple_entry', locals: { entry: @sub_entries['trees'] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ zh-CN:
|
|||
'refused': '已拒绝'
|
||||
'agreed': '已同意'
|
||||
trend:
|
||||
Issue: 易修(Issue)
|
||||
Issue: 疑修(Issue)
|
||||
PullRequest: 合并请求(PR)
|
||||
VersionRelease: 版本发布
|
||||
create: 创建了
|
||||
|
|
|
@ -9,6 +9,7 @@ Rails.application.routes.draw do
|
|||
# Serve websocket cable requests in-process
|
||||
mount ActionCable.server => '/cable'
|
||||
|
||||
|
||||
get 'attachments/entries/get_file', to: 'attachments#get_file'
|
||||
get 'attachments/download/:id', to: 'attachments#show'
|
||||
get 'attachments/download/:id/:filename', to: 'attachments#show'
|
||||
|
@ -146,6 +147,16 @@ Rails.application.routes.draw do
|
|||
get :get_children_journals
|
||||
end
|
||||
end
|
||||
|
||||
resources :claims, only: [:index] do
|
||||
collection do
|
||||
post :create
|
||||
delete :destroy
|
||||
get :index
|
||||
put :update
|
||||
end
|
||||
end
|
||||
|
||||
resources :issue_times, only: [:create] do
|
||||
collection do
|
||||
post :end_work
|
||||
|
@ -214,6 +225,7 @@ Rails.application.routes.draw do
|
|||
get :watch_users
|
||||
get :fan_users
|
||||
get :hovercard
|
||||
put :update_image
|
||||
end
|
||||
collection do
|
||||
post :following
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
class CreateClaims < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :claims do |t|
|
||||
t.integer :issue_id
|
||||
t.integer :user_id
|
||||
t.timestamps
|
||||
t.index :issue_id
|
||||
t.index :user_id
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddNoteToClaim < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :claims, :note, :text
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddTeamUserToMembers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_reference :members, :team_user
|
||||
end
|
||||
end
|
2
dir.md
2
dir.md
|
@ -87,7 +87,7 @@ forgeplus
|
|||
│ │ │ │ └── tags(标签)
|
||||
│ │ │ ├── user(用户)
|
||||
│ │ │ └── versions(发行版)
|
||||
│ │ ├── issues(易修)
|
||||
│ │ ├── issues(疑修)
|
||||
│ │ ├── libraries
|
||||
│ │ ├── oauth
|
||||
│ │ ├── organizations(组织)
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1138,31 +1138,31 @@ Success — a happy kitten is an authenticated kitten!
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>IssueAssigned</td>
|
||||
<td>有新指派给我的易修</td>
|
||||
<td>有新指派给我的疑修</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueAssignerExpire</td>
|
||||
<td>我负责的易修截止日期到达最后一天</td>
|
||||
<td>我负责的疑修截止日期到达最后一天</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueAtme</td>
|
||||
<td>在易修中@我</td>
|
||||
<td>在疑修中@我</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueChanged</td>
|
||||
<td>我创建或负责的易修状态变更</td>
|
||||
<td>我创建或负责的疑修状态变更</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueCreatorExpire</td>
|
||||
<td>我创建的易修截止日期到达最后一天</td>
|
||||
<td>我创建的疑修截止日期到达最后一天</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueDeleted</td>
|
||||
<td>我创建或负责的易修删除</td>
|
||||
<td>我创建或负责的疑修删除</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IssueJournal</td>
|
||||
<td>我创建或负责的易修有新的评论</td>
|
||||
<td>我创建或负责的疑修有新的评论</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LoginIpTip</td>
|
||||
|
@ -1194,7 +1194,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
</tr>
|
||||
<tr>
|
||||
<td>ProjectIssue</td>
|
||||
<td>我管理/关注的仓库有新的易修</td>
|
||||
<td>我管理/关注的仓库有新的疑修</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ProjectJoined</td>
|
||||
|
@ -1403,7 +1403,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
<tr>
|
||||
<td>atmeable_type</td>
|
||||
<td>string</td>
|
||||
<td>atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest</td>
|
||||
<td>atme消息对象,是从哪里@我的,比如评论:Journal、疑修:Issue、合并请求:PullRequest</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>atmeable_id</td>
|
||||
|
@ -1706,7 +1706,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
</span><span class="nl">"total_settings_count"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"settings"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
||||
</span><span class="p">{</span><span class="w">
|
||||
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"易修被指派"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"疑修被指派"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IssueAssigned"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"notification_disabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"email_disabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
|
||||
|
@ -1725,7 +1725,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
</span><span class="nl">"total_settings_count"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"settings"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
|
||||
</span><span class="p">{</span><span class="w">
|
||||
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"有新的易修"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"有新的疑修"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Issue"</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"notification_disabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
|
||||
</span><span class="nl">"email_disabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
|
||||
|
@ -2245,7 +2245,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
<tr>
|
||||
<td>issues_count</td>
|
||||
<td>array</td>
|
||||
<td>易修数量</td>
|
||||
<td>疑修数量</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pull_requests_count</td>
|
||||
|
@ -2493,7 +2493,7 @@ Success — a happy kitten is an authenticated kitten!
|
|||
<tr>
|
||||
<td>project_trends.trend_type</td>
|
||||
<td>string</td>
|
||||
<td>动态类型,Issue:易修,VersionRelease:版本发布,PullRequest:合并请求</td>
|
||||
<td>动态类型,Issue:疑修,VersionRelease:版本发布,PullRequest:合并请求</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>project_trends.action_type</td>
|
||||
|
@ -4968,7 +4968,7 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq
|
|||
<tr>
|
||||
<td>menu_name</td>
|
||||
<td>string</td>
|
||||
<td>导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置</td>
|
||||
<td>导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
|
@ -5131,7 +5131,7 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json
|
|||
<td>是</td>
|
||||
<td></td>
|
||||
<td>array</td>
|
||||
<td>项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑</td>
|
||||
<td>项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<h3 id='7447e4874e-2'>返回字段说明:</h3>
|
||||
|
@ -8346,23 +8346,23 @@ http://localhost:3000/api/yystopf/ceshi/webhooks/3/edit.json
|
|||
</tr>
|
||||
<tr>
|
||||
<td>issue</td>
|
||||
<td>易修已打开、已关闭、已重新打开或编辑</td>
|
||||
<td>疑修已打开、已关闭、已重新打开或编辑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_assign</td>
|
||||
<td>易修被指派</td>
|
||||
<td>疑修被指派</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_label</td>
|
||||
<td>易修标签被更新或删除</td>
|
||||
<td>疑修标签被更新或删除</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_milestone</td>
|
||||
<td>易修被收入里程碑</td>
|
||||
<td>疑修被收入里程碑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_comment</td>
|
||||
<td>易修评论</td>
|
||||
<td>疑修评论</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pull_request</td>
|
||||
|
@ -8568,23 +8568,23 @@ http://localhost:3000/api/yystopf/ceshi/webhooks.json
|
|||
</tr>
|
||||
<tr>
|
||||
<td>issue</td>
|
||||
<td>易修已打开、已关闭、已重新打开或编辑</td>
|
||||
<td>疑修已打开、已关闭、已重新打开或编辑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_assign</td>
|
||||
<td>易修被指派</td>
|
||||
<td>疑修被指派</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_label</td>
|
||||
<td>易修标签被更新或删除</td>
|
||||
<td>疑修标签被更新或删除</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_milestone</td>
|
||||
<td>易修被收入里程碑</td>
|
||||
<td>疑修被收入里程碑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_comment</td>
|
||||
<td>易修评论</td>
|
||||
<td>疑修评论</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pull_request</td>
|
||||
|
@ -8833,23 +8833,23 @@ http://localhost:3000/api/yystopf/ceshi/webhooks/7.json
|
|||
</tr>
|
||||
<tr>
|
||||
<td>issue</td>
|
||||
<td>易修已打开、已关闭、已重新打开或编辑</td>
|
||||
<td>疑修已打开、已关闭、已重新打开或编辑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_assign</td>
|
||||
<td>易修被指派</td>
|
||||
<td>疑修被指派</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_label</td>
|
||||
<td>易修标签被更新或删除</td>
|
||||
<td>疑修标签被更新或删除</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_milestone</td>
|
||||
<td>易修被收入里程碑</td>
|
||||
<td>疑修被收入里程碑</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issue_comment</td>
|
||||
<td>易修评论</td>
|
||||
<td>疑修评论</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pull_request</td>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>有新的易修指派给我</title>
|
||||
<title>有新的疑修指派给我</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;}
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 指派给你一个易修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/>
|
||||
<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 指派给你一个疑修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/>
|
||||
</p>
|
||||
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>有新的易修指派给我</title>
|
||||
<title>有新的疑修指派给我</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;}
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
在项目 <a href="{baseurl}/{login2}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname2}/{repository}</a> 的易修 <a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a> 中:
|
||||
在项目 <a href="{baseurl}/{login2}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname2}/{repository}</a> 的疑修 <a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a> 中:
|
||||
{ifassigner}<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>将负责人从 {assigner1} 修改为 {assigner2}{endassigner}
|
||||
{ifstatus}<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>将状态从 {status1} 修改为 {status2}{endstatus}
|
||||
{iftracker}<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>将类型从 {tracker1} 修改为 {tracker2}{endtracker}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>易修状态改变</title>
|
||||
<title>疑修状态改变</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;}
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
<a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{nickname}</a>已将易修 {title} 删除
|
||||
<a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{nickname}</a>已将疑修 {title} 删除
|
||||
</p>
|
||||
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>管理的仓库有新的易修</title>
|
||||
<title>管理的仓库有新的疑修</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;}
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 新建了一个易修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/>
|
||||
<a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 新建了一个疑修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/>
|
||||
</p>
|
||||
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>被拉入组织团队</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;">
|
||||
<div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
|
||||
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.png" height="45" ></a>
|
||||
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
|
||||
<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:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
你已被拉入组织 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a> 的 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队,拥有{role}权限
|
||||
</p>
|
||||
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
|
||||
</div>
|
||||
<div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;">
|
||||
<p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/>
|
||||
QQ群:1071514693</p>
|
||||
<p style="color:#888; float:right;font-weight: bold;font-size: 16px;">GitLink团队</p>
|
||||
<div style="clear:both; overflow:hidden;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>被移出组织团队</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;">
|
||||
<div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;">
|
||||
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.png" height="45" ></a>
|
||||
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
|
||||
<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:20px; color:#333; line-height: 1.9;">
|
||||
<p style="font-size: 14px; color:#333;">
|
||||
{receiver},您好!<br/>
|
||||
你已被移出组织 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a> 的 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队
|
||||
</p>
|
||||
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
|
||||
</div>
|
||||
<div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;">
|
||||
<p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/>
|
||||
QQ群:1071514693</p>
|
||||
<p style="color:#888; float:right;font-weight: bold;font-size: 16px;">GitLink团队</p>
|
||||
<div style="clear:both; overflow:hidden;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue