forked from Trustie/forgeplus
Compare commits
345 Commits
standalone
...
trustie_se
| Author | SHA1 | Date |
|---|---|---|
|
|
6eaf491f70 | |
|
|
d4d00b30bf | |
|
|
19ec81e975 | |
|
|
2ea78b4f20 | |
|
|
4c066b30ef | |
|
|
ad9bb8e542 | |
|
|
e36c7a4b6a | |
|
|
18c4c6ae2f | |
|
|
9979c87d0c | |
|
|
8e8ec821f2 | |
|
|
774b1bc79e | |
|
|
94166a363c | |
|
|
0219a1fdde | |
|
|
ebe5fad7dd | |
|
|
b2e7491ade | |
|
|
85a36ca2e7 | |
|
|
b0f80012ab | |
|
|
75cef14605 | |
|
|
0fc96026c8 | |
|
|
93f8b659a1 | |
|
|
b45ee11239 | |
|
|
553d3a019f | |
|
|
33fa55bcb6 | |
|
|
643a99fdf1 | |
|
|
38c5432c2a | |
|
|
5cf257c3cc | |
|
|
aa18fe0ad4 | |
|
|
1358c23ca6 | |
|
|
e8bfd0c955 | |
|
|
183eb15c7d | |
|
|
fb43268444 | |
|
|
c27cc063e6 | |
|
|
6f6fe61a9d | |
|
|
b673909f9e | |
|
|
bd4dbd577b | |
|
|
ee3a14fa28 | |
|
|
26bfc2c0bf | |
|
|
eb2d976876 | |
|
|
56721930a2 | |
|
|
2959414d56 | |
|
|
319e6ea084 | |
|
|
008fdbaf5a | |
|
|
6223cf41e2 | |
|
|
1d3f79e777 | |
|
|
b0092487e6 | |
|
|
0ae3544235 | |
|
|
05b3f2a2fb | |
|
|
97fe157279 | |
|
|
fbebd0a623 | |
|
|
a14a646768 | |
|
|
25487368e5 | |
|
|
02681abaee | |
|
|
fe23c2afbf | |
|
|
2fa0df3ae3 | |
|
|
dc0d31330a | |
|
|
b06ad71082 | |
|
|
3212bc4842 | |
|
|
779c86108a | |
|
|
e4779926bd | |
|
|
803fdfc49e | |
|
|
83e43f0c97 | |
|
|
ccec3494bc | |
|
|
e237fd46f7 | |
|
|
6dc2f0b062 | |
|
|
ca3c564529 | |
|
|
f79e4f8e81 | |
|
|
9cd18397f7 | |
|
|
bfd3298cd0 | |
|
|
077926de18 | |
|
|
4fade5d0b7 | |
|
|
f51ebaad67 | |
|
|
8ae6a0deb2 | |
|
|
d9b3711e08 | |
|
|
77620f7735 | |
|
|
acbd0d376c | |
|
|
2f4ffe3d8e | |
|
|
a6efae8b10 | |
|
|
5a728e7d4d | |
|
|
04a733d99f | |
|
|
9e8c576ff6 | |
|
|
94881dd72a | |
|
|
2c7bb1b5cd | |
|
|
0e4c0a46c2 | |
|
|
7fcbbb7922 | |
|
|
3d9fe5bba5 | |
|
|
4dccdfde97 | |
|
|
00fc83235f | |
|
|
498ee26f59 | |
|
|
5d771c824b | |
|
|
3eccd6be64 | |
|
|
9b3336c0a0 | |
|
|
12c961d70d | |
|
|
7750cbe272 | |
|
|
1f13bba52e | |
|
|
5dcee1b4dc | |
|
|
cf09b28f5e | |
|
|
f31796f344 | |
|
|
2d9bde134a | |
|
|
59db914bcc | |
|
|
a0a7f908f4 | |
|
|
17ccf3d576 | |
|
|
72a32ed8c4 | |
|
|
c64fa5135b | |
|
|
12cc37443e | |
|
|
055fa635d3 | |
|
|
5edea8960d | |
|
|
f5efbcfc04 | |
|
|
50dc5cce5d | |
|
|
bc8f032f2f | |
|
|
0d377943d5 | |
|
|
0afac46778 | |
|
|
a6cee63d17 | |
|
|
ebab541b29 | |
|
|
77797fb1f7 | |
|
|
20af4a7d82 | |
|
|
000197b0d1 | |
|
|
67b386d947 | |
|
|
6aa3321d17 | |
|
|
82df2fd6d8 | |
|
|
9d8df2b4d9 | |
|
|
d44308fc82 | |
|
|
ae7d0d1329 | |
|
|
071542bcb4 | |
|
|
676024b6db | |
|
|
55c74de8e4 | |
|
|
52c94effdc | |
|
|
7c88ea3d67 | |
|
|
d799d329ff | |
|
|
f15cd44dff | |
|
|
91ea5ca96a | |
|
|
3abd6037d9 | |
|
|
11724bf63f | |
|
|
ec3a556a6f | |
|
|
1d7c7eba24 | |
|
|
793cbb372a | |
|
|
396ac55429 | |
|
|
e1b4622ede | |
|
|
088c617cc1 | |
|
|
ff14215242 | |
|
|
121e04f751 | |
|
|
246b484ad8 | |
|
|
fc3cf01d3f | |
|
|
345fd31834 | |
|
|
8f5bb0e2d9 | |
|
|
7aea481ccf | |
|
|
37317f82bf | |
|
|
2dfd69ae21 | |
|
|
a132154136 | |
|
|
720c073f32 | |
|
|
185cb308ac | |
|
|
0076468a15 | |
|
|
910ae48556 | |
|
|
94edf8c624 | |
|
|
9cd9603869 | |
|
|
6e86f9d9f3 | |
|
|
e97e7aa550 | |
|
|
ffb3b26d3c | |
|
|
6d280ed8f2 | |
|
|
47b3816e4f | |
|
|
3f85f88c92 | |
|
|
1477811782 | |
|
|
f60cd409b6 | |
|
|
04b2a9b358 | |
|
|
9d46f2743d | |
|
|
000a4f8019 | |
|
|
aaf2b43986 | |
|
|
75a9a65b9b | |
|
|
0e8d461615 | |
|
|
49afc0e20a | |
|
|
17f2436118 | |
|
|
eac7331070 | |
|
|
2243697184 | |
|
|
551f333261 | |
|
|
18cf1d3ecb | |
|
|
f8be0e17e9 | |
|
|
7c1160b247 | |
|
|
4cefaa7e92 | |
|
|
dec264d169 | |
|
|
8aa935ad5c | |
|
|
4025d059cf | |
|
|
62a1e6730c | |
|
|
f082819496 | |
|
|
4bdff8313a | |
|
|
c4f91fb054 | |
|
|
43046a4ef3 | |
|
|
a33be8850e | |
|
|
fde01e62ef | |
|
|
7055974443 | |
|
|
d67c6f2f76 | |
|
|
e0022647ed | |
|
|
1f6ac05bad | |
|
|
0154115f6b | |
|
|
70dd2768e5 | |
|
|
c5dd099169 | |
|
|
3536918938 | |
|
|
d56da6d020 | |
|
|
56278b84f2 | |
|
|
882a50cf56 | |
|
|
234f5b900c | |
|
|
db4031b8bf | |
|
|
dd3236e310 | |
|
|
ecfc39565c | |
|
|
7fd41e13e4 | |
|
|
9ced678f91 | |
|
|
b25db9d37f | |
|
|
7951ca28d5 | |
|
|
4bbb843edf | |
|
|
747646cd9d | |
|
|
a5be4a9502 | |
|
|
d0d906d04c | |
|
|
4c69c4d20f | |
|
|
183315bbd9 | |
|
|
4dc3546124 | |
|
|
d796d59557 | |
|
|
bc639488aa | |
|
|
930805704a | |
|
|
9912ad0779 | |
|
|
d9ae4e4ba0 | |
|
|
23dc2d7fb6 | |
|
|
fe5c18c019 | |
|
|
fa6f015128 | |
|
|
7f1b95c7d7 | |
|
|
2346b0f848 | |
|
|
0156e9726c | |
|
|
ea070d4e23 | |
|
|
c0e97409cb | |
|
|
99fbecc834 | |
|
|
4cc8dd70f4 | |
|
|
8d0a6d267a | |
|
|
0db1820557 | |
|
|
b1c03ed5e8 | |
|
|
1c660213a7 | |
|
|
748f6cdd4d | |
|
|
1fe8d1defc | |
|
|
ef12f85687 | |
|
|
e120c4dac2 | |
|
|
e1cf2fcdeb | |
|
|
c4f380873e | |
|
|
5cb2e55f74 | |
|
|
ed54e2ae8e | |
|
|
386c90592e | |
|
|
664b806c0a | |
|
|
b530de4ddc | |
|
|
1dd3fbc69a | |
|
|
94d259ea03 | |
|
|
3091593d14 | |
|
|
c5d2fad913 | |
|
|
b97c42d0ae | |
|
|
c76466a883 | |
|
|
217e0fdd97 | |
|
|
f0b8489828 | |
|
|
a2612d8009 | |
|
|
2f2655525f | |
|
|
70ade7b27b | |
|
|
57c60b2fe9 | |
|
|
aa643430fa | |
|
|
1a93477635 | |
|
|
8f9aedd7d6 | |
|
|
ab989ed7d7 | |
|
|
28d07d5c54 | |
|
|
53d094784b | |
|
|
7c664addbd | |
|
|
6167834bfa | |
|
|
1bb754e9d8 | |
|
|
f2f2ce8252 | |
|
|
c6b79f82bc | |
|
|
4e3f9cc019 | |
|
|
5ed7b3e4ad | |
|
|
4e2c46260c | |
|
|
9ba00b21c9 | |
|
|
1100309038 | |
|
|
b11f5fd228 | |
|
|
af5f2b2fe3 | |
|
|
90dbe0730a | |
|
|
f39e8b7668 | |
|
|
d6633cb73a | |
|
|
86ef890f8b | |
|
|
a7a6abd22a | |
|
|
6fd47b56a5 | |
|
|
c956667ce0 | |
|
|
898453c88c | |
|
|
5701c818ed | |
|
|
1ac2ddfaa5 | |
|
|
0bd274f813 | |
|
|
4aac05d4e1 | |
|
|
b028a70646 | |
|
|
3c7da85bee | |
|
|
9751c954df | |
|
|
84b56bfcb8 | |
|
|
ac07c88f84 | |
|
|
7485564bb9 | |
|
|
5e696ae905 | |
|
|
b5acf2308a | |
|
|
e3f4313c80 | |
|
|
b223abe229 | |
|
|
b3bede308c | |
|
|
2f170a54c6 | |
|
|
22293572ac | |
|
|
d262da7c65 | |
|
|
2050559077 | |
|
|
8720cab1e9 | |
|
|
959c1e8d95 | |
|
|
52bde548fa | |
|
|
ea11672fff | |
|
|
09c4f8db0e | |
|
|
29dc3fff39 | |
|
|
da863c3963 | |
|
|
8d18149537 | |
|
|
8050af23fc | |
|
|
298abdd1b1 | |
|
|
eb0ced39f5 | |
|
|
2738d950d4 | |
|
|
3ce9b2d145 | |
|
|
26f87fba16 | |
|
|
465f38bca7 | |
|
|
1e9a32a93e | |
|
|
04bc6d363f | |
|
|
2dc79052c2 | |
|
|
f6ff8ac209 | |
|
|
b9e2a6edf1 | |
|
|
e0f5337fdd | |
|
|
380ca3a066 | |
|
|
7d19849968 | |
|
|
237b0afb08 | |
|
|
67914201bf | |
|
|
e14936e820 | |
|
|
655c85851f | |
|
|
1c7e414aa4 | |
|
|
099fc52e00 | |
|
|
490957ec3b | |
|
|
b1884d30d5 | |
|
|
98d8ee1fb6 | |
|
|
2ca77732c8 | |
|
|
1760b42127 | |
|
|
9f7725b097 | |
|
|
612101498c | |
|
|
70d22f7c4f | |
|
|
25d0e784bb | |
|
|
5d45b24299 | |
|
|
b6b8befde7 | |
|
|
f33b9559cd | |
|
|
ab6ac05a7d | |
|
|
cf69628f85 | |
|
|
4a8f8af896 | |
|
|
f9bc2258ec |
|
|
@ -84,4 +84,5 @@ redis_data/
|
|||
Dockerfile
|
||||
dump.rdb
|
||||
.tags*
|
||||
ceshi_user.xlsx
|
||||
ceshi_user.xlsx
|
||||
public/trace_task_results
|
||||
|
|
@ -1,6 +1,25 @@
|
|||
class AccountsController < ApplicationController
|
||||
before_action :require_login, only: [:login_check, :simple_update]
|
||||
include ApplicationHelper
|
||||
|
||||
#skip_before_action :check_account, :only => [:logout]
|
||||
|
||||
def simple_update
|
||||
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, ""))
|
||||
Register::RemoteForm.new(simple_update_params).validate!
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = auto_update(current_user, simple_update_params)
|
||||
if result[:message].blank?
|
||||
render_ok
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
|
@ -192,7 +211,9 @@ class AccountsController < ApplicationController
|
|||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
email: @user.mail,
|
||||
login_name: @user.name,
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
|
|
@ -313,6 +334,11 @@ class AccountsController < ApplicationController
|
|||
Register::CheckColumnsForm.new(check_params).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
def login_check
|
||||
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
@ -381,4 +407,7 @@ class AccountsController < ApplicationController
|
|||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
|
||||
def simple_update_params
|
||||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
|
|||
def create
|
||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||
|
||||
result = Admins::ImportUserService.call(params[:file].to_io)
|
||||
result = Admins::ImportUserFromExcelService.call(params[:file].to_io)
|
||||
render_ok(result)
|
||||
rescue Admins::ImportUserService::Error => ex
|
||||
render_error(ex)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
class Admins::Topic::GlccNewsController < Admins::Topic::BaseController
|
||||
before_action :find_glcc, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
q = ::Topic::GlccNews.ransack(title_cont: params[:search])
|
||||
glcc_news = q.result(distinct: true)
|
||||
@glcc_news = paginate(glcc_news)
|
||||
end
|
||||
|
||||
def new
|
||||
@glcc = ::Topic::GlccNews.new
|
||||
end
|
||||
|
||||
def create
|
||||
@glcc = ::Topic::GlccNews.new(glcc_params)
|
||||
if @glcc.save
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "新增新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "新增新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
@glcc.attributes = glcc_params
|
||||
if @glcc.save
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "更新新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "更新新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @glcc.destroy
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "删除新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "删除新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_glcc
|
||||
@glcc = ::Topic::GlccNews.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def glcc_params
|
||||
params.require(:topic_glcc_news).permit(:title, :uuid, :url, :order_index)
|
||||
end
|
||||
end
|
||||
|
|
@ -217,7 +217,7 @@ class AttachmentsController < ApplicationController
|
|||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user)
|
||||
candown = course.member?(current_user) || course.is_public
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
|
|||
namespace = params[:owner]
|
||||
id = params[:repo] || params[:id]
|
||||
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id, current_user.login)
|
||||
end
|
||||
|
||||
def load_all_repo
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class Ci::SecretsController < Ci::BaseController
|
|||
end
|
||||
|
||||
def ci_drone_url
|
||||
user = User.find_by(login: params[:owner])
|
||||
user = User.find_by(login: params[:owner]) || User.find_by(login: current_user.login)
|
||||
user&.ci_cloud_account.drone_url
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ class CompareController < ApplicationController
|
|||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
@page_size = page_size <= 0 ? 1 : page_size
|
||||
@page_limit = page_limit <=0 ? 15 : page_limit
|
||||
@page_offset = (@page_size -1) * @page_limit
|
||||
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -16,6 +20,7 @@ class CompareController < ApplicationController
|
|||
if @base.blank? || @head.blank?
|
||||
return -2, "请选择分支"
|
||||
else
|
||||
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||
if @head.include?(":")
|
||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||
|
|
@ -50,6 +55,14 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def gitea_compare(base, head)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
|
||||
end
|
||||
|
||||
def page_size
|
||||
params.fetch(:page, 1).to_i
|
||||
end
|
||||
|
||||
def page_limit
|
||||
params.fetch(:limit, 15).to_i
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ module Ci::CloudAccountManageable
|
|||
|
||||
def drone_oauth_user!(url, state)
|
||||
logger.info "[drone] drone_oauth_user url: #{url}"
|
||||
conn = Faraday.new(url: url) do |req|
|
||||
conn = Faraday.new(url: "#{Gitea.gitea_config[:domain]}#{url}") do |req|
|
||||
req.request :url_encoded
|
||||
req.adapter Faraday.default_adapter
|
||||
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
||||
|
|
@ -188,7 +188,8 @@ module Ci::CloudAccountManageable
|
|||
response = conn.get
|
||||
logger.info "[drone] response headers: #{response.headers}"
|
||||
|
||||
response.headers['location'].include?('error') ? false : true
|
||||
true
|
||||
# response.headers['location'].include?('error') ? false : true
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -108,7 +108,11 @@ module LoginHelper
|
|||
def sync_pwd_to_gitea!(user, hash={})
|
||||
return true if user.is_sync_pwd?
|
||||
|
||||
sync_params = { email: user.mail }
|
||||
sync_params = {
|
||||
login_name: user.name,
|
||||
source_id: 0,
|
||||
email: user.mail
|
||||
}
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
||||
if interactor.success?
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
||||
|
|
|
|||
|
|
@ -58,4 +58,32 @@ module RegisterHelper
|
|||
end
|
||||
end
|
||||
|
||||
def auto_update(user, params={})
|
||||
return if params.blank?
|
||||
result = {message: nil, user: nil}
|
||||
before_login = user.login
|
||||
user.login = params[:username]
|
||||
user.password = params[:password]
|
||||
user.mail = params[:email]
|
||||
|
||||
if user.save!
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: params[:email],
|
||||
login_name: params[:username],
|
||||
new_name: params[:username],
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||
if interactor.success?
|
||||
result[:user] = user
|
||||
else
|
||||
result[:message] = '用户同步Gitea失败!'
|
||||
end
|
||||
else
|
||||
result[:message] = user.errors.full_messages.join(",")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module RenderHelper
|
|||
end
|
||||
|
||||
def render_error(message = '')
|
||||
render json: { status: -1, message: message }
|
||||
render json: { status: status, message: message }
|
||||
end
|
||||
|
||||
def render_not_acceptable(message = '请求已拒绝')
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ class IssuesController < ApplicationController
|
|||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
||||
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
||||
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
||||
@assign_to_me = @filter_issues.where(assigned_to_id: current_user&.id)
|
||||
@my_published = @filter_issues.where(author_id: current_user&.id)
|
||||
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
||||
@issues_size = scopes.size
|
||||
@assign_to_me = scopes.where(assigned_to_id: current_user&.id)
|
||||
@my_published = scopes.where(author_id: current_user&.id)
|
||||
@issues = paginate(scopes)
|
||||
|
||||
respond_to do |format|
|
||||
|
|
@ -109,7 +109,7 @@ class IssuesController < ApplicationController
|
|||
|
||||
def create
|
||||
issue_params = issue_send_params(params)
|
||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
@issue = Issue.new(issue_params)
|
||||
if @issue.save!
|
||||
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||
|
|
@ -149,6 +149,8 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
|
||||
|
||||
|
||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||
|
|
@ -178,6 +180,7 @@ class IssuesController < ApplicationController
|
|||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
next if tag == [""]
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
|
|
@ -220,7 +223,7 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "不允许修改为关闭状态")
|
||||
else
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
if @issue.update_attributes(issue_params)
|
||||
if @issue&.pull_request.present?
|
||||
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||
|
|
@ -244,7 +247,7 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
@issue.update_closed_issues_count_in_project!
|
||||
# @issue.update_closed_issues_count_in_project!
|
||||
if @issue.issue_type.to_s == "2" && last_status_id != 5
|
||||
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token
|
||||
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class JournalsController < ApplicationController
|
|||
normal_status(-1, "评论内容不能为空")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
Journals::CreateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
journal_params = {
|
||||
journalized_id: @issue.id ,
|
||||
journalized_type: "Issue",
|
||||
|
|
@ -53,6 +54,9 @@ class JournalsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
@ -70,7 +74,8 @@ class JournalsController < ApplicationController
|
|||
|
||||
def update
|
||||
content = params[:content]
|
||||
if content.present?
|
||||
if content.present?
|
||||
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
if @journal.update_attribute(:notes, content)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
|
|
@ -79,7 +84,9 @@ class JournalsController < ApplicationController
|
|||
else
|
||||
normal_status(-1, "评论的内容不能为空")
|
||||
end
|
||||
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def get_children_journals
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
class NoticesController < ApplicationController
|
||||
|
||||
def create
|
||||
tip_exception("参数有误") if params["source"].blank?
|
||||
user_id = params[:user_id]
|
||||
|
||||
if params["source"] == "CompetitionBegin"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionBegin', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionResult"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionResult', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionReview"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
|
||||
else
|
||||
tip_exception("#{params["source"]}未配置")
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
|||
def index
|
||||
@organization_users = @organization.organization_users.includes(:user)
|
||||
search = params[:search].to_s.downcase
|
||||
@organization_users = @organization_users.joins(:user).merge(User.like(search))
|
||||
user_condition_users = User.like(search).to_sql
|
||||
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||
|
||||
@organization_users = @organization_users.where(user_id: users).distinct
|
||||
|
||||
@organization_users = kaminari_paginate(@organization_users)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
if @organization.teams.count >= 50
|
||||
return render_forbidden("组织的团队数量已超过限制!")
|
||||
return tip_exception("组织的团队数量已超过限制!")
|
||||
else
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class OwnersController < ApplicationController
|
|||
|
||||
def show
|
||||
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
|
||||
return render_ok(type: 'User') unless @owner.present?
|
||||
return render_not_found unless @owner.present?
|
||||
# 组织
|
||||
if @owner.is_a?(Organization)
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class PraiseTreadController < ApplicationController
|
|||
begin
|
||||
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
|
||||
current_user.like!(@project)
|
||||
SendTemplateMessageJob.perform_later('ProjectPraised', current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class ProjectsController < ApplicationController
|
|||
def menu_list
|
||||
menu = []
|
||||
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
|
||||
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")
|
||||
|
|
@ -20,9 +22,11 @@ class ProjectsController < ApplicationController
|
|||
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("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
|
||||
menu.append(menu_hash_by_name("services")) if @project.has_menu_permission("services") && @project.forge? && (current_user.admin? || @project.member?(current_user.id))
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||
menu.append(menu_hash_by_name("activity"))
|
||||
menu.append(menu_hash_by_name("settings")) if (current_user.admin? || @project.manager?(current_user)) && @project.forge?
|
||||
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
||||
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
|
||||
render json: menu
|
||||
end
|
||||
|
|
@ -59,7 +63,7 @@ class ProjectsController < ApplicationController
|
|||
Projects::MigrateForm.new(mirror_params).validate!
|
||||
|
||||
@project =
|
||||
if enable_accelerator?(mirror_params[:clone_addr])
|
||||
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
uid_logger("########## 已动加速器 ##########")
|
||||
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||
|
|
@ -71,6 +75,11 @@ class ProjectsController < ApplicationController
|
|||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
|
||||
uid_logger("########## 更改clone_addr ##########")
|
||||
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
|
|
@ -83,7 +92,7 @@ class ProjectsController < ApplicationController
|
|||
return @branches = [] unless @project.forge?
|
||||
|
||||
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
|
||||
end
|
||||
|
||||
|
|
@ -130,7 +139,7 @@ class ProjectsController < ApplicationController
|
|||
validate_params = project_params.slice(:name, :description,
|
||||
:project_category_id, :project_language_id, :private, :identifier)
|
||||
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
|
||||
|
||||
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||
|
||||
|
|
@ -172,6 +181,22 @@ class ProjectsController < ApplicationController
|
|||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def quit
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
ActiveRecord::Base.transaction do
|
||||
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
|
||||
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
render_forbidden('你不能退出该仓库')
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
||||
@watchers_count = watchers.size
|
||||
|
|
@ -185,7 +210,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def fork_users
|
||||
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
@forks_count = fork_users.size
|
||||
@fork_users = paginate(fork_users)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
|
|||
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||
before_action :require_profile_completed, only: [:create]
|
||||
before_action :load_repository
|
||||
before_action :check_menu_authorize
|
||||
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
|
||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||
before_action :load_pull_request, only: [:files, :commits]
|
||||
before_action :find_atme_receivers, only: [:create, :update]
|
||||
|
|
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
|
|||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||
@all_issues = issues.distinct
|
||||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||
|
|
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@all_branches = Branches::ListService.call(@owner, @project)
|
||||
@all_branches = Branches::ListService.call(@owner, @project, params[:branch_name])
|
||||
@is_fork = @project.forked_from_project_id.present?
|
||||
@projects_names = [{
|
||||
project_user_login: @owner.try(:login),
|
||||
|
|
@ -50,7 +50,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def get_branches
|
||||
branch_result = Branches::ListService.call(@owner, @project)
|
||||
branch_result = Branches::ListService.call(@owner, @project, params[:name])
|
||||
render json: branch_result
|
||||
# return json: branch_result
|
||||
end
|
||||
|
|
@ -58,6 +58,7 @@ class PullRequestsController < ApplicationController
|
|||
def create
|
||||
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
if @gitea_pull_request[:status] == :success
|
||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
||||
|
|
@ -89,7 +90,7 @@ class PullRequestsController < ApplicationController
|
|||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
return normal_status(-1, "title不能超过255个字符") if params[:title].length > 255
|
||||
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
merge_params
|
||||
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
|
|
@ -274,12 +275,12 @@ class PullRequestsController < ApplicationController
|
|||
base: params[:base], #目标分支
|
||||
milestone: 0, #里程碑,未与本地的里程碑关联
|
||||
}
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
@requests_params = @local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||
assignees: ["#{current_user.try(:login).to_s}"],
|
||||
labels: params[:issue_tag_ids],
|
||||
due_date: Time.now
|
||||
assignees: ["#{assignee_login.to_s}"],
|
||||
labels: params[:issue_tag_ids]
|
||||
# due_date: Time.now
|
||||
})
|
||||
@issue_params = {
|
||||
author_id: current_user.id,
|
||||
|
|
|
|||
|
|
@ -1,387 +1,391 @@
|
|||
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
|
||||
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
|
||||
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
rescue
|
||||
@contributors = []
|
||||
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)
|
||||
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
|
||||
rescue
|
||||
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/#{Addressable::URI.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/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.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
|
||||
|
|
@ -1,14 +1,24 @@
|
|||
class SettingsController < ApplicationController
|
||||
def show
|
||||
@old_projects_url = nil
|
||||
get_navbar
|
||||
get_add_menu
|
||||
get_common_menu
|
||||
get_sub_competitions
|
||||
get_personal_menu
|
||||
get_third_party
|
||||
get_top_system_notification
|
||||
end
|
||||
|
||||
private
|
||||
def get_navbar
|
||||
@navbar = default_laboratory.navbar
|
||||
if User.current.logged?
|
||||
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
|
||||
@navbar << pernal_index
|
||||
end
|
||||
end
|
||||
|
||||
def get_add_menu
|
||||
@add = []
|
||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||
|
|
@ -20,6 +30,15 @@ class SettingsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def get_sub_competitions
|
||||
@sub_competitions = []
|
||||
Site.competition.pluck(:key).uniq.each do |key|
|
||||
hash = {"identifier": "#{key.to_s}"}
|
||||
hash.merge!("list": Site.competition.where(key: key).select(:id, :name, :url, :key).to_a.map(&:serializable_hash))
|
||||
@sub_competitions << hash
|
||||
end
|
||||
end
|
||||
|
||||
def get_common_menu
|
||||
@common = {}
|
||||
Site.common.select(:url, :key).each do |site|
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
class Traces::BaseController < ApplicationController
|
||||
|
||||
helper_method :observed_logged_user?, :observed_user
|
||||
|
||||
|
||||
def observed_user
|
||||
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||
end
|
||||
|
||||
def observed_logged_user?
|
||||
observed_user.id == User.current&.id
|
||||
end
|
||||
|
||||
protected
|
||||
def check_auth
|
||||
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
class Traces::ProjectsController < Traces::BaseController
|
||||
include OperateProjectAbilityAble
|
||||
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :authorizate_user_can_edit_project!, except: [:task_results]
|
||||
|
||||
def tasks
|
||||
branch_name = params[:branch_name]
|
||||
return render_error("无可用检测次数") if @project.user_trace_tasks.size >= 5
|
||||
return render_error("分支名不能为空!") if branch_name.blank?
|
||||
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||
code, data, error = Trace::CheckService.call(current_user.trace_token, @project, "1", branch_name)
|
||||
if code == 200
|
||||
UserTraceTask.create!(
|
||||
user_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
branch_tag: branch_name,
|
||||
task_id: data["task_id"]
|
||||
)
|
||||
render_ok
|
||||
else
|
||||
render_error("检测失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def task_results
|
||||
limit = params[:limit] || params[:per_page]
|
||||
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
|
||||
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||
return render :json => {left_tasks_count: 5, data: []} if current_user.trace_user.nil?
|
||||
code, data, error = Trace::CheckResultService.call(current_user.trace_token, @project, nil, page, limit)
|
||||
if code == 200
|
||||
render :json => {left_tasks_count: 5 - @project.user_trace_tasks.size, data: data}
|
||||
else
|
||||
render_error("获取检测记录失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def reload_task
|
||||
return render_error("project_id错误") if params[:project_id].blank?
|
||||
branch_name = params[:branch_name]
|
||||
return render_error("分支名不能为空!") if branch_name.blank?
|
||||
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||
code, data, error = Trace::ReloadCheckService.call(current_user.trace_token, params[:project_id])
|
||||
if code == 200
|
||||
UserTraceTask.create!(
|
||||
user_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
branch_tag: branch_name,
|
||||
task_id: data["task_id"]
|
||||
)
|
||||
render_ok
|
||||
else
|
||||
render_error("重新检测失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
|
||||
def task_pdf
|
||||
return render_error("task_id错误") if params[:task_id].blank?
|
||||
result = Trace::PdfReportService.call(current_user.trace_token, params[:task_id])
|
||||
if result.is_a?(Hash) && result[:code] == 200
|
||||
redirect_to result[:download_url]
|
||||
else
|
||||
render_error("下载报告失败!")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
class Traces::TraceUsersController < Traces::BaseController
|
||||
before_action :require_login
|
||||
|
||||
def create
|
||||
if current_user.trace_token.present?
|
||||
render_ok
|
||||
else
|
||||
render_error(-1, "代码溯源用户初始化失败")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
end
|
||||
|
|
@ -12,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
|
|||
@commit_data = []
|
||||
date_range.each do |date|
|
||||
@date_data << date.strftime("%Y.%m.%d")
|
||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
||||
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
|
||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
||||
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class Users::TemplateMessageSettingsController < Users::BaseController
|
|||
def get_current_setting
|
||||
@current_setting = @_observed_user.user_template_message_setting
|
||||
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
||||
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
|
||||
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
|
||||
end
|
||||
|
||||
def setting_params
|
||||
|
|
|
|||
|
|
@ -1,324 +1,399 @@
|
|||
class UsersController < ApplicationController
|
||||
include ApplicationHelper
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :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, :update_image]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
||||
def connect_to_ci_db(options={})
|
||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||
return
|
||||
end
|
||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||
connect_to_trustie_ci_database(options)
|
||||
else
|
||||
connect_to_ci_database(options)
|
||||
end
|
||||
end
|
||||
|
||||
def list
|
||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||
@total_count = scope.size
|
||||
@users = paginate(scope)
|
||||
end
|
||||
|
||||
def show
|
||||
#待办事项,现在未做
|
||||
if User.current.admin? || User.current.login == @user.login
|
||||
@waiting_applied_messages = @user.applied_messages.waiting
|
||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
else
|
||||
@waiting_applied_messages = AppliedMessage.none
|
||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||
@common_applied_projects = AppliedProject.none
|
||||
@undo_events = 0
|
||||
end
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||
@user_org_count = user_organizations.size
|
||||
normal_projects = Project.members_projects(@user.id).to_sql
|
||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
# 为了缓存活跃用户的基本信息,后续删除
|
||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||
if params[:search].present?
|
||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||
watchers = watchers.where(watchable_id: search_user_ids)
|
||||
end
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def fan_users
|
||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def hovercard
|
||||
end
|
||||
|
||||
def update
|
||||
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)) if user_params[:image].present?
|
||||
@user.attributes = user_params.except(:image)
|
||||
unless @user.save
|
||||
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
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
begin
|
||||
result = Notice::Read::CountService.call(current_user.id)
|
||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||
rescue
|
||||
@message_unread_total = 0
|
||||
end
|
||||
# TODO 等消息上线再打开注释
|
||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
missing_template
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def attachment_show
|
||||
file_name = params[:file_name]
|
||||
path = params[:path] || file_storage_directory
|
||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||
:type => 'game',
|
||||
:disposition => 'attachment' #inline can open in browser
|
||||
end
|
||||
|
||||
def html_show
|
||||
@contents = File.read("#{params[:path]}")
|
||||
respond_to do |format|
|
||||
format.html {render :layout => false}
|
||||
end
|
||||
end
|
||||
|
||||
# Redo: 消息总数缓存
|
||||
def get_navigation_info
|
||||
# @old_domain = edu_setting('old_edu_host')
|
||||
# @user = current_user
|
||||
# # 新消息数
|
||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||
#
|
||||
# @user_url = "/users/#{@user.login}"
|
||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||
end
|
||||
|
||||
# 用户回复功能
|
||||
def reply_message
|
||||
message = JournalsForMessage.new(reply_message_params)
|
||||
message.user_id = current_user.id
|
||||
message.save!
|
||||
|
||||
render_ok(id: message.id)
|
||||
end
|
||||
|
||||
# 搜索用户具有管理员角色的项目
|
||||
def search_user_projects
|
||||
projects = Project.where.not(status: 9)
|
||||
|
||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||
projects = projects.where(members: { user_id: current_user.id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
@projects = projects.select(:id, :name)
|
||||
end
|
||||
|
||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||
def homepage_info
|
||||
#待办事项,现在未做
|
||||
@undo_events = 10
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 10
|
||||
end
|
||||
|
||||
def brief_introduction
|
||||
content = params[:content].to_s.strip
|
||||
|
||||
current_user.user_extension.update!(brief_introduction: content)
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def attendance
|
||||
attendance = Users::AttendanceService.call(current_user)
|
||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||
rescue Users::AttendanceService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||
def sync_token
|
||||
return render_error('未找相关用户!') unless @user
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||
token.update_column(:value, params[:token])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def trustie_related_projects
|
||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||
projects_json = []
|
||||
domain_url = EduSetting.get('host_name')
|
||||
if projects.present?
|
||||
projects.each do |p|
|
||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||
pj = {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
is_public: p.is_public,
|
||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||
status: p.status,
|
||||
is_member: p.member?(current_user.try(:id)),
|
||||
owner: {
|
||||
name: p.owner.try(:show_real_name),
|
||||
login: p.owner.login
|
||||
},
|
||||
members_count: p&.members.size,
|
||||
issues_count: p.issues_count - p.pull_requests_count,
|
||||
commits_count: p&.project_score&.changeset_num.to_i,
|
||||
http_url: domain_url + project_url,
|
||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||
http_issues_url: domain_url + project_url + "/issues",
|
||||
http_commits_url: domain_url + project_url + "/commits",
|
||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||
}
|
||||
projects_json.push(pj)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||
end
|
||||
|
||||
def trustie_projects
|
||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||
projects = Project.visible
|
||||
|
||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
projects = projects.select(:id, :name).limit(10).as_json
|
||||
render json: { projects: projects }
|
||||
end
|
||||
|
||||
def projects
|
||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||
@total_count = scope.size
|
||||
@projects = paginate(scope)
|
||||
end
|
||||
|
||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||
def sync_gitea_pwd
|
||||
return render_error("未找到相关的用户") if @user.blank?
|
||||
|
||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||
flag ? render_ok : render_error('同步失败!')
|
||||
end
|
||||
|
||||
# TODO
|
||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||
def sync_salt
|
||||
user = User.find_by_login params[:login]
|
||||
return if user.blank?
|
||||
user.update_column(:salt, params[:salt])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:nickname, :image,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id, :province, :city,
|
||||
:custom_department, :identity, :student_id, :description,
|
||||
:show_email, :show_location, :show_department]
|
||||
)
|
||||
end
|
||||
|
||||
def reply_message_params
|
||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||
end
|
||||
|
||||
def check_user_exist
|
||||
return if @user.present?
|
||||
render_not_found
|
||||
end
|
||||
|
||||
end
|
||||
class UsersController < ApplicationController
|
||||
include ApplicationHelper
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me sync_user_info]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
before_action :convert_image!, only: [:update, :update_image]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
before_action :sso_login, only: [:get_user_info]
|
||||
|
||||
def connect_to_ci_db(options={})
|
||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||
return
|
||||
end
|
||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||
connect_to_trustie_ci_database(options)
|
||||
else
|
||||
connect_to_ci_database(options)
|
||||
end
|
||||
end
|
||||
|
||||
def list
|
||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||
@total_count = scope.size
|
||||
@users = paginate(scope)
|
||||
end
|
||||
|
||||
def show
|
||||
#待办事项,现在未做
|
||||
if User.current.admin? || User.current.login == @user.login
|
||||
@waiting_applied_messages = @user.applied_messages.waiting
|
||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
else
|
||||
@waiting_applied_messages = AppliedMessage.none
|
||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||
@common_applied_projects = AppliedProject.none
|
||||
@undo_events = 0
|
||||
end
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||
@user_org_count = user_organizations.size
|
||||
normal_projects = Project.members_projects(@user.id).to_sql
|
||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
# 为了缓存活跃用户的基本信息,后续删除
|
||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||
if params[:search].present?
|
||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||
watchers = watchers.where(watchable_id: search_user_ids)
|
||||
end
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def fan_users
|
||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def hovercard
|
||||
end
|
||||
|
||||
def update
|
||||
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)) if user_params[:image].present?
|
||||
@user.attributes = user_params.except(:image)
|
||||
unless @user.save
|
||||
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 get_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)
|
||||
|
||||
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
begin
|
||||
result = Notice::Read::CountService.call(current_user.id)
|
||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||
rescue
|
||||
@message_unread_total = 0
|
||||
end
|
||||
# TODO 等消息上线再打开注释
|
||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
missing_template
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def attachment_show
|
||||
file_name = params[:file_name]
|
||||
path = params[:path] || file_storage_directory
|
||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||
:type => 'game',
|
||||
:disposition => 'attachment' #inline can open in browser
|
||||
end
|
||||
|
||||
def html_show
|
||||
@contents = File.read("#{params[:path]}")
|
||||
respond_to do |format|
|
||||
format.html {render :layout => false}
|
||||
end
|
||||
end
|
||||
|
||||
# Redo: 消息总数缓存
|
||||
def get_navigation_info
|
||||
# @old_domain = edu_setting('old_edu_host')
|
||||
# @user = current_user
|
||||
# # 新消息数
|
||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||
#
|
||||
# @user_url = "/users/#{@user.login}"
|
||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||
end
|
||||
|
||||
# 用户回复功能
|
||||
def reply_message
|
||||
message = JournalsForMessage.new(reply_message_params)
|
||||
message.user_id = current_user.id
|
||||
message.save!
|
||||
|
||||
render_ok(id: message.id)
|
||||
end
|
||||
|
||||
# 搜索用户具有管理员角色的项目
|
||||
def search_user_projects
|
||||
projects = Project.where.not(status: 9)
|
||||
|
||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||
projects = projects.where(members: { user_id: current_user.id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
@projects = projects.select(:id, :name)
|
||||
end
|
||||
|
||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||
def homepage_info
|
||||
#待办事项,现在未做
|
||||
@undo_events = 10
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 10
|
||||
end
|
||||
|
||||
def brief_introduction
|
||||
content = params[:content].to_s.strip
|
||||
|
||||
current_user.user_extension.update!(brief_introduction: content)
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def attendance
|
||||
attendance = Users::AttendanceService.call(current_user)
|
||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||
rescue Users::AttendanceService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||
def sync_token
|
||||
return render_error('未找相关用户!') unless @user
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||
token.update_column(:value, params[:token])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def trustie_related_projects
|
||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||
projects_json = []
|
||||
domain_url = EduSetting.get('host_name')
|
||||
if projects.present?
|
||||
projects.each do |p|
|
||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||
pj = {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
is_public: p.is_public,
|
||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||
status: p.status,
|
||||
is_member: p.member?(current_user.try(:id)),
|
||||
owner: {
|
||||
name: p.owner.try(:show_real_name),
|
||||
login: p.owner.login
|
||||
},
|
||||
members_count: p&.members.size,
|
||||
issues_count: p.issues_count - p.pull_requests_count,
|
||||
commits_count: p&.project_score&.changeset_num.to_i,
|
||||
http_url: domain_url + project_url,
|
||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||
http_issues_url: domain_url + project_url + "/issues",
|
||||
http_commits_url: domain_url + project_url + "/commits",
|
||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||
}
|
||||
projects_json.push(pj)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||
end
|
||||
|
||||
def trustie_projects
|
||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||
projects = Project.visible
|
||||
|
||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
projects = projects.select(:id, :name).limit(10).as_json
|
||||
render json: { projects: projects }
|
||||
end
|
||||
|
||||
def projects
|
||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||
@total_count = scope.size
|
||||
@projects = paginate(scope)
|
||||
end
|
||||
|
||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||
def sync_gitea_pwd
|
||||
return render_error("未找到相关的用户") if @user.blank?
|
||||
|
||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||
flag ? render_ok : render_error('同步失败!')
|
||||
end
|
||||
|
||||
# TODO
|
||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||
def sync_salt
|
||||
user = User.find_by_login params[:login]
|
||||
return if user.blank?
|
||||
user.update_column(:salt, params[:salt])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def email_search
|
||||
return render_error('请输入email') if params[:email].blank?
|
||||
@user = User.find_by(mail: params[:email])
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:nickname, :image,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id, :province, :city,
|
||||
:custom_department, :identity, :student_id, :description,
|
||||
:show_super_description, :super_description,
|
||||
:show_email, :show_location, :show_department]
|
||||
)
|
||||
end
|
||||
|
||||
def reply_message_params
|
||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||
end
|
||||
|
||||
def check_user_exist
|
||||
return if @user.present?
|
||||
render_not_found
|
||||
end
|
||||
|
||||
def sso_login
|
||||
if params[:login].present? && !current_user.logged? && params[:websiteName].present?
|
||||
user = User.where("login = ?", "#{params[:login].presence}").first
|
||||
# 已同步注册,直接登录
|
||||
if user.present?
|
||||
successful_authentication(user)
|
||||
else
|
||||
autologin_register_by_educoder(params[:login].presence)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 通过login参数查询头歌账号信息,注册并登录
|
||||
def autologin_register_by_educoder(edu_login)
|
||||
req_params = { "login" => "#{edu_login}", "private_token" => "hriEn3UwXfJs3PmyXnSH" }
|
||||
api_url= "https://data.educoder.net"
|
||||
client = Faraday.new(url: api_url)
|
||||
response = client.public_send("get", "/api/sources/get_user_info_by_login", req_params)
|
||||
result = JSON.parse(response.body)
|
||||
#查询
|
||||
return nil if result["status"].to_s != "0"
|
||||
|
||||
# login 邮箱 手机号 姓名 学校/单位
|
||||
user_info = result["data"]
|
||||
Rails.logger.info("user_info====== #{user_info}")
|
||||
login = user_info["login"]
|
||||
email = user_info["mail"]
|
||||
phone = user_info["phone"]
|
||||
real_name = user_info["username"]
|
||||
department_name = user_info["school"]
|
||||
password = "12345678"
|
||||
|
||||
# 没有用户时,新建用户并登录
|
||||
user = User.where("login = ? or phone = ? or mail = ? ", "#{login}", phone, email).first
|
||||
if user.present?
|
||||
# 手机号先记录,后续用
|
||||
user.update_column(:phone, "#{phone}") if phone.present?
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
email = "#{login}@gitlink.org.cn" if email.blank?
|
||||
user_params = { status: 1, type: 'User', login: "#{login}", lastname: "#{real_name}", mail: "#{email}",
|
||||
nickname: "#{real_name}", professional_certification: 0, certification: 0, grade: 0,
|
||||
password: "#{password}", phone: "#{phone}", profile_completed: 1 }
|
||||
user = User.create!(user_params)
|
||||
UserExtension.create!(user_id: user.id, gender: 1, custom_department: "#{department_name}")
|
||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
Rails.logger.info("Gitea::RegisterInteractor.call result====== #{gitea_user}")
|
||||
result = Gitea::User::GenerateTokenService.call(login, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
user.save!
|
||||
else
|
||||
Rails.logger.info("Gitea::RegisterInteractor.call error====== #{interactor.error}")
|
||||
end
|
||||
end
|
||||
end
|
||||
successful_authentication(user) if user.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class VersionReleasesController < ApplicationController
|
|||
def new
|
||||
#获取所有的分支
|
||||
@all_branches = []
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier), params[:branch_name]).call
|
||||
if get_all_branches && get_all_branches.size > 0
|
||||
get_all_branches.each do |b|
|
||||
@all_branches.push(b["name"])
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ includes:
|
|||
- users
|
||||
- projects
|
||||
- repositories
|
||||
- traces
|
||||
- pulls
|
||||
- issues
|
||||
- organizations
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ repo |是| |string |项目标识identifier
|
|||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,services:服务,activity:动态,setting:仓库设置
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
|
@ -408,7 +408,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
|
|||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,resources:资源库,services:服务 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,217 @@
|
|||
# Traces
|
||||
|
||||
## 代码溯源初始化
|
||||
用户同意协议后请求的接口,创建代码溯源的账号
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
http://localhost:3000/api/traces/trace_users.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/traces/trace_users.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/traces/trace_users.json`
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 代码分析结果列表
|
||||
查询项目下代码分析的结果
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/task_results.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/task_results.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/task_results.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner|是|否|string | 项目所有者标识|
|
||||
repo|是 | 否|string | 项目标识 |
|
||||
page |否| 1 | int | 页码 |
|
||||
limit |否| 15 | int | 每页数量 |
|
||||
|
||||
### 返回字段说明(暂缺)
|
||||
<!-- 参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
total_count |int |总数 |
|
||||
public_keys.id |int |ID|
|
||||
public_keys.name |string|密钥标题|
|
||||
public_keys.content |string|密钥内容|
|
||||
public_keys.fingerprint |string|密钥标识|
|
||||
public_keys.created_time |string|密钥创建时间| -->
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"accuracy": "20",
|
||||
"code_type": "C",
|
||||
"depth": "2",
|
||||
"detect_flag": "快速-组件级",
|
||||
"detect_rule": "快速-组件级,2,20,,开源软件,50,10",
|
||||
"detect_startdate": "2022-05-10 15:59:46 ",
|
||||
"detect_status": "fail",
|
||||
"detectflag": "快速-组件级",
|
||||
"fail_reason": "Invalid package type",
|
||||
"file_name": "many_branch.zip",
|
||||
"license_process": "100",
|
||||
"licenseparam": "开源软件",
|
||||
"package_type": "",
|
||||
"product_name": "84727546110",
|
||||
"project_id": "6dbc3e42-5857-4ca4-a54d-58fd9dbf6dc5",
|
||||
"sim_process": "100",
|
||||
"similarity_process": "2",
|
||||
"task_id": "15139171-091b-4316-98b1-6068970efa44",
|
||||
"totalsize": 5,
|
||||
"uid": "78",
|
||||
"vuln_process": "",
|
||||
"vulnlevel": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
|
||||
## 新建分析
|
||||
用户选择仓库分支进行代码分析的接口
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/tasks.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/traces/:owner/:repo/tasks.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/traces/:owner/:repo/tasks.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
branch_name|是 | 否| string | 分支名称 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 重新扫描
|
||||
对代码分析结果进行再次分析
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/reload_task.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/reload_task.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/reload_task.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
project_id|是 | 否| string | 代码分析结果里的project_id |
|
||||
branch_name|是 | 否| string | 分支名称 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
## 下载报告
|
||||
把代码分析的结果下载到本地
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/task_pdf.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/task_pdf.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/task_pdf.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
task_id|是 | 否| string | 代码分析结果里的task_id |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
|
@ -91,10 +91,9 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
类型|说明
|
||||
--------- | -----------
|
||||
|IssueAssigned | 有新指派给我的疑修 |
|
||||
|IssueAssignerExpire | 我负责的疑修截止日期到达最后一天 |
|
||||
|IssueExpire | 我创建或负责的疑修截止日期到达最后一天 |
|
||||
|IssueAtme | 在疑修中@我 |
|
||||
|IssueChanged | 我创建或负责的疑修状态变更 |
|
||||
|IssueCreatorExpire | 我创建的疑修截止日期到达最后一天 |
|
||||
|IssueDeleted | 我创建或负责的疑修删除 |
|
||||
|IssueJournal | 我创建或负责的疑修有新的评论 |
|
||||
|LoginIpTip | 登录异常提示 |
|
||||
|
|
@ -109,6 +108,7 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
|ProjectLeft | 账号被移出项目 |
|
||||
|ProjectMemberJoined | 我管理的仓库有成员加入 |
|
||||
|ProjectMemberLeft | 我管理的仓库有成员移出 |
|
||||
|ProjectMilestoneCompleted | 我管理的仓库有里程碑完成度100% |
|
||||
|ProjectMilestone | 我管理的仓库有新的里程碑 |
|
||||
|ProjectPraised | 我管理的仓库被点赞 |
|
||||
|ProjectPullRequest | 我管理/关注的仓库有新的合并请求 |
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class BaseForm
|
|||
|
||||
def check_verifi_code(verifi_code, code)
|
||||
code = strip(code)
|
||||
# return if code == "123123" # TODO 万能验证码,用于测试
|
||||
return if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
||||
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class Gitea::User::UpdateForm
|
|||
|
||||
attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local,
|
||||
:full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login,
|
||||
:source_id, :website
|
||||
:source_id, :website, :new_name
|
||||
|
||||
validates :username, presence: true
|
||||
validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
class Issues::CreateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
attr_accessor :subject, :description
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
|
||||
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
class Issues::UpdateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
attr_accessor :subject, :description
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class Journals::CreateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :notes
|
||||
|
||||
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
class Journals::UpdateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :notes
|
||||
|
||||
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
end
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
class Projects::UpdateForm < BaseForm
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier, :project_name
|
||||
validates :name, presence: true
|
||||
validates :name, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
|
|
@ -10,6 +10,7 @@ class Projects::UpdateForm < BaseForm
|
|||
check_project_language(project_language_id)
|
||||
|
||||
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
|
||||
check_project_name(user_id, name) unless name.blank? || name == project_name
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,28 +3,40 @@ module Register
|
|||
include ActiveModel::Model
|
||||
|
||||
private
|
||||
def check_login(login)
|
||||
def check_login(login, user=nil)
|
||||
login = strip(login)
|
||||
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
||||
|
||||
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
||||
raise LoginError, '登录名已被使用' if login_exist
|
||||
if user.present?
|
||||
raise LoginError, '登录名已被使用' if login_exist && login != user&.login
|
||||
else
|
||||
raise LoginError, '登录名已被使用' if login_exist
|
||||
end
|
||||
end
|
||||
|
||||
def check_mail(mail)
|
||||
def check_mail(mail, user=nil)
|
||||
mail = strip(mail)
|
||||
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
||||
|
||||
mail_exist = Owner.exists?(mail: mail)
|
||||
raise EmailError, '邮箱已被使用' if mail_exist
|
||||
if user.present?
|
||||
raise EmailError, '邮箱已被使用' if mail_exist && mail != user&.mail
|
||||
else
|
||||
raise EmailError, '邮箱已被使用' if mail_exist
|
||||
end
|
||||
end
|
||||
|
||||
def check_phone(phone)
|
||||
def check_phone(phone, user=nil)
|
||||
phone = strip(phone)
|
||||
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
||||
|
||||
phone_exist = Owner.exists?(phone: phone)
|
||||
raise PhoneError, '手机号已被使用' if phone_exist
|
||||
if user.present?
|
||||
raise PhoneError, '手机号已被使用' if phone_exist && phone != user&.phone
|
||||
else
|
||||
raise PhoneError, '手机号已被使用' if phone_exist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ module Register
|
|||
validate :check!
|
||||
|
||||
def check!
|
||||
Rails.logger.info "Register::Form params: code: #{code}; login: #{login};
|
||||
namespace: #{namespace}; password: #{password}; password_confirmation: #{password_confirmation}"
|
||||
|
||||
Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}"
|
||||
type = phone_mail_type(strip(login))
|
||||
db_verifi_code =
|
||||
db_verifi_code =
|
||||
if type == 1
|
||||
check_phone(login)
|
||||
VerificationCode.where(phone: login, code: code, code_type: 1).last
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
module Register
|
||||
class LoginCheckColumnsForm < Register::BaseForm
|
||||
attr_accessor :type, :value, :user
|
||||
|
||||
validates :type, presence: true, numericality: true
|
||||
validates :value, presence: true
|
||||
validate :check!
|
||||
|
||||
def check!
|
||||
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||
case strip(type).to_i
|
||||
when 1 then check_login(strip(value), user)
|
||||
when 2 then check_mail(strip(value), user)
|
||||
when 3 then check_phone(strip(value), user)
|
||||
else raise("type值无效")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,477 +1,486 @@
|
|||
# 所有的方法请按首字母的顺序依次列出
|
||||
module ApplicationHelper
|
||||
include Gitlink::I18n
|
||||
include GitHelper
|
||||
|
||||
ONE_MINUTE = 60 * 1000
|
||||
ONE_HOUR = 60 * ONE_MINUTE
|
||||
ONE_DAY = 24 * ONE_HOUR
|
||||
ONE_MONTH = 30 * ONE_DAY
|
||||
|
||||
ONE_YEAR = 12 * ONE_MONTH
|
||||
|
||||
# 全局参数配置
|
||||
def edu_setting name
|
||||
EduSetting.get(name)
|
||||
end
|
||||
|
||||
# xss共计问题
|
||||
def content_safe content
|
||||
tags = %w(
|
||||
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
||||
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
||||
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
||||
tfoot th thead time tr u ul var wbr div span
|
||||
)
|
||||
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
||||
sanitize content, tags: tags, attributes: attributes
|
||||
end
|
||||
|
||||
def graduation_navigation graduation
|
||||
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
||||
end
|
||||
|
||||
def graduation_navigation_id course
|
||||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||
end
|
||||
|
||||
# git用户
|
||||
# git用户命名规则:login+"@educoder.net"
|
||||
def git_username(email)
|
||||
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
||||
end
|
||||
|
||||
# 不同的类型扩展不同的目录
|
||||
def relative_path
|
||||
"avatars"
|
||||
end
|
||||
|
||||
def replace_bytes_to_b(size_string)
|
||||
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
||||
end
|
||||
|
||||
def storage_path
|
||||
File.join(Rails.root, "public", "images", relative_path)
|
||||
end
|
||||
|
||||
# 推荐实训
|
||||
def recommend_shixun(shixun)
|
||||
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
||||
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
||||
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
||||
|
||||
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
||||
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
||||
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
||||
|
||||
end
|
||||
|
||||
# shixun开启挑战对应的行为名及url
|
||||
def task_operation_url current_myshixun, shixun
|
||||
if current_myshixun.blank?
|
||||
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
||||
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
||||
else
|
||||
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
||||
if current_myshixun.status == 1
|
||||
name = "查看实战"
|
||||
else
|
||||
name = "继续挑战"
|
||||
end
|
||||
url = identifier
|
||||
end
|
||||
[name, url]
|
||||
end
|
||||
|
||||
# 获取当前时间
|
||||
def time_from_now(time)
|
||||
if String === time
|
||||
time = Time.parse(time)
|
||||
end
|
||||
|
||||
lastUpdateTime = time.to_i*1000
|
||||
|
||||
currentTime = Time.now.to_i*1000
|
||||
timePassed = currentTime - lastUpdateTime
|
||||
timeIntoFormat = 0
|
||||
updateAtValue = ""
|
||||
if timePassed < 0
|
||||
updateAtValue = "刚刚"
|
||||
elsif timePassed < ONE_MINUTE
|
||||
updateAtValue = "1分钟前"
|
||||
elsif timePassed < ONE_HOUR
|
||||
timeIntoFormat = timePassed / ONE_MINUTE
|
||||
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
||||
elsif (timePassed < ONE_DAY)
|
||||
timeIntoFormat = timePassed / ONE_HOUR
|
||||
updateAtValue = timeIntoFormat.to_s + "小时前"
|
||||
elsif (timePassed < ONE_MONTH)
|
||||
timeIntoFormat = timePassed / ONE_DAY
|
||||
updateAtValue = timeIntoFormat.to_s + "天前"
|
||||
elsif (timePassed < ONE_YEAR)
|
||||
timeIntoFormat = timePassed / ONE_MONTH
|
||||
updateAtValue = timeIntoFormat.to_s + "个月前"
|
||||
else
|
||||
timeIntoFormat = timePassed / ONE_YEAR
|
||||
updateAtValue = timeIntoFormat.to_s + "年前"
|
||||
end
|
||||
updateAtValue
|
||||
end
|
||||
|
||||
# 计算到结束还有多长时间 **天**小时**分
|
||||
def how_much_time(time)
|
||||
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
||||
''
|
||||
else
|
||||
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
||||
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
||||
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
||||
end
|
||||
end
|
||||
|
||||
def format_time(time)
|
||||
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
||||
end
|
||||
|
||||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
source.get_letter_avatar_url
|
||||
end
|
||||
end
|
||||
|
||||
# 主页banner图
|
||||
def banner_img(source_type)
|
||||
if File.exist?(disk_filename(source_type, "banner"))
|
||||
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
||||
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
||||
end
|
||||
end
|
||||
|
||||
def disk_filename(source_type,source_id,image_file=nil)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}")
|
||||
end
|
||||
|
||||
def disk_auth_filename(source_type, source_id, type)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def disk_real_name_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def auth_file_url(source_type, source_id, type)
|
||||
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def real_name_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def disk_professional_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def professional_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def shixun_url_to_avatar(shixun)
|
||||
if File.exist?(disk_filename(shixun.class, shixun.id))
|
||||
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
||||
else
|
||||
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
# 选用实训的学校情况
|
||||
def school_user_detail shixun
|
||||
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
||||
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
||||
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
||||
school_size = school_ids.size
|
||||
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
||||
end
|
||||
|
||||
# 普通/分组 作业作品状态数组
|
||||
def student_work_status homework, user_id, course, work
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting user_id, true
|
||||
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
||||
late_time = homework.late_time || course.end_date
|
||||
|
||||
if course.is_end && work && work.work_status > 0
|
||||
status << "查看作品"
|
||||
elsif !course.is_end
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
||||
# 作业未截止时
|
||||
if homework_setting.end_time > Time.now
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 补交阶段
|
||||
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 匿评阶段
|
||||
elsif work.work_status != 0
|
||||
if homework.homework_detail_manual.comment_status == 3
|
||||
work_ids = homework.student_works.has_committed.pluck(:id)
|
||||
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
||||
status << "匿评作品"
|
||||
end
|
||||
end
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commit_des_status work, homework
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting work.user_id
|
||||
|
||||
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
||||
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
||||
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
||||
work.description.present? ? status << "修改总结" : status << "提交总结"
|
||||
end
|
||||
end
|
||||
|
||||
def download_url attachment,options={}
|
||||
attachment_path(attachment,options)
|
||||
end
|
||||
|
||||
# 耗时:天、小时、分、秒
|
||||
# 小于1分钟则不显示
|
||||
def game_spend_time time
|
||||
day = time / 86400
|
||||
hour = time % (24*60*60) / (60*60)
|
||||
min = time % (24*60*60) % (60*60) / 60
|
||||
sec = time % (24*60*60) % (60*60) % 60
|
||||
if day < 1
|
||||
if hour < 1
|
||||
if min < 1
|
||||
if sec < 1
|
||||
time = "--"
|
||||
else
|
||||
time = "#{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
def absolute_path(file_path)
|
||||
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
||||
end
|
||||
|
||||
def file_root_directory
|
||||
Rails.root.to_s
|
||||
end
|
||||
|
||||
def file_storage_directory
|
||||
file_root_directory + edu_setting('attachment_folder')
|
||||
end
|
||||
|
||||
def local_path(file)
|
||||
File.join(file.disk_directory, file.disk_filename)
|
||||
end
|
||||
|
||||
def update_downloads(file)
|
||||
file.update_attributes(:downloads => file.downloads + 1)
|
||||
end
|
||||
|
||||
# 项目信息,
|
||||
def project_info work, current_user, course_identity
|
||||
project = work.project
|
||||
if project
|
||||
if project.status == 9
|
||||
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
||||
else
|
||||
project_score = project.project_score
|
||||
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
||||
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
else
|
||||
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
end
|
||||
end
|
||||
else
|
||||
{id: -1, name: "--", title: "--"}
|
||||
end
|
||||
end
|
||||
|
||||
def message_content(content)
|
||||
content = (strip_html content).strip
|
||||
content = content.gsub(/\s+/, " ")
|
||||
if content.gsub(" ", "") == ""
|
||||
content = "[非文本消息]"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def strip_html(text, len=0, endss="...")
|
||||
ss = ""
|
||||
if !text.nil? && text.length>0
|
||||
ss=text.gsub(/<\/?.*?>/, '').strip
|
||||
ss = ss.gsub(/ */, '')
|
||||
ss = ss.gsub(/\r\n/,'') #新增
|
||||
ss = ss.gsub(/\n/,'') #新增
|
||||
if len > 0 && ss.length > len
|
||||
ss = ss[0, len] + endss
|
||||
elsif len > 0 && ss.length <= len
|
||||
ss = ss
|
||||
#ss = truncate(ss, :length => len)
|
||||
end
|
||||
end
|
||||
ss
|
||||
end
|
||||
|
||||
def strip_export_title(content)
|
||||
con_ = ""
|
||||
if content.length > 0
|
||||
con_ = strip_tags(content)
|
||||
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
||||
end
|
||||
con_
|
||||
end
|
||||
|
||||
def pdf_load_sources(*arg)
|
||||
arr = arg.map do |path|
|
||||
content_tag(:script) do
|
||||
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
raw arr.join('')
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 导出pdf时,转化markdown为html
|
||||
def to_markdown(text,origin_url)
|
||||
return nil if text.blank?
|
||||
options = {
|
||||
:autolink => true,
|
||||
:no_intra_emphasis => true,
|
||||
:fenced_code_blocks => true,
|
||||
:lax_html_blocks => true,
|
||||
:strikethrough => true,
|
||||
:superscript => false,
|
||||
:tables => true
|
||||
}
|
||||
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
||||
m_t = markdown.render(text)
|
||||
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
||||
end
|
||||
|
||||
def shixun_status_class(shixun)
|
||||
case shixun.status
|
||||
when 0 then 'text-info'
|
||||
when 1 then 'text-warning'
|
||||
when 2 then 'text-success'
|
||||
when 3 then 'text-secondary'
|
||||
end
|
||||
end
|
||||
|
||||
def render_unix_time(date)
|
||||
date.to_time.to_i
|
||||
end
|
||||
|
||||
def find_user_by_login(login)
|
||||
User.find_by_login login
|
||||
end
|
||||
|
||||
def find_user_by_login_and_mail(login, mail)
|
||||
User.find_by(login: login, mail: mail)
|
||||
end
|
||||
|
||||
def find_user_by_gitea_uid(gitea_uid)
|
||||
User.find_by(gitea_uid: gitea_uid)
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache(login, email)
|
||||
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache_by_id(id)
|
||||
$redis_cache.hgetall("v2-owner-common:#{id}")
|
||||
end
|
||||
|
||||
def render_base64_decoded(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64 str
|
||||
end
|
||||
|
||||
def render_admin_statistics_item
|
||||
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
||||
|
||||
return if url.blank?
|
||||
content_tag(:li) do
|
||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||
end
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
def strip(str)
|
||||
str.to_s.strip.presence
|
||||
end
|
||||
|
||||
end
|
||||
# 所有的方法请按首字母的顺序依次列出
|
||||
module ApplicationHelper
|
||||
include Gitlink::I18n
|
||||
include GitHelper
|
||||
|
||||
ONE_MINUTE = 60 * 1000
|
||||
ONE_HOUR = 60 * ONE_MINUTE
|
||||
ONE_DAY = 24 * ONE_HOUR
|
||||
ONE_MONTH = 30 * ONE_DAY
|
||||
|
||||
ONE_YEAR = 12 * ONE_MONTH
|
||||
|
||||
# 全局参数配置
|
||||
def edu_setting name
|
||||
EduSetting.get(name)
|
||||
end
|
||||
|
||||
# xss共计问题
|
||||
def content_safe content
|
||||
tags = %w(
|
||||
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
||||
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
||||
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
||||
tfoot th thead time tr u ul var wbr div span
|
||||
)
|
||||
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
||||
sanitize content, tags: tags, attributes: attributes
|
||||
end
|
||||
|
||||
def graduation_navigation graduation
|
||||
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
||||
end
|
||||
|
||||
def graduation_navigation_id course
|
||||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||
end
|
||||
|
||||
# git用户
|
||||
# git用户命名规则:login+"@educoder.net"
|
||||
def git_username(email)
|
||||
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
||||
end
|
||||
|
||||
# 不同的类型扩展不同的目录
|
||||
def relative_path
|
||||
"avatars"
|
||||
end
|
||||
|
||||
def replace_bytes_to_b(size_string)
|
||||
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
||||
end
|
||||
|
||||
def storage_path
|
||||
File.join(Rails.root, "public", "images", relative_path)
|
||||
end
|
||||
|
||||
# 推荐实训
|
||||
def recommend_shixun(shixun)
|
||||
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
||||
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
||||
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
||||
|
||||
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
||||
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
||||
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
||||
|
||||
end
|
||||
|
||||
# shixun开启挑战对应的行为名及url
|
||||
def task_operation_url current_myshixun, shixun
|
||||
if current_myshixun.blank?
|
||||
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
||||
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
||||
else
|
||||
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
||||
if current_myshixun.status == 1
|
||||
name = "查看实战"
|
||||
else
|
||||
name = "继续挑战"
|
||||
end
|
||||
url = identifier
|
||||
end
|
||||
[name, url]
|
||||
end
|
||||
|
||||
# 获取当前时间
|
||||
def time_from_now(time)
|
||||
if String === time
|
||||
time = Time.parse(time)
|
||||
end
|
||||
|
||||
lastUpdateTime = time.to_i*1000
|
||||
|
||||
currentTime = Time.now.to_i*1000
|
||||
timePassed = currentTime - lastUpdateTime
|
||||
timeIntoFormat = 0
|
||||
updateAtValue = ""
|
||||
if timePassed < 0
|
||||
updateAtValue = "刚刚"
|
||||
elsif timePassed < ONE_MINUTE
|
||||
updateAtValue = "1分钟前"
|
||||
elsif timePassed < ONE_HOUR
|
||||
timeIntoFormat = timePassed / ONE_MINUTE
|
||||
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
||||
elsif (timePassed < ONE_DAY)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_HOUR).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "小时前"
|
||||
elsif (timePassed < ONE_MONTH)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_DAY).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "天前"
|
||||
elsif (timePassed < ONE_YEAR)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_MONTH).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "个月前"
|
||||
else
|
||||
timeIntoFormat = timePassed / ONE_YEAR
|
||||
updateAtValue = timeIntoFormat.to_s + "年前"
|
||||
end
|
||||
updateAtValue
|
||||
end
|
||||
|
||||
# 计算到结束还有多长时间 **天**小时**分
|
||||
def how_much_time(time)
|
||||
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
||||
''
|
||||
else
|
||||
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
||||
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
||||
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
||||
end
|
||||
end
|
||||
|
||||
def format_time(time)
|
||||
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
||||
end
|
||||
|
||||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
source.get_letter_avatar_url
|
||||
end
|
||||
end
|
||||
|
||||
def url_to_avatar_with_platform_url(source)
|
||||
platform_url = Rails.application.config_for(:configuration)['platform_url']
|
||||
if platform_url
|
||||
return Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(source).to_s
|
||||
else
|
||||
return url_to_avatar(source).to_s
|
||||
end
|
||||
end
|
||||
|
||||
# 主页banner图
|
||||
def banner_img(source_type)
|
||||
if File.exist?(disk_filename(source_type, "banner"))
|
||||
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
||||
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
||||
end
|
||||
end
|
||||
|
||||
def disk_filename(source_type,source_id,image_file=nil)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}")
|
||||
end
|
||||
|
||||
def disk_auth_filename(source_type, source_id, type)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def disk_real_name_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def auth_file_url(source_type, source_id, type)
|
||||
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def real_name_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def disk_professional_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def professional_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def shixun_url_to_avatar(shixun)
|
||||
if File.exist?(disk_filename(shixun.class, shixun.id))
|
||||
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
||||
else
|
||||
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
# 选用实训的学校情况
|
||||
def school_user_detail shixun
|
||||
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
||||
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
||||
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
||||
school_size = school_ids.size
|
||||
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
||||
end
|
||||
|
||||
# 普通/分组 作业作品状态数组
|
||||
def student_work_status homework, user_id, course, work
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting user_id, true
|
||||
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
||||
late_time = homework.late_time || course.end_date
|
||||
|
||||
if course.is_end && work && work.work_status > 0
|
||||
status << "查看作品"
|
||||
elsif !course.is_end
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
||||
# 作业未截止时
|
||||
if homework_setting.end_time > Time.now
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 补交阶段
|
||||
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 匿评阶段
|
||||
elsif work.work_status != 0
|
||||
if homework.homework_detail_manual.comment_status == 3
|
||||
work_ids = homework.student_works.has_committed.pluck(:id)
|
||||
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
||||
status << "匿评作品"
|
||||
end
|
||||
end
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commit_des_status work, homework
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting work.user_id
|
||||
|
||||
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
||||
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
||||
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
||||
work.description.present? ? status << "修改总结" : status << "提交总结"
|
||||
end
|
||||
end
|
||||
|
||||
def download_url attachment,options={}
|
||||
attachment_path(attachment,options)
|
||||
end
|
||||
|
||||
# 耗时:天、小时、分、秒
|
||||
# 小于1分钟则不显示
|
||||
def game_spend_time time
|
||||
day = time / 86400
|
||||
hour = time % (24*60*60) / (60*60)
|
||||
min = time % (24*60*60) % (60*60) / 60
|
||||
sec = time % (24*60*60) % (60*60) % 60
|
||||
if day < 1
|
||||
if hour < 1
|
||||
if min < 1
|
||||
if sec < 1
|
||||
time = "--"
|
||||
else
|
||||
time = "#{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
def absolute_path(file_path)
|
||||
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
||||
end
|
||||
|
||||
def file_root_directory
|
||||
Rails.root.to_s
|
||||
end
|
||||
|
||||
def file_storage_directory
|
||||
file_root_directory + edu_setting('attachment_folder')
|
||||
end
|
||||
|
||||
def local_path(file)
|
||||
File.join(file.disk_directory, file.disk_filename)
|
||||
end
|
||||
|
||||
def update_downloads(file)
|
||||
file.update_attributes(:downloads => file.downloads + 1)
|
||||
end
|
||||
|
||||
# 项目信息,
|
||||
def project_info work, current_user, course_identity
|
||||
project = work.project
|
||||
if project
|
||||
if project.status == 9
|
||||
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
||||
else
|
||||
project_score = project.project_score
|
||||
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
||||
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
else
|
||||
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
end
|
||||
end
|
||||
else
|
||||
{id: -1, name: "--", title: "--"}
|
||||
end
|
||||
end
|
||||
|
||||
def message_content(content)
|
||||
content = (strip_html content).strip
|
||||
content = content.gsub(/\s+/, " ")
|
||||
if content.gsub(" ", "") == ""
|
||||
content = "[非文本消息]"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def strip_html(text, len=0, endss="...")
|
||||
ss = ""
|
||||
if !text.nil? && text.length>0
|
||||
ss=text.gsub(/<\/?.*?>/, '').strip
|
||||
ss = ss.gsub(/ */, '')
|
||||
ss = ss.gsub(/\r\n/,'') #新增
|
||||
ss = ss.gsub(/\n/,'') #新增
|
||||
if len > 0 && ss.length > len
|
||||
ss = ss[0, len] + endss
|
||||
elsif len > 0 && ss.length <= len
|
||||
ss = ss
|
||||
#ss = truncate(ss, :length => len)
|
||||
end
|
||||
end
|
||||
ss
|
||||
end
|
||||
|
||||
def strip_export_title(content)
|
||||
con_ = ""
|
||||
if content.length > 0
|
||||
con_ = strip_tags(content)
|
||||
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
||||
end
|
||||
con_
|
||||
end
|
||||
|
||||
def pdf_load_sources(*arg)
|
||||
arr = arg.map do |path|
|
||||
content_tag(:script) do
|
||||
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
raw arr.join('')
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 导出pdf时,转化markdown为html
|
||||
def to_markdown(text,origin_url)
|
||||
return nil if text.blank?
|
||||
options = {
|
||||
:autolink => true,
|
||||
:no_intra_emphasis => true,
|
||||
:fenced_code_blocks => true,
|
||||
:lax_html_blocks => true,
|
||||
:strikethrough => true,
|
||||
:superscript => false,
|
||||
:tables => true
|
||||
}
|
||||
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
||||
m_t = markdown.render(text)
|
||||
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
||||
end
|
||||
|
||||
def shixun_status_class(shixun)
|
||||
case shixun.status
|
||||
when 0 then 'text-info'
|
||||
when 1 then 'text-warning'
|
||||
when 2 then 'text-success'
|
||||
when 3 then 'text-secondary'
|
||||
end
|
||||
end
|
||||
|
||||
def render_unix_time(date)
|
||||
date.to_time.to_i
|
||||
end
|
||||
|
||||
def find_user_by_login(login)
|
||||
User.find_by_login login
|
||||
end
|
||||
|
||||
def find_user_by_login_and_mail(login, mail)
|
||||
User.find_by(login: login, mail: mail)
|
||||
end
|
||||
|
||||
def find_user_by_gitea_uid(gitea_uid)
|
||||
User.find_by(gitea_uid: gitea_uid)
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache(login, email)
|
||||
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache_by_id(id)
|
||||
$redis_cache.hgetall("v2-owner-common:#{id}")
|
||||
end
|
||||
|
||||
def render_base64_decoded(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64 str
|
||||
end
|
||||
|
||||
def render_admin_statistics_item
|
||||
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
||||
|
||||
return if url.blank?
|
||||
content_tag(:li) do
|
||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||
end
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
def strip(str)
|
||||
str.to_s.strip.presence
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module RepositoriesHelper
|
|||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
|
|
@ -22,7 +22,7 @@ module RepositoriesHelper
|
|||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase)
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
|
|
@ -36,7 +36,6 @@ module RepositoriesHelper
|
|||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
Rails.logger.info author_json['Email']
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
|
|
@ -45,36 +44,56 @@ module RepositoriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref)
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_images = ss + ss_src
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
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
|
||||
new_r_content = r_content
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
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 = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
content = content.gsub(/#{r_content}/, new_r_content)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -84,6 +103,46 @@ module RepositoriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
|
||||
if image_type?(ext) || download_type(ext)
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub(s[0], "/#{s_content}")
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
def render_format_time_with_unix(unix_time)
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
|
|
@ -94,10 +153,21 @@ module RepositoriesHelper
|
|||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{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, owner, repo, ref)
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
class Admins::NewImportUserFromExcel < BaseImportXlsx
|
||||
UserData = Struct.new(:login, :email, :password, :nickname)
|
||||
|
||||
def read_each(&block)
|
||||
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||
data = row.map(&method(:cell_value))[0..3]
|
||||
block.call UserData.new(*data)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def cell_value(obj)
|
||||
obj&.cell_value
|
||||
end
|
||||
end
|
||||
|
|
@ -13,7 +13,7 @@ module Gitea
|
|||
end
|
||||
|
||||
def success?
|
||||
@error.nil?
|
||||
@error.nil? && @result[:status].to_s == "success"
|
||||
end
|
||||
|
||||
def result
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ class CacheAsyncClearJob < ApplicationJob
|
|||
Cache::V2::ProjectCommonService.new(id).clear
|
||||
when "owner_common_service"
|
||||
Cache::V2::OwnnerCommonService.new(id).clear
|
||||
when "project_rank_service"
|
||||
Cache::V2::ProjectRankService.new(id).clear
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,8 +3,7 @@ class DelayExpiredIssueJob < ApplicationJob
|
|||
|
||||
def perform
|
||||
Issue.where(due_date: Date.today + 1.days).find_each do |issue|
|
||||
SendTemplateMessageJob.perform_later('IssueAssignerExpire', issue.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,6 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueAssignerExpire'
|
||||
issue_id = args[0]
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue.present?
|
||||
receivers = User.where(id: issue&.assigned_to_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueAssignerExpire.get_message_content(receivers, issue)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
|
||||
when 'IssueAtme'
|
||||
receivers, operator_id, issue_id = args[0], args[1], args[2]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -52,13 +45,17 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::IssueChanged.get_email_message_content(receiver, operator, issue, change_params)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueCreatorExpire'
|
||||
when 'IssueExpire'
|
||||
issue_id = args[0]
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue.present?
|
||||
receivers = User.where(id: issue&.author_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue)
|
||||
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id])
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueExpire.get_message_content(receivers, issue)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::IssueExpire.get_email_message_content(receiver, issue)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueDeleted'
|
||||
operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -94,6 +91,14 @@ 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 'ProjectForked'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
return unless operator.present? && project.present?
|
||||
receivers = project&.all_managers.where.not(id: operator&.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectForked.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectIssue'
|
||||
operator_id, issue_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -163,6 +168,37 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectMilestoneCompleted'
|
||||
milestone_id = args[0]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
return unless milestone.present? && milestone&.project.present?
|
||||
receivers = milestone&.project&.all_managers
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneCompleted.get_message_content(receivers, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestoneCompleted.get_email_message_content(receiver, milestone)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectMilestone'
|
||||
milestone_id, operator_id = args[0], args[1]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
operator = User.find_by_id(operator_id)
|
||||
return unless milestone.present? && milestone&.project.present? && operator.present?
|
||||
receivers = milestone&.project&.all_managers.where.not(id: operator_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestone.get_message_content(receivers, operator, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectPraised'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
return unless operator.present? && project.present?
|
||||
receivers = project&.all_managers.where.not(id: operator&.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectPraised.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectPullRequest'
|
||||
operator_id, pull_request_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -290,6 +326,30 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
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
|
||||
when 'CompetitionBegin'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionBegin.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
when 'CompetitionReview'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionReview.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
when 'CompetitionResult'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionResult.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
module CustomRegexp
|
||||
PHONE = /1\d{10}/
|
||||
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
||||
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
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/
|
||||
|
|
@ -11,5 +11,5 @@ module CustomRegexp
|
|||
|
||||
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
|
||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
|
||||
MD_REGEX = /^.+(\.[m|M][d|D])$/
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Notice
|
|||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
notice_config = config[:notice].symbolize_keys!
|
||||
raise 'notice config missing' if notice_config.blank?
|
||||
rescue => exception
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
module Trace
|
||||
class << self
|
||||
def trace_config
|
||||
trace_config = {}
|
||||
|
||||
begin
|
||||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
trace_config = config[:trace].symbolize_keys!
|
||||
raise 'trace config missing' if trace_config.blank?
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
|
||||
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
|
||||
trace_config = {}
|
||||
end
|
||||
|
||||
trace_config
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,10 +5,10 @@ class Ci::Repo < Ci::RemoteBase
|
|||
has_one :perm, foreign_key: :perm_repo_uid
|
||||
has_many :builds, foreign_key: :build_repo_id, dependent: :destroy
|
||||
|
||||
def self.find_with_namespace(namespace_path, identifier)
|
||||
def self.find_with_namespace(namespace_path, identifier, user_login)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Ci::User.find_by_user_login namespace_path
|
||||
user_login = user_login || namespace_path
|
||||
user = Ci::User.find_by(user_login: user_login)
|
||||
repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first
|
||||
|
||||
[user, repo]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module Matchable
|
|||
scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? }
|
||||
scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? }
|
||||
scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) }
|
||||
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "%#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
class ForkUser < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id
|
||||
belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id
|
||||
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class Issue < ApplicationRecord
|
|||
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
|
||||
scope :closed, ->{where(status_id: 5)}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
after_update :change_versions_count
|
||||
after_save :change_versions_count, :send_update_message_to_notice_system
|
||||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
|
||||
|
||||
def incre_project_common
|
||||
|
|
@ -171,11 +171,25 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def change_versions_count
|
||||
if self.version.present? && self.saved_change_to_status_id?
|
||||
if self.saved_change_to_fixed_version_id?
|
||||
before_version = Version.find_by_id(self.fixed_version_id_before_last_save)
|
||||
Rails.logger.info self.fixed_version_id_before_last_save
|
||||
if before_version.present?
|
||||
Rails.logger.info self.status_id
|
||||
Rails.logger.info self.status_id_before_last_save
|
||||
# 更改前状态为完成 或者 更改前后都为完成状态
|
||||
if self.status_id_before_last_save == 5
|
||||
percent = before_version.issues_count == 0 ? 0.0 : ((before_version.closed_issues_count - 1).to_f / before_version.issues_count)
|
||||
before_version.update_attributes(closed_issues_count: (before_version.closed_issues_count - 1), percent: percent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.version.present? && (self.saved_change_to_status_id? || self.saved_change_to_fixed_version_id?)
|
||||
if self.status_id == 5
|
||||
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count + 1).to_f / self.version.issues_count)
|
||||
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count + 1), percent: percent)
|
||||
elsif self.status_id_before_last_save == 5
|
||||
elsif self.status_id_before_last_save == 5 && !self.saved_change_to_fixed_version_id?
|
||||
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count - 1).to_f / self.version.issues_count)
|
||||
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count - 1), percent: percent)
|
||||
end
|
||||
|
|
@ -183,7 +197,11 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def update_closed_issues_count_in_project!
|
||||
self.project.decrement!(:closed_issues_count)
|
||||
self.project.decrement!(:closed_issues_count) if self.status_id == 5
|
||||
end
|
||||
|
||||
def send_update_message_to_notice_system
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# journalized_id :integer default("0"), not null
|
||||
# journalized_type :string(30) default(""), not null
|
||||
# user_id :integer default("0"), not null
|
||||
# notes :text(65535)
|
||||
# notes :text(4294967295)
|
||||
# created_on :datetime not null
|
||||
# private_notes :boolean default("0"), not null
|
||||
# parent_id :integer
|
||||
|
|
|
|||
|
|
@ -13,61 +13,72 @@
|
|||
#
|
||||
|
||||
class MessageTemplate < ApplicationRecord
|
||||
PLATFORM = 'GitLink'
|
||||
|
||||
def self.build_init_data
|
||||
MessageTemplate::IssueAssignerExpire.destroy_all
|
||||
MessageTemplate::IssueCreatorExpire.destroy_all
|
||||
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::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修")
|
||||
self.create(type: 'MessageTemplate::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: "#{PLATFORM}: 疑修 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_expire.html")
|
||||
self.create(type: 'MessageTemplate::IssueExpire', sys_notice: '疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: 疑修截止日期到达最后一天")
|
||||
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::IssueDeleted', sys_notice: '{nickname}已将疑修 <b>{title}</b> 删除', email: email_html, email_title: "#{PLATFORM}: 疑修 {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} 组织')
|
||||
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {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} 组织')
|
||||
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {organization} 组织")
|
||||
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}')
|
||||
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库 <b>{nickname2}/{repository}</b> 到 <b>{nickname1}/{repository}</b>', 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: "#{PLATFORM}: {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} 项目')
|
||||
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {repository} 项目")
|
||||
email_html = File.read("#{email_template_html_dir}/project_left.html")
|
||||
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {repository} 项目')
|
||||
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {repository} 项目")
|
||||
email_html = File.read("#{email_template_html_dir}/project_member_joined.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已加入项目 {nickname2}/{repository}')
|
||||
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 已加入项目 {nickname2}/{repository}")
|
||||
email_html = File.read("#{email_template_html_dir}/project_member_left.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已被移出项目 {nickname2}/{repository}')
|
||||
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 已被移出项目 {nickname2}/{repository}")
|
||||
email_html = File.read("#{email_template_html_dir}/project_milestone.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{name}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑")
|
||||
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
|
||||
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求')
|
||||
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求")
|
||||
email_html = File.read("#{email_template_html_dir}/project_role.html")
|
||||
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '#{PLATFORM}: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_setting_changed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: 'GitLink: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改')
|
||||
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: "#{PLATFORM}: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改")
|
||||
self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求')
|
||||
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求")
|
||||
self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_changed.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_closed.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '')
|
||||
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}')
|
||||
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {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}')
|
||||
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: "#{PLATFORM}: 在 {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}')
|
||||
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
|
||||
|
||||
# 竞赛通知
|
||||
self.create(type: 'MessageTemplate::CompetitionBegin', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入比赛进行阶段,可在此期间提交作品', notification_url: '{to_url}')
|
||||
self.create(type: 'MessageTemplate::CompetitionResult', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入成绩公示阶段,可查看排行榜信息', notification_url: '{to_url}')
|
||||
self.create(type: 'MessageTemplate::CompetitionReview', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交', notification_url: '{to_url}')
|
||||
end
|
||||
|
||||
def self.sys_notice
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# == 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)
|
||||
#
|
||||
|
||||
# 报名的竞赛进入比赛进行阶段
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛已进入比赛进行阶段
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 已进入比赛进行阶段,可在此阶段提交作品
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 已进入比赛进行阶段,可在此期间提交作品
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionBegin < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.to_s.gsub('{competition_name}', competition&.name), notification_url.to_s.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
# rescue
|
||||
# return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# == 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)
|
||||
#
|
||||
|
||||
# 报名的竞赛进入成绩公示阶段
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛已进入成绩公示阶段
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 已进入成绩公示阶段,可查看排行榜信息
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 已进入成绩公示阶段,可查看排行榜信息
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionResult < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
rescue
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# == 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)
|
||||
#
|
||||
|
||||
# 报名的竞赛比赛结束时间临近
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛阶段处于比赛进行中,且距比赛结束日期仅剩3天
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionReview < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
rescue
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -53,6 +53,7 @@ class MessageTemplate::IssueAssigned < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
|
||||
end
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,29 +1,3 @@
|
|||
# == 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::IssueCreatorExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
def self.get_message_content(receivers, issue)
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{title}', issue&.subject)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::IssueDeleted < MessageTemplate
|
|||
content.gsub!('{login}', operator&.login)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue_title)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
# == 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::IssueExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
def self.get_message_content(receivers, issue)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueExpire"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["CreateOrAssign::IssueExpire"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{title}', issue&.subject)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueExpire.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, issue)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["CreateOrAssign::IssueExpire"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["CreateOrAssign::IssueExpire"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueExpire.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::OrganizationJoined < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::OrganizationLeft < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class MessageTemplate::OrganizationRole < MessageTemplate
|
|||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{role}', role)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,11 +12,21 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库被复刻
|
||||
# 我管理的仓库被复刻
|
||||
class MessageTemplate::ProjectForked < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectForked.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, user, project)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Forked"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Forked"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
|
||||
url = notification_url.gsub('{owner}', user&.login).gsub('{identifier}', project&.identifier)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}")
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class MessageTemplate::ProjectIssue < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class MessageTemplate::ProjectJoined < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{nickname}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class MessageTemplate::ProjectLeft < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{nickname}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class MessageTemplate::ProjectMemberJoined < MessageTemplate
|
|||
content.gsub!('{nickname1}', user&.real_name)
|
||||
content.gsub!('{nickname2}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class MessageTemplate::ProjectMemberLeft < MessageTemplate
|
|||
content.gsub!('{nickname1}', user&.real_name)
|
||||
content.gsub!('{nickname2}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,14 +12,61 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库有新的里程碑
|
||||
# 我管理的仓库有新的里程碑
|
||||
class MessageTemplate::ProjectMilestone < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestone.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, operator, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Milestone"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestone.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, operator, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::Milestone"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::Milestone"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname1}', operator&.real_name)
|
||||
title.gsub!('{nickname2}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname1}', operator&.real_name)
|
||||
content.gsub!('{nickname2}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestone.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我管理的仓库有里程碑完成
|
||||
class MessageTemplate::ProjectMilestoneCompleted < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestoneCompleted.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneCompleted"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneCompleted"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneCompleted.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneCompleted"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneCompleted"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneCompleted.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -12,11 +12,21 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库被点赞
|
||||
# 我管理的仓库被点赞
|
||||
class MessageTemplate::ProjectPraised < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectPraised.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, user, project)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Praised"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Praised"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
|
||||
url = notification_url.gsub('{login}', user&.login)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectPraised.get_message_content [ERROR] #{e}")
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class MessageTemplate::ProjectPullRequest < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class MessageTemplate::ProjectRole < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{role}', role)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
navbar.gsub!('devops', '工作流')
|
||||
navbar.gsub!('versions', '里程碑')
|
||||
navbar.gsub!('resources', '资源库')
|
||||
navbar.gsub!('services', '服务')
|
||||
if change_count > 1
|
||||
content.sub!('{ifnavbar}', '<br/>')
|
||||
else
|
||||
|
|
@ -290,6 +291,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
navbar.gsub!('devops', '工作流')
|
||||
navbar.gsub!('versions', '里程碑')
|
||||
navbar.gsub!('resources', '资源库')
|
||||
navbar.gsub!('services', '服务')
|
||||
if change_count > 1
|
||||
content.sub!('{ifnavbar}', '<br/>')
|
||||
else
|
||||
|
|
@ -300,6 +302,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '')
|
||||
end
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class MessageTemplate::PullRequestAssigned < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ class MessageTemplate::PullRequestChanged < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
change_count = change_params.keys.size
|
||||
# 合并请求审查成员修改
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class MessageTemplate::PullRequestClosed < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class MessageTemplate::PullRequestMerged < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class MessageTemplate::TeamJoined < MessageTemplate
|
|||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class MessageTemplate::TeamLeft < MessageTemplate
|
|||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ class Organization < Owner
|
|||
|
||||
after_save :reset_cache_data
|
||||
|
||||
def gitea_token
|
||||
team_users.joins(:team).where(teams: {authorize: "owner"}).take&.user&.gitea_token
|
||||
end
|
||||
|
||||
def reset_cache_data
|
||||
Cache::V2::OwnerCommonService.new(self.id).reset
|
||||
end
|
||||
|
|
|
|||
|
|
@ -124,9 +124,10 @@ class Project < ApplicationRecord
|
|||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members, :reset_cache_data
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
before_destroy :decre_project_common, :decre_forked_from_project_count
|
||||
after_destroy :decre_user_statistic, :decre_platform_statistic
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :description, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
|
|
@ -150,7 +151,7 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def reset_cache_data
|
||||
CacheAsyncResetJob.perform_later("project_common_service", self.id)
|
||||
CacheAsyncResetJob.set(wait: 5.seconds).perform_later("project_common_service", self.id)
|
||||
if changes[:user_id].present?
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1}, changes[:user_id].first)
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1}, changes[:user_id].last)
|
||||
|
|
@ -163,6 +164,14 @@ class Project < ApplicationRecord
|
|||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1})
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1})
|
||||
end
|
||||
if changes[:is_public].present?
|
||||
if changes[:is_public][0] && !changes[:is_public][1]
|
||||
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
|
||||
end
|
||||
if !changes[:is_public][0] && changes[:is_public][1]
|
||||
$redis_cache.srem("v2-project-rank-deleted", self.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
class ProjectUnit < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7}
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
|
||||
|
||||
validates :unit_type, uniqueness: { scope: :project_id}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# Table name: pull_requests
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# pull_request_id :integer
|
||||
# gpid :integer
|
||||
# gitea_id :integer
|
||||
# gitea_number :integer
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
# project_id :integer
|
||||
# title :string(255)
|
||||
# milestone :integer
|
||||
# body :text(65535)
|
||||
# body :text(4294967295)
|
||||
# head :string(255)
|
||||
# base :string(255)
|
||||
# issue_id :integer
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class Site < ApplicationRecord
|
|||
# add: 添加类链接
|
||||
# personal: 个人名下类链接,
|
||||
# common: 普通链接
|
||||
enum site_type: { add: 0, personal: 1, common: 2 }
|
||||
enum site_type: { add: 0, personal: 1, common: 2, competition: 3 }
|
||||
|
||||
scope :by_search, -> (keyword){ where("name LIKE :keyword OR url LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
|
||||
scope :by_site_type, -> (site_type){ where(site_type: strip_param(site_type)) unless strip_param(site_type).blank? }
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ class Team < ApplicationRecord
|
|||
has_many :team_units, dependent: :destroy
|
||||
has_many :team_users, dependent: :destroy
|
||||
|
||||
scope :like, lambda { |keywords|
|
||||
sql = "teams.nickname LIKE :search OR teams.name LIKE :search"
|
||||
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
validates :name, uniqueness: {scope: :organization_id}
|
||||
|
||||
enum authorize: {read: 1, write: 2, admin: 3, owner: 4}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class TeamUser < ApplicationRecord
|
|||
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)
|
||||
self.find_or_create_by!(organization_id: organization_id, user_id: user_id, team_id: team_id)
|
||||
end
|
||||
|
||||
def remove_project_member
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class TemplateMessageSetting < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.build_init_data
|
||||
TemplateMessageSetting.destroy_all
|
||||
TemplateMessageSetting::CreateOrAssign.build_init_data
|
||||
TemplateMessageSetting::ManageProject.build_init_data
|
||||
TemplateMessageSetting::Normal.build_init_data
|
||||
|
|
|
|||
|
|
@ -27,5 +27,6 @@ class TemplateMessageSetting::CreateOrAssign < TemplateMessageSetting
|
|||
def self.build_init_data
|
||||
self.find_or_create_by(name: "疑修状态变更", key: "IssueChanged")
|
||||
self.find_or_create_by(name: "合并请求状态变更", key: "PullRequestChanged")
|
||||
self.find_or_create_by(name: "疑修截止日期到达最后一天", key: "IssueExpire", notification_disabled: false)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,5 +29,9 @@ class TemplateMessageSetting::ManageProject < TemplateMessageSetting
|
|||
self.find_or_create_by(name: "有新的合并请求", key: "PullRequest")
|
||||
self.find_or_create_by(name: "有成员变动", key: "Member")
|
||||
self.find_or_create_by(name: "仓库设置被更改", key: "SettingChanged")
|
||||
self.find_or_create_by(name: "被点赞", key: "Praised", notification_disabled: false, email_disabled: true)
|
||||
self.find_or_create_by(name: "被fork", key: "Forked", notification_disabled: false, email_disabled: true)
|
||||
self.find_or_create_by(name: "有新的里程碑", key: "Milestone", notification_disabled: false)
|
||||
self.find_or_create_by(name: "有里程碑已完成", key: "MilestoneCompleted", notification_disabled: false)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class Topic < ApplicationRecord
|
|||
'Topic::ExcellentProject'
|
||||
when 'experience_forum'
|
||||
'Topic::ExperienceForum'
|
||||
when "glcc_news"
|
||||
'Topic::GlccNews'
|
||||
when 'pinned_forum'
|
||||
'Topic::PinnedForum'
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue