Compare commits

..

178 Commits

Author SHA1 Message Date
Xunhui Zhang 4e72e1e1bf 将创建项目时blockchain_init_token从百分比修改为具体值 2023-03-10 10:53:16 +08:00
xxq250 6bb3f92973 开启确权激励的用户或项目可配置 2023-03-09 17:45:03 +08:00
xxq250 d98b5b9f72 Merge branch 'develop' into standalone_develop 2023-03-09 16:23:20 +08:00
xxq250 6f7b40ec24 fixed 搜索用户项目时过虑表情字符 2023-03-09 16:22:48 +08:00
xxq250 d993df7df4 fixed 搜索用户时过虑表情字符 2023-03-09 16:07:38 +08:00
xxq250 701d5dea40 fixed 搜索用户时过虑表情字符 2023-03-09 16:06:04 +08:00
xxq250 6e16a9397c fixed 搜索用户时过虑表情字符 2023-03-09 16:02:50 +08:00
yystopf e9a152032c Merge branch 'develop' into standalone_develop 2023-03-09 11:09:14 +08:00
yystopf 917bae4321 新增:创建疑修消息修复 2023-03-09 11:09:04 +08:00
yystopf ccc8f13959 Merge branch 'develop' into standalone_develop 2023-03-09 10:33:12 +08:00
yystopf 4b618d1a61 修复:消息通知issue跳转使用index 2023-03-09 10:33:00 +08:00
xxq250 9da61bd69e 项目列表默认查询时count性能问题处理 2023-03-07 16:34:31 +08:00
xxq250 db845e7df0 开启确权激励的用户或项目 2023-03-07 09:59:42 +08:00
xxq250 d0209490c6 Merge remote-tracking branch 'origin/standalone_develop' into standalone_develop 2023-03-07 09:49:24 +08:00
xxq250 9cd150be88 开启确权激励的用户或项目 2023-03-07 09:49:17 +08:00
yystopf de6ff8d863 Merge branch 'develop' into standalone_develop 2023-03-06 17:49:36 +08:00
yystopf 620ed26e45 更改:评论列表分页数量限制变大 2023-03-06 17:49:28 +08:00
yystopf 8a67c19c67 Merge branch 'develop' into standalone_develop 2023-03-06 10:42:21 +08:00
yystopf 5580a96fe7 修复 2023-03-06 10:42:12 +08:00
yystopf fd17fcab17 Merge branch 'develop' into standalone_develop 2023-03-06 10:33:49 +08:00
yystopf 2827e28b07 新增:评论/操作记录总数返回 2023-03-06 10:33:26 +08:00
yystopf b19560b174 Merge branch 'develop' into standalone_develop 2023-03-03 18:43:28 +08:00
yystopf b5383bfa5a 修复:消息内容修复 2023-03-03 18:43:18 +08:00
yystopf 5b056c04da Merge branch 'develop' into standalone_develop 2023-03-03 18:03:08 +08:00
yystopf bc862f8d98 修复:部分用户无法收到消息 2023-03-03 18:01:46 +08:00
xxq250 b1c10d66f9 区块链确权相关 2023-03-02 13:49:50 +08:00
yystopf 5216e61479 更改:移除操作日志中标记的色值 2023-03-01 16:34:27 +08:00
yystopf ce70378fc3 Merge branch 'develop' into standalone_develop 2023-03-01 16:29:45 +08:00
yystopf cbb0a639b2 Merge pull request '平台issue模块升级相关' (#24) from yystopf/forgeplus:hh_issue_upgrade into develop 2023-03-01 16:29:19 +08:00
yystopf a654a08e0c Merge branch 'develop' into standalone_develop 2023-03-01 14:40:26 +08:00
yystopf b8724c02f7 修复:组织权限关于操作权限部分 2023-03-01 14:40:11 +08:00
yystopf e59e4e4bd5 修复 2023-02-28 17:05:38 +08:00
yystopf ec44376e4d 修复:issue 评论中@无参与记录 2023-02-28 16:57:44 +08:00
xxq250 a80b4d954e dockerfile可预览 2023-02-28 16:03:33 +08:00
xxq250 2842df87c6 群智熵分析报表接口调整到项目动态接口 2023-02-28 15:01:23 +08:00
xxq250 6f9d902e70 群智熵分析报表接口调整到项目动态接口 2023-02-28 14:59:06 +08:00
yystopf 4091872091 更改:默认标记任务色值 2023-02-28 14:40:27 +08:00
xxq250 5a7aaff112 群智熵分析报表接口调整到项目动态接口 2023-02-28 09:37:18 +08:00
xxq250 558d720203 群智熵分析报表接口调整到项目动态接口 2023-02-28 09:26:45 +08:00
xxq250 46da5a0d84 群智熵分析报表接口调整 2023-02-27 16:41:40 +08:00
xxq250 f59ab5bcf1 Merge remote-tracking branch 'origin/standalone_develop' into standalone_develop 2023-02-27 16:02:13 +08:00
xxq250 f8350c4043 群智熵分析报表接口 2023-02-27 16:02:08 +08:00
yystopf ed7f5a08bb 修复:rake任务 2023-02-27 15:17:10 +08:00
yystopf acaa28cd02 修复:last index 获取方式 2023-02-27 15:13:35 +08:00
yystopf ddb5010e6d 修复:issue 查询需排除pr下issue 2023-02-27 15:04:18 +08:00
yystopf f05cf0c000 修复 2023-02-27 14:12:25 +08:00
yystopf ff025e07dd 新增:里程碑列表支持id查询 2023-02-27 11:25:37 +08:00
yystopf 4c26085e58 修复 2023-02-27 11:07:09 +08:00
yystopf a30a3c56b6 修复 2023-02-27 10:55:53 +08:00
yystopf 2e0b32f86b 修复:atme和issue category 无法正常搜索 2023-02-27 10:46:56 +08:00
yystopf dab636d122 修复 2023-02-24 15:26:40 +08:00
yystopf b616c971db 修复 2023-02-24 14:32:21 +08:00
yystopf 35bb8fbc11 修复 2023-02-24 10:24:57 +08:00
yystopf 267279df2d 修复 2023-02-24 09:04:29 +08:00
yystopf e53d6cd763 修复 2023-02-23 21:03:40 +08:00
yystopf 3fd04109d6 修复 2023-02-23 20:54:48 +08:00
yystopf 8487c67bab 修复:issue_classify 使用小写 2023-02-23 17:32:55 +08:00
yystopf dc01d7fc3e 修复 2023-02-23 16:18:09 +08:00
yystopf 7cb2321c02 修复 2023-02-23 15:31:03 +08:00
yystopf c589fcc6a4 修复 2023-02-23 15:27:26 +08:00
yystopf 1fcdbe9dce 修复 2023-02-23 15:26:30 +08:00
yystopf dc9ca7d0ca 更改:疑修param为index以及新增统计标签下合并请求数量 2023-02-23 15:24:30 +08:00
yystopf edc00d28a7 新增:标记列表返回合并请求数量 2023-02-22 16:25:40 +08:00
yystopf 317ff3c76b 修复 2023-02-22 16:05:24 +08:00
yystopf c781ca0da1 更改:部分细节问题 2023-02-22 15:56:44 +08:00
yystopf a07da79e89 修复:重复初始化标签问题 2023-02-22 14:42:52 +08:00
yystopf 54a85a60fa 更改:疑修列表开启、关闭数量规则以及排序规则 2023-02-22 13:56:12 +08:00
xxq250 895cd8f737 Merge pull request '修复bug' (#26) from KingChan/forgeplus:chenjing into standalone_develop 2023-02-22 10:55:39 +08:00
chenjing 54b7f2c726 fix api/users/:login/headmaps.json bug 2023-02-22 10:48:23 +08:00
chenjing e440ee8483 api/users/{{user}}/messages add check auth 2023-02-22 10:38:40 +08:00
yystopf ed5d12654e 修复 2023-02-22 09:57:39 +08:00
yystopf 8239f13eaa 新增:要求登录接口处理 2023-02-22 09:55:05 +08:00
xxq250 6c1f9cabda fixed 左侧菜单组织列表 2023-02-22 09:38:32 +08:00
xxq250 5f3d51027e fixed 左侧菜单组织列表 2023-02-22 09:36:13 +08:00
xxq250 84029bf49a Merge pull request '用户版块增加组织列表' (#25) from KingChan/forgeplus:chenjing into standalone_develop 2023-02-22 09:29:39 +08:00
chenjing ee77be7c8a fix 2023-02-22 09:25:49 +08:00
chenjing 05f103b0c4 team count and delete orgs 2023-02-22 09:24:11 +08:00
chenjing ac8372d7e1 orgs search 2023-02-22 09:24:11 +08:00
chenjing b9e2a3736c admins org list 2023-02-22 09:24:11 +08:00
yystopf 311776a004 修复:标签列表无id返回 2023-02-21 18:30:29 +08:00
xxq250 12eaec0319 Merge remote-tracking branch 'origin/standalone_develop' into standalone_develop 2023-02-21 16:43:53 +08:00
xxq250 47a5fe24c8 调整Bot授权接口,fixed注册信息手机号 2023-02-21 16:43:28 +08:00
yystopf 4a3d1e5a69 Merge branch 'develop' into standalone_develop 2023-02-21 15:40:08 +08:00
yystopf 3a5d8e75df 修改:后台管理sidebar冲突 2023-02-21 15:39:52 +08:00
yystopf 23a65798df Merge branch 'develop' into standalone_develop 2023-02-21 15:31:58 +08:00
yystopf cab5466ae4 更改:项目排行榜项目需显示全称 2023-02-21 15:31:00 +08:00
yystopf b18051ec31 新增:里程碑相关数量返回 2023-02-21 13:55:40 +08:00
yystopf 02526878fe 修复:更新无法设置空值 2023-02-20 18:22:14 +08:00
yystopf 4657618753 新增:修复数据rake任务 2023-02-20 17:25:07 +08:00
yystopf cb3bb23e79 新增:操作权限 2023-02-20 16:47:19 +08:00
yystopf 656d5b69b6 新增:接口附件内容返回 2023-02-20 13:54:00 +08:00
yystopf 121fa2bff4 新增:里程碑相关接口 2023-02-20 11:42:22 +08:00
yystopf c63a86a797 新增:评论相关接口补足 2023-02-18 23:23:33 +08:00
yystopf 15d71bfd24 修复:创建数据无法创建负责人 2023-02-17 17:40:09 +08:00
xxq250 df38df45d5 fixed 向jianmu推送时项目不存在时处理 2023-02-17 17:24:27 +08:00
yystopf b85913e485 新增:疑修操作记录、评论列表接口以及更新疑修无法产生操作记录修复 2023-02-17 16:11:39 +08:00
xxq250 3427fa6768 新增时向grimoirelab推送事件,修正 2023-02-16 16:11:40 +08:00
xxq250 e92b288f41 新增时向grimoirelab推送事件,异常处理,log 2023-02-16 16:07:51 +08:00
xxq250 0725ef74de 新增时向grimoirelab推送事件,异常处理 2023-02-16 15:54:43 +08:00
xxq250 00bb1e82af 新增时向grimoirelab推送事件,异常处理 2023-02-16 15:51:06 +08:00
xxq250 f93e665239 新增时向grimoirelab推送事件 2023-02-16 15:46:15 +08:00
xxq250 d578c5c8df 新增时向grimoirelab推送事件 2023-02-16 15:44:42 +08:00
xxq250 c872f50685 新增时向grimoirelab推送事件 2023-02-16 15:42:15 +08:00
xxq250 368be1849c 新增时向grimoirelab推送事件 2023-02-16 15:41:20 +08:00
xxq250 7d3d95c406 新增时向grimoirelab推送事件 2023-02-16 15:37:01 +08:00
xxq250 5c3c47d13b 调整Bot授权接口 2023-02-16 14:37:16 +08:00
xxq250 676d2ddce1 调整Bot授权接口 2023-02-16 13:52:38 +08:00
xxq250 3d0fa0d50c 调整Bot授权接口 2023-02-16 11:01:21 +08:00
xxq250 3c51d69555 调整Bot授权接口 2023-02-16 09:57:25 +08:00
xxq250 1d9df770b5 调整Bot授权接口 2023-02-16 09:41:39 +08:00
xxq250 c0fcf3445a 调整Bot授权接口 2023-02-16 09:40:08 +08:00
xxq250 6fe16c7c82 调整Bot授权接口 2023-02-16 09:19:37 +08:00
xxq250 5e7fe0f28c Merge branch 'standalone_develop' of https://gitlink.org.cn/Trustie/forgeplus into standalone_develop 2023-02-15 18:38:24 +08:00
xxq250 1cd43de75b 增加Bot授权相关 2023-02-15 18:37:36 +08:00
yystopf 2a8e0d2be8 新增:标记管理接口,以及列表下拉框搜索参数 2023-02-15 17:24:36 +08:00
yystopf c38a4e4e08 Merge branch 'standalone_develop' of https://gitlink.org.cn/Trustie/forgeplus into standalone_develop 2023-02-15 11:31:02 +08:00
yystopf 202be8246b Merge branch 'develop' into standalone_develop 2023-02-15 11:30:54 +08:00
yystopf 774210206e 修复:支持以.开头文件的代码预览 2023-02-15 11:30:33 +08:00
yystopf 2899f3b18e 修复:删除、更改逻辑测试修改 2023-02-15 11:25:42 +08:00
yystopf 404a6a00e7 新增:issue编辑删除接口 2023-02-14 23:19:17 +08:00
xxq250 f0c1e9e319 项目搜索结果同步es结果 2023-02-13 11:27:44 +08:00
xxq250 7d17b654f6 更新gems源 2023-02-13 10:22:36 +08:00
yystopf db2d398d94 更改:participants创建规则 2023-02-13 09:43:26 +08:00
xxq250 c0271707a1 fixed merge 2023-02-10 21:46:24 +08:00
xxq250 0af87a67ec fixed merge 2023-02-10 17:54:12 +08:00
yystopf 7bce320113 修复:冲突代码回归 2023-02-10 16:23:06 +08:00
yystopf 4a8e3324af 修复 2023-02-10 15:39:09 +08:00
yystopf 3a14aa10ce Merge branch 'develop' into standalone_develop 2023-02-10 13:44:43 +08:00
yystopf b799780637 Merge pull request '分支标签页面改版' (#23) from yystopf/forgeplus:hh_branch_tag into develop 2023-02-10 13:43:57 +08:00
yystopf 53c2ffffb3 新增:疑修创建以及详情接口 2023-02-10 11:38:51 +08:00
yystopf 934b42f1a1 新增:优先级和所有仓库成员接口 2023-02-09 16:20:16 +08:00
yystopf c1d791741c 修复:无法正常查询关联数据 2023-02-09 10:15:59 +08:00
yystopf 1aeed8236d 更改:部分接口传参以及路由修复 2023-02-09 09:29:02 +08:00
yystopf f0750333f9 修复 2023-02-08 16:57:42 +08:00
yystopf 4085da7837 新增:issue和里程碑列表接口 2023-02-08 16:56:01 +08:00
yystopf ade03c5e2f 新增:issue参与记录 2023-02-08 16:55:20 +08:00
yystopf fe972f1141 新增:项目标记接口 2023-02-08 10:15:29 +08:00
yystopf af67d984b4 新增:里程碑接口 2023-02-08 09:49:02 +08:00
yystopf 241bbc06ca 新增:issue负责人变更为一对多 2023-02-07 17:47:28 +08:00
yystopf 587facfb3d 新增:发布人和状态接口 2023-02-07 17:12:43 +08:00
yystopf 8210404f4a Merge branch 'develop' into standalone_develop 2023-02-07 15:56:52 +08:00
yystopf 128c5c48e6 修复 2023-02-07 15:56:35 +08:00
yystopf 99be556d5b Merge branch 'develop' into standalone_develop 2023-02-07 14:24:26 +08:00
yystopf 353449c53c 修复 2023-02-07 14:23:24 +08:00
yystopf c983df57ee merge from develop 2023-02-07 14:21:32 +08:00
yystopf 39ae14bce7 新增:entry新增submodule url 2023-02-07 14:18:57 +08:00
yystopf 8c8925f3ae 修复 2023-02-07 10:39:25 +08:00
yystopf 6cfb5dfbe2 新增:删除保护分支和删除发行版提示 2023-02-07 10:33:46 +08:00
yystopf 0eb17aa90f 更改:分支列表搜索参数 2023-02-06 10:07:15 +08:00
yystopf 7c911f5b86 新增:路由匹配特殊符号 2023-02-06 09:49:36 +08:00
yystopf 0800f9e6e0 修复 2023-02-03 18:24:07 +08:00
yystopf 726453ea99 修复:tags detail 无法获取commit_user 2023-02-03 18:23:16 +08:00
yystopf bef1350933 新增:load_project新增repository 2023-02-03 18:20:00 +08:00
yystopf 2772b97e32 新增:标签列表和删除接口 2023-02-03 18:03:57 +08:00
xxq250 f2a456c6ed Merge remote-tracking branch 'origin/develop' into standalone_develop
# Conflicts:
#	app/queries/projects/list_query.rb
2023-02-03 15:52:28 +08:00
xxq250 4bc945028b fixed 项目搜索用户名失败修正 2023-02-03 15:50:33 +08:00
yystopf 8b90164247 新增:删除分支接口 2023-02-03 15:03:59 +08:00
yystopf f2cdba29ea 新增:更改默认分支接口 2023-02-03 13:45:32 +08:00
yystopf 3f78899c58 新增:branch列表接口 2023-02-03 10:53:24 +08:00
yystopf 5fc433d130 Merge branch 'develop' into standalone_develop 2023-02-02 18:30:33 +08:00
yystopf bfe14352c0 更改:codestats回退 2023-02-02 18:30:07 +08:00
yystopf a746e791b0 Merge branch 'develop' into standalone_develop 2023-02-02 18:13:19 +08:00
yystopf 87412643cd 修复 2023-02-02 18:13:02 +08:00
yystopf e4b5427725 Merge branch 'develop' into standalone_develop 2023-02-02 18:11:31 +08:00
yystopf 9fe3b5ae3e 新增:code_stats分页 2023-02-02 18:10:26 +08:00
xxq250 a03d1efcb0 fixed 如果有搜索关键字根据ES搜索结果排序 2023-02-02 14:05:40 +08:00
xxq250 2668630f2a 项目fored_count更新时updated_on同时更新 2023-02-01 17:23:48 +08:00
xxq250 785ae13649 创建仓库开通建木DevOps job延迟5秒 2023-02-01 17:03:16 +08:00
yystopf c4b93f2bd3 Merge branch 'develop' into standalone_develop 2023-02-01 15:47:43 +08:00
yystopf 913eb62923 新增:排行榜每日统计数据设置一个过期时间 2023-02-01 15:44:40 +08:00
yystopf 112ee39efd 修复:排行榜数据不展示已删除数据 2023-02-01 14:50:12 +08:00
yystopf 08d8abd163 Merge branch 'develop' into standalone_develop 2023-02-01 14:26:52 +08:00
yystopf 0229d99e74 新增:后台管理排行榜数据 2023-02-01 14:25:55 +08:00
yystopf 40873fe95d Merge branch 'develop' into standalone_develop 2023-01-09 15:40:12 +08:00
yystopf dfe56d9f75 修复 2023-01-09 15:39:49 +08:00
yystopf 5f46d205a9 Merge branch 'develop' into standalone_develop 2023-01-09 15:15:32 +08:00
yystopf fdb713b76d 更改:更改用户邮箱移除旧的cache 2023-01-09 15:14:51 +08:00
xxq250 7c80f74e26 fixed 代码贡献者email 2023-01-06 11:16:50 +08:00
564 changed files with 1253213 additions and 44608 deletions

3
.gitignore vendored
View File

@ -73,7 +73,7 @@ vendor/bundle/
/public/admin
/mysql_data
/public/repo/
/coverage
.generators
.rakeTasks
@ -81,6 +81,7 @@ db/bak/
docker/
educoder.sql
redis_data/
Dockerfile
dump.rdb
.tags*
ceshi_user.xlsx

View File

@ -1,33 +0,0 @@
FROM ubuntu:18.04
RUN apt update
RUN apt install -y openssl libssl-dev imagemagick git ruby-dev nodejs libmariadb-dev libmysqlclient-dev shared-mime-info libpq-dev libxml2-dev libxslt-dev
RUN DEBIAN_FRONTEND="noninteractive" apt -y install tzdata
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /home/app/gitlink
ADD ./ /home/app/gitlink
RUN gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
RUN gem update --system
RUN gem install bundler
RUN gem install rake
RUN rm -rf Gemfile.lock
#RUN cp config/configuration.yml.example config/configuration.yml
#RUN cp config/database.yml.example config/database.yml
#RUN touch config/redis.yml
#RUN touch config/elasticsearch.yml
RUN bundle install
EXPOSE 4000
RUN rails s -p 4000 -b '0.0.0.0'

15
Gemfile
View File

@ -1,4 +1,4 @@
# 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" }
@ -60,7 +60,6 @@ gem 'ransack'
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'rails-controller-testing'
end
group :development do
@ -79,7 +78,6 @@ 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,11 +99,9 @@ gem 'font-awesome-sass', '4.7.0'
gem 'rails-i18n', '~> 5.1'
# job
gem 'sidekiq',"5.2.8"
gem 'sidekiq'
gem 'sinatra'
gem "sidekiq-cron", "1.2.0"
gem 'whenever'
gem 'sidekiq_schedulable'
gem "sidekiq-cron", "~> 1.1"
# batch insert
gem 'bulk_insert'
@ -136,9 +132,6 @@ gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'
# log
gem 'multi_logger'
gem 'letter_avatar'
gem 'jwt'
@ -147,4 +140,4 @@ gem 'doorkeeper'
gem 'doorkeeper-jwt'
gem 'gitea-client', '~> 0.11.1'
gem 'gitea-client', '~> 0.11.6'

View File

@ -106,8 +106,6 @@ GEM
activerecord (>= 3.1.0, < 7)
diff-lcs (1.3)
diffy (3.3.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.5.1)
railties (>= 5)
doorkeeper-jwt (0.4.1)
@ -135,8 +133,6 @@ GEM
fugit (1.4.1)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.4)
gitea-client (0.10.5)
rest-client (~> 2.1.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
grape-entity (0.7.1)
@ -147,9 +143,6 @@ GEM
harmonious_dictionary (0.0.1)
hashie (3.6.0)
htmlentities (4.3.4)
http-accept (1.7.0)
http-cookie (1.0.5)
domain_name (~> 0.5)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
io-like (0.3.1)
@ -187,9 +180,6 @@ GEM
mimemagic (~> 0.3.2)
maruku (0.7.3)
method_source (0.9.2)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mimemagic (0.3.10)
nokogiri (~> 1)
rake
@ -203,7 +193,6 @@ GEM
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
mysql2 (0.5.3)
netrc (0.11.0)
nio4r (2.5.2)
nokogiri (1.10.8)
mini_portile2 (~> 2.4.0)
@ -303,11 +292,6 @@ GEM
regexp_parser (1.7.0)
request_store (1.5.0)
rack (>= 1.4)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
reverse_markdown (1.4.0)
nokogiri
roo (2.8.3)
@ -434,9 +418,6 @@ GEM
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.6.1)
web-console (3.7.0)
actionview (>= 5.0)
@ -478,7 +459,6 @@ DEPENDENCIES
enumerize
faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0)
gitea-client (~> 0.10.2)
grape-entity (~> 0.7.1)
groupdate (~> 4.1.0)
harmonious_dictionary (~> 0.0.1)
@ -516,8 +496,8 @@ DEPENDENCIES
sass-rails (~> 5.0)
searchkick
selenium-webdriver
sidekiq (= 5.2.8)
sidekiq-cron (= 1.2.0)
sidekiq
sidekiq-cron (~> 1.1)
simple_form
simple_xlsx_reader
sinatra
@ -532,4 +512,4 @@ DEPENDENCIES
wkhtmltopdf-binary
BUNDLED WITH
2.2.3
2.1.4

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.

204
README.md
View File

@ -1,27 +1,17 @@
# GitLink - CCF开源创新服务平台
Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台。
GitLink确实开源是中国计算机学会CCF官方指定的开源创新服务平台旨在以“为开源创新服务”为使命以“成为开源创新的汇聚地”为愿景秉承“创新、开放、协作、共享”的价值观致力于为大规模开源开放协同创新助力赋能打造创新成果孵化和新工科人才培养的开源创新生态
## 特性
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/gitlink.png?raw=true" width=80% /></center>
## 特色功能
- 软件创作与生产深度融合的软件开发环境体系结构 软件自由创作和工程生产的高效衔接,适于软件开发中群体智慧的有效汇聚。
- **分布式协作开发**基于Git打造分布式代码托管环境提供免费公、私有代码仓库支持在线文件编辑、代码分支管理、协作贡献统计、代码仓库复刻Fork、贡献合并请求PR、群智贡献审阅等功能让您的项目在这里健康、快速的成长
- 构件化协同开发环境的可扩展运行框架多样化工具的集成和联动,形成了强动态扩展能力的平台框架。
- **一站式过程管理**提供疑修Issue、里程碑、通知提醒、标签归档等多样化任务管理工具支持各类开发任务的发布、指派与跟踪同时提供在线Wiki文档、组织多粒度管理等功能为您搭建一站式的项目过程管理环境让您的团队协作更高效、过程更透明
- “互联网即资源库”的全新软件复用模式 成长式软件资源管理系统,实现了分散资源的知识融合、资源的可持续增长和有效复用。
- **高效流水线运维**融合DevOps思想提供轻量级的工作流引擎Engine打通编码、测试、构建、部署等开发运维环节支持自定义配置、代码静态扫描、构建自动触发、容器镜像托管等功能同时支持接入第三方运维工具让您的代码更加快速、可靠地形成高质量的产品
- **多层次代码分析**提供软件软代码和芯片RTL代码的溯源分析、文件级和组件级许可证识别及风险分析、输入性开源漏洞检测和加固建议支持分析结果的多层次可视化展示帮助您实施有效开源治理厘清代码引用链发现并消除漏洞感染链为安全合规的开源引用保驾护航
- **多维度用户画像**:实时采集和分析平台中的各类开源资源数据,搭建多维度用户画像评估系统,提供开发活动统计、贡献度日历、用户能力建模、角色与专业定位分析等功能,让您在个人主页展示开发动态与创新能力!
## 部署
## 部署流程
### 依赖库
### Depends Versions
* Ruby 2.4.5
@ -33,53 +23,22 @@ GitLink确实开源是中国计算机学会CCF官方指定的开源
* imagemagick
### 步骤
1安装 Rails 必要的一些三方库:
- Mac OS X
```bash
brew install imagemagick ghostscript libxml2 libxslt libiconv
### Steps
#### 1. 克隆稳定版本
```
git clone -b standalone https://git.trustie.net/jasder/forgeplus.git
```
- Ubuntu
#### 2. 安装依赖包
```bash
sudo apt-get update
sudo apt-get install -y openssl libssl-dev imagemagick git ruby-dev nodejs libmariadb-dev libmysqlclient-dev shared-mime-info libpq-dev libxml2-dev libxslt-dev
sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y tzdata
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
cd forgeplus && bundle install
```
2安装 Ruby, Rails 运行环境:[如何快速正确的安装 Ruby, Rails 运行环境](https://ruby-china.org/wiki/install_ruby_guide)
```bash
#检验环境是否正确
ruby -v
#ruby 2.4.x ...
#### 3. 配置初始化文件
进入项目根目录执行一下命令:
gem -v
#3.x.x
bundle -v
#Bundler version 2.x.x
rails -v
#Rails 5.2.x
```
3克隆稳定版本
```bash
git clone -b master https://gitlink.org.cn/Gitlink/forgeplus.git
```
4安装依赖包
```bash
#进入目录
cd forgeplus
#删除Gemfile.lock
rm -rf Gemfile.lock
#安装依赖包
bundle install
```
5配置初始化文件进入项目根目录执行以下命令
```bash
cp config/configuration.yml.example config/configuration.yml
cp config/database.yml.example config/database.yml
@ -87,8 +46,12 @@ touch config/redis.yml
touch config/elasticsearch.yml
```
6配置数据库数据库配置信息请查看/config/database.yml文件项目默认采用mysql数据库, 如需更改,请自行修改配置信息,默认配置如下
```yaml
#### 4. 配置数据库
数据库配置信息请查看/config/database.yml文件
项目默认采用mysql数据库, 如需更改,请自行修改配置信息,
默认配置如下:
```bash
default: &default
adapter: mysql2
host: 127.0.0.1
@ -97,15 +60,16 @@ default: &default
password: 123456
```
7配置gitea服务(可选)如需要部署自己的gitea平台请参考[gitea官方平台文档](https://docs.gitea.io/zh-cn/install-from-binary/)。因目前gitea平台api受限暂时推荐从forge平台获取[gitea部署文件](https://www.gitlink.org.cn/Gitlink/gitea-binary)进行部署
#### 5. 配置gitea服务(可选)
**如需要部署自己的gitea平台请参考gitea官方平台https://docs.gitea.io/zh-cn/install-from-binary/**
- 配置gitea服务步骤
-- 部署gitea服务并注册root账户
-- 修改forge平台的 config/configuration.yml中的gitea服务指向地址
**因目前gitea平台api受限暂时推荐从forge平台获取gitea部署文件进行部署https://forgeplus.trustie.net/projects/Trustie/gitea-binary**
```yaml
**配置gitea服务步骤**
1. 部署gitea服务并注册root账户
2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址
```ruby
gitea:
access_key_id: 'root'
access_key_secret: 'password'
@ -113,100 +77,102 @@ gitea:
base_url: '/api/v1'
```
8配置/config/database.yml文件(安装redis环境:请自行搜索各平台如何安装部署redis环境)
```yaml
default: &default
url: redis://localhost:6379
db: 1
#### 6. 安装redis环境
**请自行搜索各平台如何安装部署redis环境**
production:
<<: *default
url: redis://localhost:6379
#### 7. 安装imagemagick插件
- Mac OS X
```bash
brew install imagemagick ghostscript
```
9创建数据库开发环境为development 生成环境为production
- Linux
```bash
sudo apt-get install -y imagemagick
```
#### 8. 创建数据库
**开发环境为development 生成环境为production**
```bash
rails db:create RAILS_ENV=development
```
10导入数据表结构
#### 9. 导入数据表结构
```bash
bundle exec rake sync_table_structure:import_csv
```
11执行migrate迁移文件开发环境为development 生成环境为production
#### 10. 执行migrate迁移文件
**开发环境为development 生成环境为production**
```bash
rails db:migrate RAILS_ENV=development
```
12clone前端代码将前端代码克隆到public/react目录下目录结构应该是: public/react/build
#### 11. clone前端代码
**将前端代码克隆到public/react目录下目录结构应该是: public/react/build**
```bash
git clone -b master https://gitlink.org.cn/Gitlink/build.git
git clone -b standalone https://git.trustie.net/jasder/build.git
```
13启动redis(此处以macOS系统为例)
#### 12. 启动redis(此处已mac系统为例)
```bash
redis-server&
```
14启动sidekiq开发环境为development 生成环境为production
#### 13. 启动sidekiq
**开发环境为development 生成环境为production**
```bash
bundle exec sidekiq -C config/sidekiq.yml -e production -d
```
15启动rails服务
#### 14. 启动rails服务
```bash
rails s
```
16浏览器访问在浏览器中输入如下地址访问
#### 15. 浏览器访问
在浏览器中输入如下地址访问:
```bash
http://localhost:3000/
```
17其他说明通过页面注册以第一个用户为平台管理员用户
#### 16. 其他说明
通过页面注册都第一个用户为平台管理员用户
## 页面展示
- 项目列表
- 代码库
![](docs/figs/code.png?raw=true)
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/project_list.png?raw=true" width=50% />
</center>
- 代码仓库
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/repo.png?raw=true" width=50% />
</center>
- 任务管理
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/issues.png?raw=true" width=50% />
</center>
- 合并请求
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/PR.png?raw=true" width=50% />
</center>
- 引擎配置
<center>
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/master/docs/figs/engine.png?raw=true" width=50% />
</center>
![](docs/figs/issue_manage.png?raw=true)
- 任务查看
![](docs/figs/issue_view.png?raw=true)
- 任务指派
![](docs/figs/issue_assign2.png?raw=true)
- 里程碑
![](docs/figs/milestone.png?raw=true)
### API
- [API文档](https://forgeplus.trustie.net/docs/api)
- [API](showdoc.com.cn)
账号forgeplus@admin.com 密码forge123
## 贡献代码
我们期待您向GitLink提交贡献在您贡献时请遵循流程[【Wiki文档-GitLink协作开发流程】](https://www.gitlink.org.cn/Gitlink/forgeplus/wiki "【Wiki文档-GitLink协作开发流程】")
1. Fork 项目
2. 创建本地分支(git checkout -b my-new-feature)
3. 提交更改 (git commit -am 'Add some feature')
4. 推送到分支 (git push origin my-new-feature)
5. 向源项目的 **develop** 分支发起 Pull Request
#### 指导文档
- [API文档](https://www.gitlink.org.cn/docs/api)
- [Git常用命令](https://git-scm.com/)
## 许可证协议
## License

View File

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

View File

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

View File

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

View File

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

View File

@ -1,84 +0,0 @@
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

@ -1,3 +0,0 @@
// 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

@ -1,3 +0,0 @@
// 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

@ -1,3 +0,0 @@
// 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,7 +270,6 @@ 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}")
@ -343,11 +342,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: 验证手机号是否有效 # 如果有新的继续后面加
@ -390,7 +389,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
@ -405,7 +404,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
@ -414,7 +413,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

@ -0,0 +1,27 @@
class Admins::OrganizationsController < Admins::BaseController
before_action :finder_org, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
orgs = Admins::OrganizationQuery.call(params)
@orgs = paginate orgs
end
def show
end
def destroy
@org.destroy!
Admins::DeleteOrganizationService.call(@org.login)
render_delete_success
end
private
def finder_org
@org = Organization.find(params[:id])
end
end

View File

@ -0,0 +1,16 @@
class Admins::ProjectsRankController < Admins::BaseController
def index
@rank_date = rank_date
deleted_data = $redis_cache.smembers("v2-project-rank-deleted")
$redis_cache.zrem("v2-project-rank-#{rank_date}", deleted_data) unless deleted_data.blank?
@date_rank = $redis_cache.zrevrange("v2-project-rank-#{rank_date}", 0, -1, withscores: true)
end
private
def rank_date
params.fetch(:date, Date.today.to_s)
end
end

View File

@ -0,0 +1,15 @@
class Admins::UsersRankController < Admins::BaseController
def index
@rank_date = rank_date
@date_rank = $redis_cache.zrevrange("v2-user-rank-#{rank_date}", 0, -1, withscores: true)
end
private
def rank_date
params.fetch(:date, Date.today.to_s)
end
end

View File

@ -20,10 +20,19 @@ class Api::V1::BaseController < ApplicationController
# User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
# end
# end
def kaminary_select_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 200) ? 200 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
end
def limit
params.fetch(:limit, 15)
end
def page
params.fetch(:page, 1)
end
@ -43,7 +52,6 @@ class Api::V1::BaseController < ApplicationController
# 具有仓库的操作权限或者fork仓库的操作权限
def require_operate_above_or_fork_project
@project = load_project
puts !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
return render_forbidden if !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
end

View File

@ -0,0 +1,12 @@
class Api::V1::Issues::AssignersController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
# 负责人列表
def index
@assigners = User.joins(assigned_issues: :project).where(projects: {id: @project&.id})
@assigners = @assigners.order("users.id=#{current_user.id} desc").distinct
@assigners = @assigners.ransack(login_or_nickname_cont: params[:keyword]).result if params[:keyword].present?
@assigners = kaminary_select_paginate(@assigners)
end
end

View File

@ -0,0 +1,11 @@
class Api::V1::Issues::AuthorsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
# 发布人列表
def index
@authors = User.joins(issues: :project).where(projects: {id: @project&.id})
@authors = @authors.order("users.id=#{current_user.id} desc").distinct
@authors = @authors.ransack(login_or_nickname_cont: params[:keyword]).result if params[:keyword].present?
@authors = kaminary_select_paginate(@authors)
end
end

View File

@ -0,0 +1,10 @@
class Api::V1::Issues::IssuePrioritiesController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
def index
@priorities = IssuePriority.order(position: :asc)
@priorities = @priorities.ransack(name_cont: params[:keyword]).result if params[:keyword]
@priorities = kaminary_select_paginate(@priorities)
end
end

View File

@ -0,0 +1,65 @@
class Api::V1::Issues::IssueTagsController < Api::V1::BaseController
before_action :require_login, except: [:index]
before_action :require_public_and_member_above, only: [:index]
before_action :require_operate_above, only: [:create, :update, :destroy]
def index
@issue_tags = @project.issue_tags.reorder("#{sort_by} #{sort_direction}")
@issue_tags = @issue_tags.ransack(name_cont: params[:keyword]).result if params[:keyword].present?
if params[:only_name]
@issue_tags = kaminary_select_paginate(@issue_tags.select(:id, :name, :color))
else
@issue_tags = kaminari_paginate(@issue_tags.includes(:project, :user, :issue_issues, :pull_request_issues))
end
end
def create
@issue_tag = @project.issue_tags.new(issue_tag_params)
if @issue_tag.save!
render_ok
else
render_error("创建标记失败!")
end
end
before_action :load_issue_tag, only: [:update, :destroy]
def update
@issue_tag.attributes = issue_tag_params
if @issue_tag.save!
render_ok
else
render_error("更新标记失败!")
end
end
def destroy
if @issue_tag.destroy!
render_ok
else
render_error("删除标记失败!")
end
end
private
def sort_by
sort_by = params.fetch(:sort_by, "created_at")
sort_by = IssueTag.column_names.include?(sort_by) ? sort_by : "created_at"
sort_by
end
def sort_direction
sort_direction = params.fetch(:sort_direction, "desc").downcase
sort_direction = %w(desc asc).include?(sort_direction) ? sort_direction : "desc"
sort_direction
end
def issue_tag_params
params.permit(:name, :description, :color)
end
def load_issue_tag
@issue_tag = @project.issue_tags.find_by_id(params[:id])
end
end

View File

@ -0,0 +1,63 @@
class Api::V1::Issues::JournalsController < Api::V1::BaseController
before_action :require_login, except: [:index, :children_journals]
before_action :require_public_and_member_above
before_action :load_issue
before_action :load_journal, only: [:children_journals, :update, :destroy]
before_action :check_journal_operate_permission, only: [:update, :destroy]
def index
@object_result = Api::V1::Issues::Journals::ListService.call(@issue, query_params, current_user)
@total_journals_count = @object_result[:total_journals_count]
@total_operate_journals_count = @object_result[:total_operate_journals_count]
@total_comment_journals_count = @object_result[:total_comment_journals_count]
@journals = kaminary_select_paginate(@object_result[:data])
end
def create
@object_result = Api::V1::Issues::Journals::CreateService.call(@issue, journal_params, current_user)
end
def children_journals
@object_results = Api::V1::Issues::Journals::ChildrenListService.call(@issue, @journal, query_params, current_user)
@journals = kaminari_paginate(@object_results)
end
def update
@object_result = Api::V1::Issues::Journals::UpdateService.call(@issue, @journal, journal_params, current_user)
end
def destroy
if @journal.destroy!
render_ok
else
render_error("删除评论失败!")
end
end
private
def query_params
params.permit(:category, :keyword, :sort_by, :sort_direction)
end
def journal_params
params.permit(:notes, :parent_id, :reply_id, :attachment_ids => [], :receivers_login => [])
end
def load_issue
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || Issue.find_by_id(params[:index])
if @issue.blank?
render_not_found("疑修不存在!")
end
end
def load_journal
@journal = Journal.find_by_id(params[:id])
return render_not_found("评论不存在!") unless @journal.present?
end
def check_journal_operate_permission
return render_forbidden("您没有操作权限!") unless @project.member?(current_user) || current_user.admin? || @issue.user == current_user || @journal.user == current_user || @journal.parent_journal&.user == current_user
end
end

View File

@ -0,0 +1,87 @@
class Api::V1::Issues::MilestonesController < Api::V1::BaseController
before_action :require_login, except: [:index, :show]
before_action :require_public_and_member_above, only: [:index, :show]
before_action :require_operate_above, only: [:create, :update, :destroy]
before_action :load_milestone, only: [:show, :update, :destroy]
# 里程碑列表
def index
@milestones = @project.versions
@milestones = @milestones.ransack(id_eq: params[:keyword]).result.or(@milestones.ransack(name_or_description_cont: params[:keyword]).result) if params[:keyword].present?
@closed_milestone_count = @milestones.closed.size
@opening_milestone_count = @milestones.opening.size
@milestones = params[:category] == "closed" ? @milestones.closed : @milestones.opening
@milestones = @milestones.reorder("versions.#{sort_by} #{sort_direction}")
if params[:only_name]
@milestones = @milestones.select(:id, :name)
@milestones = kaminary_select_paginate(@milestones)
else
@milestones = @milestones.includes(:issues, :closed_issues, :opened_issues)
@milestones = kaminari_paginate(@milestones)
end
end
def create
@milestone = @project.versions.new(milestone_params)
if @milestone.save!
render_ok
else
render_error(@milestone.errors.full_messages.join(","))
end
end
# 里程碑详情
def show
@object_result = Api::V1::Issues::Milestones::DetailIssuesService.call(@project, @milestone, query_params, current_user)
@total_issues_count = @object_result[:total_issues_count]
@opened_issues_count = @object_result[:opened_issues_count]
@closed_issues_count = @object_result[:closed_issues_count]
@issues = kaminari_paginate(@object_result[:data])
end
def update
@milestone.attributes = milestone_params
if @milestone.save!
render_ok
else
render_error(@milestone.errors.full_messages.join(","))
end
end
def destroy
if @milestone.destroy!
render_ok
else
render_error("删除里程碑失败!")
end
end
private
def milestone_params
params.permit(:name, :description, :effective_date)
end
def query_params
params.permit(:category, :author_id, :assigner_id, :sort_by, :sort_direction, :issue_tag_ids)
end
def load_milestone
@milestone = @project.versions.find_by_id(params[:id])
return render_not_found('里程碑不存在!') unless @milestone.present?
end
def sort_by
sort_by = params.fetch(:sort_by, "created_on")
sort_by = Version.column_names.include?(sort_by) ? sort_by : "created_on"
sort_by
end
def sort_direction
sort_direction = params.fetch(:sort_direction, "desc").downcase
sort_direction = %w(desc asc).include?(sort_direction) ? sort_direction : "desc"
sort_direction
end
end

View File

@ -0,0 +1,11 @@
class Api::V1::Issues::StatuesController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
# 状态列表
def index
@statues = IssueStatus.order("position asc")
@statues = @statues.ransack(name_cont: params[:keyword]).result if params[:keyword].present?
@statues = kaminary_select_paginate(@statues)
end
end

View File

@ -0,0 +1,115 @@
class Api::V1::IssuesController < Api::V1::BaseController
before_action :require_login, except: [:index, :show]
before_action :require_public_and_member_above, only: [:index, :show, :create, :update, :destroy]
before_action :require_operate_above, only: [:batch_update, :batch_destroy]
def index
IssueTag.init_data(@project.id) unless $redis_cache.hget("project_init_issue_tags", @project.id)
@object_result = Api::V1::Issues::ListService.call(@project, query_params, current_user)
@total_issues_count = @object_result[:total_issues_count]
@opened_issues_count = @object_result[:opened_issues_count]
@closed_issues_count = @object_result[:closed_issues_count]
if params[:only_name].present?
@issues = kaminary_select_paginate(@object_result[:data].pluck(:id, :subject))
else
@issues = kaminari_paginate(@object_result[:data])
end
end
def create
@object_result = Api::V1::Issues::CreateService.call(@project, issue_params, current_user)
end
before_action :load_issue, only: [:show, :update, :destroy]
before_action :check_issue_operate_permission, only: [:update, :destroy]
def show
@user_permission = current_user.present? && current_user.logged? && (@project.member?(current_user) || current_user.admin? || @issue.user == current_user)
end
def update
@object_result = Api::V1::Issues::UpdateService.call(@project, @issue, issue_params, current_user)
end
def destroy
@object_result = Api::V1::Issues::DeleteService.call(@project, @issue, current_user)
if @object_result
render_ok
else
render_error("删除疑修失败!")
end
end
before_action :load_issues, only: [:batch_update, :batch_destroy]
def batch_update
@object_result = Api::V1::Issues::BatchUpdateService.call(@project, @issues, batch_issue_params, current_user)
if @object_result
render_ok
else
render_error("批量更新疑修失败!")
end
end
def batch_destroy
@object_result = Api::V1::Issues::BatchDeleteService.call(@project, @issues, current_user)
if @object_result
render_ok
else
render_error("批量删除疑修失败!")
end
end
private
def load_issue
@issue = @project.issues.issue_issue.where(project_issues_index: params[:index]).where.not(id: params[:index]).take || Issue.find_by_id(params[:index])
if @issue.blank?
render_not_found("疑修不存在!")
end
end
def load_issues
return render_error("请输入正确的ID数组") unless params[:ids].is_a?(Array)
params[:ids].each do |id|
@issue = Issue.find_by_id(id)
if @issue.blank?
return render_not_found("ID为#{id}的疑修不存在!")
end
end
@issues = Issue.where(id: params[:ids])
end
def check_issue_operate_permission
return render_forbidden("您没有操作权限!") unless @project.member?(current_user) || current_user.admin? || @issue.user == current_user
end
def query_params
params.permit(
:category,
:participant_category,
:keyword, :author_id,
:milestone_id, :assigner_id,
:status_id,
:sort_by, :sort_direction,
:issue_tag_ids)
end
def issue_params
params.permit(
:status_id, :priority_id, :milestone_id,
:branch_name, :start_date, :due_date,
:subject, :description,
:issue_tag_ids => [],
:assigner_ids => [],
:attachment_ids => [],
:receivers_login => [])
end
def batch_issue_params
params.permit(
:status_id, :priority_id, :milestone_id,
:issue_tag_ids => [],
:assigner_ids => [])
end
end

View File

@ -1,16 +1,40 @@
class Api::V1::Projects::BranchesController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:all]
before_action :require_public_and_member_above, only: [:index, :all]
def index
@result_object = Api::V1::Projects::Branches::ListService.call(@project, {name: params[:keyword], page: page, limit: limit}, current_user&.gitea_token)
end
def all
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
end
before_action :require_operate_above, only: [:create]
before_action :require_operate_above, only: [:create, :destroy]
def create
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
end
def destroy
@result_object = Api::V1::Projects::Branches::DeleteService.call(@project, params[:name], current_user&.gitea_token)
if @result_object
return render_ok
else
return render_error('删除分支失败!')
end
end
before_action :require_manager_above, only: [:update_default_branch]
def update_default_branch
@result_object = Api::V1::Projects::Branches::UpdateDefaultBranchService.call(@project, params[:name], current_user&.gitea_token)
if @result_object
return render_ok
else
return render_error('更新默认分支失败!')
end
end
private
def branch_params
params.require(:branch).permit(:new_branch_name, :old_branch_name)

View File

@ -3,6 +3,6 @@ class Api::V1::Projects::CodeStatsController < Api::V1::BaseController
def index
@result_object = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: params[:ref]}, current_user&.gitea_token)
puts @result_object
# puts @result_object
end
end

View File

@ -0,0 +1,10 @@
class Api::V1::Projects::CollaboratorsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
def index
@collaborators = @project.all_collaborators.like(params[:keyword])
@collaborators = kaminary_select_paginate(@collaborators)
end
end

View File

@ -0,0 +1,19 @@
class Api::V1::Projects::TagsController < Api::V1::BaseController
before_action :require_public_and_member_above, only: [:index]
def index
@release_tags = @repository.version_releases.pluck(:tag_name)
@result_object = Api::V1::Projects::Tags::ListService.call(@project, {page: page, limit: limit}, current_user&.gitea_token)
end
before_action :require_operate_above, only: [:destroy]
def destroy
@result_object = Api::V1::Projects::Tags::DeleteService.call(@project, params[:name], current_user&.gitea_token)
if @result_object
return render_ok
else
return render_error('删除标签失败!')
end
end
end

View File

@ -1,4 +1,6 @@
require 'oauth2'
# require 'openssl'
# require 'jwt'
class ApplicationController < ActionController::Base
include CodeExample
@ -10,14 +12,12 @@ 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
@ -27,8 +27,6 @@ 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"
@ -86,7 +84,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, "该手机号码或邮箱已被注册")
@ -299,14 +297,21 @@ class ApplicationController < ActionController::Base
# Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
if @doorkeeper_token.present?
# client方法对接需要一直带着用户标识uid
if @doorkeeper_token.resource_owner_id.blank?
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
User.current = User.find(params[:uid])
else
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
if !valid_doorkeeper_token?
header = request.authorization
pattern = /^Bearer /i
token = header.gsub(pattern, "")
User.current, message = Bot.decode_jwt_token(token)
tip_exception(401, message) if message.present?
else
if @doorkeeper_token.present?
# client方法对接需要一直带着用户标识uid
if @doorkeeper_token.resource_owner_id.blank?
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
User.current = User.find(params[:uid])
else
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
end
end
end
else
@ -367,20 +372,7 @@ class ApplicationController < ActionController::Base
# RSS key authentication does not start a session
User.find_by_rss_key(params[:key])
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
end
def try_to_autologin
if cookies[autologin_cookie_name]
@ -406,17 +398,12 @@ class ApplicationController < ActionController::Base
respond_to do |format|
format.json
end
end
end
## 输出错误信息
def error_status(message = nil)
@status = -1
@message = message
end
# 实训等对应的仓库地址
def repo_ip_url(repo_path)
"#{edu_setting('git_address_ip')}/#{repo_path}"
## 输出错误信息
def error_status(message = nil)
@status = -1
@message = message
end
def repo_url(repo_path)
@ -655,23 +642,6 @@ 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
@ -683,8 +653,8 @@ class ApplicationController < ActionController::Base
# 获取Oauth Client
def get_client(site)
client_id = Rails.configuration.educoder['client_id']
client_secret = Rails.configuration.educoder['client_secret']
client_id = Rails.configuration.Gitlink['client_id']
client_secret = Rails.configuration.Gitlink['client_secret']
OAuth2::Client.new(client_id, client_secret, site: site)
end
@ -704,7 +674,7 @@ class ApplicationController < ActionController::Base
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
limit = (limit.to_i.zero? || limit.to_i > 50) ? 50 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
@ -789,11 +759,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
@ -838,54 +808,21 @@ class ApplicationController < ActionController::Base
end
private
def update_last_login_on
if current_user.logged?
current_user.update_column(:last_login_on, Time.now)
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 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

View File

@ -1,48 +0,0 @@
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

@ -1,7 +0,0 @@
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

@ -6,7 +6,8 @@ module Api::ProjectHelper
repo = params[:repo]
@project, @owner = Project.find_with_namespace(namespace, repo)
@repository = @project&.repository
if @project
logger.info "###########project founded"
@project

View File

@ -44,7 +44,6 @@ 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,12 +3,9 @@ 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

@ -0,0 +1,67 @@
class InstallationsController < ApplicationController
include RegisterHelper
before_action :require_login
def index
@install_bots = BotInstall.where(:installer_id => current_user.id)
end
def update_secret
ActiveRecord::Base.transaction do
bot = Bot.find params[:id]
application = Doorkeeper::Application.find_by(uid: bot.client_id, secret: bot.client_secret)
bot.client_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate
bot.save!
application.secret = bot.client_secret
application.save!
render_ok
end
end
def update_private_key
bot = Bot.find params[:id]
bot.private_key = OpenSSL::PKey::RSA::generate(2048).to_s
bot.save!
render_ok
end
def auth_active
begin
@bot = Bot.find params[:id]
tip_exception("该Bot已激活") if Doorkeeper::Application.find_by(uid: @bot.client_id, secret: @bot.client_secret).present?
@bot.client_id = Doorkeeper::OAuth::Helpers::UniqueToken.generate if params[:client_id].blank?
@bot.client_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate if params[:client_secret].blank?
@bot.private_key = OpenSSL::PKey::RSA::generate(2048).to_s
@bot.owner_id = current_user.id
ActiveRecord::Base.transaction do
# 注册bot对应oauth应用
Doorkeeper::Application.create!(name: @bot.name, uid: @bot.client_id, secret: @bot.client_secret, redirect_uri: "https://gitlink.org.cn")
# 注册bot对应用户
result = autologin_register(User.generate_user_login('b'), nil, "#{SecureRandom.hex(6)}", 'bot', nil, nickname: @bot.name)
tip_exception(-1, result[:message]) if result[:message].present?
@bot.uid = result[:user][:id]
@bot.save
render_ok
end
rescue Exception => e
tip_exception(-1, e.message)
end
end
def access_tokens
@install_bot = BotInstall.find params[:id]
@bot = @install_bot.bot
@application = Doorkeeper::Application.find_by(uid: @bot.client_id, secret: @bot.client_secret)
tip_exception("该Bot未激活") if @application.blank?
# 给bot生成token因为bot是机器人操作
@access_token = Doorkeeper::AccessToken.create!({ :application_id => @application.id,
:resource_owner_id => @bot.uid,
:scopes => "public write",
:expires_in => "604800",
:use_refresh_token => true
})
render_ok(token: @access_token.token)
end
end

View File

@ -11,8 +11,6 @@ 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
@ -113,7 +111,9 @@ class IssuesController < ApplicationController
issue_params = issue_send_params(params)
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
@issue = Issue.new(issue_params)
@issue.project_issues_index = @project.get_last_project_issues_index + 1
if @issue.save!
@project.del_project_issue_cache_delete_count
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @issue&.id) if Site.has_notice_menu?
if params[:attachment_ids].present?
@ -157,6 +157,8 @@ class IssuesController < ApplicationController
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
# 新增时向grimoirelab推送事件
IssueWebhookJob.set(wait: 5.seconds).perform_later(@issue.id)
# author: zxh
# 扣除发起人的token
@ -230,7 +232,6 @@ 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, "不允许修改为关闭状态")
@ -238,9 +239,6 @@ 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?
@ -318,6 +316,7 @@ class IssuesController < ApplicationController
login = @issue.user.try(:login)
SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigned_to_id, @issue.author_id) if Site.has_notice_menu?
if @issue.destroy
@project.incre_project_issue_cache_delete_count
if issue_type == "2" && status_id != 5
post_to_chain("add", token, login)
end

View File

@ -4,7 +4,6 @@ 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
@ -80,11 +79,9 @@ class JournalsController < ApplicationController
def update
content = params[:content]
if content.present?
old_value = old_value_to_hash(@journal, params)
if content.present?
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
if @journal.update_attribute(:notes, content)
user_trace_update_log(old_value)
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")

View File

@ -1,19 +0,0 @@
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,7 +6,6 @@ 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)
@ -43,9 +42,7 @@ 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

@ -8,14 +8,17 @@ class Organizations::ProjectsController < Organizations::BaseController
.joins(team_projects: {team: :team_users})
.where(team_users: {user_id: current_user.id}).to_sql
@projects = Project.from("( #{ public_projects_sql} UNION #{ private_projects_sql } ) AS projects")
@projects = @projects.ransack(name_or_identifier_cont: params[:search]).result if params[:search].present?
# 表情处理
keywords = params[:search].to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
@projects = @projects.ransack(name_or_identifier_cont: keywords).result if params[:search].present?
@projects = @projects.includes(:owner).order("projects.#{sort} #{sort_direction}")
@projects = paginate(@projects)
end
def search
tip_exception("请输入搜索关键词") if params[:search].nil?
# 表情处理
keywords = params[:search].to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
public_projects_sql = @organization.projects.where(is_public: true).to_sql
private_projects_sql = @organization.projects
.where(is_public: false)
@ -23,7 +26,7 @@ class Organizations::ProjectsController < Organizations::BaseController
.where(team_users: {user_id: current_user.id}).to_sql
@projects = Project.from("( #{ public_projects_sql} UNION #{ private_projects_sql } ) AS projects")
@projects = @projects.ransack(name_or_identifier_cont: params[:search]).result
@projects = @projects.ransack(name_or_identifier_cont: keywords).result
@projects = @projects.includes(:owner).order("projects.#{sort} #{sort_direction}")
end

View File

@ -39,13 +39,14 @@ class ProjectsController < ApplicationController
category_id = params[:category_id]
@total_count =
if category_id.blank?
# ps = ProjectStatistic.first
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
if category_id.blank? && params[:search].blank?
# 默认查询时count性能问题处理
ProjectCategory.sum("projects_count") - Project.visible.joins("left join organization_extensions on organization_extensions.organization_id = projects.user_id").where("organization_extensions.visibility =2").count
elsif params[:search].present?
@projects.total_count
else
cate = ProjectCategory.find_by(id: category_id)
cate&.projects_count || 0
cate = ProjectCategory.find_by(id: category_id)
cate&.projects_count || 0
end
end
@ -53,7 +54,7 @@ class ProjectsController < ApplicationController
ActiveRecord::Base.transaction do
Projects::CreateForm.new(project_params).validate!
@project = Projects::CreateService.new(current_user, project_params).call
OpenProjectDevOpsJob.perform_later(@project&.id, current_user.id)
OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(@project&.id, current_user.id)
end
rescue Exception => e
uid_logger_error(e.message)

View File

@ -7,7 +7,6 @@ class PullRequestsController < ApplicationController
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
@ -110,13 +109,8 @@ 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)
@ -241,10 +235,8 @@ class PullRequestsController < ApplicationController
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)

View File

@ -1,7 +1,6 @@
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
@ -13,14 +12,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|
@ -87,7 +86,7 @@ class SettingsController < ApplicationController
}
end
end
def get_top_system_notification
@top_system_notification = SystemNotification.is_top.first
end

View File

@ -1,90 +0,0 @@
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

@ -1,212 +0,0 @@
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

@ -10,15 +10,15 @@ class Users::HeadmapsController < Users::BaseController
private
def start_stamp
if params[:year].present?
Date.new(params[:year], 1).to_time.to_i
Date.new(params[:year].to_i, 1).to_time.to_i
else
Date.today.to_time.to_i - 365*24*60*60
(Date.today - 1.years).to_time.to_i
end
end
def end_stamp
if params[:year].present?
Date.new(params[:year], 1).to_time.to_i + 365*24*60*60
(Date.new(params[:year].to_i, 1) + 1.years).to_time.to_i
else
Date.today.to_time.to_i
end

View File

@ -1,6 +1,7 @@
class Users::MessagesController < Users::BaseController
before_action :private_user_resources!
before_action :find_receivers, only: [:create]
before_action :check_auth
def index
limit = params[:limit] || params[:per_page]
@ -63,6 +64,10 @@ class Users::MessagesController < Users::BaseController
end
private
def check_auth
return render_forbidden unless current_user.admin? || observed_logged_user?
end
def message_type
@message_type = begin
case params[:type]

View File

@ -266,10 +266,6 @@ 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
@ -502,136 +498,136 @@ class UsersController < ApplicationController
# 替代解决方案
# 读取所有交易信息
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_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
@ -677,21 +673,6 @@ 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
@ -729,7 +710,7 @@ class UsersController < ApplicationController
:occupation, :technical_title,
:school_id, :department_id, :province, :city,
:custom_department, :identity, :student_id, :description,
:show_super_description, :super_description,:sponsor_description,
:show_super_description, :super_description,
:show_email, :show_location, :show_department]
)
end

View File

@ -4,7 +4,6 @@ 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))
@ -23,7 +22,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
@ -84,14 +83,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

@ -1,113 +0,0 @@
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

@ -0,0 +1,2 @@
module Admins::OrganizationsHelper
end

View File

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

View File

@ -66,6 +66,7 @@ module ProjectsHelper
jianmu_devops: jianmu_devops_code(project, user),
jianmu_devops_url: jianmu_devops_url,
cloud_ide_saas_url: cloud_ide_saas_url(user),
open_blockchain: EduSetting.get("open_blockchain_projects").to_s.split(",").include?(project.id.to_s) || EduSetting.get("open_blockchain_projects").to_s.split(",").include?(project.identifier) || EduSetting.get("open_blockchain_users").to_s.split(",").include?(user.id) || EduSetting.get("open_blockchain_users").to_s.split(",").include?(user.login),
ignore_id: project.ignore_id
}).compact
@ -138,6 +139,62 @@ module ProjectsHelper
"#{saas_url}/oauth/login?product_account_id=PA1001218&tenant_code=TI1001383&oauth_url=#{oauth_url}&token=#{token.value}"
end
def ai_shang_v1_url(project)
url = EduSetting.get("ai_shang_url") || "https://shang.gitlink.org.cn"
case project.identifier.to_s.downcase
when nil then ""
when 'rails' then "#{url}/v1/rails/entropy"
when 'jittor' then "#{url}/v1/jittor/entropy"
when 'paddle' then "#{url}/v1/Paddle/entropy"
when 'vue' then "#{url}/v1/vue/entropy"
when 'bootstrap' then "#{url}/v1/bootstrap/entropy"
when 'tensorflow' then "#{url}/v1/tensorflow/entropy"
else ''
end
end
def ai_shang_v2_url(project)
url = EduSetting.get("ai_shang_url") || "https://shang.gitlink.org.cn"
case project.identifier.to_s.downcase
when nil then ""
when 'rails' then "#{url}/v2/getMediumData?repo_login=rails&repo_name=rails"
when 'jittor' then "#{url}/v2/getMediumData?repo_login=Jittor&repo_name=jittor"
when 'paddle' then "#{url}/v2/getMediumData?repo_login=PaddlePaddle&repo_name=Paddle"
when 'vue' then "#{url}/v2/getMediumData?repo_login=vuejs&repo_name=vue"
when 'bootstrap' then "#{url}/v2/getMediumData?repo_login=twbs&repo_name=bootstrap"
when 'tensorflow' then "#{url}/v2/getMediumData?repo_login=tensorflow&repo_name=tensorflow"
else ''
end
end
def ai_shang_v4_url(project)
url = EduSetting.get("ai_shang_url") || "https://shang.gitlink.org.cn"
case project.identifier.to_s.downcase
when nil then ""
when 'rails' then "#{url}/v2/getIndexData?repo_login=rails&repo_name=rails"
when 'jittor' then "#{url}/v2/getIndexData?repo_login=Jittor&repo_name=jittor"
when 'paddle' then "#{url}/v2/getIndexData?repo_login=PaddlePaddle&repo_name=Paddle"
when 'vue' then "#{url}/v2/getIndexData?repo_login=vuejs&repo_name=vue"
when 'bootstrap' then "#{url}/v2/getIndexData?repo_login=twbs&repo_name=bootstrap"
when 'tensorflow' then "#{url}/v2/getIndexData?repo_login=tensorflow&repo_name=tensorflow"
else ''
end
end
def ai_shang_v3_url(project)
url = EduSetting.get("ai_shang_v3_url") || "https://entropy.ingress.isa.buaanlsde.cn"
case project.identifier.to_s.downcase
when nil then ""
when 'rails' then "#{url}/rails/entropy"
when 'jittor' then "#{url}/jittor/entropy"
when 'paddle' then "#{url}/paddle/entropy"
when 'vue' then "#{url}/vue/entropy"
when 'bootstrap' then "#{url}/bootstrap/entropy"
when 'tensorflow' then "#{url}/tensorflow/entropy"
else ''
end
end
def aes_encrypt(key, des_text)
# des_text='{"access_key_id":"STS.NTuC9RVmWfJqj3JkcMzPnDf7X","access_key_secret":"E8NxRZWGNxxMfwgt5nFLnBFgg6AzgXCZkSNCyqygLuHM","end_point":"oss-accelerate.aliyuncs.com","security_token":"CAIS8gF1q6Ft5B2yfSjIr5fACIPmu7J20YiaaBX7j2MYdt9Cq6Ocujz2IHhMenVhA+8Wv/02n2hR7PcYlq9IS55VWEqc/VXLaywQo22beIPkl5Gfz95t0e+IewW6Dxr8w7WhAYHQR8/cffGAck3NkjQJr5LxaTSlWS7OU/TL8+kFCO4aRQ6ldzFLKc5LLw950q8gOGDWKOymP2yB4AOSLjIx6lAt2T8vs/7hmZPFukSFtjCglL9J/baWC4O/csxhMK14V9qIx+FsfsLDqnUIs0YWpf0p3P0doGyf54vMWUM05A6dduPS7txkLAJwerjVl1/ADxc0/hqAASXhPeiktbmDjwvnSn4iKcSGQ+xoQB468eHXNdvf13dUlbbE1+JhRi0pZIB2UCtN9oTsLHcwIHt+EJaoMd3+hGwPVmvHSXzECDFHylZ8l/pzTwlE/aCtZyVmI5cZEvmWu2xBa3GRbULo7lLvyeX1cHTVmVWf4Nk6D09PzTU8qlAj","bucket":"edu-bigfiles1","region":"oss-cn-hangzhou","callback_url":"https://data.educoder.net/api/buckets/callback.json","bucket_host":"data.educoder.net"}'
# des = OpenSSL::Cipher::Cipher.new('aes-256-ctr')

View File

@ -213,5 +213,12 @@ module RepositoriesHelper
def tmp_dir
"repo"
end
def repo_git_submodule_url(owner, repo, path)
unless (path.starts_with?('http://') || path.starts_with?('https://'))
path = File.expand_path(path, "/#{owner&.login}/#{repo&.identifier}")
end
return path
end
end

View File

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

View File

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

View File

@ -1,6 +0,0 @@
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

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

View File

@ -0,0 +1,186 @@
class IssueWebhookJob < ApplicationJob
include ApplicationHelper
queue_as :message
def perform(issue_id)
issue = Issue.find_by(id: issue_id)
return if issue.blank?
project = issue.project
user = issue.user
domain = "#{Rails.application.config_for(:configuration)['platform_url']}"
gitea_domain = GiteaService.gitea_config[:domain]
ssh_url = "git@#{gitea_domain.gsub("https://", "")}:#{project.owner.login}/#{project.identifier}.git"
event_json = {
"action": "opened",
"number": 1,
"issue": {
"id": issue.id,
"url": "#{domain}/api/v1/#{project.owner.login}/#{project.identifier}/issues/#{issue.id}",
"html_url": "#{domain}/#{project.owner.login}/#{project.identifier}/issues/#{issue.id}",
"number": 1,
"user": {
"id": user.id,
"login": "#{user.login}",
"full_name": "",
"email": "#{user.mail}",
"avatar_url": "#{domain}/#{url_to_avatar(user)}",
"language": "",
"is_admin": false,
"last_login": "#{user.last_login_on}",
"created": "#{user.created_on}",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "#{user.login}"
},
"original_author": "",
"original_author_id": 0,
"title": "#{issue.subject}",
"body": "#{issue.description}",
"ref": "",
"labels": [],
"milestone": nil,
"assignee": nil,
"assignees": nil,
"state": "open",
"is_locked": false,
"comments": 0,
"created_at": "#{issue.created_on}",
"updated_at": "#{issue.updated_on}",
"closed_at": nil,
"due_date": nil,
"pull_request": nil,
"repository": {
"id": 11307,
"name": "#{project.identifier}",
"owner": "#{project.owner.login}",
"full_name": "#{project.owner.login}/#{project.identifier}"
}
},
"repository": {
"id": project.id,
"owner": {
"id": project.owner.id,
"login": "#{project.owner.login}",
"full_name": "",
"email": "#{project.owner.mail}",
"avatar_url": "#{domain}/#{url_to_avatar(project.owner)}",
"language": "",
"is_admin": false,
"last_login": "#{project.owner.last_login_on}",
"created": "#{project.owner.created_on}",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "#{project.owner.login}"
},
"name": "#{project.identifier}",
"full_name": "#{project.owner.login}/#{project.identifier}",
"description": "",
"empty": false,
"private": false,
"fork": false,
"template": false,
"parent": nil,
"mirror": false,
"size": 843,
"html_url": "#{domain}/#{project.owner.login}/#{project.identifier}",
"ssh_url": "#{ssh_url}",
"clone_url": "#{domain}/#{project.owner.login}/#{project.identifier}.git",
"original_url": "#{project.repository.mirror_url}",
"website": "",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 1,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "master",
"archived": false,
"created_at": "#{project.created_on}",
"updated_at": "#{project.updated_on}",
"permissions": {
"admin": true,
"push": true,
"pull": true
},
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": true,
"has_projects": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_squash_merge": true,
"default_merge_style": "merge",
"avatar_url": "",
"internal": false,
"mirror_interval": ""
},
"sender": {
"id": user.id,
"login": "#{user.login}",
"full_name": "",
"email": "#{user.mail}",
"avatar_url": "#{domain}/#{url_to_avatar(user)}",
"language": "",
"is_admin": false,
"last_login": "#{user.last_login_on}",
"created": "#{user.created_on}",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "",
"website": "",
"description": "",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "#{user.login}"
}
}
# puts "event_json:#{event_json.to_json}"
begin
url = URI("http://117.50.185.50:80")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"
uuid = SecureRandom.uuid
request['X-GitHub-Delivery'] = uuid
request['X-Gitea-Delivery'] = uuid
request['X-Gogs-Delivery'] = uuid
request['X-GitHub-Event'] = 'issues'
request['X-Gitea-Event'] = 'issues'
request['X-Gogs-Event'] = 'issues'
request.body = JSON.dump(event_json)
response = http.request(request)
Rails.logger.info "issue #{issue_id} webhook event======#{response.read_body}"
rescue Exception => e
Rails.logger.info "issue #{issue_id} webhook event error======#{e.message}"
puts "issue: #{issue_id} webhook event error======#{e.message}"
end
end
end

View File

@ -15,7 +15,7 @@ class MigrateRemoteRepositoryJob < ApplicationJob
## open jianmu devops
project_id = repo&.project&.id
puts "############ mirror project_id,user_id: #{project_id},#{user_id} ############"
OpenProjectDevOpsJob.perform_later(project_id, user_id) if project_id.present? && user_id.present?
OpenProjectDevOpsJob.set(wait: 5.seconds).perform_later(project_id, user_id) if project_id.present? && user_id.present?
puts "############ mirror status: #{repo.mirror.status} ############"
else
repo&.mirror&.failed!

View File

@ -1,15 +0,0 @@
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

View File

@ -5,6 +5,7 @@ class OpenProjectDevOpsJob < ApplicationJob
def perform(project_id, user_id)
project = Project.find_by(id: project_id)
return if project.blank?
user = User.find_by(id: user_id)
code = jianmu_devops_code(project, user)
uri = URI.parse("#{jianmu_devops_url}/activate?code=#{URI.encode_www_form_component(code)}")

View File

@ -34,8 +34,8 @@ class SendTemplateMessageJob < ApplicationJob
operator_id, issue_id = args[0], args[1]
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id)
return unless operator.present? && issue.present?
receivers = issue&.assigners.where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueAssigned.get_message_content(receivers, operator, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id})
receivers.find_each do |receiver|
@ -56,7 +56,7 @@ class SendTemplateMessageJob < ApplicationJob
operator = User.find_by_id(operator_id)
issue = Issue.find_by_id(issue_id)
return unless operator.present? && issue.present?
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id]).where.not(id: operator&.id)
receivers = User.where(id: issue.assigners.pluck(:id).append(issue&.author_id)).where.not(id: operator&.id)
receivers_string, content, notification_url = MessageTemplate::IssueChanged.get_message_content(receivers, operator, issue, change_params.symbolize_keys)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id, change_params: change_params.symbolize_keys})
receivers.find_each do |receiver|
@ -67,7 +67,7 @@ class SendTemplateMessageJob < ApplicationJob
issue_id = args[0]
issue = Issue.find_by_id(issue_id)
return unless issue.present?
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id])
receivers = User.where(id: issue.assigners.pluck(:id).append(issue&.author_id))
receivers_string, content, notification_url = MessageTemplate::IssueExpire.get_message_content(receivers, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
receivers.find_each do |receiver|
@ -78,7 +78,11 @@ class SendTemplateMessageJob < ApplicationJob
operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3]
operator = User.find_by_id(operator_id)
return unless operator.present?
receivers = User.where(id: [issue_assigned_to_id, issue_author_id]).where.not(id: operator&.id)
if issue_assigned_to_id.is_a?(Array)
receivers = User.where(id: issue_assigned_to_id.append(issue_author_id)).where.not(id: operator&.id)
else
receivers = User.where(id: [issue_assigned_to_id, issue_author_id]).where.not(id: operator&.id)
end
receivers_string, content, notification_url = MessageTemplate::IssueDeleted.get_message_content(receivers, operator, issue_title)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_title: issue_title})
receivers.find_each do |receiver|

View File

@ -1,20 +0,0 @@
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 :integer
# copy_from :string(255)
# 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

@ -1,18 +0,0 @@
# == 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

51
app/models/bot.rb Normal file
View File

@ -0,0 +1,51 @@
# == Schema Information
#
# Table name: bot
#
# id :integer not null, primary key
# bot_name :string(255)
# bot_des :text(4294967295)
# webhook :string(255)
# is_public :integer
# logo :string(255)
# state :integer
# client_id :string(255)
# client_secret :string(255)
# web_url :string(255)
# category :string(255)
# install_num :integer default("0")
# update_time :datetime not null
# create_time :datetime not null
# private_key :text(65535)
# uid :integer
# owner_id :integer
#
# Indexes
#
# name (bot_name) UNIQUE
#
class Bot < ApplicationRecord
self.table_name = "bot"
has_many :install_bots
def name
self.bot_name
end
def self.decode_jwt_token(token)
decoded_token = JWT.decode token, nil, false
return [nil, "Token已过期"] if Time.now.to_i - 60 - decoded_token[0]["exp"].to_i > 0
bot = Bot.find_by(id: decoded_token[0]["iss"])
return [nil, "Token不存在"] if bot.blank?
rsa_private = OpenSSL::PKey::RSA.new(bot.private_key)
rsa_public = rsa_private.public_key
JWT.decode token, rsa_public, true, { algorithm: 'RS256' }
[User.find_by(id: bot.owner_id), ""]
rescue JWT::DecodeError
Rails.logger.error "jwt token decode error:#{token}"
[nil, "无效Token"]
end
end

20
app/models/bot_install.rb Normal file
View File

@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: install_bot
#
# id :integer not null, primary key
# bot_id :integer not null
# installer_id :integer not null
# store_id :integer not null
# state :integer not null
# create_time :datetime not null
# update_time :datetime not null
#
# frozen_string_literal: true
class BotInstall < ApplicationRecord
self.table_name = "install_bot"
belongs_to :bot
end

View File

@ -39,18 +39,15 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# gitea_uid :integer
# 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")
# award_time :datetime
# gitea_token :string(255)
# platform :string(255)
#
# Indexes
#
@ -58,8 +55,9 @@
# 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)
# index_users_on_mail (mail)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_type (type)
#

View File

@ -1,19 +0,0 @@
# == 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

@ -194,7 +194,7 @@ module ProjectOperable
if owner.is_a?(User)
managers.exists?(user_id: user.id)
elsif owner.is_a?(Organization)
managers.exists?(user_id: user.id) || owner.is_owner?(user.id) || owner.is_only_admin?(user.id)
managers.exists?(user_id: user.id) || owner.is_owner?(user.id) || (owner.is_only_admin?(user.id) && (teams.pluck(:id) & user.teams.pluck(:id)).size > 0)
else
false
end
@ -205,7 +205,7 @@ module ProjectOperable
if owner.is_a?(User)
developers.exists?(user_id: user.id)
elsif owner.is_a?(Organization)
developers.exists?(user_id: user.id) || owner.is_only_write?(user.id)
developers.exists?(user_id: user.id) || (owner.is_only_write?(user.id) && (teams.pluck(:id) & user.teams.pluck(:id)).size > 0)
else
false
end

View File

@ -1,19 +1,18 @@
# == 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,24 +1,3 @@
# == 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,6 +6,9 @@
# 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
@ -17,11 +20,6 @@
# 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,37 +1,4 @@
# == 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
class Gitea::Webhook < Gitea::Base
serialize :events, JSON
self.inheritance_column = nil

View File

@ -1,34 +1,6 @@
# == 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
class Gitea::WebhookTask < Gitea::Base
serialize :payload_content, JSON
serialize :request_content, JSON
serialize :response_content, JSON
self.inheritance_column = nil
@ -40,7 +12,7 @@ class Gitea::WebhookTask < Gitea::Base
def response_content_json
JSON.parse(response_content)
rescue
rescue
{}
end
end
end

View File

@ -33,7 +33,6 @@
# issue_classify :string(255)
# ref_name :string(255)
# branch_name :string(255)
# blockchain_token_num :integer
#
# Indexes
#
@ -70,12 +69,24 @@ class Issue < ApplicationRecord
has_many :issue_tags, through: :issue_tags_relates
has_many :issue_times, dependent: :destroy
has_many :issue_depends, dependent: :destroy
has_many :issue_assigners, dependent: :destroy
has_many :assigners, through: :issue_assigners
has_many :issue_participants, dependent: :destroy
has_many :participants, through: :issue_participants
has_many :show_participants, -> {joins(:issue_participants).where.not(issue_participants: {participant_type: "atme"}).distinct}, through: :issue_participants, source: :participant
has_many :show_assigners, -> {joins(:issue_assigners).distinct}, through: :issue_assigners, source: :assigner
has_many :show_issue_tags, -> {joins(:issue_tags_relates).distinct}, through: :issue_tags_relates, source: :issue_tag
has_many :comment_journals, -> {where.not(notes: nil)}, class_name: "Journal", :as => :journalized
has_many :operate_journals, -> {where(notes: nil)}, class_name: "Journal", :as => :journalized
scope :issue_includes, ->{includes(:user)}
scope :issue_many_includes, ->{includes(journals: :user)}
scope :issue_issue, ->{where(issue_classify: [nil,"issue"])}
scope :issue_pull_request, ->{where(issue_classify: "pull_request")}
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
scope :closed, ->{where(status_id: 5)}
scope :opened, ->{where.not(status_id: 5)}
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
after_save :change_versions_count, :send_update_message_to_notice_system
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic

View File

@ -0,0 +1,20 @@
# == Schema Information
#
# Table name: issue_assigners
#
# id :integer not null, primary key
# issue_id :integer
# assigner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_issue_assigners_on_assigner_id (assigner_id)
# index_issue_assigners_on_issue_id (issue_id)
#
class IssueAssigner < ApplicationRecord
belongs_to :issue
belongs_to :assigner, class_name: "User"
end

View File

@ -0,0 +1,9 @@
class IssueParticipant < ApplicationRecord
belongs_to :issue
belongs_to :participant, class_name: "User"
enum participant_type: {"authored": 0, "assigned": 1, "commented": 2, "edited": 3, "atme": 4}
end

View File

@ -15,4 +15,21 @@
class IssuePriority < ApplicationRecord
has_many :issues
def self.init_data
map = {
"1" => "",
"2" => "正常",
"3" => "",
"4" => "紧急"
}
IssuePriority.order(id: :asc).each do |prty|
if map["#{prty.id}"] == prty.name
IssuePriority.find_or_create_by(id: prty.id, name: prty.name)
else
Issue.where(priority_id: prty.id).each{|i| i.update_column(:priority_id, 2)}
prty.destroy!
end
end
end
end

View File

@ -20,10 +20,28 @@ class IssueStatus < ApplicationRecord
ADD = 1
SOLVING = 2
SOLVED = 3
FEEDBACK = 4
# FEEDBACK = 4
CLOSED = 5
REJECTED = 6
has_many :issues
belongs_to :project, optional: true
def self.init_data
map = {
"1" => "新增",
"2" => "正在解决",
"3" => "已解决",
"5" => "关闭",
"6" => "拒绝"
}
IssueStatus.order(id: :asc).each do |stat|
if map["#{stat.id}"] == stat.name
IssueStatus.find_or_create_by(id: stat.id, name: stat.name)
else
Issue.where(status_id: stat.id).each{|i| i.update_column(:status_id, 1)}
stat.destroy!
end
end
end
end

View File

@ -23,6 +23,34 @@ class IssueTag < ApplicationRecord
has_many :issue_tags_relates, dependent: :destroy
has_many :issues, through: :issue_tags_relates
has_many :issue_issues, -> {where(issue_classify: [nil,"issue"])}, source: :issue, through: :issue_tags_relates
has_many :pull_request_issues, -> {where(issue_classify: "pull_request")}, source: :issue, through: :issue_tags_relates
belongs_to :project, optional: true, counter_cache: true
belongs_to :user, optional: true
def self.init_data(project_id)
data = [
["缺陷", "表示项目存在问题", "#d92d4c"],
["功能", "表示新功能申请", "#ee955a"],
["疑问", "表示存在的问题", "#2d6ddc"],
["支持", "表示特定功能或特定需求", "#019549"],
["任务", "表示需要分配的任务", "#c1a30d"],
["协助", "表示需要社区用户协助", "#2a0dc1"],
["搁置", "表示此问题暂时不会继续处理", "#892794"],
["文档", "表示文档材料补充", "#9ed600"],
["测试", "表示需要测试的需求", "#2897b9"],
["重复", "表示已存在类似的疑修", "#bb5332"]
]
data.each do |item|
next if IssueTag.exists?(project_id: project_id, name: item[0])
IssueTag.create!(project_id: project_id, name: item[0], description: item[1], color: item[2])
end
$redis_cache.hset("project_init_issue_tags", project_id, 1)
end
def reset_counter_field
self.update_column(:issues_count, issue_issues.size)
self.update_column(:pull_requests_count, pull_request_issues.size)
end
end

View File

@ -15,5 +15,29 @@
class IssueTagsRelate < ApplicationRecord
belongs_to :issue
belongs_to :issue_tag, counter_cache: :issues_count
belongs_to :issue_tag
after_create :increment_issue_tags_counter_cache
after_destroy :decrement_issue_tags_counter_cache
def increment_issue_tags_counter_cache
Rails.logger.info "11111"
Rails.logger.info self.issue.issue_classify
if self.issue.issue_classify == "issue"
IssueTag.increment_counter :issues_count, issue_tag_id
else
IssueTag.increment_counter :pull_requests_count, issue_tag_id
end
end
def decrement_issue_tags_counter_cache
Rails.logger.info "2222222"
Rails.logger.info self.issue.issue_classify
if self.issue.issue_classify == "issue"
IssueTag.decrement_counter :issues_count, issue_tag_id
else
IssueTag.decrement_counter :pull_requests_count, issue_tag_id
end
end
end

View File

@ -40,9 +40,12 @@ class Journal < ApplicationRecord
belongs_to :journalized, polymorphic: true
belongs_to :review, optional: true
belongs_to :resolveer, class_name: 'User', foreign_key: :resolveer_id, optional: true
belongs_to :parent_journal, class_name: 'Journal', foreign_key: :parent_id, optional: true, counter_cache: :comments_count
belongs_to :reply_journal, class_name: 'Journal', foreign_key: :reply_id, optional: true
has_many :journal_details, :dependent => :delete_all
has_many :attachments, as: :container, dependent: :destroy
has_many :children_journals, class_name: 'Journal', foreign_key: :parent_id
has_many :first_ten_children_journals, -> { order(created_on: :asc).limit(10)}, class_name: 'Journal', foreign_key: :parent_id
has_many :children_journals, class_name: 'Journal', foreign_key: :parent_id, dependent: :destroy
scope :journal_includes, ->{includes(:user, :journal_details, :attachments)}
scope :parent_journals, ->{where(parent_id: nil)}
@ -54,6 +57,81 @@ class Journal < ApplicationRecord
self.notes.blank? && self.journal_details.present?
end
def operate_content
content = ""
detail = self.journal_details.take
case detail.property
when 'issue'
return "创建了<b>疑修</b>"
when 'attachment'
old_value = Attachment.where(id: detail.old_value.split(",")).pluck(:filename).join("")
new_value = Attachment.where(id: detail.value.split(",")).pluck(:filename).join("")
if old_value.nil? || old_value.blank?
content += "添加了<b>#{new_value}</b>附件"
else
new_value = "" if new_value.blank?
content += "将附件由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
end
when 'issue_tag'
old_value = IssueTag.where(id: detail.old_value.split(",")).pluck(:name).join("")
new_value = IssueTag.where(id: detail.value.split(",")).pluck(:name).join("")
if old_value.nil? || old_value.blank?
content += "添加了<b>#{new_value}</b>标记"
else
new_value = "" if new_value.blank?
content += "将标记由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
end
when 'assigner'
old_value = User.where(id: detail.old_value.split(",")).pluck(:nickname).join("")
new_value = User.where(id: detail.value.split(",")).pluck(:nickname).join("")
if old_value.nil? || old_value.blank?
content += "添加负责人<b>#{new_value}</b>"
else
new_value = "" if new_value.blank?
content += "将负责人由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
end
when 'attr'
content = ""
case detail.prop_key
when 'subject'
return "修改了<b>标题</b>"
when 'description'
return "修改了<b>描述</b>"
when 'status_id'
old_value = IssueStatus.find_by_id(detail.old_value)&.name
new_value = IssueStatus.find_by_id(detail.value)&.name
content += "状态"
when 'priority_id'
old_value = IssuePriority.find_by_id(detail.old_value)&.name
new_value = IssuePriority.find_by_id(detail.value)&.name
content += "优先级"
when 'fixed_version_id'
old_value = Version.find_by_id(detail.old_value)&.name
new_value = Version.find_by_id(detail.value)&.name
content += "里程碑"
when 'branch_name'
old_value = detail.old_value
new_value = detail.value
content += "关联分支"
when 'start_date'
old_value = detail.old_value
new_value = detail.value
content += "开始日期"
when 'due_date'
old_value = detail.old_value
new_value = detail.value
content += "结束日期"
end
if old_value.nil? || old_value.blank?
content += "设置为<b>#{new_value}</b>"
else
new_value = "" if new_value.blank?
content += "由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
end
end
end
def journal_content
send_details = []
if self.is_journal_detail?

View File

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

View File

@ -26,7 +26,7 @@ class MessageTemplate::IssueAssigned < MessageTemplate
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}")
@ -52,7 +52,7 @@ class MessageTemplate::IssueAssigned < MessageTemplate
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', issue&.subject)
content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{id}', issue&.project_issues_index.to_s)
content.gsub!('{platform}', PLATFORM)
return receiver&.mail, title, content

View File

@ -20,7 +20,7 @@ class MessageTemplate::IssueAssignerExpire < MessageTemplate
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}")

View File

@ -20,7 +20,7 @@ class MessageTemplate::IssueAtme < MessageTemplate
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}")

View File

@ -27,20 +27,20 @@ class MessageTemplate::IssueChanged < MessageTemplate
project = issue&.project
owner = project&.owner
content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
change_count = change_params.keys.size
# 疑修负责人修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
assigner1 = User.where(id: change_params[:assigned_to_id][0])
assigner2 = User.where(id: change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
content.gsub!('{assigner1}', assigner1.present? ? assigner1.map{|a| a&.real_name}.join("") : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2.map{|a| a&.real_name}.join("") : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end
@ -205,20 +205,20 @@ class MessageTemplate::IssueChanged < MessageTemplate
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{repository}', project&.name)
content.gsub!('{title}', issue&.subject)
content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{id}', issue&.project_issues_index.to_s)
change_count = change_params.keys.size
# 疑修负责人修改
if change_params[:assigned_to_id].present?
assigner1 = User.find_by_id(change_params[:assigned_to_id][0])
assigner2 = User.find_by_id(change_params[:assigned_to_id][1])
assigner1 = User.where(id: change_params[:assigned_to_id][0])
assigner2 = User.where(id: change_params[:assigned_to_id][1])
if change_count > 1
content.sub!('{ifassigner}', '<br/>')
else
content.sub!('{ifassigner}', '')
end
content.sub!('{endassigner}', '')
content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员')
content.gsub!('{assigner1}', assigner1.present? ? assigner1.map{|a| a&.real_name}.join("") : '未指派成员')
content.gsub!('{assigner2}', assigner2.present? ? assigner2.map{|a| a&.real_name}.join("") : '未指派成员')
else
content.gsub!(/({ifassigner})(.*)({endassigner})/, '')
end

View File

@ -1,17 +1,3 @@
# == Schema Information
#
# Table name: message_templates
#
# id :integer not null, primary key
# type :string(255)
# sys_notice :text(65535)
# email :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# notification_url :string(255)
# email_title :string(255)
#
class MessageTemplate::IssueCreatorExpire < MessageTemplate
end
end

View File

@ -28,7 +28,7 @@ class MessageTemplate::IssueExpire < MessageTemplate
project = issue&.project
owner = project&.owner
content = sys_notice.gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
return receivers_string(receivers), content, url
rescue => e
@ -53,7 +53,7 @@ class MessageTemplate::IssueExpire < MessageTemplate
content.gsub!('{repository}', project&.name)
content.gsub!('{baseurl}', base_url)
content.gsub!('{title}', issue&.subject)
content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{id}', issue&.project_issues_index.to_s)
content.gsub!('{platform}', PLATFORM)
return receiver&.mail, title, content

View File

@ -27,7 +27,7 @@ class MessageTemplate::ProjectIssue < MessageTemplate
receivers = managers + followers
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.project_issues_index.to_s)
return receivers_string(receivers), content, url
rescue => e
@ -54,7 +54,7 @@ class MessageTemplate::ProjectIssue < MessageTemplate
content.gsub!('{repository}', project&.name)
content.gsub!('{login2}', owner&.login)
content.gsub!('{identifier}', project&.identifier)
content.gsub!('{id}', issue&.id.to_s)
content.gsub!('{id}', issue&.project_issues_index.to_s)
content.gsub!('{title}', issue&.subject)
content.gsub!('{platform}', PLATFORM)

View File

@ -39,18 +39,15 @@
# business :boolean default("0")
# profile_completed :boolean default("0")
# laboratory_id :integer
# platform :string(255) default("0")
# gitea_token :string(255)
# gitea_uid :integer
# is_shixun_marker :boolean default("0")
# admin_visitable :boolean default("0")
# collaborator :boolean default("0")
# gitea_uid :integer
# 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")
# award_time :datetime
# gitea_token :string(255)
# platform :string(255)
#
# Indexes
#
@ -58,8 +55,9 @@
# 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)
# index_users_on_mail (mail)
# index_users_on_login (login) UNIQUE
# index_users_on_mail (mail) UNIQUE
# index_users_on_phone (phone) UNIQUE
# index_users_on_type (type)
#
@ -146,6 +144,18 @@ class Organization < Owner
end
end
def projects_count
Project.where( user_id: self.id).count
end
def teams_count
teams.count
end
def organization_users_count
organization_users.count
end
def real_name
name = lastname + firstname
name = name.blank? ? (nickname.blank? ? login : nickname) : name

View File

@ -69,6 +69,8 @@ class Owner < ApplicationRecord
has_many :applied_transfer_projects, dependent: :destroy
scope :like, lambda { |keywords|
# 表情处理
keywords = keywords.to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
sql = "CONCAT(lastname, firstname) LIKE :search OR nickname LIKE :search OR login LIKE :search "
where(sql, :search => "%#{keywords.strip}%") unless keywords.blank?
}

View File

@ -1,16 +0,0 @@
# == 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

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