Compare commits

...

134 Commits

Author SHA1 Message Date
zhangxunhui ba9b66df3d after merge pr 2023-02-10 16:02:28 +08:00
zhangxunhui 06a6794245 调整了blockchain api 2023-02-04 11:06:04 +08:00
zhangxunhui b1ef05e0be change reponame to identifier 2023-02-03 14:08:22 +08:00
zhangxunhui 11023cbc70 change reponame to identifier 2023-02-03 14:07:39 +08:00
zhangxunhui 7b1b03ab41 change push_activity_2_blockchain by querying projects with identifier 2023-02-03 13:19:27 +08:00
zhangxunhui 7aca2e487e change find by name to find by identifier 2023-02-03 09:23:31 +08:00
zhangxunhui 8aa844749f 对token初始化增加了非空数量的判断 2023-02-03 09:11:45 +08:00
zhangxunhui 8e89be831c 添加了对blockchain相关数据格式的检查 2023-02-02 21:31:05 +08:00
zhangxunhui 45cef457d3 修改了use blockchain的判断条件 2023-02-02 20:44:01 +08:00
zhangxunhui 015d221ccf fix bug of blockchain_balance_one_project function 2023-02-02 20:42:38 +08:00
zhangxunhui 2f6c568688 添加了对区块链项目基本信息的查询函数 2023-02-02 17:00:49 +08:00
zhangxunhui 18a900a07e 添加了对contribution perc的路由支持 2023-02-02 17:00:12 +08:00
zhangxunhui 1da1c51ba7 watchable用户贡献度的支持 2023-02-02 16:59:10 +08:00
zhangxunhui efc96f3467 添加对hovercard4proj的支持 2023-02-02 16:56:04 +08:00
zhangxunhui c5ee0e5400 添加了针对项目贡献度量的hover json请求模板 2023-02-02 16:55:25 +08:00
zhangxunhui ada6afa500 修改了contribution_perc函数,添加了对区块链确权项目的支持 2023-02-02 14:00:13 +08:00
zhangxunhui c5314f7439 添加了对区块链上仓库基本信息的查询 2023-02-02 13:59:24 +08:00
zhangxunhui bbe8407311 add contribution percentage route 2023-02-01 14:48:10 +08:00
zhangxunhui 19e7fcaafa add contribution_perc function 2023-02-01 14:47:56 +08:00
zhangxunhui 3c18d1ee9b remove duplicate render of journal 2023-02-01 14:45:04 +08:00
zhangxunhui aabf1ee50f remove render_ok after creating pull request 2023-01-31 15:29:08 +08:00
xxq250 0ca2ee7959 Merge pull request '更新了贡献确权(blockchain)相关代码' (#323) from Nigel/forgeplus:master into dev_nanda 2023-01-30 21:50:04 +08:00
zhangxunhui 6b6a4bc48e change render_okr to render_ok 2023-01-30 21:45:48 +08:00
zhangxunhui 84f094ac55 change end comment 2023-01-30 21:37:31 +08:00
zhangxunhui d9a0b34cb8 comment user.current 2023-01-30 21:35:22 +08:00
zhangxunhui 81685f88cd Merge branch 'dev_nanda' of https://gitlink.org.cn/Gitlink/forgeplus 2023-01-30 21:25:20 +08:00
zhangxunhui 79eb1b93e9 update blockchain related services 2023-01-30 21:18:11 +08:00
zhangxunhui 3f618b3a09 update application_service 2023-01-30 20:21:36 +08:00
zhangxunhui 31a3e6ccea update push_activity_2_blockchain function 2023-01-30 20:20:44 +08:00
zhangxunhui 744e0eddf8 update two services 2023-01-30 14:32:14 +08:00
zhangxunhui dc486d0a73 update issue controller for blockchain 2023-01-28 16:50:46 +08:00
zhangxunhui f0f7a1dcd7 update configuration 2023-01-28 10:14:21 +08:00
zhangxunhui 38333ab7b1 re-add the invocation of create_repo_on_blockchain when creating projects 2023-01-28 10:12:01 +08:00
xxq250 cc9f2214b5 redis对象开启 2023-01-13 11:19:53 +08:00
xxq250 8a1c8074c3 Merge pull request '修正合并错误' (#322) from Nigel/forgeplus:master into dev_nanda 2023-01-12 23:58:07 +08:00
xxq250 45d23a0aad 修正合并错误 2023-01-12 23:55:17 +08:00
xxq250 86e36263fd Merge pull request '修正合并错误' (#321) from Nigel/forgeplus:master into dev_nanda 2023-01-12 23:50:37 +08:00
xxq250 6be3fbbebd Merge pull request '合并代码错误' (#320) from Nigel/forgeplus:master into dev_nanda 2023-01-12 23:48:25 +08:00
xxq250 141414dcf2 修正合并错误 2023-01-12 23:47:43 +08:00
xxq250 422c801224 修正合并错误 2023-01-12 23:43:19 +08:00
xxq250 a8ae755af3 Merge pull request '区块链版本' (#319) from Nigel/forgeplus:master into dev_nanda 2023-01-12 21:33:25 +08:00
xxq250 78545d0f9c 配置文件更新 2023-01-12 18:05:01 +08:00
xxq250 e01e01b610 配置文件更新 2023-01-12 18:00:13 +08:00
xxq250 fc4db3bb9a Merge branch 'dev_nanda' of https://gitlink.org.cn/Gitlink/forgeplus
# Conflicts:
#	app/controllers/application_controller.rb
#	app/controllers/pull_requests_controller.rb
#	app/controllers/users_controller.rb
#	app/models/ci/user.rb
#	app/models/gitea/pull.rb
#	app/models/gitea/webhook.rb
#	app/models/gitea/webhook_task.rb
#	app/models/organization.rb
#	app/models/project.rb
#	app/models/project_category.rb
#	app/models/user.rb
#	app/services/projects/create_service.rb
2023-01-12 17:51:48 +08:00
xxq250 3612c8aa60 Merge pull request 'nanda版本' (#318) from qyzh1996/forgeplus:sponsor into dev_nanda 2023-01-12 17:40:18 +08:00
xxq250 9065029d08 Merge branch 'master' into sponsor
# Conflicts:
#	.gitignore
#	Gemfile
#	Gemfile.lock
#	app/controllers/accounts_controller.rb
#	app/controllers/application_controller.rb
#	app/controllers/compare_controller.rb
#	app/controllers/journals_controller.rb
#	app/controllers/members_controller.rb
#	app/controllers/pull_requests_controller.rb
#	app/controllers/settings_controller.rb
#	app/controllers/users_controller.rb
#	app/controllers/version_releases_controller.rb
#	app/models/gitea/webhook_task.rb
#	app/models/message_template/pull_request_atme.rb
#	app/models/project.rb
#	app/models/project_category.rb
#	app/models/user_extension.rb
#	app/views/users/get_user_info.json.jbuilder
#	app/views/users/show.json.jbuilder
#	config/routes.rb
2023-01-12 17:33:18 +08:00
zhangxunhui d155bdb71a 删除了gitea domain后的3000端口号 2022-05-15 11:28:26 +08:00
zhangxunhui e927f95d4f fix end keyword bug 2022-05-15 09:35:52 +08:00
zhangxunhui 600d6ab174 merge conflict 2022-05-12 09:32:25 +08:00
zhangxunhui 6b83719632 merge conflict 2022-05-12 09:15:36 +08:00
zhangxunhui 365eaca857 model schema information changed 2022-05-12 09:14:25 +08:00
Xunhui Zhang 8cf576946b merge conflicts 2022-05-06 21:48:59 +08:00
qyzh 0f776c5cdb update user.last_login_on before every requests 2021-12-24 15:25:14 +08:00
qyzh fc3f50a2bf add column to statistics 2021-12-24 15:14:26 +08:00
qyzh 13263a44e4 merge 2021-12-22 17:39:22 +08:00
qyzh ce5b6a67bf fix 无法创建PR 2021-12-22 17:10:58 +08:00
qyzh c9b1e30583 profile_completed = true 2021-12-15 19:06:34 +08:00
testaccount 88b96565d1 Initial commit 2021-12-07 16:32:16 +08:00
qyzh 6571db8a3c sponsor config 2021-12-07 16:20:42 +08:00
qyzh 2a02b6f530 每日统计 2021-12-07 09:45:33 +08:00
qyzh aa81e7030d add test case 2021-11-30 10:19:52 +08:00
qyzh 5a61965704 add test case 2021-11-30 10:19:04 +08:00
qyzh 0cd58a4e7a 整理测试代码 2021-10-29 09:10:36 +08:00
qyzh 859566e4be 整理测试代码 2021-10-29 09:09:47 +08:00
qyzh 34212a3468 merge gitlink/develop 2021-09-28 16:31:33 +08:00
qyzh c9b15a02d6 添加统计图标接口 2021-06-09 11:06:33 +08:00
nigel007 f8fa3c2b31 add project.nil? in 2021-05-14 11:17:03 +08:00
nigel007 c0515b9e7f change bug in balanceQuery 2021-05-13 23:22:36 +08:00
nigel007 56e9a9175d change is_current_admin_user 2021-05-13 23:04:24 +08:00
nigel007 6d399fe8d5 add 存证信息 2021-05-13 22:27:25 +08:00
nigel007 ac2974f7e0 change is_current_admin_user = true 2021-05-13 12:53:26 +08:00
nigel007 bf10df9f38 modify find_one_balance 2021-05-13 12:50:39 +08:00
nigel007 ad3a3b4460 add return 2021-05-13 12:45:29 +08:00
nigel007 2d8fd93994 change is_current_admin_user 2021-05-13 12:40:02 +08:00
qyzh 7776ab29ed coinchange chart 2021-05-13 11:15:54 +08:00
nigel007 c069bb0544 merge conflict 2021-05-11 21:38:22 +08:00
qyzh 661c8dda85 修复赞助支付bug 2021-05-10 16:15:02 +08:00
nigel007 e05fc89a92 add test User.current 2021-04-26 20:32:56 +08:00
nigel007 ac4aa300c2 add find user 36 2021-04-26 17:32:06 +08:00
nigel007 282bd1f149 remove find user 2021-04-26 17:28:04 +08:00
nigel007 e55e71266e add logs 2021-04-26 17:20:24 +08:00
nigel007 1725b24778 add logs 2021-04-26 17:18:13 +08:00
nigel007 4682457b6b change logs 2021-04-26 17:03:45 +08:00
nigel007 bc2721deb0 resolve conflicts 2021-04-23 22:27:02 +08:00
nigel007 3ad45f86f2 change blockchain related functions 2021-04-23 21:36:22 +08:00
qyzh 8b11fb604a 新增:发表issue奖励 2021-04-20 09:58:43 +08:00
qyzh eaf78c4d8f rewrite wallet module 2021-04-14 15:10:39 +08:00
qyzh b524111ae6 fix structure.sql 2021-04-08 18:41:31 +08:00
qyzh 244c1b865a merge integrated_blockchain 2021-04-08 16:19:27 +08:00
qyzh dafdbadb6b fix bugs 2021-04-08 16:05:40 +08:00
qyzh bf68c1c544 add daily reward 2021-03-08 20:45:15 +08:00
nigel007 c5b24a3447 add operation for pull request create/merge/refuse 2021-01-03 17:09:54 +08:00
nigel007 cbb666052c add blockchain operation after comments 2021-01-03 17:09:19 +08:00
nigel007 f4f1aef365 更新了显示文字,增加了功字 2021-01-03 17:08:44 +08:00
nigel007 6aef8e19c7 modify common function for update blockchain 2021-01-03 17:08:13 +08:00
nigel007 43374c8019 add gitea service for commit 2021-01-03 17:07:05 +08:00
nigel007 fcc17eb07b change create function for issue controller, add invocation of blockchain related function and add ActiveRecord Rollback operation 2020-12-31 20:29:41 +08:00
nigel007 f230c0d640 add common function for blockchain operation 2020-12-31 20:28:38 +08:00
nigel007 2395d4ef5e add blockchain api url 2020-12-31 20:27:42 +08:00
nigel007 c11cbf738c add this class to read blockchain configuration 2020-12-31 20:27:29 +08:00
nigel007 904ac86c86 add column use_blockchain 2020-12-30 16:24:32 +08:00
nigel007 99b631ced3 add function repo_use_blockchain to get param from front end form 2020-12-30 16:18:46 +08:00
nigel007 4c9df8c830 add column use_blockchain into attrs 2020-12-30 16:17:23 +08:00
nigel007 27b3bdc97b add two columns into permits, namely private and use_blockchain 2020-12-30 16:16:44 +08:00
nigel007 213c24892d add use_blockchain column into table: projects 2020-12-30 16:14:27 +08:00
nigel007 da9d268e04 fix issue #43166 2020-12-29 12:45:31 +08:00
qyzh 6de617d898 fix bugs, add test cases 2020-12-14 22:04:25 +08:00
qyzh 5addece8d5 fix bugs 2020-12-14 17:59:01 +08:00
qyzh ffbe4942b7 delete some interface 2020-12-11 17:01:52 +08:00
qyzh c963a80e8c merge origin_trustie/master to dev 2020-12-03 17:24:52 +08:00
qyzh 01f15da5ed fix bugs 2020-12-01 14:48:19 +08:00
qyzh cd595646d8 新增:修改赞助关系 2020-11-09 20:42:58 +08:00
qyzh 1ac5498091 完成用户log 2020-10-20 19:58:08 +08:00
qyzh faf2302b8e sponsor tiers增删改查 2020-09-19 09:59:05 +08:00
qyzh 5433920724 Merge branch 'dev_trustie' of https://git.trustie.net/qyzh1996/forgeplus into dev_trustie 2020-09-13 14:48:45 +08:00
qyzh 0e33b12989 before update 2020-09-13 14:48:23 +08:00
wyx 1c45b48063 update model passed_waitlist 2020-07-25 12:19:16 +08:00
wyx 80d6cbf823 update model waitlist 2020-07-25 12:18:49 +08:00
wyx 0ebcf3d7f7 update model coin_change 2020-07-25 12:17:46 +08:00
wyx 0f69255422 update model wallet 2020-07-25 12:12:34 +08:00
wyx d480deee64 update model stopped_sponsorship 2020-07-25 11:23:57 +08:00
wyx 50bef66261 update model sponsor_tier 2020-07-25 11:22:53 +08:00
wyx 9915c10bcf update model user 2020-07-25 11:21:44 +08:00
wyx c546eda537 update table waitlist and passed_waitlist 2020-07-25 10:57:45 +08:00
wyx 769bf2b90e create passedlist 2020-07-24 17:51:14 +08:00
wyx 94ad4ce56c create waitlist 2020-07-24 17:50:25 +08:00
wyx 98176f839d create coinchange 2020-07-24 17:49:07 +08:00
wyx 33951af37d create table wallet 2020-07-24 17:45:29 +08:00
wyx 46b906d2ac create stoppedsponsorship 2020-07-24 17:40:58 +08:00
wyx 0a460d1d37 create sponsor_tier 2020-07-24 17:38:31 +08:00
wyx cb089b1bb8 create table sponsorship 2020-07-24 17:21:16 +08:00
wyx 8e2cf4ecc0 add column to users 2020-07-24 16:58:25 +08:00
qyzh 38193dff54 Merge remote-tracking branch 'origin_trustie/dev_trustie' into dev_trustie 2020-07-15 10:55:16 +08:00
qyzh e07dddde98 before merge 2020-07-15 10:55:13 +08:00
356 changed files with 4352 additions and 1870 deletions

2
.gitignore vendored
View File

@ -73,7 +73,7 @@ vendor/bundle/
/public/admin
/mysql_data
/public/repo/
/coverage
.generators
.rakeTasks

10
Gemfile
View File

@ -1,4 +1,5 @@
source 'https://gems.ruby-china.com'
# source 'https://gems.ruby-china.com'
source 'https://mirrors.cloud.tencent.com/rubygems/'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '~> 5.2.0'
@ -59,6 +60,7 @@ gem 'ransack'
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'rails-controller-testing'
end
group :development do
@ -77,6 +79,7 @@ group :test do
gem 'capybara', '>= 2.15', '< 4.0'
gem 'selenium-webdriver'
gem 'chromedriver-helper'
gem 'simplecov', '~>0.12.0', require: false
end
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
@ -101,6 +104,8 @@ gem 'rails-i18n', '~> 5.1'
gem 'sidekiq',"5.2.8"
gem 'sinatra'
gem "sidekiq-cron", "1.2.0"
gem 'whenever'
gem 'sidekiq_schedulable'
# batch insert
gem 'bulk_insert'
@ -131,6 +136,9 @@ gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'
# log
gem 'multi_logger'
gem 'letter_avatar'
gem 'jwt'

View File

@ -532,4 +532,4 @@ DEPENDENCIES
wkhtmltopdf-binary
BUNDLED WITH
2.1.4
2.2.3

View File

@ -121,4 +121,4 @@ You may obtain a copy of Mulan PSL v2 at:
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
See the Mulan PSL v2 for more details.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,3 @@
// Place all the styles related to the log controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,84 @@
body {
background-color: #fff;
color: #333;
margin: 33px;
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
p, ol, ul, td {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
pre {
background-color: #eee;
padding: 10px;
font-size: 11px;
}
a {
color: #000;
&:visited {
color: #666;
}
&:hover {
color: #fff;
background-color: #000;
}
}
th {
padding-bottom: 5px;
}
td {
padding: 0 5px 7px;
}
div {
&.field, &.actions {
margin-bottom: 10px;
}
}
#notice {
color: green;
}
.field_with_errors {
padding: 2px;
background-color: red;
display: table;
}
#error_explanation {
width: 450px;
border: 2px solid red;
padding: 7px 7px 0;
margin-bottom: 20px;
background-color: #f0f0f0;
h2 {
text-align: left;
font-weight: bold;
padding: 5px 5px 5px 15px;
font-size: 12px;
margin: -7px -7px 0;
background-color: #c00;
color: #fff;
}
ul li {
font-size: 12px;
list-style: square;
}
}
label {
display: block;
}

View File

@ -0,0 +1,3 @@
// Place all the styles related to the SponsorTiers controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Sponsorships controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Wallets controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -4,13 +4,13 @@ class AccountsController < ApplicationController
#skip_before_action :check_account, :only => [:logout]
def simple_update
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
ActiveRecord::Base.transaction do
result = auto_update(current_user, simple_update_params)
if result[:message].blank?
render_ok
@ -270,6 +270,7 @@ class AccountsController < ApplicationController
set_autologin_cookie(user)
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
# user.daily_reward
user.update_column(:last_login_on, Time.now)
session[:"#{default_yun_session}"] = user.id
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
@ -342,11 +343,11 @@ class AccountsController < ApplicationController
render_ok
end
def login_check
def login_check
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
render_ok
end
private
# type 事件类型 1用户注册 2忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
@ -389,7 +390,7 @@ class AccountsController < ApplicationController
params.require(:user).permit(:login, :email, :phone)
end
def login_params
def login_params
params.require(:account).permit(:login, :password)
end
@ -404,7 +405,7 @@ class AccountsController < ApplicationController
def reset_password_params
params.permit(:login, :password, :password_confirmation, :code)
end
def find_user
phone_or_mail = strip(reset_password_params[:login])
User.where("phone = :search OR mail = :search", search: phone_or_mail).last
@ -413,7 +414,7 @@ class AccountsController < ApplicationController
def remote_register_params
params.permit(:username, :email, :password, :platform)
end
def simple_update_params
params.permit(:username, :email, :password, :platform)
end

View File

@ -10,12 +10,14 @@ class ApplicationController < ActionController::Base
include LoggerHelper
include LoginHelper
include RegisterHelper
include UpdateHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? }
before_action :check_sign
before_action :user_setup
#before_action :check_account
after_action :user_trace_log
# TODO
# check sql query time
@ -25,6 +27,8 @@ class ApplicationController < ActionController::Base
# end
end
before_action :update_last_login_on
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
OPENKEY = Rails.application.config_for(:configuration)['sign_key'] || "79e33abd4b6588941ab7622aed1e67e8"
@ -82,7 +86,7 @@ class ApplicationController < ActionController::Base
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end
user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
if user_exist && type.to_i == 1
tip_exception(-2, "该手机号码或邮箱已被注册")
@ -305,7 +309,7 @@ class ApplicationController < ActionController::Base
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
end
end
else
else
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
@ -363,7 +367,20 @@ class ApplicationController < ActionController::Base
# RSS key authentication does not start a session
User.find_by_rss_key(params[:key])
end
end
# User.current = User.find(2) # need to remove this statement before running in production
end
def user_trace_log
user = current_user
# print("*********************url:", request.url, "****routes", request.request_method)
Rails.logger.user_trace.info("{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params}, response_code: #{response.code}, time: #{Time.now}}")
end
def user_trace_update_log(old_value_hash)
user = current_user
str = "{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params.merge(old_value: old_value_hash)}, response_code: #{response.code}, time: #{Time.now}}"
Rails.logger.user_trace.info(str)
end
def try_to_autologin
if cookies[autologin_cookie_name]
@ -389,12 +406,17 @@ class ApplicationController < ActionController::Base
respond_to do |format|
format.json
end
end
end
## 输出错误信息
def error_status(message = nil)
@status = -1
@message = message
## 输出错误信息
def error_status(message = nil)
@status = -1
@message = message
end
# 实训等对应的仓库地址
def repo_ip_url(repo_path)
"#{edu_setting('git_address_ip')}/#{repo_path}"
end
def repo_url(repo_path)
@ -633,6 +655,23 @@ class ApplicationController < ActionController::Base
ss
end
def strip_html(text, len=0, endss="...")
ss = ""
if !text.nil? && text.length>0
ss=text.gsub(/<\/?.*?>/, '').strip
ss = ss.gsub(/&nbsp;*/, '')
ss = ss.gsub(/\r\n/,'') #新增
ss = ss.gsub(/\n/,'') #新增
if len > 0 && ss.length > len
ss = ss[0, len] + endss
elsif len > 0 && ss.length <= len
ss = ss
#ss = truncate(ss, :length => len)
end
end
ss
end
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE|Trident|Edge} ? ERB::Util.url_encode(name) : name
@ -644,8 +683,8 @@ class ApplicationController < ActionController::Base
# 获取Oauth Client
def get_client(site)
client_id = Rails.configuration.Gitlink['client_id']
client_secret = Rails.configuration.Gitlink['client_secret']
client_id = Rails.configuration.educoder['client_id']
client_secret = Rails.configuration.educoder['client_secret']
OAuth2::Client.new(client_id, client_secret, site: site)
end
@ -665,7 +704,7 @@ class ApplicationController < ActionController::Base
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 50) ? 50 : limit.to_i
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
@ -750,11 +789,11 @@ class ApplicationController < ActionController::Base
# @project = nil if !@project.is_public?
# render_forbidden and return
else
if @project.present?
if @project.present?
logger.info "########### has project and but can't read project"
@project = nil
render_forbidden and return
else
else
logger.info "###########project not found"
@project = nil
render_not_found and return
@ -799,21 +838,54 @@ class ApplicationController < ActionController::Base
end
private
def object_not_found
uid_logger("Missing template or cant't find record, responding with 404")
render json: {message: "您访问的页面不存在或已被删除", status: 404}
false
def update_last_login_on
if current_user.logged?
current_user.update_column(:last_login_on, Time.now)
end
end
def object_not_found
uid_logger("Missing template or cant't find record, responding with 404")
render json: {message: "您访问的页面不存在或已被删除", status: 404}
false
end
def tip_show(exception)
uid_logger("Tip show status is #{exception.status}, message is #{exception.message}")
render json: exception.tip_json
end
def render_parameter_missing
render json: { status: -1, message: '参数缺失' }
end
def set_export_cookies
cookies[:fileDownload] = true
end
# 149课程的评审用户数据创建包含创建课堂学生
def open_class_user
user = User.find_by(login: "OpenClassUser")
unless user
ActiveRecord::Base.transaction do
user_params = {status: 1, login: "OpenClassUser", lastname: "开放课程",
nickname: "开放课程", professional_certification: 1, certification: 1, grade: 0,
password: "12345678", phone: "11122223333", profile_completed: 1}
user = User.create!(user_params)
UserExtension.create!(user_id: user.id, gender: 0, school_id: 3396, :identity => 1, :student_id => "openclassuser") # 3396
subject = Subject.find_by(id: 149)
if subject
subject.courses.each do |course|
CourseMember.create!(course_id: course.id, role: 3, user_id: user.id) if !course.course_members.exists?(user_id: user.id)
end
end
end
end
user
end
# 记录热门搜索关键字
def record_search_keyword
keyword = params[:keyword].to_s.strip
@ -823,6 +895,325 @@ class ApplicationController < ActionController::Base
HotSearchKeyword.add(keyword)
end
# author: zxh
# blockchain相关项目活动调用函数
# return true: 表示上链操作成功; return false: 表示上链操作失败
def push_activity_2_blockchain(activity_type, model)
if activity_type == "issue_create"
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
id = model['id']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
identifier = project['identifier']
author_id = project['user_id']
author = User.find(author_id)
username = author['login']
action = 'opened'
title = model['subject']
content = model['description']
created_at = model['created_on']
updated_at = model['updated_on']
# 调用区块链接口
params = {
"request-type": "upload issue info",
"issue_id": "gitlink-" + id.to_s,
"repo_id": "gitlink-" + project_id.to_s,
"issue_number": 0, # 暂时不需要改字段
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"title": title,
"content": content,
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "issue_comment_create"
issue_comment_id = model['id']
issue_id = model['journalized_id']
parent_id = model['parent_id'].nil? ? "" : model['parent_id']
issue = Issue.find(issue_id)
issue_classify = issue['issue_classify'] # issue或pull_request
project_id = issue['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
action = 'created'
content = model['notes']
created_at = model['created_on']
if issue_classify == "issue"
params = {
"request-type": "upload issue comment info",
"issue_comment_id": "gitlink-" + issue_comment_id.to_s,
"issue_comment_number": 0, # 暂时不需要
"issue_number": 0, # 暂时不需要
"issue_id": "gitlink-" + issue_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"parent_id": parent_id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
elsif issue_classify == "pull_request"
params = {
"request-type": "upload pull request comment info",
"pull_request_comment_id": "gitlink-" + issue_comment_id.to_s,
"pull_request_comment_number": 0, # 不考虑该字段
"pull_request_number": 0, # 不考虑该字段
"pull_request_id": "gitlink-" + issue_id.to_s,
"parent_id": parent_id.to_s,
"repo_id": "gitlink-" + project.id.to_s,
"reponame": identifier,
"ownername": ownername,
"username": username,
"action": action,
"content": content,
"created_at": created_at,
}.to_json
end
# 调用区块链接口
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 10
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_create"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'opened'
title = model['title']
content = model['body']
source_branch = model['head']
source_repo_id = model['fork_project_id'].nil? ? project_id : model['fork_project_id']
target_branch = model['base']
target_repo_id = project_id
author_id = model['user_id']
author = User.find(author_id)
username = author['login']
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
elsif activity_type == "pull_request_merge"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'merged'
created_at = model['created_at']
updated_at = model['updated_at']
# 查询pull request对应的commit信息
commits = Gitea::PullRequest::CommitsService.call(ownername, identifier, model['gitea_number'])
if commits.nil?
raise Error, "区块链接口请求失败" # 获取pr中变更的commit信息失败
end
commit_shas = []
commits.each do |c|
commit_shas << c["Sha"]
end
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
# 将commit相关信息写入链上
commit_shas.each do |commit_sha|
commit_diff = Gitea::Commit::DiffService.call(ownername, identifier, commit_sha, owner['gitea_token'])
commit = Gitea::Commit::InfoService.call(ownername, identifier, commit_sha, owner['gitea_token'])
params = {
"request-type": "upload commit info",
"commit_hash": commit_sha,
"repo_id": "gitlink-" + project_id.to_s,
"author": commit['commit']['author']['name'],
"author_email": commit['commit']['author']['email'],
"committer": commit['commit']['committer']['name'],
"committer_email": commit['commit']['committer']['email'],
"author_time": commit['commit']['author']['date'],
"committer_time": commit['commit']['committer']['date'],
"content": commit['commit']['message'],
"commit_diff": commit_diff['Files'].to_s
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 7
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
end
elsif activity_type == "pull_request_refuse"
# 调用区块链接口
project_id = model['project_id']
project = Project.find(project_id)
if project['use_blockchain'] == 0 || project['use_blockchain'] == false
# 无需执行上链操作
return true
end
pull_request_id = model['id']
identifier = project['identifier']
owner_id = project['user_id']
owner = User.find(owner_id)
ownername = owner['login']
action = 'refused'
# 将pull request相关信息写入链上
params = {
"request-type": "upload pull request info",
"pull_request_id": "gitlink-" + pull_request_id.to_s,
"pull_request_number": 0, # trustie没有该字段
"repo_id": "gitlink-" + project_id.to_s,
"ownername": ownername,
"reponame": identifier,
"username": username,
"action": action,
"title": title,
"content": content,
"source_branch": source_branch,
"target_branch": target_branch,
"reviewers": [], # trustie没有该字段
"commit_shas": commit_shas,
"merge_user": "", # trustie没有该字段
"created_at": created_at,
"updated_at": updated_at
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 9
raise Error, resp_body['message']
elsif resp_body['status'] != 0
raise Error, "区块链接口请求失败."
end
end
end
def find_atme_receivers
@atme_receivers = User.where(login: params[:receivers_login])
end

View File

@ -0,0 +1,48 @@
class Blockchain::BaseController < ApplicationController
before_action :require_login
before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? }
before_action :connect_to_ci_database, only: :load_repo
def load_repo
namespace = params[:owner]
id = params[:repo] || params[:id]
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
end
private
def authorize_access_project!
unless @project.manager?(current_user)
return render_forbidden
end
end
def authenticate_manager!
unless @project.manager?(current_user)
return render_forbidden
end
end
def authenticate_admin!
return render_forbidden unless current_user.admin?
end
def authorize_owner!
unless @project.owner?(current_user)
return render_forbidden
end
end
def find_cloud_account
@cloud_account ||= current_user.ci_cloud_account
@cloud_account.blank? ? nil : @cloud_account
end
def load_ci_user
@ci_user ||= Ci::User.find_by(user_login: params[:owner])
@ci_user.blank? ? raise("未找到相关的记录") : @ci_user
end
end

View File

@ -0,0 +1,7 @@
class BlockchainController < ApplicationController
def get_issue_token_num
puts "pause"
end
end

View File

@ -6,10 +6,10 @@ class CompareController < ApplicationController
end
def show
if params[:type] == "sha"
if params[:type] == "sha"
load_compare_params
@compare_result ||= gitea_compare(@base, @head)
else
else
load_compare_params
compare
@merge_status, @merge_message = get_merge_message
@ -63,7 +63,7 @@ class CompareController < ApplicationController
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
def page_size
params.fetch(:page, 1).to_i
end

View File

@ -44,6 +44,7 @@ module LoginHelper
set_autologin_cookie(user)
UserAction.create(action_id: user&.id, action_type: 'Login', user_id: user&.id, ip: request.remote_ip)
# user.daily_reward
user.update_column(:last_login_on, Time.now)
# 注册完成后有一天的试用申请(先去掉)
# UserDayCertification.create(user_id: user.id, status: 1)

View File

@ -3,9 +3,12 @@ class ForksController < ApplicationController
before_action :require_profile_completed, only: [:create]
before_action :load_project
before_action :authenticate_project!, :authenticate_user!
skip_after_action :user_trace_log, only: [:create]
def create
@new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call
user = current_user
Rails.logger.user_trace.info("{id: #{user.id}, login: #{user.login}, url: #{request.url}, method: #{request.method}, params: #{params.merge(forkee: @new_project.id)}, response_code: #{response.code}, time: #{Time.now}}")
end
private

View File

@ -11,6 +11,8 @@ class IssuesController < ApplicationController
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
before_action :check_token_enough, :find_atme_receivers, only: [:create, :update]
skip_after_action :user_trace_log, only: [:update]
include ApplicationHelper
include TagChosenHelper
@ -149,12 +151,22 @@ 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
# author: zxh
# 扣除发起人的token
if @issue.blockchain_token_num > 0
Blockchain::CreateIssue.call(user_id: @issue.author_id, project_id: @issue.project_id, token_num: @issue.blockchain_token_num)
end
# 调用上链API存证
push_activity_2_blockchain("issue_create", @issue)
render json: {status: 0, message: "创建成功", id: @issue.id}
else
normal_status(-1, "创建失败")
@ -218,6 +230,7 @@ class IssuesController < ApplicationController
# end
# end
# end
issue_hash = old_value_to_hash(@issue, params)
if @issue.issue_type.to_s == "2" && params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id)
normal_status(-1, "不允许修改为关闭状态")
@ -225,6 +238,9 @@ class IssuesController < ApplicationController
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
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)
user_trace_update_log(issue_hash)
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?
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @issue&.pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? && Site.has_notice_menu?
@ -541,7 +557,8 @@ class IssuesController < ApplicationController
branch_name: params[:branch_name].to_s,
issue_classify: "issue",
author_id: current_user.id,
project_id: @project.id
project_id: @project.id,
blockchain_token_num: params[:blockchain_token_num]
}
end

View File

@ -4,6 +4,7 @@ class JournalsController < ApplicationController
before_action :set_issue
before_action :check_issue_permission
before_action :set_journal, only: [:destroy, :edit, :update]
skip_after_action :user_trace_log, only: [:update]
def index
@page = params[:page] || 1
@ -47,10 +48,15 @@ class JournalsController < ApplicationController
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
AtmeService.call(current_user, @atme_receivers, journal) if @atme_receivers.size > 0
# @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
# author: zxh
# 调用上链API
push_activity_2_blockchain("issue_comment_create", journal)
render :json => { status: 0, message: "评论成功", id: journal.id}
# normal_status(0, "评论成功")
else
normal_status(-1, "评论失败")
raise ActiveRecord::Rollback
end
end
end
@ -74,9 +80,11 @@ class JournalsController < ApplicationController
def update
content = params[:content]
if content.present?
if content.present?
old_value = old_value_to_hash(@journal, params)
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)
user_trace_update_log(old_value)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")

View File

@ -0,0 +1,19 @@
class LogController < ApplicationController
def list
path = "#{Rails.root}/log"
@file_list = []
Dir.foreach(path) do |file|
@file_list << file
end
@file_list = @file_list.sort
end
def download
path = "#{Rails.root}/log/#{params[:filename]}"
if params[:filename] && File.exist?(path) && File.file?(path)
send_file(path, filename: params[:filename])
else
render json: { message: 'no such file!' }
end
end
end

View File

@ -6,6 +6,7 @@ class MembersController < ApplicationController
before_action :operate!
before_action :check_member_exists!, only: %i[create]
before_action :check_member_not_exists!, only: %i[remove change_role]
skip_after_action :user_trace_log, only: [:change_role]
def create
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
@ -42,7 +43,9 @@ class MembersController < ApplicationController
end
def change_role
old_value = @project.members.where(user_id: params[:user_id])[0].roles.last.name
interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role])
user_trace_update_log(old_value)
SendTemplateMessageJob.perform_later('ProjectRole', current_user.id, @user.id, @project.id, message_role_name) if Site.has_notice_menu?
render_response(interactor)
rescue Exception => e

View File

@ -273,7 +273,8 @@ class ProjectsController < ApplicationController
private
def project_params
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, :identifier,
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
:project_category_id, :project_language_id, :license_id, :ignore_id, :private,
:blockchain, :blockchain_token_all, :blockchain_init_token)
end
def mirror_params

View File

@ -6,6 +6,8 @@ class PullRequestsController < ApplicationController
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]
skip_after_action :user_trace_log, only: [:update]
include TagChosenHelper
include ApplicationHelper
@ -73,6 +75,11 @@ class PullRequestsController < ApplicationController
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
AtmeService.call(current_user, @atme_receivers, @pull_request) if @atme_receivers.size > 0
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_create", @pull_request)
else
render_error("create pull request error: #{@gitea_pull_request[:status]}")
raise ActiveRecord::Rollback
@ -103,8 +110,13 @@ class PullRequestsController < ApplicationController
reviewers = User.where(id: params[:reviewer_ids])
@pull_request.reviewers = reviewers
old_issue_value = old_value_to_hash(@issue, @issue_params)
old_pr_value = old_value_to_hash(@pull_request, @local_params.compact)
old_value = {issue: old_issue_value, pull_request: old_pr_value}
if @issue.update_attributes(@issue_params)
if @pull_request.update_attributes(@local_params.compact)
user_trace_update_log(old_value)
gitea_pull = Gitea::PullRequest::UpdateService.call(@owner.login, @repository.identifier,
@pull_request.gitea_number, @requests_params, current_user.gitea_token)
@ -119,7 +131,7 @@ class PullRequestsController < ApplicationController
end
else
return normal_status(-1, "请输入正确的标记。")
end
end
end
if params[:status_id].to_i == 5
@issue.issue_times.update_all(end_time: Time.now)
@ -149,12 +161,16 @@ class PullRequestsController < ApplicationController
ActiveRecord::Base.transaction do
begin
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
if colsed === true
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_refuse", @pull_request)
if colsed === true
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
# 合并请求下issue处理为关闭
@issue&.update_attributes!({status_id:5})
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
normal_status(1, "已拒绝")
normal_status(1, "已拒绝")
else
normal_status(-1, '合并失败')
end
@ -198,6 +214,45 @@ class PullRequestsController < ApplicationController
# @pull_request.project_trend_status!
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
# author: zxh
# 调用上链API
push_activity_2_blockchain("pull_request_merge", @pull_request)
# 查看是否fix了相关issue如果fix就转账
if params["fix_issue_id"].nil? || params["fix_issue_id"] == ""
else
issue = Issue.find_by(id: params["fix_issue_id"])
if issue.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
token_num = issue.blockchain_token_num
token_num = token_num.nil? ? 0 : token_num
owner = User.find_by(login: params["owner"])
pr = PullRequest.find_by(id: params["pull_request"]["id"])
if owner.nil? || pr.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
project = Project.find_by(user_id: owner.id, identifier: params["project_id"])
if project.nil?
normal_status(-1, "关联issue失败")
raise ActiveRecord::Rollback
else
author_id = pr.user_id
author = User.find(author_id)
if token_num > 0
Blockchain::FixIssue.call({user_id: author_id.to_s, project_id: project.id.to_s, token_num: token_num})
Blockchain::TransferService.call({payer_id: issue.author_id.to_s, transfer_login: author.login, transfer_amount: token_num, project_id: project.id})
end
# update issue to state 5
issue.update(status_id: 5)
end
end
end
end
# 合并请求下issue处理为关闭
@issue&.update_attributes!({status_id:5})
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?

View File

@ -1,6 +1,7 @@
class SettingsController < ApplicationController
def show
@old_projects_url = nil
@old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged?
get_navbar
get_add_menu
get_common_menu
@ -12,14 +13,14 @@ class SettingsController < ApplicationController
end
private
def get_navbar
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|
@ -86,7 +87,7 @@ class SettingsController < ApplicationController
}
end
end
def get_top_system_notification
@top_system_notification = SystemNotification.is_top.first
end

View File

@ -0,0 +1,90 @@
class SponsorTiersController < ApplicationController
before_action :set_sponsor_tier, only: [:show, :edit, :update, :destroy]
before_action :check_sponsor, only: [:show]
before_action :require_login, only: [:create, :update, :destroy]
# GET /sponsor_tiers
# GET /sponsor_tiers.json
def index
# @sponsor_tiers = SponsorTier.all
user = User.find_by_login(params[:login])
@sponsor_tiers = user.sponsor_tier
end
# GET /sponsor_tiers/1
# GET /sponsor_tiers/1.json
def show
end
# POST /sponsor_tiers
# POST /sponsor_tiers.json
def create
# print("------------\n", sponsor_tier_params, "\n------------\n")
@check_sponsorship = nil
@sponsor_tier = SponsorTier.new(sponsor_tier_params)
respond_to do |format|
if @sponsor_tier.user_id == User.current.id && @sponsor_tier.save
format.html { redirect_to @sponsor_tier, notice: 'Sponsor tier was successfully created.' }
format.json { render :show, status: :created, location: @sponsor_tier }
# render json: {status: 1, message: '创建成功' }
else
format.html { render :new }
format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sponsor_tiers/1
# PATCH/PUT /sponsor_tiers/1.json
def update
@check_sponsorship = nil
old_value = old_value_to_hash(@sponsor_tier, params)
respond_to do |format|
if User.current.id == @sponsor_tier.user_id && @sponsor_tier.update(sponsor_tier_update_params)
user_trace_update_log(old_value)
format.html { redirect_to @sponsor_tier, notice: 'Sponsor tier was successfully updated.' }
format.json { render :show, status: :ok, location: @sponsor_tier }
# render json: {status: 1, message: '修改成功' }
else
format.html { render :edit }
format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity }
# format.json { render status: :unprocessable_entity }
# render json: {status: -1, message: '修改失败' }
end
end
end
# DELETE /sponsor_tiers/1
# DELETE /sponsor_tiers/1.json
def destroy
if User.current.id == @sponsor_tier.user_id
@sponsor_tier.destroy
respond_to do |format|
format.html { redirect_to sponsor_tiers_url, notice: 'Sponsor tier was successfully destroyed.' }
format.json { head :no_content }
end
else
format.json { render json: @sponsor_tier.errors, status: :unprocessable_entity }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def check_sponsor
@check_sponsorship = Sponsorship.where("sponsor_id=? AND developer_id=?", current_user.id, @sponsor_tier.user.id)
end
def set_sponsor_tier
@sponsor_tier = SponsorTier.find(params[:id])
end
def sponsor_tier_update_params
params.require(:sponsor_tier).permit(:tier, :description)
end
# Only allow a list of trusted parameters through.
def sponsor_tier_params
params.require(:sponsor_tier).permit(:tier, :user_id, :description)
end
end

View File

@ -0,0 +1,212 @@
class SponsorshipsController < ApplicationController
before_action :set_sponsorship, only: [:show, :edit, :update, :destroy]
# before_action :require_login, except: [:index, :stopped, :sponsored, :sponsoring, :stopped_sponsored, :stopped_sponsoring]
before_action :require_login, only: [:create, :edit, :update, :destroy]
skip_after_action :user_trace_log, only: [:update]
# GET /sponsorships
# GET /sponsorships.json
def index
@sponsorships = Sponsorship.all
end
def stopped
@stopped_sponsorships = StoppedSponsorship.all
end
def sponsored
if User.current.id == Integer(params[:id])
@sponsorships = Sponsorship.where('developer_id=?', params[:id])
else
@sponsorships = Sponsorship.where('developer_id=? AND visible=1', params[:id])
end
sort = params[:sort_by] || 'created_at'
sort_direction = params[:sort_direction] || 'desc'
@sponsorships = @sponsorships.reorder("#{sort} #{sort_direction}")
@total = @sponsorships.length
@sponsorships = kaminari_paginate(@sponsorships)
end
def sponsoring
if User.current.id == Integer(params[:id])
@sponsorships = Sponsorship.where('sponsor_id=?', params[:id])
else
@sponsorships = Sponsorship.where('sponsor_id=? AND visible=1', params[:id])
end
sort = params[:sort_by] || 'created_at'
sort_direction = params[:sort_direction] || 'desc'
@sponsorships = @sponsorships.reorder("#{sort} #{sort_direction}")
@total = @sponsorships.length
@sponsorships = kaminari_paginate(@sponsorships)
end
def stopped_sponsored
if User.current.id == Integer(params[:id])
@stopped_sponsorships = StoppedSponsorship.where('developer_id=?', params[:id])
else
@stopped_sponsorships = StoppedSponsorship.where('developer_id=? AND visible=1', params[:id])
end
sort = params[:sort_by] || 'created_at'
sort_direction = params[:sort_direction] || 'desc'
@stopped_sponsorships = @stopped_sponsorships.reorder("#{sort} #{sort_direction}")
@total = @stopped_sponsorships.length
@stopped_sponsorships = kaminari_paginate(@stopped_sponsorships)
end
def stopped_sponsoring
if User.current.id == Integer(params[:id])
@stopped_sponsorships = StoppedSponsorship.where('sponsor_id=?', params[:id])
else
@stopped_sponsorships = StoppedSponsorship.where('sponsor_id=? AND visible=1', params[:id])
end
sort = params[:sort_by] || 'created_at'
sort_direction = params[:sort_direction] || 'desc'
@stopped_sponsorships = @stopped_sponsorships.reorder("#{sort} #{sort_direction}")
@total = @stopped_sponsorships.length
@stopped_sponsorships = kaminari_paginate(@stopped_sponsorships)
end
# GET /sponsorships/1
# GET /sponsorships/1.json
def show; end
# POST /sponsorships
# POST /sponsorships.json
def create
sponsor_id = User.current.id
check_sponsorship = Sponsorship.where('sponsor_id=? AND developer_id=?', sponsor_id, params[:developer_id])
@sponsorship = Sponsorship.new(sponsorship_params.merge({sponsor_id: sponsor_id}))
unless check_sponsorship.length.zero?
return render json: {status: -1, message: '您已经赞助了TA' }
end
if @sponsorship.pay && @sponsorship.save
if params[:single] && @sponsorship.stop
return render json: { status: 1, message: '赞助成功' }
elsif !params[:single]
User.current.update(sponsor_num: User.current.sponsor_num+1)
@sponsorship.developer.update(sponsored_num: @sponsorship.developer.sponsored_num + 1)
return render json: { status: 1, message: '赞助成功' }
else
return render json: { status: -1, message: '赞助失败' }
end
else
return render json: { status: -1, message: '赞助失败' }
end
# return render_result message: '赞助成功' if @sponsorship.save
# respond_to do |format|
# if check_sponsorship.length.zero? && @sponsorship.save
# format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully created.' }
# format.json { render :show, status: :created, location: @sponsorship }
# # render_result status=0, message="赞助成功"
# else
# format.html { render :new }
# format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
# end
# end
end
# PATCH/PUT /sponsorships/1
# PATCH/PUT /sponsorships/1.json
def update
# respond_to do |format|
# if @sponsorship.update(sponsorship_params)
# format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully updated.' }
# format.json { render :show, status: :ok, location: @sponsorship }
# else
# format.html { render :edit }
# format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
# end
# end
if @sponsorship.sponsor.id != current_user.id
return render json: {status: 401, message: '没有权限' }
end
old_value = old_value_to_hash(@sponsorship, params)
if @sponsorship.update(sponsorship_params)
user_trace_update_log(old_value)
render json: {status: 1, message: '修改成功' }
else
render json: {status: -1, message: '修改失败' }
end
end
# DELETE /sponsorships/1
# DELETE /sponsorships/1.json
def destroy
# @sponsorship.destroy
# respond_to do |format|
# format.html { redirect_to sponsorships_url, notice: 'Sponsorship was successfully destroyed.' }
# format.json { head :no_content }
# end
developer = @sponsorship.developer
sponsor = @sponsorship.sponsor
if (User.current.id == developer.id || User.current.id == sponsor.id) && developer.update(sponsored_num: developer.sponsored_num-1) && sponsor.update(sponsor_num: sponsor.sponsor_num-1) && @sponsorship.stop
render json: {status: 1, message: '终止成功'}
else
render json: {status: -1, message: '失败'}
end
end
def community_data
@sponsorships = Sponsorship.all
t1 = Time.now
t2 = Time.new(t1.year, t1.month, t1.day - 6)
@stopped_sponsorships = StoppedSponsorship.where('created_at >= ?', t2)
@community_data_array = to_array(@sponsorships, @stopped_sponsorships)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_sponsorship
@sponsorship = Sponsorship.find(params[:id])
end
# Only allow a list of trusted parameters through.
def sponsorship_params
params.require(:sponsorship).permit(:amount, :visible, :sponsor_id, :developer_id, :single, :page, :limit, :sort_by, :search)
end
def to_array(sponsorships, stopped_sponsorships)
t1 = Time.now
start_time = Time.new(t1.year, t1.month, t1.day - 6)
sponsor = Array.new(7)
sponsored = Array.new(7)
date = Array.new(7)
# date[0] = Time.new(start_time.year, start_time.month, start_time.day)
index = 0
(0..6).each do |i|
# 更新日期date[i]表示第i天0点
date[i] = Time.new(start_time.year, start_time.month, start_time.day + i)
end_time = Time.new(start_time.year, start_time.month, start_time.day + i+1)
sponsor_set = Set.new
sponsored_set = Set.new
# 所有创建时间早于今天23:59的sponsorship
today_sponsor = sponsorships.where('created_at < ?', end_time)
# 所有结束时间晚于今天0:00的stopped_sponsorship
today_stopped_sponsor = stopped_sponsorships.where('created_at <= ?', date[i])
today_sponsor.each do |s|
sponsor_set.add s.sponsor_id
sponsored_set.add s.developer_id
end
today_stopped_sponsor.each do |s|
sponsor_set.add s.sponsor_id
sponsored_set.add s.developer_id
end
sponsor[i] = sponsor_set.size
sponsored[i] = sponsored_set.size
end
Array[sponsor, sponsored, date]
end
end

View File

@ -2,8 +2,8 @@ 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 :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard, :hovercard4proj]
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard, :hovercard4proj]
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]
@ -81,9 +81,134 @@ class UsersController < ApplicationController
@watchers = paginate(watchers)
end
def contribution_perc
project_id = params[:project_id]
@project = Project.find(project_id)
user_id = params[:id]
@user = User.find(user_id)
def cal_perc(count_user, count_all)
(count_user * 1.0 / (count_all + 0.000000001)).round(5)
end
if @project['use_blockchain'] == true or @project['use_blockchain'] == 1
balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": user_id, "project_id": project_id})
balance_all = Blockchain::RepoBasicInfo.call({"project_id": project_id})["cur_supply"]
scores = {
"final" => cal_perc(balance_user, balance_all),
"blockchain" => true
}
else
# 获取所有行为对应的项目内记录总数和个人记录数
features = {
"requirement" => {},
"development" => {},
"review" => {}
}
# 1. issue创建
issues = Issue.where(project_id: project_id, issue_classify: 'issue')
issue_all = issues.count
issue_user = issues.where(author_id: user_id).count
features["requirement"] = features["requirement"].merge({"issue" => {"all" => issue_all, "perc" => cal_perc(issue_user, issue_all)}})
# 2. 里程碑创建
milestones = Version.where(project_id: project_id)
milestone_all = milestones.count
milestone_user = milestones.where(user_id: user_id).count
features["requirement"] = features["requirement"].merge({"milestone" => {"all" => milestone_all, "perc" => cal_perc(milestone_user, milestone_all)}})
# 3. issue评论
issue_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{project_id} and journalized_type='Issue' and issues.issue_classify='issue'")
issue_comment_all = issue_comments.count
issue_comment_user = issue_comments.where("journals.user_id=#{user_id}").count
features["requirement"] = features["requirement"].merge({"issue_comment" => {"all" => issue_comment_all, "perc" => cal_perc(issue_comment_user, issue_comment_all)}})
# 4. 合并请求
prs = PullRequest.where(project_id: project_id)
pr_all = prs.count
pr_user = prs.where(user_id: user_id).count
features["development"] = features["development"].merge({"pr" => {"all" => pr_all, "perc" => cal_perc(pr_user, pr_all)}})
# 5. pr评论
pr_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{project_id} and journalized_type='Issue' and issues.issue_classify='pull_request'")
pr_comment_all = pr_comments.count
pr_comment_user = pr_comments.where("journals.user_id=#{user_id}").count
features["review"] = features["review"].merge({"pr_comment" => {"all" => pr_comment_all, "perc" => cal_perc(pr_comment_user, pr_comment_all)}})
# 6. 代码行评论
line_comments = Journal.joins("INNER JOIN pull_requests on journals.journalized_id=pull_requests.id").where("pull_requests.project_id=#{project_id} and journalized_type='PullRequest'")
line_comment_all = line_comments.count
line_comment_user = line_comments.where("journals.user_id=#{user_id}").count
features["review"] = features["review"].merge({"line_comment" => {"all" => line_comment_all, "perc" => cal_perc(line_comment_user, line_comment_all)}})
# 7. 代码行、commit贡献统计
code_contributions = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: nil})
commit_all = code_contributions["commit_count"]
addition_all = code_contributions["additions"]
deletion_all = code_contributions["deletions"]
commit_user = 0
addition_user = 0
deletion_user = 0
code_contributions["authors"].each do |author|
if author["name"] == @user.login
commit_user = author["commits"]
addition_user = author["additions"]
deletion_user = author["deletions"]
end
end
features["development"] = features["development"].merge({"commit" => {"all" => commit_all, "perc" => cal_perc(commit_user, commit_all)}})
features["development"] = features["development"].merge({"addition" => {"all" => addition_all, "perc" => cal_perc(addition_user, addition_all)}})
features["development"] = features["development"].merge({"deletion" => {"all" => deletion_all, "perc" => cal_perc(deletion_user, deletion_all)}})
def cal_weight(features)
weights = {} # 计算每一项的权重
categories = []
features.each do |key, _|
categories << key
weights[key] = Hash.new
end
count_all = 0
counts = {}
categories.each do |category|
count_1 = 0
features[category].each do |_, value|
count_1 += value["all"]
end
count_all += count_1
counts[category] = count_1
features[category].each do |key, value|
weight = cal_perc(value["all"], count_1)
weights[category] = weights[category].merge({key => weight})
end
end
categories.each do |category|
weight = cal_perc(counts[category], count_all)
weights[category] = weights[category].merge({"category_weight" => weight})
end
return weights
end
weights_categories = cal_weight(features)
scores = {
"final" => 0.0,
"blockchain" => false
}
features.each do |category, value_1|
category_score = 0.0
value_1.each do |action, value_2|
category_score += weights_categories[category][action] * value_2["perc"]
end
scores["final"] += weights_categories[category]["category_weight"] * category_score.round(4)
scores = scores.merge({category => category_score.round(4)})
end
end
render json: { scores: scores }
end
def hovercard
end
# author: zxh, 查询贡献者的贡献度
def hovercard4proj
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)
@ -94,11 +219,11 @@ class UsersController < ApplicationController
end
end
def update_image
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
def update_image
return render_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))
Util.write_file(@image, avatar_path(@user))
return render_ok({message: '头像修改成功'})
rescue Exception => e
uid_logger_error(e.message)
@ -141,6 +266,10 @@ class UsersController < ApplicationController
end
# TODO 等消息上线再打开注释
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
#
if(@user.logged?)
@user.daily_reward
end
rescue Exception => e
uid_logger_error(e.message)
missing_template
@ -284,6 +413,252 @@ class UsersController < ApplicationController
@projects = paginate(scope)
end
# query all projects with tokens by a user
def blockchain_balance
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
results = Blockchain::BalanceQuery.call(params, is_current_admin_user)
if results[:status] == 0
@total_count = results[:projects].size
@projects = results[:projects]
else
@total_count = -1
@projects = []
end
render json: { status: results[:status], projects: @projects, total_count: @total_count }
end
# query one balance
def blockchain_balance_one_project
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
owner = User.find_by(login: params['owner_login'])
if owner.nil?
normal_status(-1, "创建者无法找到")
else
p = Project.find_by(user_id: owner.id, identifier: params['project_identifier'])
balance = Blockchain::BalanceQueryOneProject.call({"user_id": params['user_id'].to_i, "project_id": p.id.to_i})
render json: { status: 0, balance: balance}
end
else
normal_status(-1, "缺少权限")
end
end
def blockchain_transfer
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['payer_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
Blockchain::TransferService.call(params)
render json: {status: 2} # 重新查询余额
else
normal_status(-1, "缺少权限")
end
rescue Exception => e
normal_status(-1, e.to_s)
end
# exchange money
def blockchain_exchange
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
#require 'alipay'
## setup the client to communicate with either production API or sandbox API
## https://openapi.alipay.com/gateway.do (Production)
## https://openapi.alipaydev.com/gateway.do (Sandbox)
#api_url = 'https://openapi.alipay.com/gateway.do'
#
## setup your own credentials and certificates
#app_id = '2021002140631434'
#app_private_key="-----BEGIN RSA PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCPDsgc0n0RWRnbe9OMqtUbde8gu88OyjuZm8cJXeiSING18HX56C5zV4DsHQ6K9/JmQi/NYCc7/2Prh66Bei0L4Xm5TysJTPYi90+WlbJJESFF6fqULi8sSqZXUtaoMKRcUyeR144l2GQgXbZWBbVSQeZW5DqUDlurTF0I7vQ21wGqxQqBjQK8PSVw5hF+aIsNOfAY9M1tzdD5Jzo2Y3FJdsbXIJNMyhJJCZ+7KHFqma7lpjkXdCoyh/nOISkQdGtFI29gI94sqewI2AMU84uxuBIE3h90iLT+8xrd2dQKdBS7qfhQ3PgkBPVNs5jxsVBqSFdSFT6zcqFdHJzulCUJAgMBAAECggEAWocAGz0X5+J6emnhdSKluLrol85BORrAnHP3f/XtNouOKZQBFCPZQSQecUvx5/7/ZbZ8iXpPWahDkshJpaWq29nTLXDryvboyze1JZWVPKeaZqOp7htLvrt+h8PkEoq1d7cnUyMU0N4eflzPBaCXHXaWTGYgq5Bqcfvg48ZSxGBYeHt5WWU2+GW5fpsaVBBYkdyxxGMoy/bzYzGhvfSJkexqnl0XkAAODa02mu3WsHrzRid6Mf+3syYbq/MfUodU6Vng2tbCqwnWrHCyrD4RYl6rg1TKuAv2YAfBhLzwBxHYVC4SRqzjs+8AaOQoF+lCjr4JklPhEuRThzD31YwIAQKBgQDAg4S7ciMmxvbNxR+1eimoAYLLF9jPpPU6w3VFNPb4rDu4tX77bNf082YplfJX5TYtZKjKPKyYG87K6slGunyPL4AFRW81WPB9u1uP26dihyPCBSUE01jKRPPfRrQnnru5fpm8LL3L03V3yA6J+GyQ8wltRJJi1eBSSm+IWRsZewKBgQC+PBD9J1LYOEIVeK9KvN8BpkA1ZIkk//VuJaoGfVXn+1EzM1yFB05fnsEQkHFynisvuCIr7pH63HcdyffQhe1YOnw9iDCG1zPjsi5uTe9WAM0dnb7xdsaLPr/Q2LyoDOTN9344Qovy1AAnpWtGTn6omgHst5nZpp/mHOuBlKiqSwKBgBKRXM77fjpyPEGyfpFxW+0xYB0YirfUUDa/vWLUbfGkIwp4ruuvHtEoXLUsGjiyCdys9b6zxW3SWMqnhIxG1la1HSLlBInfryphVL52UBmnsSI4fs6NV+YCaocheaTMoYyNkmRc6F1tYsoPyJ80D7yXRFR+paPUvxMQzNsYxQ1bAoGAHd2uSSBQWFPUxCwzUQd/93FTaU6EXYO103okTGqG/ymsoN4ya0wvWMHCy8fxl64PV6mP69fDoV/Vb57SwjEUhyJ/eOWVwMWuhtPliDnCFn1/tmOao6wjFZ9fW/l6/OMxVMjDTy/bat8vuwm0YtBWAEBVhwV4KPyI5AasTqa5KCsCgYB/usnqhVx2zt+MxpBt2Q9Vxc0zXcZxMDs69UUdTY86gjcJyCFGe3bbumUcyfSJzIznC2hfFX5ZyS0oMwiAzWtslRMh9LRh3kofD/6BogL3RKOlBk3iekvQ8Gn0tbwk2Qzr4WJgfA7A4GTf5r7Y+bvOfazzsUQAfSK6nUTIlOj2Ew==\n-----END RSA PRIVATE KEY-----\n"
#alipay_public_key="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgHXLD1BshMymbqqtZVKNyo95FNfxzXzaw3P1eI0KeO6RaL+JzrWxzIBFfTjkWv/8WM9u/NcXMOFt2QO9q5KIDx6PkqjRDTd1hgP/cTgdjOHQqnVSihCrQDVCDBSOXIujC8Lk/P4pFVRhQkYeZqEb1qb8b/2tzTY8g9PKKBSCQv7SfgL2TBcpAVbb+9xdJ6VainC/wYGk8T+c+st1hXnuBJSS0m7LFxJOsYkNk0wbA0tfdZLrO3us2F7sjC9t4h/05nr+gSuDkzo+1kCEefYLqScexN+vnQiLoylp/C82wNiP6okxfhmHz3EcYfUqUyGTN/oFaFcPFPpUtFNS8jFV9QIDAQAB\n-----END PUBLIC KEY-----\n"
#
## initialize a client to communicate with the Alipay API
#@alipay_client = Alipay::Client.new(
# url: api_url,
# app_id: app_id,
# app_private_key: app_private_key,
# alipay_public_key: alipay_public_key
#)
#
#return_result = @alipay_client.page_execute_url(
# method: 'alipay.trade.page.pay',
# biz_content: JSON.generate({
# out_trade_no: '20210420104600',
# product_code: 'FAST_INSTANT_TRADE_PAY',
# total_amount: '0.01',
# subject: 'test'
# }, ascii_only: true), # ascii_only is important!
# timestamp: '2021-04-20 10:46:00'
#)
#render json: { pay_url: return_result }
#
# 替代解决方案
# 读取所有交易信息
end
def blockchain_create_trade
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
user_id = params['user_id'].to_i
project_id = params['project_id'].to_i
money = params['money'].to_f
#description = params['description']
token_num = params['token_num'].to_i
# 锁仓
result = Blockchain::CreateTrade.call({user_id: user_id, project_id: project_id, token_num: token_num})
if result == false
normal_status(-1, "创建交易失败")
else
bt = BlockchainTrade.new(user_id: user_id, project_id: project_id, token_num: token_num, money: money, state: 0) # state=0表示创建交易; state=1表示执行中; state=2表示执行完成
bt.save()
status = 2 # 交易创建成功
render json: { status: status }
end
else
normal_status(-1, "缺少权限")
end
end
def blockchain_get_trades
trades = BlockchainTrade.where(state: 0).all()
results = []
trades.each do |t|
project_id = t.project_id
project = Project.find_by(id: project_id)
if !project.nil?
owner = User.find_by(id: project.user_id)
else
owner = nil
end
user_id = t.user_id
creator = User.find_by(id: user_id)
if project.nil? || owner.nil? || creator.nil?
else
results << [creator, owner, project, t]
end
end
render json: { results: results }
end
def blockchain_trade
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
user_id2 = params['user_id2'].to_i
trade_id = params['trade_id'].to_i
BlockchainTrade.find(trade_id).update(user_id2: user_id2, state: 1) # state=1表示锁定了等待线下卖家发货
render json: {status: 2} # window.location.reload()
else
normal_status(-1, "缺少权限")
end
end
def blockchain_verify_trade
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
trade_id = params['trade_id'].to_i
BlockchainTrade.find(trade_id).update(state: 2) # state=2表示确认收货
render json: {status: 2} # window.location.reload()
else
normal_status(-1, "缺少权限")
end
end
def blockchain_get_verify_trades
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
trades = BlockchainTrade.where(state: 1).all()
results = []
trades.each do |t|
project_id = t.project_id
project = Project.find_by(id: project_id)
if !project.nil?
owner = User.find_by(id: project.user_id)
else
owner = nil
end
user_id = t.user_id
creator = User.find_by(id: user_id)
user_id2 = t.user_id2
buyer = User.find_by(id: user_id2)
if project.nil? || owner.nil? || creator.nil? || buyer.nil?
else
results << [creator, owner, project, t, buyer]
end
end
render json: { results: results }
else
normal_status(-1, "缺少权限")
end
end
def blockchain_get_history_trades
#is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == params['user_id'].to_i)
is_current_admin_user = true
if is_current_admin_user
trades = BlockchainTrade.where(state: 2).all()
results = []
trades.each do |t|
project_id = t.project_id
project = Project.find_by(id: project_id)
if !project.nil?
owner = User.find_by(id: project.user_id)
else
owner = nil
end
user_id = t.user_id
creator = User.find_by(id: user_id)
user_id2 = t.user_id2
buyer = User.find_by(id: user_id2)
if project.nil? || owner.nil? || creator.nil? || buyer.nil?
else
results << [creator, owner, project, t, buyer]
end
end
render json: { results: results }
else
normal_status(-1, "缺少权限")
end
end
def blockchain_get_issue_token_num
issue_id = params["issue_id"]['orderId'].to_i
issue = Issue.find_by(id: issue_id)
project = Project.find(issue.project_id)
if project[:use_blockchain]
render json: {"blockchain_token_num": issue.blockchain_token_num}
else
render json: {"blockchain_token_num": -1} # 未使用blockchain
end
end
def blockchain_get_unclosed_issue_list
ownername = params["ownername"]
identifier = params["reponame"]
owner = User.find_by(login: ownername)
project = Project.find_by(user_id: owner.id, identifier: identifier)
unclosed_issues = Issue.where(project_id: project.id, issue_classify: "issue").where.not(status_id: 5)
results = []
unclosed_issues.each do |i|
results << [i.id, i.subject]
end
render json: {unclosed_issues: results}
end
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
# 该方法主要用于别的平台初次部署对接forge平台同步用户后gitea平台对应的用户密码与forge平台用户密码不一致是问题
def sync_gitea_pwd
@ -302,6 +677,21 @@ class UsersController < ApplicationController
render_ok
end
def update_sponsor_description
@user = User.find params[:id]
if @user.id == User.current.id
# @user.update(description: params[:description])
@user.sponsor_description = params[:sponsor_description]
if @user.save!
render_ok
else
render_error
end
else
render_error
end
end
def sync_user_info
user = User.find_by_login params[:login]
return render_forbidden unless user === current_user
@ -322,7 +712,7 @@ class UsersController < ApplicationController
end
end
def email_search
def email_search
return render_error('请输入email') if params[:email].blank?
@user = User.find_by(mail: params[:email])
end
@ -339,7 +729,7 @@ class UsersController < ApplicationController
:occupation, :technical_title,
:school_id, :department_id, :province, :city,
:custom_department, :identity, :student_id, :description,
:show_super_description, :super_description,
:show_super_description, :super_description,:sponsor_description,
:show_email, :show_location, :show_department]
)
end

View File

@ -4,6 +4,7 @@ class VersionReleasesController < ApplicationController
before_action :require_login, except: [:index, :show]
before_action :check_release_authorize, except: [:index, :show]
before_action :find_version , only: [:show, :edit, :update, :destroy]
skip_after_action :user_trace_log, only: [:update]
def index
@version_releases = kaminari_paginate(@repository.version_releases.order(created_at: :desc))
@ -22,7 +23,7 @@ class VersionReleasesController < ApplicationController
end
end
def show
def show
# @release = Gitea::Versions::GetService.call(current_user.gitea_token, @user&.login, @repository&.identifier, @version&.version_gid)
end
@ -83,14 +84,14 @@ class VersionReleasesController < ApplicationController
ActiveRecord::Base.transaction do
begin
version_params = releases_params
old_value = old_value_to_hash(@version, version_params)
if @version.update_attributes!(version_params)
create_attachments(params[:attachment_ids], @version) if params[:attachment_ids].present?
git_version_release = Gitea::Versions::UpdateService.new(current_user.gitea_token, @user.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
unless git_version_release
raise Error, "更新失败"
end
user_trace_update_log(old_value)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")

View File

@ -0,0 +1,113 @@
class WalletsController < ApplicationController
before_action :require_login, except: :community_data
def balance
user = User.find_by_id(params[:id])
@wallet = user.get_wallet
end
def coin_changes
user = User.find_by_id(params[:id])
@wallet = user.get_wallet
if params[:category] == 'all'
scope = CoinChange.where('to_wallet_id = ? OR from_wallet_id = ?', @wallet.id, @wallet.id)
elsif params[:category] == 'income'
# @coin_changes = CoinChange.where('to_wallet_id = ?', @wallet.id).limit(100)
scope = @wallet.income
elsif params[:category] == 'outcome'
scope = @wallet.outcome
end
sort = params[:sort_by] || "created_at"
sort_direction = params[:sort_direction] || "desc"
scope = scope.reorder("#{sort} #{sort_direction}") unless scope.nil?
@total = 0
@total = scope.length unless scope.nil?
@coin_changes = kaminari_paginate(scope) unless scope.nil?
end
def balance_chart
user = User.find_by_id(params[:id])
@wallet = user.get_wallet
scope = CoinChange.where('to_wallet_id = ? OR from_wallet_id = ?', @wallet.id, @wallet.id)
t1 = Time.now
t2 = Time.new(t1.year, t1.month, t1.day - 6)
@balance_chart_data = scope.where('created_at > ? AND created_at < ?', t2, t1)
@balance_chart_array = to_array(@balance_chart_data, @wallet.id)
end
def community_data
t1 = Time.now
t2 = Time.new(t1.year, t1.month, t1.day - 6)
coin_changes = CoinChange.where('created_at >= ?', t2)
@community_data_array = community_data_to_array(coin_changes)
end
private
def to_array(data, id)
t1 = Time.now
start_time = Time.new(t1.year, t1.month, t1.day - 6)
end_time = Time.new(start_time.year, start_time.month, start_time.day + 1)
income = Array.new(7, 0) # 收入、支出
outcome = Array.new(7, 0)
date = Array.new(7)
date[0] = Time.new(start_time.year, start_time.month, start_time.day)
index = 0
data.each do |i|
# 更新日期
until (i.created_at >= start_time) && (i.created_at < end_time)
index += 1
start_time = end_time
end_time = Time.new(start_time.year, start_time.month, start_time.day + 1)
date[index] = Time.new(start_time.year, start_time.month, start_time.day)
end
if i.from_wallet_id == id
outcome[index] += i.amount
else
next if params[:sponsor] == true && i.from_wallet_id.nil?
income[index] += i.amount
end
end
until end_time >= Time.now
index += 1
start_time = end_time
end_time = Time.new(start_time.year, start_time.month, start_time.day + 1)
date[index] = Time.new(start_time.year, start_time.month, start_time.day)
end
Array[income, outcome, date]
end
def community_data_to_array(coin_changes)
t1 = Time.now
start_time = Time.new(t1.year, t1.month, t1.day - 6)
nums = Array.new(7, 0)
date = Array.new(7)
end_time = Array.new(7)
# date[0] = Time.new(start_time.year, start_time.month, start_time.day)
index = 0
(0..6).each do |i|
# 更新日期date[i]表示第i天0点
date[i] = Time.new(start_time.year, start_time.month, start_time.day + i)
end_time[i] = Time.new(start_time.year, start_time.month, start_time.day + i+1)
end
coin_changes.each do |cc|
(0..6).each do |i|
if !cc.from_wallet_id.nil? && cc.created_at>=date[i] && cc.created_at<end_time[i]
nums[i] += 1
end
end
end
Array[nums, date]
end
end

View File

@ -30,6 +30,14 @@ class BaseForm
raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists?
end
def check_blockchain_token_all(blockchain_token_all)
raise "请正确填写项目token总数." if (Float(blockchain_token_all) rescue false) == false or blockchain_token_all.to_i < 0 or Float(blockchain_token_all) != blockchain_token_all.to_i
end
def check_blockchain_init_token(blockchain_init_token)
raise "请正确填写项目创始人token占比." if (Float(blockchain_init_token) rescue false) == false or blockchain_init_token.to_i < 0 or blockchain_init_token.to_i > 100 or Float(blockchain_init_token) != blockchain_init_token.to_i
end
def check_reversed_keyword(repository_name)
raise "项目标识已被占用." if ReversedKeyword.check_exists?(repository_name)
end

View File

@ -1,6 +1,7 @@
class Projects::CreateForm < BaseForm
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
:project_language_id, :ignore_id, :license_id, :private, :owner
:project_language_id, :ignore_id, :license_id, :private, :owner,
:blockchain, :blockchain_token_all, :blockchain_init_token
validates :user_id, :name, :repository_name, presence: true
validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
@ -15,6 +16,8 @@ class Projects::CreateForm < BaseForm
check_project_language(project_language_id)
check_project_name(user_id, name) unless name.blank?
check_repository_name(user_id, repository_name) unless repository_name.blank?
check_blockchain_token_all(blockchain_token_all) unless blockchain_token_all.blank?
check_blockchain_init_token(blockchain_init_token) unless blockchain_init_token.blank?
end
def check_license

View File

@ -0,0 +1,2 @@
module LogHelper
end

View File

@ -0,0 +1,2 @@
module SponsorTiersHelper
end

View File

@ -0,0 +1,2 @@
module SponsorshipsHelper
end

View File

@ -21,7 +21,8 @@ module TagChosenHelper
"issue_tag": render_issue_tags(project),
"issue_type": render_issue_species,
"all_issues": all_issues,
"branches": render_branches(project)
"branches": render_branches(project),
"use_blockchain": project['use_blockchain']
}
end

View File

@ -0,0 +1,6 @@
module UpdateHelper
def old_value_to_hash(old_value, params)
params = params.dup.stringify_keys
old_value.attributes.select { |key, value| params.key?(key) }
end
end

View File

@ -0,0 +1,2 @@
module WalletsHelper
end

View File

@ -0,0 +1,15 @@
class MonthlyPaymentWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence do
minutely(2)
# monthly.day_of_month(12) #每月的12号0点执行
# monthly.day_of_month(23).hour_of_day(20) #每月的12号1点执行
end
def perform(*args)
Sponsorship.monthly_payment
puts Time.now, 'sponsor payment done'
end
end

20
app/libs/blockchain.rb Normal file
View File

@ -0,0 +1,20 @@
class Blockchain
class << self
def blockchain_config
blockchain_config = {}
begin
config = Rails.application.config_for(:configuration).symbolize_keys!
blockchain_config = config[:blockchain].symbolize_keys!
raise 'blockchain config missing' if blockchain_config.blank?
rescue => ex
raise ex if Rails.env.production?
puts %Q{\033[33m [warning] blockchain config or configuration.yml missing,
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
blockchain_config = {}
end
blockchain_config
end
end
end

View File

@ -17,7 +17,7 @@
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :string(255)
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
@ -26,15 +26,15 @@
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
# link :string(255)
# clone_id :integer
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_clone_id (clone_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#

View File

@ -0,0 +1,18 @@
# == Schema Information
#
# Table name: blockchain_trades
#
# id :integer not null, primary key
# project_id :integer
# description :text(65535)
# money :float(24)
# created_at :datetime not null
# updated_at :datetime not null
# user_id :integer
# state :integer
# user_id2 :integer
# token_num :integer
#
class BlockchainTrade < ApplicationRecord
end

View File

@ -39,15 +39,18 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# sponsor_description :text(65535)
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# award_time :datetime
#
# Indexes
#
@ -55,9 +58,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#

19
app/models/coin_change.rb Normal file
View File

@ -0,0 +1,19 @@
# == Schema Information
#
# Table name: coin_changes
#
# id :integer not null, primary key
# amount :integer
# description :string(255)
# reason :string(255)
# to_wallet_id :integer
# from_wallet_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class CoinChange < ApplicationRecord
belongs_to :to_wallet, class_name: 'Wallet'
belongs_to :from_wallet, class_name: 'Wallet', optional: true
validates :amount, presence: true
end

View File

@ -1,45 +1,160 @@
module Watchable
extend ActiveSupport::Concern
included do
has_many :watchers, as: :watchable, dependent: :destroy
has_many :watcher_users, through: :watchers, source: :user, validate: false
scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) }
scope :following, -> (user_id) { watched_by(user_id) }
end
def watched?(watchable)
watchable.watchers.exists?(user: self)
end
def watch!(watchable)
watchable.watchers.create!(user: self, created_at: Time.current)
end
def unwatch!(watchable)
obj = watchable.watchers.find_by(user: self)
obj.destroy! if obj.present?
end
# 我正在关注的、我追随的
def following
User.following(self.id)
end
def following_count
following.size
end
# 关注我的、我的粉丝、我的追随者
def followers
watcher_users
end
def followers_count
followers.size
end
module ClassMethods
end
end
module Watchable
extend ActiveSupport::Concern
included do
has_many :watchers, as: :watchable, dependent: :destroy
has_many :watcher_users, through: :watchers, source: :user, validate: false
scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) }
scope :following, -> (user_id) { watched_by(user_id) }
end
def watched?(watchable)
watchable.watchers.exists?(user: self)
end
def watch!(watchable)
watchable.watchers.create!(user: self, created_at: Time.current)
end
def unwatch!(watchable)
obj = watchable.watchers.find_by(user: self)
obj.destroy! if obj.present?
end
# 我正在关注的、我追随的
def following
User.following(self.id)
end
def following_count
following.size
end
def contribution_perc
project_identifier = params[:project_identifier]
user_login = params[:id]
@project = Project.find_by_identifier(project_identifier)
@user = User.find_by_login(user_login)
def cal_perc(count_user, count_all)
(count_user * 1.0 / (count_all + 0.000000001)).round(5)
end
if @project['use_blockchain'] == true or @project['use_blockchain'] == 1
balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": @user.id, "project_id": @project.id})
balance_all = Blockchain::RepoBasicInfo.call({"project_id": @project.id})["cur_supply"]
score = cal_perc(balance_user, balance_all)
else
# 获取所有行为对应的项目内记录总数和个人记录数
features = {
"requirement" => {},
"development" => {},
"review" => {}
}
# 1. issue创建
issues = Issue.where(project_id: @project.id, issue_classify: 'issue')
issue_all = issues.count
issue_user = issues.where(author_id: @user.id).count
features["requirement"] = features["requirement"].merge({"issue" => {"all" => issue_all, "perc" => cal_perc(issue_user, issue_all)}})
# 2. 里程碑创建
milestones = Version.where(project_id: @project.id)
milestone_all = milestones.count
milestone_user = milestones.where(user_id: @user.id).count
features["requirement"] = features["requirement"].merge({"milestone" => {"all" => milestone_all, "perc" => cal_perc(milestone_user, milestone_all)}})
# 3. issue评论
issue_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{@project.id} and journalized_type='Issue' and issues.issue_classify='issue'")
issue_comment_all = issue_comments.count
issue_comment_user = issue_comments.where("journals.user_id=#{@user.id}").count
features["requirement"] = features["requirement"].merge({"issue_comment" => {"all" => issue_comment_all, "perc" => cal_perc(issue_comment_user, issue_comment_all)}})
# 4. 合并请求
prs = PullRequest.where(project_id: @project.id)
pr_all = prs.count
pr_user = prs.where(user_id: @user.id).count
features["development"] = features["development"].merge({"pr" => {"all" => pr_all, "perc" => cal_perc(pr_user, pr_all)}})
# 5. pr评论
pr_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{@project.id} and journalized_type='Issue' and issues.issue_classify='pull_request'")
pr_comment_all = pr_comments.count
pr_comment_user = pr_comments.where("journals.user_id=#{@user.id}").count
features["review"] = features["review"].merge({"pr_comment" => {"all" => pr_comment_all, "perc" => cal_perc(pr_comment_user, pr_comment_all)}})
# 6. 代码行评论
line_comments = Journal.joins("INNER JOIN pull_requests on journals.journalized_id=pull_requests.id").where("pull_requests.project_id=#{@project.id} and journalized_type='PullRequest'")
line_comment_all = line_comments.count
line_comment_user = line_comments.where("journals.user_id=#{@user.id}").count
features["review"] = features["review"].merge({"line_comment" => {"all" => line_comment_all, "perc" => cal_perc(line_comment_user, line_comment_all)}})
# 7. 代码行、commit贡献统计
code_contributions = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: nil})
commit_all = code_contributions["commit_count"]
addition_all = code_contributions["additions"]
deletion_all = code_contributions["deletions"]
commit_user = 0
addition_user = 0
deletion_user = 0
code_contributions["authors"].each do |author|
if author["name"] == @user.login
commit_user = author["commits"]
addition_user = author["additions"]
deletion_user = author["deletions"]
end
end
features["development"] = features["development"].merge({"commit" => {"all" => commit_all, "perc" => cal_perc(commit_user, commit_all)}})
features["development"] = features["development"].merge({"addition" => {"all" => addition_all, "perc" => cal_perc(addition_user, addition_all)}})
features["development"] = features["development"].merge({"deletion" => {"all" => deletion_all, "perc" => cal_perc(deletion_user, deletion_all)}})
def cal_weight(features)
weights = {} # 计算每一项的权重
categories = []
features.each do |key, _|
categories << key
weights[key] = Hash.new
end
count_all = 0
counts = {}
categories.each do |category|
count_1 = 0
features[category].each do |_, value|
count_1 += value["all"]
end
count_all += count_1
counts[category] = count_1
features[category].each do |key, value|
weight = cal_perc(value["all"], count_1)
weights[category] = weights[category].merge({key => weight})
end
end
categories.each do |category|
weight = cal_perc(counts[category], count_all)
weights[category] = weights[category].merge({"category_weight" => weight})
end
return weights
end
weights_categories = cal_weight(features)
score = 0.0
features.each do |category, value_1|
category_score = 0.0
value_1.each do |action, value_2|
category_score += weights_categories[category][action] * value_2["perc"]
end
score += weights_categories[category]["category_weight"] * category_score.round(4)
end
end
score
(score * 100).round(1).to_s + "%"
end
# 关注我的、我的粉丝、我的追随者
def followers
watcher_users
end
def followers_count
followers.size
end
module ClassMethods
end
end

View File

@ -1,18 +1,19 @@
# == Schema Information
#
# Table name: edu_settings
#
# id :integer not null, primary key
# name :string(255)
# value :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255)
#
# Indexes
#
# index_edu_settings_on_name (name) UNIQUE
#
# == Schema Information
#
# Table name: edu_settings
#
# id :integer not null, primary key
# name :string(255)
# value :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255)
#
# Indexes
#
# index_edu_settings_on_name (name) UNIQUE
#
class EduSetting < ApplicationRecord
after_commit :expire_value_cache

View File

@ -1,3 +1,24 @@
# == Schema Information
#
# Table name: public_key
#
# id :integer not null, primary key
# owner_id :integer not null
# name :string(255) not null
# fingerprint :string(255) not null
# content :text(65535) not null
# mode :integer default("2"), not null
# type :integer default("1"), not null
# login_source_id :integer default("0"), not null
# created_unix :integer
# updated_unix :integer
#
# Indexes
#
# IDX_public_key_fingerprint (fingerprint)
# IDX_public_key_owner_id (owner_id)
#
class Gitea::PublicKey < Gitea::Base
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
# establish_connection :gitea_db

View File

@ -6,9 +6,6 @@
# type :integer
# status :integer
# conflicted_files :text(65535)
# commits_ahead :integer
# commits_behind :integer
# changed_protected_files :text(65535)
# issue_id :integer
# index :integer
# head_repo_id :integer
@ -20,6 +17,11 @@
# merged_commit_id :string(40)
# merger_id :integer
# merged_unix :integer
# commits_ahead :integer
# commits_behind :integer
# changed_protected_files :text(65535)
# commit_num :integer
# changed_files :integer
#
# Indexes
#

View File

@ -1,4 +1,37 @@
class Gitea::Webhook < Gitea::Base
# == Schema Information
#
# Table name: webhook
#
# id :integer not null, primary key
# repo_id :integer
# org_id :integer
# url :text(65535)
# http_method :string(255)
# content_type :integer
# secret :text(65535)
# events :text(65535)
# is_active :boolean
# meta :text(65535)
# last_status :integer
# created_unix :integer
# updated_unix :integer
# is_system_webhook :boolean default("0"), not null
# type :string(16)
# branch_filter :text(65535)
# signature :text(65535)
# is_ssl :boolean
# hook_task_type :integer
#
# Indexes
#
# IDX_webhook_created_unix (created_unix)
# IDX_webhook_is_active (is_active)
# IDX_webhook_org_id (org_id)
# IDX_webhook_repo_id (repo_id)
# IDX_webhook_updated_unix (updated_unix)
#
class Gitea::Webhook < Gitea::Base
serialize :events, JSON
self.inheritance_column = nil

View File

@ -1,6 +1,34 @@
class Gitea::WebhookTask < Gitea::Base
# == Schema Information
#
# Table name: hook_task
#
# id :integer not null, primary key
# repo_id :integer
# hook_id :integer
# uuid :string(255)
# payload_content :text(65535)
# event_type :string(255)
# is_delivered :boolean
# delivered :integer
# is_succeed :boolean
# request_content :text(65535)
# response_content :text(65535)
# type :string(255)
# url :text(65535)
# signature :text(65535)
# http_method :string(255)
# content_type :integer
# is_ssl :boolean
#
# Indexes
#
# IDX_hook_task_repo_id (repo_id)
#
class Gitea::WebhookTask < Gitea::Base
serialize :payload_content, JSON
serialize :request_content, JSON
serialize :response_content, JSON
self.inheritance_column = nil
@ -12,7 +40,7 @@ class Gitea::WebhookTask < Gitea::Base
def response_content_json
JSON.parse(response_content)
rescue
rescue
{}
end
end
end

View File

@ -33,6 +33,7 @@
# issue_classify :string(255)
# ref_name :string(255)
# branch_name :string(255)
# blockchain_token_num :integer
#
# Indexes
#

View File

@ -10,7 +10,6 @@
# sync_course :boolean default("0")
# sync_subject :boolean default("0")
# sync_shixun :boolean default("0")
# is_local :boolean default("0")
#
# Indexes
#

View File

@ -1,3 +1,17 @@
# == 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
end
end

View File

@ -39,15 +39,18 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# sponsor_description :text(65535)
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# award_time :datetime
#
# Indexes
#
@ -55,9 +58,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#

View File

@ -0,0 +1,16 @@
# == Schema Information
#
# Table name: passed_waitlists
#
# id :integer not null, primary key
# applicant_id :string(255)
# integer :string(255)
# reviewer_id :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class PassedWaitlist < ApplicationRecord
belongs_to :applicant, class_name: 'User'
belongs_to :reviewer, class_name: 'User'
end

View File

@ -1,19 +1,20 @@
# == Schema Information
#
# Table name: praise_treads
#
# id :integer not null, primary key
# user_id :integer not null
# praise_tread_object_id :integer
# praise_tread_object_type :string(255)
# praise_or_tread :integer default("1")
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# praise_tread (praise_tread_object_id,praise_tread_object_type)
#
# == Schema Information
#
# Table name: praise_treads
#
# id :integer not null, primary key
# user_id :integer not null
# praise_tread_object_id :integer
# praise_tread_object_type :string(255)
# praise_or_tread :integer default("1")
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# praise_tread (praise_tread_object_id,praise_tread_object_type)
#
class PraiseTread < ApplicationRecord

View File

@ -55,6 +55,7 @@
# default_branch :string(255) default("master")
# website :string(255)
# lesson_url :string(255)
# use_blockchain :boolean default("0")
# is_pinned :boolean default("0")
# recommend_index :integer default("0")
#
@ -63,6 +64,7 @@
# index_projects_on_forked_from_project_id (forked_from_project_id)
# index_projects_on_identifier (identifier)
# index_projects_on_invite_code (invite_code)
# index_projects_on_is_pinned (is_pinned)
# index_projects_on_is_public (is_public)
# index_projects_on_lft (lft)
# index_projects_on_license_id (license_id)
@ -124,14 +126,14 @@ 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
has_many :user_trace_tasks, dependent: :destroy
has_many :project_invite_links, dependent: :destroy
after_create :incre_user_statistic, :incre_platform_statistic
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)}
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, :use_blockchain)}
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
scope :pinned, -> {where(is_pinned: true)}
@ -192,7 +194,7 @@ class Project < ApplicationRecord
end
end
def incre_user_statistic
def incre_user_statistic
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1, project_language_count_key: self.project_language&.name, project_language_count: 1}, self.user_id)
end
@ -235,7 +237,7 @@ class Project < ApplicationRecord
unless self.is_public
self.recommend = false
self.recommend_index = 0
self.is_pinned = false
self.is_pinned = false
end
end

View File

@ -27,6 +27,7 @@
#
# Indexes
#
# index_repositories_on_identifier (identifier)
# index_repositories_on_project_id (project_id)
# index_repositories_on_user_id (user_id)
#

View File

@ -0,0 +1,16 @@
# == Schema Information
#
# Table name: sponsor_tiers
#
# id :integer not null, primary key
# tier :integer
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255) default("")
# user_id :integer
#
class SponsorTier < ApplicationRecord
belongs_to :user
end

49
app/models/sponsorship.rb Normal file
View File

@ -0,0 +1,49 @@
# == Schema Information
#
# Table name: sponsorships
#
# id :integer not null, primary key
# amount :integer
# visible :integer
# sponsor_id :integer
# developer_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# accumulate :integer default("0")
#
class Sponsorship < ApplicationRecord
belongs_to :sponsor, class_name: 'User'
belongs_to :developer, class_name: 'User'
validates :amount, presence: true
def stop
stopped_sponsorship = StoppedSponsorship.new(developer_id: developer_id, sponsor_id: sponsor_id, start_time: created_at, amount: amount, visible: visible, accumulate: accumulate)
stopped_sponsorship.save && destroy
end
def pay
sponsor_wallet = sponsor.get_wallet
developer_wallet = developer.get_wallet
success = false
Wallet.transaction do
success = sponsor_wallet.pay(amount)
if success
developer_wallet.receive(amount)
update(accumulate: self.accumulate += amount)
reason = "#{sponsor.full_name}#{developer.full_name}的赞助支付。"
coinchange = CoinChange.new(amount: amount, reason: reason, to_wallet_id: developer_wallet.id, from_wallet_id: sponsor_wallet.id)
return true if coinchange.save
end
end
success
end
def self.monthly_payment
sponsorships = Sponsorship.all
sponsorships.each do |s|
s.stop unless s.pay
end
end
end

26
app/models/statistic.rb Normal file
View File

@ -0,0 +1,26 @@
# == Schema Information
#
# Table name: statistics
#
# id :integer not null, primary key
# dau :integer
# created_at :datetime not null
# updated_at :datetime not null
# wau :integer
# mau :integer
#
class Statistic < ApplicationRecord
def self.record
users = User.all
count = 0
t = Time.now - 1.day
# t = Time.now.at_beginning_of_day
users.each do |u|
if !u.last_login_on.nil? && u.last_login_on >= t
count += 1
end
end
Statistic.create(dau: count)
end
end

View File

@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: stopped_sponsorships
#
# id :integer not null, primary key
# amount :integer
# sponsor_id :integer
# developer_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# start_time :datetime
# visible :integer
# accumulate :integer default("0")
#
class StoppedSponsorship < ApplicationRecord
belongs_to :sponsor, class_name: 'User'
belongs_to :developer, class_name: 'User'
validates :amount, presence: true
end

View File

@ -2,16 +2,16 @@
#
# Table name: system_notification_histories
#
# id :integer not null, primary key
# system_message_id :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# id :integer not null, primary key
# system_notification_id :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_system_notification_histories_on_system_message_id (system_message_id)
# index_system_notification_histories_on_user_id (user_id)
# index_system_notification_histories_on_system_notification_id (system_notification_id)
# index_system_notification_histories_on_user_id (user_id)
#
class SystemNotificationHistory < ApplicationRecord

View File

@ -6,9 +6,9 @@
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# openning :boolean default("1")
# notification_disabled :boolean default("1")
# email_disabled :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#

View File

@ -6,9 +6,9 @@
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# openning :boolean default("1")
# notification_disabled :boolean default("1")
# email_disabled :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#

View File

@ -6,9 +6,9 @@
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# openning :boolean default("1")
# notification_disabled :boolean default("1")
# email_disabled :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#

View File

@ -6,9 +6,9 @@
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# openning :boolean default("1")
# notification_disabled :boolean default("1")
# email_disabled :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#

View File

@ -6,9 +6,9 @@
# type :string(255)
# name :string(255)
# key :string(255)
# openning :boolean
# notification_disabled :boolean
# email_disabled :boolean
# openning :boolean default("1")
# notification_disabled :boolean default("1")
# email_disabled :boolean default("0")
# created_at :datetime not null
# updated_at :datetime not null
#

View File

@ -1,18 +1,19 @@
# == Schema Information
#
# Table name: tokens
#
# id :integer not null, primary key
# user_id :integer default("0"), not null
# action :string(30) default(""), not null
# value :string(40) default(""), not null
# created_on :datetime not null
#
# Indexes
#
# index_tokens_on_user_id (user_id)
# tokens_value (value) UNIQUE
#
# == Schema Information
#
# Table name: tokens
#
# id :integer not null, primary key
# user_id :integer default("0"), not null
# action :string(30) default(""), not null
# value :string(40) default(""), not null
# created_on :datetime not null
#
# Indexes
#
# index_tokens_on_user_id (user_id)
# tokens_value (value) UNIQUE
#
#
# This program is free software; you can redistribute it and/or

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#
@ -14,4 +13,4 @@
# GLCC 新闻稿
class Topic::GlccNews < Topic
end
end

View File

@ -6,7 +6,6 @@
# type :string(255)
# title :string(255)
# uuid :integer
# image_url :string(255)
# url :string(255)
# order_index :integer
#

View File

@ -39,15 +39,18 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# sponsor_description :text(65535)
# devops_step :integer default("0")
# gitea_token :string(255)
# platform :string(255)
# award_time :datetime
#
# Indexes
#
@ -55,9 +58,8 @@
# index_users_on_homepage_engineer (homepage_engineer)
# index_users_on_homepage_teacher (homepage_teacher)
# index_users_on_laboratory_id (laboratory_id)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_login (login)
# index_users_on_mail (mail)
# index_users_on_type (type)
#
@ -161,6 +163,18 @@ class User < Owner
has_many :project_trends, dependent: :destroy
has_many :oauths , dependent: :destroy
# sponsor
has_many :as_sponsors, class_name: 'Sponsorship', foreign_key: 'sponsor_id', dependent: :destroy
has_many :as_sponsored, class_name: 'Sponsorship', foreign_key: 'developer_id', dependent: :destroy
has_many :stopped_sponsors, class_name: 'StoppedSponsorship', foreign_key: 'sponsor_id', dependent: :destroy
has_many :stopped_sponsored, class_name: 'StoppedSponsorship', foreign_key: 'developer_id', dependent: :destroy
has_many :sponsor_tier, dependent: :destroy
has_one :wallet, dependent: :destroy
has_many :waitlist, class_name: 'Waitlist', foreign_key: 'reviewer_id'
has_many :passed_waitlist, class_name: 'PassedWaitlist', foreign_key: 'reviewer_id' #as reviewer
has_one :application, class_name: 'Waitlist', foreign_key: 'applicant_id'
has_one :passed_application, class_name: 'PassedWaitlist', foreign_key: 'applicant_id'
has_many :organization_users, dependent: :destroy
has_many :organizations, through: :organization_users
has_many :pinned_projects, dependent: :destroy
@ -175,8 +189,8 @@ class User < Owner
has_many :system_notification_histories
has_many :system_notifications, through: :system_notification_histories
has_one :trace_user, dependent: :destroy
has_many :user_trace_tasks, dependent: :destroy
has_many :user_trace_tasks, dependent: :destroy
has_many :feedbacks, dependent: :destroy
# Groups and active users
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
@ -646,6 +660,7 @@ class User < Owner
# Returns the user who matches the given autologin +key+ or nil
def self.try_to_autologin(key)
user = Token.find_active_user('autologin', key)
# user.daily_reward if user
user.update(last_login_on: Time.now) if user
user
end
@ -817,6 +832,36 @@ class User < Owner
laboratory_id.present? && laboratory_id != 1
end
def get_wallet
if wallet.nil?
Wallet.transaction(isolation: :serializable) do
if wallet.nil?
create_wallet(balance: 100)
reason = "系统初始赠送"
CoinChange.create(amount: 100, reason: reason, to_wallet_id: wallet.id)
end
end
end
wallet
end
def daily_reward
if !Rails.application.config_for(:configuration)["sponsor"]
return
end
t1 = Time.now
t2 = Time.new(t1.year, t1.month, t1.day)
if(award_time.nil? or t2 > award_time)
self.update_column(:award_time, Time.now)
amount = 2
user_wallet = get_wallet
user_wallet.receive(amount)
reason = "每日登录奖励"
CoinChange.create(amount: amount, reason: reason, to_wallet_id: user_wallet.id)
end
end
def profile_is_completed?
self.nickname.present? && self.mail.present?
end

View File

@ -12,9 +12,7 @@
#
# Indexes
#
# index_user_actions_on_ip (ip)
# index_user_actions_on_user_id (user_id)
# index_user_actions_on_user_id_and_action_type (user_id,action_type)
# index_user_actions_on_ip (ip)
#
class UserAction < ApplicationRecord

View File

@ -10,13 +10,10 @@
# updated_at :datetime not null
# register_status :integer default("0")
# action_status :integer default("0")
# is_delete :boolean default("0")
# user_id :integer
#
# Indexes
#
# index_user_agents_on_ip (ip)
# index_user_agents_on_user_id (user_id)
# index_user_agents_on_ip (ip) UNIQUE
#
class UserAgent < ApplicationRecord

16
app/models/waitlist.rb Normal file
View File

@ -0,0 +1,16 @@
# == Schema Information
#
# Table name: waitlists
#
# id :integer not null, primary key
# applicant_id :string(255)
# integer :string(255)
# reviewer_id :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class Waitlist < ApplicationRecord
belongs_to :applicant, class_name: 'User'
belongs_to :reviewer, class_name: 'User', optional: true
end

42
app/models/wallet.rb Normal file
View File

@ -0,0 +1,42 @@
# == Schema Information
#
# Table name: wallets
#
# id :integer not null, primary key
# balance :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Wallet < ApplicationRecord
belongs_to :user
has_many :outcome, class_name: 'CoinChange', foreign_key: 'from_wallet_id', dependent: :destroy
has_many :income, class_name: 'CoinChange', foreign_key: 'to_wallet_id', dependent: :destroy
validates :balance, presence: true
@@wallet_lock = Mutex.new
def receive(amount)
with_lock do
self.balance += amount
save!
end
end
def pay(amount)
with_lock do
if self.balance < amount
reload
return false
else
self.balance -= amount
save!
end
end
true
end
def self.wallet_lock
@@wallet_lock
end
end

View File

@ -6,4 +6,53 @@ class ApplicationQuery
def strip_param(key)
params[key].to_s.strip.presence
end
# find all the repos that a user has tokens
def find_repo_with_token(user_id)
params = {
"request-type": "query user balance of all repos",
"username": user_id.to_s
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] != 0
raise "区块链接口请求失败."
else
token_list = resp_body['UserBalanceList'].nil? ? [] : resp_body['UserBalanceList']
return token_list
end
end
# find one repo that a user has tokens
def find_one_balance(user_id, project_id)
# return 3 statuses: UnknownErr/ResUserNotExisted/Success
params = {
"request-type": "query user balance of single repo",
"username": user_id.to_s,
"token_name": project_id.to_s
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 0
return resp_body['balance']
elsif resp_body['status'] == 100
return 0 # 找不到用户返回0
else
raise "区块链接口请求失败."
end
end
# query the basic info of a repository
def find_blockchain_repo_info(project_id)
params = {
"request-type": "query repo basic info",
"token_name": project_id.to_s
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 0
return resp_body
else
raise "区块链接口请求失败."
end
end
end

View File

@ -0,0 +1,31 @@
class Blockchain::BalanceQuery < ApplicationQuery
attr_reader :params, :is_current_admin_user
def initialize(params,is_current_admin_user)
@params = params
@is_current_admin_user = is_current_admin_user
end
def call
if is_current_admin_user
token_list = find_repo_with_token(params["user_id"])
result_list = []
token_list.each do |t|
project = Project.find_by(id: t['token_name'].to_i)
if project.nil?
next
end
owner = User.find_by(id: project.user_id)
if owner.nil? || project.nil?
else
balance = t['balance']
result_list << [owner, project, balance]
end
end
results = {"status": 0, "projects": result_list}
else
results = {"status": 1} # query failed
end
end
end

View File

@ -0,0 +1,12 @@
class Blockchain::BalanceQueryOneProject < ApplicationQuery
attr_reader :params, :is_current_admin_user
def initialize(params)
@params = params
end
def call
find_one_balance(params[:user_id].to_s, params[:project_id].to_s)
end
end

View File

@ -0,0 +1,13 @@
class Blockchain::RepoBasicInfo < ApplicationQuery
attr_reader :params, :is_current_admin_user
def initialize(params)
@params = params
end
def call
info = find_blockchain_repo_info(params[:project_id].to_s)
return info
end
end

View File

@ -38,6 +38,12 @@ class Projects::ListMyQuery < ApplicationQuery
# projects = projects.visible.joins(:members).where(members: { user_id: user.id })
# elsif params[:category].to_s == "private"
# projects = projects.is_private.joins(:members).where(members: { user_id: user.id })
elsif params[:category].to_s == "blockchain_token" # 所有钱包中有token的项目有哪些
token_list = find_repo_with_token(user.id)
project_names = token_list.map { |x| x['token_name'] }
projects = projects.where(name: project_names)
tokens = token_list.map { |x| x['balance'] }
puts "pause"
end
if params[:is_public].present?

View File

@ -1,26 +1,100 @@
class ApplicationService
include Callable
Error = Class.new(StandardError)
def regix_emoji content
" " if content.blank?
regex = /[^a-zA-Z0-9\u4E00-\u9FFF]/
content.gsub(regex, '')
end
private
def strip(str)
str.to_s.strip.presence
end
def str_to_boolean str
ActiveModel::Type::Boolean.new.cast str
end
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end
end
class ApplicationService
include Callable
Error = Class.new(StandardError)
def regix_emoji content
" " if content.blank?
regex = /[^a-zA-Z0-9\u4E00-\u9FFF]/
content.gsub(regex, '')
end
private
def strip(str)
str.to_s.strip.presence
end
def str_to_boolean str
ActiveModel::Type::Boolean.new.cast str
end
# params: params from index.js page
def create_repo_on_blockchain(params, project)
username = params['user_id'].to_s
token_name = project.id.to_s
total_supply = params['blockchain_token_all'].to_i
token_balance = [[username, (total_supply * params['blockchain_init_token'].to_i / 100).to_i]]
params = {
"request-type": "create repo",
"username": username,
"token_name": token_name,
"total_supply": total_supply,
"token_balance": token_balance
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] != 0
raise "区块链接口请求失败."
end
end
def transfer_balance_on_blockchain(payer, payee, token_name, amount)
params = {
"request-type": "transfer amount",
"payer": payer,
"payee": payee,
"token_name": token_name,
"amount": amount
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 5 or resp_body['status'] == 106 or resp_body['status'] == 105
raise resp_body['message']
elsif resp_body['status'] != 0
raise "区块链接口请求失败."
else
end
end
def lock_balance_on_blockchain(username, tokenname, amount)
params = {
"request-type": "lock user balance",
"username": username,
"token_name": tokenname,
"amount": amount
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 5 or resp_body['status'] == 106 or resp_body['status'] == 103
raise resp_body['message']
elsif resp_body['status'] != 0
raise "区块链接口请求失败."
else
end
end
def unlock_balance_on_blockchain(username, tokenname, amount)
params = {
"request-type": "unlock user balance",
"username": username,
"token_name": tokenname,
"amount": amount
}.to_json
resp_body = Blockchain::InvokeBlockchainApi.call(params)
if resp_body['status'] == 5 or resp_body['status'] == 106 or resp_body['status'] == 104
raise resp_body['message']
elsif resp_body['status'] != 0
raise "区块链接口请求失败."
else
end
end
def phone_mail_type value
value =~ /^1\d{10}$/ ? 1 : 0
end
end

View File

@ -0,0 +1,28 @@
class Blockchain::CreateIssue < ApplicationService
attr_reader :params
def initialize(params)
@params = params
end
def call
ActiveRecord::Base.transaction do
username = @params[:user_id].to_s
token_name = @params[:project_id].to_s
amount = @params[:token_num].to_i
# 调用token锁仓函数
lock_balance_on_blockchain(username, token_name, amount)
end
rescue => e
puts "转账失败: #{e.message}"
raise Error, e.message
end
private
def no_use
puts "this function does not have any usage"
end
end

View File

@ -0,0 +1,29 @@
class Blockchain::CreateTrade < ApplicationService
attr_reader :params
def initialize(params)
@params = params
end
def call
ActiveRecord::Base.transaction do
username = @params[:user_id].to_s
token_name = @params[:project_id].to_s
amount = @params[:token_num].to_i
# 调用token锁仓函数
results = lock_balance_on_blockchain(username, token_name, amount)
return results
end
rescue => e
puts "转账失败: #{e.message}"
raise Error, e.message
end
private
def no_use
puts "this function does not have any usage"
end
end

View File

@ -0,0 +1,28 @@
class Blockchain::FixIssue < ApplicationService
attr_reader :params
def initialize(params)
@params = params
end
def call
ActiveRecord::Base.transaction do
username = @params[:user_id].to_s
token_name = @params[:project_id].to_s
amount = @params[:token_num].to_i
# 调用token锁仓函数
unlock_balance_on_blockchain(username, token_name, amount)
end
rescue => e
puts "关联issue失败: #{e.message}"
raise Error, e.message
end
private
def no_use
puts "this function does not have any usage"
end
end

View File

@ -0,0 +1,34 @@
class Blockchain::InvokeBlockchainApi < ApplicationService
# 调用blockchain
attr_reader :params
def initialize(params)
@params = params
end
def call
begin
uri = Blockchain.blockchain_config[:api_url]
uri = URI.parse(URI.encode(uri.strip))
res = Net::HTTP.start(uri.host, uri.port) do |http|
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = @params
http.request(req)
end
if res.code.to_i != 200
raise "区块链接口请求失败."
else
res_body = JSON.parse(res.body)
if res_body.has_key?("status")
else
raise "区块链接口请求失败."
end
end
return res_body
rescue Exception => e
raise "区块链接口请求失败."
end
end
end

View File

@ -0,0 +1,36 @@
class Blockchain::TransferService < ApplicationService
attr_reader :params
def initialize(params)
@params = params
end
def call
ActiveRecord::Base.transaction do
transfer_amount = params[:transfer_amount]
if (Float(transfer_amount) rescue false) == false or transfer_amount.to_i < 0 or Float(transfer_amount) != transfer_amount.to_i
raise Error, "请输入正确的转账金额"
end
transfer_amount = transfer_amount.to_i
transfer_login = params[:transfer_login]
payer = params[:payer_id].to_s
payee = User.find_by(login: transfer_login)
if payee.nil?
raise Error, "未找到接收转账的用户"
else
payee = payee.id.to_s
token_name = params[:project_id].to_s
# 调用token转移函数
transfer_balance_on_blockchain(payer, payee, token_name, transfer_amount)
end
end
end
private
def no_use
puts "this function does not have any usage"
end
end

View File

@ -0,0 +1,40 @@
# get the diff info for the commit
class Gitea::Commit::DiffService < Gitea::ClientService
attr_reader :owner, :repo, :sha, :token
# GET /repos/{owner}/{repo}/commits/{sha}/diff
# owner: 用户
# repo: 仓库名称/标识
# sha: commit唯一标识
# eg:
# Gitea::Commit::DiffService.call('jasder', 'repo_identifier', 'sha value')
def initialize(owner, repo, sha, token=nil)
@owner = owner
@repo = repo
@sha = sha
@token = token
end
def call
response = get(url, params)
render_result(response)
end
private
def params
Hash.new.merge(token: token)
end
def url
"/repos/#{owner}/#{repo}/commits/#{sha}/diff".freeze
end
def render_result(response)
case response.status
when 200
JSON.parse(response.body)
else
nil
end
end
end

View File

@ -0,0 +1,40 @@
# get the detailed info of the commit
class Gitea::Commit::InfoService < Gitea::ClientService
attr_reader :owner, :repo, :sha, :token
# GET /repos/{owner}/{repo}/commits/{sha}/diff
# owner: 用户
# repo: 仓库名称/标识
# sha: commit唯一标识
# eg:
# Gitea::Commit::InfoService.call('jasder', 'repo_identifier', 'sha value', token='gitea token')
def initialize(owner, repo, sha, token=nil)
@owner = owner
@repo = repo
@sha = sha
@token = token
end
def call
response = get(url, params)
render_result(response)
end
private
def params
Hash.new.merge(token: token)
end
def url
"/repos/#{owner}/#{repo}/git/commits/#{sha}".freeze
end
def render_result(response)
case response.status
when 200
JSON.parse(response.body)
else
nil
end
end
end

View File

@ -17,6 +17,9 @@ class Projects::CreateService < ApplicationService
ProjectUnit.init_types(@project.id)
Repositories::CreateService.new(user, @project, repository_params).call
upgrade_project_category_private_projects_count
if repo_use_blockchain
create_repo_on_blockchain(params, @project)
end
else
Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}")
end
@ -29,7 +32,7 @@ class Projects::CreateService < ApplicationService
private
def upgrade_project_category_private_projects_count
def upgrade_project_category_private_projects_count
# 如果为空或者项目为公有项目直接返回
return unless params[:project_category_id].present?
return if repo_is_public
@ -37,7 +40,7 @@ class Projects::CreateService < ApplicationService
project_category.increment!(:private_projects_count, 1)
end
def authroize_user_id_success
def authroize_user_id_success
(user.id == params[:user_id].to_i) || (user.organizations.find_by_id(params[:user_id]).present?)
end
@ -52,7 +55,8 @@ class Projects::CreateService < ApplicationService
ignore_id: params[:ignore_id],
license_id: params[:license_id],
website: params[:website],
identifier: params[:repository_name]
identifier: params[:repository_name],
use_blockchain: repo_use_blockchain # 新增,zxh
}
end
@ -71,4 +75,8 @@ class Projects::CreateService < ApplicationService
def repo_is_public
params[:private].blank? ? true : !(ActiveModel::Type::Boolean.new.cast(params[:private]).nil? ? false : ActiveModel::Type::Boolean.new.cast(params[:private]))
end
def repo_use_blockchain
params[:blockchain].blank? ? false : params[:blockchain]
end
end

View File

@ -75,7 +75,8 @@ class Repositories::CreateService < ApplicationService
name: params[:identifier],
private: params[:hidden],
# readme: "ReadMe",
"auto_init": true,
auto_init: true,
description: @project.description
# "description": "string",
# "gitignores": "string",
# "issue_labels": "string",

Some files were not shown because too many files have changed in this diff Show More