forked from Trustie/forgeplus
Compare commits
345 Commits
standalone
...
trustie_se
| Author | SHA1 | Date |
|---|---|---|
|
|
6eaf491f70 | |
|
|
d4d00b30bf | |
|
|
19ec81e975 | |
|
|
2ea78b4f20 | |
|
|
4c066b30ef | |
|
|
ad9bb8e542 | |
|
|
e36c7a4b6a | |
|
|
18c4c6ae2f | |
|
|
9979c87d0c | |
|
|
8e8ec821f2 | |
|
|
774b1bc79e | |
|
|
94166a363c | |
|
|
0219a1fdde | |
|
|
ebe5fad7dd | |
|
|
b2e7491ade | |
|
|
85a36ca2e7 | |
|
|
b0f80012ab | |
|
|
75cef14605 | |
|
|
0fc96026c8 | |
|
|
93f8b659a1 | |
|
|
b45ee11239 | |
|
|
553d3a019f | |
|
|
33fa55bcb6 | |
|
|
643a99fdf1 | |
|
|
38c5432c2a | |
|
|
5cf257c3cc | |
|
|
aa18fe0ad4 | |
|
|
1358c23ca6 | |
|
|
e8bfd0c955 | |
|
|
183eb15c7d | |
|
|
fb43268444 | |
|
|
c27cc063e6 | |
|
|
6f6fe61a9d | |
|
|
b673909f9e | |
|
|
bd4dbd577b | |
|
|
ee3a14fa28 | |
|
|
26bfc2c0bf | |
|
|
eb2d976876 | |
|
|
56721930a2 | |
|
|
2959414d56 | |
|
|
319e6ea084 | |
|
|
008fdbaf5a | |
|
|
6223cf41e2 | |
|
|
1d3f79e777 | |
|
|
b0092487e6 | |
|
|
0ae3544235 | |
|
|
05b3f2a2fb | |
|
|
97fe157279 | |
|
|
fbebd0a623 | |
|
|
a14a646768 | |
|
|
25487368e5 | |
|
|
02681abaee | |
|
|
fe23c2afbf | |
|
|
2fa0df3ae3 | |
|
|
dc0d31330a | |
|
|
b06ad71082 | |
|
|
3212bc4842 | |
|
|
779c86108a | |
|
|
e4779926bd | |
|
|
803fdfc49e | |
|
|
83e43f0c97 | |
|
|
ccec3494bc | |
|
|
e237fd46f7 | |
|
|
6dc2f0b062 | |
|
|
ca3c564529 | |
|
|
f79e4f8e81 | |
|
|
9cd18397f7 | |
|
|
bfd3298cd0 | |
|
|
077926de18 | |
|
|
4fade5d0b7 | |
|
|
f51ebaad67 | |
|
|
8ae6a0deb2 | |
|
|
d9b3711e08 | |
|
|
77620f7735 | |
|
|
acbd0d376c | |
|
|
2f4ffe3d8e | |
|
|
a6efae8b10 | |
|
|
5a728e7d4d | |
|
|
04a733d99f | |
|
|
9e8c576ff6 | |
|
|
94881dd72a | |
|
|
2c7bb1b5cd | |
|
|
0e4c0a46c2 | |
|
|
7fcbbb7922 | |
|
|
3d9fe5bba5 | |
|
|
4dccdfde97 | |
|
|
00fc83235f | |
|
|
498ee26f59 | |
|
|
5d771c824b | |
|
|
3eccd6be64 | |
|
|
9b3336c0a0 | |
|
|
12c961d70d | |
|
|
7750cbe272 | |
|
|
1f13bba52e | |
|
|
5dcee1b4dc | |
|
|
cf09b28f5e | |
|
|
f31796f344 | |
|
|
2d9bde134a | |
|
|
59db914bcc | |
|
|
a0a7f908f4 | |
|
|
17ccf3d576 | |
|
|
72a32ed8c4 | |
|
|
c64fa5135b | |
|
|
12cc37443e | |
|
|
055fa635d3 | |
|
|
5edea8960d | |
|
|
f5efbcfc04 | |
|
|
50dc5cce5d | |
|
|
bc8f032f2f | |
|
|
0d377943d5 | |
|
|
0afac46778 | |
|
|
a6cee63d17 | |
|
|
ebab541b29 | |
|
|
77797fb1f7 | |
|
|
20af4a7d82 | |
|
|
000197b0d1 | |
|
|
67b386d947 | |
|
|
6aa3321d17 | |
|
|
82df2fd6d8 | |
|
|
9d8df2b4d9 | |
|
|
d44308fc82 | |
|
|
ae7d0d1329 | |
|
|
071542bcb4 | |
|
|
676024b6db | |
|
|
55c74de8e4 | |
|
|
52c94effdc | |
|
|
7c88ea3d67 | |
|
|
d799d329ff | |
|
|
f15cd44dff | |
|
|
91ea5ca96a | |
|
|
3abd6037d9 | |
|
|
11724bf63f | |
|
|
ec3a556a6f | |
|
|
1d7c7eba24 | |
|
|
793cbb372a | |
|
|
396ac55429 | |
|
|
e1b4622ede | |
|
|
088c617cc1 | |
|
|
ff14215242 | |
|
|
121e04f751 | |
|
|
246b484ad8 | |
|
|
fc3cf01d3f | |
|
|
345fd31834 | |
|
|
8f5bb0e2d9 | |
|
|
7aea481ccf | |
|
|
37317f82bf | |
|
|
2dfd69ae21 | |
|
|
a132154136 | |
|
|
720c073f32 | |
|
|
185cb308ac | |
|
|
0076468a15 | |
|
|
910ae48556 | |
|
|
94edf8c624 | |
|
|
9cd9603869 | |
|
|
6e86f9d9f3 | |
|
|
e97e7aa550 | |
|
|
ffb3b26d3c | |
|
|
6d280ed8f2 | |
|
|
47b3816e4f | |
|
|
3f85f88c92 | |
|
|
1477811782 | |
|
|
f60cd409b6 | |
|
|
04b2a9b358 | |
|
|
9d46f2743d | |
|
|
000a4f8019 | |
|
|
aaf2b43986 | |
|
|
75a9a65b9b | |
|
|
0e8d461615 | |
|
|
49afc0e20a | |
|
|
17f2436118 | |
|
|
eac7331070 | |
|
|
2243697184 | |
|
|
551f333261 | |
|
|
18cf1d3ecb | |
|
|
f8be0e17e9 | |
|
|
7c1160b247 | |
|
|
4cefaa7e92 | |
|
|
dec264d169 | |
|
|
8aa935ad5c | |
|
|
4025d059cf | |
|
|
62a1e6730c | |
|
|
f082819496 | |
|
|
4bdff8313a | |
|
|
c4f91fb054 | |
|
|
43046a4ef3 | |
|
|
a33be8850e | |
|
|
fde01e62ef | |
|
|
7055974443 | |
|
|
d67c6f2f76 | |
|
|
e0022647ed | |
|
|
1f6ac05bad | |
|
|
0154115f6b | |
|
|
70dd2768e5 | |
|
|
c5dd099169 | |
|
|
3536918938 | |
|
|
d56da6d020 | |
|
|
56278b84f2 | |
|
|
882a50cf56 | |
|
|
234f5b900c | |
|
|
db4031b8bf | |
|
|
dd3236e310 | |
|
|
ecfc39565c | |
|
|
7fd41e13e4 | |
|
|
9ced678f91 | |
|
|
b25db9d37f | |
|
|
7951ca28d5 | |
|
|
4bbb843edf | |
|
|
747646cd9d | |
|
|
a5be4a9502 | |
|
|
d0d906d04c | |
|
|
4c69c4d20f | |
|
|
183315bbd9 | |
|
|
4dc3546124 | |
|
|
d796d59557 | |
|
|
bc639488aa | |
|
|
930805704a | |
|
|
9912ad0779 | |
|
|
d9ae4e4ba0 | |
|
|
23dc2d7fb6 | |
|
|
fe5c18c019 | |
|
|
fa6f015128 | |
|
|
7f1b95c7d7 | |
|
|
2346b0f848 | |
|
|
0156e9726c | |
|
|
ea070d4e23 | |
|
|
c0e97409cb | |
|
|
99fbecc834 | |
|
|
4cc8dd70f4 | |
|
|
8d0a6d267a | |
|
|
0db1820557 | |
|
|
b1c03ed5e8 | |
|
|
1c660213a7 | |
|
|
748f6cdd4d | |
|
|
1fe8d1defc | |
|
|
ef12f85687 | |
|
|
e120c4dac2 | |
|
|
e1cf2fcdeb | |
|
|
c4f380873e | |
|
|
5cb2e55f74 | |
|
|
ed54e2ae8e | |
|
|
386c90592e | |
|
|
664b806c0a | |
|
|
b530de4ddc | |
|
|
1dd3fbc69a | |
|
|
94d259ea03 | |
|
|
3091593d14 | |
|
|
c5d2fad913 | |
|
|
b97c42d0ae | |
|
|
c76466a883 | |
|
|
217e0fdd97 | |
|
|
f0b8489828 | |
|
|
a2612d8009 | |
|
|
2f2655525f | |
|
|
70ade7b27b | |
|
|
57c60b2fe9 | |
|
|
aa643430fa | |
|
|
1a93477635 | |
|
|
8f9aedd7d6 | |
|
|
ab989ed7d7 | |
|
|
28d07d5c54 | |
|
|
53d094784b | |
|
|
7c664addbd | |
|
|
6167834bfa | |
|
|
1bb754e9d8 | |
|
|
f2f2ce8252 | |
|
|
c6b79f82bc | |
|
|
4e3f9cc019 | |
|
|
5ed7b3e4ad | |
|
|
4e2c46260c | |
|
|
9ba00b21c9 | |
|
|
1100309038 | |
|
|
b11f5fd228 | |
|
|
af5f2b2fe3 | |
|
|
90dbe0730a | |
|
|
f39e8b7668 | |
|
|
d6633cb73a | |
|
|
86ef890f8b | |
|
|
a7a6abd22a | |
|
|
6fd47b56a5 | |
|
|
c956667ce0 | |
|
|
898453c88c | |
|
|
5701c818ed | |
|
|
1ac2ddfaa5 | |
|
|
0bd274f813 | |
|
|
4aac05d4e1 | |
|
|
b028a70646 | |
|
|
3c7da85bee | |
|
|
9751c954df | |
|
|
84b56bfcb8 | |
|
|
ac07c88f84 | |
|
|
7485564bb9 | |
|
|
5e696ae905 | |
|
|
b5acf2308a | |
|
|
e3f4313c80 | |
|
|
b223abe229 | |
|
|
b3bede308c | |
|
|
2f170a54c6 | |
|
|
22293572ac | |
|
|
d262da7c65 | |
|
|
2050559077 | |
|
|
8720cab1e9 | |
|
|
959c1e8d95 | |
|
|
52bde548fa | |
|
|
ea11672fff | |
|
|
09c4f8db0e | |
|
|
29dc3fff39 | |
|
|
da863c3963 | |
|
|
8d18149537 | |
|
|
8050af23fc | |
|
|
298abdd1b1 | |
|
|
eb0ced39f5 | |
|
|
2738d950d4 | |
|
|
3ce9b2d145 | |
|
|
26f87fba16 | |
|
|
465f38bca7 | |
|
|
1e9a32a93e | |
|
|
04bc6d363f | |
|
|
2dc79052c2 | |
|
|
f6ff8ac209 | |
|
|
b9e2a6edf1 | |
|
|
e0f5337fdd | |
|
|
380ca3a066 | |
|
|
7d19849968 | |
|
|
237b0afb08 | |
|
|
67914201bf | |
|
|
e14936e820 | |
|
|
655c85851f | |
|
|
1c7e414aa4 | |
|
|
099fc52e00 | |
|
|
490957ec3b | |
|
|
b1884d30d5 | |
|
|
98d8ee1fb6 | |
|
|
2ca77732c8 | |
|
|
1760b42127 | |
|
|
9f7725b097 | |
|
|
612101498c | |
|
|
70d22f7c4f | |
|
|
25d0e784bb | |
|
|
5d45b24299 | |
|
|
b6b8befde7 | |
|
|
f33b9559cd | |
|
|
ab6ac05a7d | |
|
|
cf69628f85 | |
|
|
4a8f8af896 | |
|
|
f9bc2258ec |
|
|
@ -84,4 +84,5 @@ redis_data/
|
|||
Dockerfile
|
||||
dump.rdb
|
||||
.tags*
|
||||
ceshi_user.xlsx
|
||||
ceshi_user.xlsx
|
||||
public/trace_task_results
|
||||
143
README.md
143
README.md
|
|
@ -1,30 +1,17 @@
|
|||
# GitLink - CCF开源创新服务平台
|
||||
Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台。
|
||||
|
||||
GitLink(确实开源)是中国计算机学会(CCF)官方指定的开源创新服务平台,旨在以“为开源创新服务”为使命,以“成为开源创新的汇聚地”为愿景,秉承“创新、开放、协作、共享”的价值观,致力于为大规模开源开放协同创新助力赋能,打造创新成果孵化和新工科人才培养的开源创新生态!
|
||||
## 特性
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/gitlink.png?raw=true" width=80% />
|
||||
</center>
|
||||
|
||||
## 特色功能
|
||||
- 软件创作与生产深度融合的软件开发环境体系结构 软件自由创作和工程生产的高效衔接,适于软件开发中群体智慧的有效汇聚。
|
||||
|
||||
- **分布式协作开发**:基于Git打造分布式代码托管环境,提供免费公、私有代码仓库,支持在线文件编辑、代码分支管理、协作贡献统计、代码仓库复刻(Fork)、贡献合并请求(PR)、群智贡献审阅等功能,让您的项目在这里健康、快速的成长!
|
||||
- 构件化协同开发环境的可扩展运行框架多样化工具的集成和联动,形成了强动态扩展能力的平台框架。
|
||||
|
||||
- **一站式过程管理**:提供易修(Issue)、里程碑、通知提醒、标签归档等多样化任务管理工具,支持各类开发任务的发布、指派与跟踪,同时提供在线Wiki文档、组织多粒度管理等功能,为您搭建一站式的项目过程管理环境,让您的团队协作更高效、过程更透明!
|
||||
- “互联网即资源库”的全新软件复用模式 成长式软件资源管理系统,实现了分散资源的知识融合、资源的可持续增长和有效复用。
|
||||
|
||||
- **高效流水线运维**:融合DevOps思想,提供轻量级的工作流引擎(Engine),打通编码、测试、构建、部署等开发运维环节;支持自定义配置、代码静态扫描、构建自动触发、容器镜像托管等功能,同时支持接入第三方运维工具,让您的代码更加快速、可靠地形成高质量的产品!
|
||||
|
||||
- **多层次代码分析**:提供软件软代码和芯片RTL代码的溯源分析、文件级和组件级许可证识别及风险分析、输入性开源漏洞检测和加固建议,支持分析结果的多层次可视化展示,帮助您实施有效开源治理,厘清代码引用链,发现并消除漏洞感染链,为安全合规的开源引用保驾护航!
|
||||
|
||||
- **多维度用户画像**:实时采集和分析平台中的各类开源资源数据,搭建多维度用户画像评估系统,提供开发活动统计、贡献度日历、用户能力建模、角色与专业定位分析等功能,让您在个人主页展示开发动态与创新能力!
|
||||
|
||||
## 第三方组件
|
||||
## 部署
|
||||
|
||||
|
||||
## 部署流程
|
||||
|
||||
|
||||
### 依赖库
|
||||
### Depends Versions
|
||||
|
||||
* Ruby 2.4.5
|
||||
|
||||
|
|
@ -36,19 +23,22 @@ GitLink(确实开源)是中国计算机学会(CCF)官方指定的开源
|
|||
|
||||
* imagemagick
|
||||
|
||||
### 步骤
|
||||
### Steps
|
||||
|
||||
(1)克隆稳定版本
|
||||
#### 1. 克隆稳定版本
|
||||
```
|
||||
git clone -b standalone https://git.trustie.net/jasder/forgeplus.git
|
||||
```
|
||||
|
||||
(2)安装依赖包
|
||||
#### 2. 安装依赖包
|
||||
|
||||
```bash
|
||||
cd forgeplus && bundle install
|
||||
```
|
||||
|
||||
(3)配置初始化文件:进入项目根目录执行以下命令
|
||||
#### 3. 配置初始化文件
|
||||
进入项目根目录执行一下命令:
|
||||
|
||||
```bash
|
||||
cp config/configuration.yml.example config/configuration.yml
|
||||
cp config/database.yml.example config/database.yml
|
||||
|
|
@ -56,7 +46,11 @@ touch config/redis.yml
|
|||
touch config/elasticsearch.yml
|
||||
```
|
||||
|
||||
(4)配置数据库:数据库配置信息请查看/config/database.yml文件,项目默认采用mysql数据库, 如需更改,请自行修改配置信息,默认配置如下
|
||||
#### 4. 配置数据库
|
||||
数据库配置信息请查看/config/database.yml文件,
|
||||
项目默认采用mysql数据库, 如需更改,请自行修改配置信息,
|
||||
默认配置如下:
|
||||
|
||||
```bash
|
||||
default: &default
|
||||
adapter: mysql2
|
||||
|
|
@ -66,13 +60,14 @@ default: &default
|
|||
password: 123456
|
||||
```
|
||||
|
||||
(5)配置gitea服务(可选):如需要部署自己的gitea平台,请参考[gitea官方平台文档](https://docs.gitea.io/zh-cn/install-from-binary/)。因目前gitea平台api受限,暂时推荐从forge平台获取[gitea部署文件](https://forgeplus.trustie.net/projects/Trustie/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**
|
||||
|
||||
**配置gitea服务步骤**
|
||||
1. 部署gitea服务,并注册root账户
|
||||
2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如:
|
||||
|
||||
```ruby
|
||||
gitea:
|
||||
|
|
@ -82,9 +77,10 @@ gitea:
|
|||
base_url: '/api/v1'
|
||||
```
|
||||
|
||||
(6)安装redis环境:请自行搜索各平台如何安装部署redis环境
|
||||
#### 6. 安装redis环境
|
||||
**请自行搜索各平台如何安装部署redis环境**
|
||||
|
||||
(7)安装imagemagick插件:
|
||||
#### 7. 安装imagemagick插件
|
||||
- Mac OS X
|
||||
```bash
|
||||
brew install imagemagick ghostscript
|
||||
|
|
@ -95,95 +91,88 @@ gitea:
|
|||
sudo apt-get install -y imagemagick
|
||||
```
|
||||
|
||||
(8)创建数据库:开发环境为development, 生成环境为production
|
||||
#### 8. 创建数据库
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
rails db:create RAILS_ENV=development
|
||||
```
|
||||
|
||||
(9)导入数据表结构
|
||||
#### 9. 导入数据表结构
|
||||
|
||||
```bash
|
||||
bundle exec rake sync_table_structure:import_csv
|
||||
```
|
||||
|
||||
(10)执行migrate迁移文件:开发环境为development, 生成环境为production
|
||||
#### 10. 执行migrate迁移文件
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
rails db:migrate RAILS_ENV=development
|
||||
```
|
||||
|
||||
(11)clone前端代码:将前端代码克隆到public/react目录下,目录结构应该是: public/react/build
|
||||
#### 11. clone前端代码
|
||||
**将前端代码克隆到public/react目录下,目录结构应该是: public/react/build**
|
||||
```bash
|
||||
git clone -b standalone https://git.trustie.net/jasder/build.git
|
||||
```
|
||||
|
||||
(12)启动redis(此处以macOS系统为例)
|
||||
#### 12. 启动redis(此处已mac系统为例)
|
||||
```bash
|
||||
redis-server&
|
||||
```
|
||||
|
||||
(13)启动sidekiq:开发环境为development, 生成环境为production
|
||||
#### 13. 启动sidekiq
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
bundle exec sidekiq -C config/sidekiq.yml -e production -d
|
||||
```
|
||||
|
||||
(14)启动rails服务
|
||||
#### 14. 启动rails服务
|
||||
```bash
|
||||
rails s
|
||||
```
|
||||
|
||||
(15)浏览器访问:在浏览器中输入如下地址访问
|
||||
#### 15. 浏览器访问
|
||||
在浏览器中输入如下地址访问:
|
||||
```bash
|
||||
http://localhost:3000/
|
||||
```
|
||||
|
||||
(16)其他说明:通过页面注册以第一个用户为平台管理员用户
|
||||
|
||||
#### 16. 其他说明
|
||||
通过页面注册都第一个用户为平台管理员用户
|
||||
|
||||
## 页面展示
|
||||
|
||||
- 项目列表
|
||||
- 代码库
|
||||
|
||||

|
||||
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/project_list.png?raw=true" width=50% />
|
||||
</center>
|
||||
|
||||
- 代码仓库
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/repo.png?raw=true" width=50% />
|
||||
</center>
|
||||
|
||||
- 任务管理
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/issues.png?raw=true" width=50% />
|
||||
</center>
|
||||
|
||||
- 合并请求
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/PR.png?raw=true" width=50% />
|
||||
</center>
|
||||
|
||||
- 引擎配置
|
||||
|
||||
<center>
|
||||
<img src="https://code.gitlink.org.cn/young/forgeplus/raw/branch/standalone/docs/figs/engine.png?raw=true" width=50% />
|
||||
</center>
|
||||

|
||||
|
||||
- 任务查看
|
||||
|
||||

|
||||
|
||||
- 任务指派
|
||||
|
||||

|
||||
|
||||
- 里程碑
|
||||
|
||||

|
||||
|
||||
### API
|
||||
- [API文档](https://forgeplus.trustie.net/docs/api)
|
||||
- [API](showdoc.com.cn)
|
||||
账号:forgeplus@admin.com 密码:forge123
|
||||
|
||||
## 贡献代码
|
||||
|
||||
我们期待您向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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
class AccountsController < ApplicationController
|
||||
before_action :require_login, only: [:login_check, :simple_update]
|
||||
include ApplicationHelper
|
||||
|
||||
#skip_before_action :check_account, :only => [:logout]
|
||||
|
||||
def simple_update
|
||||
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, ""))
|
||||
Register::RemoteForm.new(simple_update_params).validate!
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = auto_update(current_user, simple_update_params)
|
||||
if result[:message].blank?
|
||||
render_ok
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
|
@ -192,7 +211,9 @@ class AccountsController < ApplicationController
|
|||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
email: @user.mail,
|
||||
login_name: @user.name,
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
|
|
@ -313,6 +334,11 @@ class AccountsController < ApplicationController
|
|||
Register::CheckColumnsForm.new(check_params).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
def login_check
|
||||
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
@ -381,4 +407,7 @@ class AccountsController < ApplicationController
|
|||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
|
||||
def simple_update_params
|
||||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
|
|||
def create
|
||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||
|
||||
result = Admins::ImportUserService.call(params[:file].to_io)
|
||||
result = Admins::ImportUserFromExcelService.call(params[:file].to_io)
|
||||
render_ok(result)
|
||||
rescue Admins::ImportUserService::Error => ex
|
||||
render_error(ex)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
class Admins::Topic::GlccNewsController < Admins::Topic::BaseController
|
||||
before_action :find_glcc, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
q = ::Topic::GlccNews.ransack(title_cont: params[:search])
|
||||
glcc_news = q.result(distinct: true)
|
||||
@glcc_news = paginate(glcc_news)
|
||||
end
|
||||
|
||||
def new
|
||||
@glcc = ::Topic::GlccNews.new
|
||||
end
|
||||
|
||||
def create
|
||||
@glcc = ::Topic::GlccNews.new(glcc_params)
|
||||
if @glcc.save
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "新增新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "新增新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
@glcc.attributes = glcc_params
|
||||
if @glcc.save
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "更新新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "更新新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @glcc.destroy
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:success] = "删除新闻稿成功"
|
||||
else
|
||||
redirect_to admins_topic_glcc_news_index_path
|
||||
flash[:danger] = "删除新闻稿失败"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_glcc
|
||||
@glcc = ::Topic::GlccNews.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def glcc_params
|
||||
params.require(:topic_glcc_news).permit(:title, :uuid, :url, :order_index)
|
||||
end
|
||||
end
|
||||
|
|
@ -217,7 +217,7 @@ class AttachmentsController < ApplicationController
|
|||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user)
|
||||
candown = course.member?(current_user) || course.is_public
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
|
|||
namespace = params[:owner]
|
||||
id = params[:repo] || params[:id]
|
||||
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id, current_user.login)
|
||||
end
|
||||
|
||||
def load_all_repo
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class Ci::SecretsController < Ci::BaseController
|
|||
end
|
||||
|
||||
def ci_drone_url
|
||||
user = User.find_by(login: params[:owner])
|
||||
user = User.find_by(login: params[:owner]) || User.find_by(login: current_user.login)
|
||||
user&.ci_cloud_account.drone_url
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ class CompareController < ApplicationController
|
|||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
@page_size = page_size <= 0 ? 1 : page_size
|
||||
@page_limit = page_limit <=0 ? 15 : page_limit
|
||||
@page_offset = (@page_size -1) * @page_limit
|
||||
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -16,6 +20,7 @@ class CompareController < ApplicationController
|
|||
if @base.blank? || @head.blank?
|
||||
return -2, "请选择分支"
|
||||
else
|
||||
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||
if @head.include?(":")
|
||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||
|
|
@ -50,6 +55,14 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def gitea_compare(base, head)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
|
||||
end
|
||||
|
||||
def page_size
|
||||
params.fetch(:page, 1).to_i
|
||||
end
|
||||
|
||||
def page_limit
|
||||
params.fetch(:limit, 15).to_i
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ module Ci::CloudAccountManageable
|
|||
|
||||
def drone_oauth_user!(url, state)
|
||||
logger.info "[drone] drone_oauth_user url: #{url}"
|
||||
conn = Faraday.new(url: url) do |req|
|
||||
conn = Faraday.new(url: "#{Gitea.gitea_config[:domain]}#{url}") do |req|
|
||||
req.request :url_encoded
|
||||
req.adapter Faraday.default_adapter
|
||||
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
||||
|
|
@ -188,7 +188,8 @@ module Ci::CloudAccountManageable
|
|||
response = conn.get
|
||||
logger.info "[drone] response headers: #{response.headers}"
|
||||
|
||||
response.headers['location'].include?('error') ? false : true
|
||||
true
|
||||
# response.headers['location'].include?('error') ? false : true
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -108,7 +108,11 @@ module LoginHelper
|
|||
def sync_pwd_to_gitea!(user, hash={})
|
||||
return true if user.is_sync_pwd?
|
||||
|
||||
sync_params = { email: user.mail }
|
||||
sync_params = {
|
||||
login_name: user.name,
|
||||
source_id: 0,
|
||||
email: user.mail
|
||||
}
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
||||
if interactor.success?
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
||||
|
|
|
|||
|
|
@ -58,4 +58,32 @@ module RegisterHelper
|
|||
end
|
||||
end
|
||||
|
||||
def auto_update(user, params={})
|
||||
return if params.blank?
|
||||
result = {message: nil, user: nil}
|
||||
before_login = user.login
|
||||
user.login = params[:username]
|
||||
user.password = params[:password]
|
||||
user.mail = params[:email]
|
||||
|
||||
if user.save!
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: params[:email],
|
||||
login_name: params[:username],
|
||||
new_name: params[:username],
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||
if interactor.success?
|
||||
result[:user] = user
|
||||
else
|
||||
result[:message] = '用户同步Gitea失败!'
|
||||
end
|
||||
else
|
||||
result[:message] = user.errors.full_messages.join(",")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module RenderHelper
|
|||
end
|
||||
|
||||
def render_error(message = '')
|
||||
render json: { status: -1, message: message }
|
||||
render json: { status: status, message: message }
|
||||
end
|
||||
|
||||
def render_not_acceptable(message = '请求已拒绝')
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ class IssuesController < ApplicationController
|
|||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
||||
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
||||
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
||||
@assign_to_me = @filter_issues.where(assigned_to_id: current_user&.id)
|
||||
@my_published = @filter_issues.where(author_id: current_user&.id)
|
||||
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
||||
@issues_size = scopes.size
|
||||
@assign_to_me = scopes.where(assigned_to_id: current_user&.id)
|
||||
@my_published = scopes.where(author_id: current_user&.id)
|
||||
@issues = paginate(scopes)
|
||||
|
||||
respond_to do |format|
|
||||
|
|
@ -109,7 +109,7 @@ class IssuesController < ApplicationController
|
|||
|
||||
def create
|
||||
issue_params = issue_send_params(params)
|
||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
@issue = Issue.new(issue_params)
|
||||
if @issue.save!
|
||||
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||
|
|
@ -149,6 +149,8 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
|
||||
|
||||
|
||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||
|
|
@ -178,6 +180,7 @@ class IssuesController < ApplicationController
|
|||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
next if tag == [""]
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
|
|
@ -220,7 +223,7 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "不允许修改为关闭状态")
|
||||
else
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
if @issue.update_attributes(issue_params)
|
||||
if @issue&.pull_request.present?
|
||||
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||
|
|
@ -244,7 +247,7 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
@issue.update_closed_issues_count_in_project!
|
||||
# @issue.update_closed_issues_count_in_project!
|
||||
if @issue.issue_type.to_s == "2" && last_status_id != 5
|
||||
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token
|
||||
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class JournalsController < ApplicationController
|
|||
normal_status(-1, "评论内容不能为空")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
Journals::CreateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
journal_params = {
|
||||
journalized_id: @issue.id ,
|
||||
journalized_type: "Issue",
|
||||
|
|
@ -53,6 +54,9 @@ class JournalsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
@ -70,7 +74,8 @@ class JournalsController < ApplicationController
|
|||
|
||||
def update
|
||||
content = params[:content]
|
||||
if content.present?
|
||||
if content.present?
|
||||
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
if @journal.update_attribute(:notes, content)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
|
|
@ -79,7 +84,9 @@ class JournalsController < ApplicationController
|
|||
else
|
||||
normal_status(-1, "评论的内容不能为空")
|
||||
end
|
||||
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def get_children_journals
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
class NoticesController < ApplicationController
|
||||
|
||||
def create
|
||||
tip_exception("参数有误") if params["source"].blank?
|
||||
user_id = params[:user_id]
|
||||
|
||||
if params["source"] == "CompetitionBegin"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionBegin', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionResult"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionResult', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionReview"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
|
||||
else
|
||||
tip_exception("#{params["source"]}未配置")
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,11 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
|||
def index
|
||||
@organization_users = @organization.organization_users.includes(:user)
|
||||
search = params[:search].to_s.downcase
|
||||
@organization_users = @organization_users.joins(:user).merge(User.like(search))
|
||||
user_condition_users = User.like(search).to_sql
|
||||
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||
|
||||
@organization_users = @organization_users.where(user_id: users).distinct
|
||||
|
||||
@organization_users = kaminari_paginate(@organization_users)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
if @organization.teams.count >= 50
|
||||
return render_forbidden("组织的团队数量已超过限制!")
|
||||
return tip_exception("组织的团队数量已超过限制!")
|
||||
else
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class OwnersController < ApplicationController
|
|||
|
||||
def show
|
||||
@owner = Owner.find_by(login: params[:id]) || Owner.find_by(id: params[:id])
|
||||
return render_ok(type: 'User') unless @owner.present?
|
||||
return render_not_found unless @owner.present?
|
||||
# 组织
|
||||
if @owner.is_a?(Organization)
|
||||
return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class PraiseTreadController < ApplicationController
|
|||
begin
|
||||
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
|
||||
current_user.like!(@project)
|
||||
SendTemplateMessageJob.perform_later('ProjectPraised', current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class ProjectsController < ApplicationController
|
|||
def menu_list
|
||||
menu = []
|
||||
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
|
||||
menu.append(menu_hash_by_name("home"))
|
||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||
|
|
@ -20,9 +22,11 @@ class ProjectsController < ApplicationController
|
|||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
|
||||
menu.append(menu_hash_by_name("services")) if @project.has_menu_permission("services") && @project.forge? && (current_user.admin? || @project.member?(current_user.id))
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||
menu.append(menu_hash_by_name("activity"))
|
||||
menu.append(menu_hash_by_name("settings")) if (current_user.admin? || @project.manager?(current_user)) && @project.forge?
|
||||
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
||||
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
|
||||
render json: menu
|
||||
end
|
||||
|
|
@ -59,7 +63,7 @@ class ProjectsController < ApplicationController
|
|||
Projects::MigrateForm.new(mirror_params).validate!
|
||||
|
||||
@project =
|
||||
if enable_accelerator?(mirror_params[:clone_addr])
|
||||
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
uid_logger("########## 已动加速器 ##########")
|
||||
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||
|
|
@ -71,6 +75,11 @@ class ProjectsController < ApplicationController
|
|||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
|
||||
uid_logger("########## 更改clone_addr ##########")
|
||||
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
|
|
@ -83,7 +92,7 @@ class ProjectsController < ApplicationController
|
|||
return @branches = [] unless @project.forge?
|
||||
|
||||
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
|
||||
end
|
||||
|
||||
|
|
@ -130,7 +139,7 @@ class ProjectsController < ApplicationController
|
|||
validate_params = project_params.slice(:name, :description,
|
||||
:project_category_id, :project_language_id, :private, :identifier)
|
||||
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
|
||||
|
||||
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||
|
||||
|
|
@ -172,6 +181,22 @@ class ProjectsController < ApplicationController
|
|||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def quit
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
ActiveRecord::Base.transaction do
|
||||
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
|
||||
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
render_forbidden('你不能退出该仓库')
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
||||
@watchers_count = watchers.size
|
||||
|
|
@ -185,7 +210,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def fork_users
|
||||
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
@forks_count = fork_users.size
|
||||
@fork_users = paginate(fork_users)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
|
|||
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||
before_action :require_profile_completed, only: [:create]
|
||||
before_action :load_repository
|
||||
before_action :check_menu_authorize
|
||||
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
|
||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||
before_action :load_pull_request, only: [:files, :commits]
|
||||
before_action :find_atme_receivers, only: [:create, :update]
|
||||
|
|
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
|
|||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||
@all_issues = issues.distinct
|
||||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||
|
|
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@all_branches = Branches::ListService.call(@owner, @project)
|
||||
@all_branches = Branches::ListService.call(@owner, @project, params[:branch_name])
|
||||
@is_fork = @project.forked_from_project_id.present?
|
||||
@projects_names = [{
|
||||
project_user_login: @owner.try(:login),
|
||||
|
|
@ -50,7 +50,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def get_branches
|
||||
branch_result = Branches::ListService.call(@owner, @project)
|
||||
branch_result = Branches::ListService.call(@owner, @project, params[:name])
|
||||
render json: branch_result
|
||||
# return json: branch_result
|
||||
end
|
||||
|
|
@ -58,6 +58,7 @@ class PullRequestsController < ApplicationController
|
|||
def create
|
||||
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
if @gitea_pull_request[:status] == :success
|
||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
||||
|
|
@ -89,7 +90,7 @@ class PullRequestsController < ApplicationController
|
|||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
return normal_status(-1, "title不能超过255个字符") if params[:title].length > 255
|
||||
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
merge_params
|
||||
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
|
|
@ -274,12 +275,12 @@ class PullRequestsController < ApplicationController
|
|||
base: params[:base], #目标分支
|
||||
milestone: 0, #里程碑,未与本地的里程碑关联
|
||||
}
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
@requests_params = @local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||
assignees: ["#{current_user.try(:login).to_s}"],
|
||||
labels: params[:issue_tag_ids],
|
||||
due_date: Time.now
|
||||
assignees: ["#{assignee_login.to_s}"],
|
||||
labels: params[:issue_tag_ids]
|
||||
# due_date: Time.now
|
||||
})
|
||||
@issue_params = {
|
||||
author_id: current_user.id,
|
||||
|
|
|
|||
|
|
@ -1,387 +1,391 @@
|
|||
class RepositoriesController < ApplicationController
|
||||
include RepositoriesHelper
|
||||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include Repository::LanguagesPercentagable
|
||||
|
||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||
before_action :require_profile_completed, only: [:create_file]
|
||||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
def top_counts
|
||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
begin
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
end
|
||||
rescue
|
||||
return render_error('该文件暂未开放,敬请期待.')
|
||||
end
|
||||
end
|
||||
else
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits
|
||||
if @project.educoder?
|
||||
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
|
||||
else
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits_slice
|
||||
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def commit
|
||||
@sha = params[:sha]
|
||||
if @project.educoder?
|
||||
return render_error('暂未开放,敬请期待.')
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def contributors
|
||||
if params[:filepath].present? || @project.educoder?
|
||||
@contributors = []
|
||||
else
|
||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
||||
end
|
||||
|
||||
def create_file
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# create_new_pr(params)
|
||||
#如果是更新流水线文件
|
||||
if params[:pipeline_id]
|
||||
update_pipeline(params[:pipeline_id])
|
||||
end
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def update_pipeline(pipeline_id)
|
||||
pipeline = Ci::Pipeline.find(pipeline_id)
|
||||
if pipeline
|
||||
pipeline.update!(sync: 1)
|
||||
end
|
||||
end
|
||||
|
||||
def update_file
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# TODO: 是否创建pr
|
||||
# create_new_pr(params)
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "文件删除成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def repo_hook
|
||||
|
||||
end
|
||||
|
||||
def sync_mirror
|
||||
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
||||
|
||||
@repository.sync_mirror!
|
||||
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def readme
|
||||
if params[:filepath].present?
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
end
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
||||
rescue
|
||||
render json: nil
|
||||
end
|
||||
|
||||
def languages
|
||||
if @project.educoder?
|
||||
render json: {}
|
||||
else
|
||||
render json: languages_precentagable
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_project
|
||||
@project = Project.find params[:id]
|
||||
render_not_found("未找到相关的仓库") unless @project
|
||||
end
|
||||
|
||||
def find_project_with_includes
|
||||
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
||||
end
|
||||
|
||||
def authorizate!
|
||||
return if current_user && current_user.admin?
|
||||
if @project.repository.hidden? && !@project.member?(current_user)
|
||||
render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
# TODO 获取最新commit信息
|
||||
def project_commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
else
|
||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
@ref = params[:ref] || @project&.default_branch
|
||||
end
|
||||
|
||||
def get_latest_commit
|
||||
latest_commit = @project.educoder? ? nil : project_commits
|
||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||
end
|
||||
|
||||
def content_params
|
||||
{
|
||||
filepath: params[:filepath],
|
||||
branch: params[:branch],
|
||||
new_branch: params[:new_branch],
|
||||
content: params[:content],
|
||||
message: params[:message],
|
||||
committer: {
|
||||
email: current_user.mail,
|
||||
name: current_user.login
|
||||
},
|
||||
identifier: @project.identifier
|
||||
}
|
||||
end
|
||||
|
||||
def hook_params(hook_type, params)
|
||||
# if hook_type == "push"
|
||||
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
||||
# uploadPushInfo = {
|
||||
# "sha": params["commits"].present? ? params["commits"].last : "",
|
||||
# "branch": params["ref"].to_s.split("/").last,
|
||||
# "modification_lines": params["commits"].length
|
||||
# }
|
||||
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
||||
# uploadPushInfo = {
|
||||
# "branch": params["base"]["ref"].to_s.split("/").last,
|
||||
# "sha": params["pull_request"]["merge_base"],
|
||||
# "modification_lines": 1 #pull_request中没有commits数量
|
||||
# }
|
||||
# else
|
||||
# uploadPushInfo = {}
|
||||
# end
|
||||
|
||||
# uploadPushInfo
|
||||
end
|
||||
|
||||
def create_new_pr(params)
|
||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||
local_params = {
|
||||
title: params[:message], #标题
|
||||
body: params[:content], #内容
|
||||
head: params[:new_branch], #源分支
|
||||
base: params[:branch], #目标分支
|
||||
milestone: 0 #里程碑,未与本地的里程碑关联
|
||||
|
||||
}
|
||||
requests_params = local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
assignees: [],
|
||||
labels: [],
|
||||
due_date: Time.now
|
||||
})
|
||||
|
||||
issue_params = {
|
||||
author_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
subject: params[:message],
|
||||
description: params[:content],
|
||||
assigned_to_id: nil,
|
||||
fixed_version_id: nil,
|
||||
issue_tags_value: nil,
|
||||
issue_classify: "pull_request",
|
||||
issue_type: "1",
|
||||
tracker_id: 2,
|
||||
status_id: 1,
|
||||
priority_id: params[:priority_id] || "2"
|
||||
}
|
||||
@pull_issue = Issue.new(issue_params)
|
||||
if @pull_issue.save!
|
||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
class RepositoriesController < ApplicationController
|
||||
include RepositoriesHelper
|
||||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include Repository::LanguagesPercentagable
|
||||
|
||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||
before_action :require_profile_completed, only: [:create_file]
|
||||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
@result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
def top_counts
|
||||
@result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call
|
||||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
begin
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
end
|
||||
rescue
|
||||
return render_error('该文件暂未开放,敬请期待.')
|
||||
end
|
||||
end
|
||||
else
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
@sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits
|
||||
if @project.educoder?
|
||||
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
|
||||
else
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commits_slice
|
||||
@hash_commit = Gitea::Repository::Commits::ListSliceService.call(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def commit
|
||||
@sha = params[:sha]
|
||||
if @project.educoder?
|
||||
return render_error('暂未开放,敬请期待.')
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def contributors
|
||||
if params[:filepath].present? || @project.educoder?
|
||||
@contributors = []
|
||||
else
|
||||
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
rescue
|
||||
@contributors = []
|
||||
end
|
||||
|
||||
def edit
|
||||
return render_forbidden if !@project.manager?(current_user) && !current_user.admin?
|
||||
end
|
||||
|
||||
def create_file
|
||||
interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params)
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# create_new_pr(params)
|
||||
#如果是更新流水线文件
|
||||
if params[:pipeline_id]
|
||||
update_pipeline(params[:pipeline_id])
|
||||
end
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def update_pipeline(pipeline_id)
|
||||
pipeline = Ci::Pipeline.find(pipeline_id)
|
||||
if pipeline
|
||||
pipeline.update!(sync: 1)
|
||||
end
|
||||
end
|
||||
|
||||
def update_file
|
||||
interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
# TODO: 是否创建pr
|
||||
# create_new_pr(params)
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file
|
||||
interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier))
|
||||
if interactor.success?
|
||||
@file = interactor.result
|
||||
render_result(1, "文件删除成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def repo_hook
|
||||
|
||||
end
|
||||
|
||||
def sync_mirror
|
||||
return render_error("正在镜像中..") if @repository.mirror.waiting?
|
||||
|
||||
@repository.sync_mirror!
|
||||
SyncMirroredRepositoryJob.perform_later(@repository.id, current_user.id)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def readme
|
||||
if params[:filepath].present?
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
end
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
|
||||
rescue
|
||||
render json: nil
|
||||
end
|
||||
|
||||
def languages
|
||||
if @project.educoder?
|
||||
render json: {}
|
||||
else
|
||||
render json: languages_precentagable
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_project
|
||||
@project = Project.find params[:id]
|
||||
render_not_found("未找到相关的仓库") unless @project
|
||||
end
|
||||
|
||||
def find_project_with_includes
|
||||
@project = Project.includes(:repository, :owner, :watchers, :praise_treads).find params[:id]
|
||||
end
|
||||
|
||||
def authorizate!
|
||||
return if current_user && current_user.admin?
|
||||
if @project.repository.hidden? && !@project.member?(current_user)
|
||||
render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
# TODO 获取最新commit信息
|
||||
def project_commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
else
|
||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
end
|
||||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
@ref = params[:ref] || @project&.default_branch
|
||||
end
|
||||
|
||||
def get_latest_commit
|
||||
latest_commit = @project.educoder? ? nil : project_commits
|
||||
@latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil
|
||||
@commits_count = latest_commit.present? ? latest_commit[:total_count] : 0
|
||||
end
|
||||
|
||||
def content_params
|
||||
{
|
||||
filepath: params[:filepath],
|
||||
branch: params[:branch],
|
||||
new_branch: params[:new_branch],
|
||||
content: params[:content],
|
||||
message: params[:message],
|
||||
committer: {
|
||||
email: current_user.mail,
|
||||
name: current_user.login
|
||||
},
|
||||
identifier: @project.identifier
|
||||
}
|
||||
end
|
||||
|
||||
def hook_params(hook_type, params)
|
||||
# if hook_type == "push"
|
||||
# # TODO hook返回的记录中,暂时没有文件代码数量的增减,暂时根据 commits数量来计算
|
||||
# uploadPushInfo = {
|
||||
# "sha": params["commits"].present? ? params["commits"].last : "",
|
||||
# "branch": params["ref"].to_s.split("/").last,
|
||||
# "modification_lines": params["commits"].length
|
||||
# }
|
||||
# elsif hook_type == "pull_request" && params["action"].to_s == "closed" #合并请求合并后才会有上链操作
|
||||
# uploadPushInfo = {
|
||||
# "branch": params["base"]["ref"].to_s.split("/").last,
|
||||
# "sha": params["pull_request"]["merge_base"],
|
||||
# "modification_lines": 1 #pull_request中没有commits数量
|
||||
# }
|
||||
# else
|
||||
# uploadPushInfo = {}
|
||||
# end
|
||||
|
||||
# uploadPushInfo
|
||||
end
|
||||
|
||||
def create_new_pr(params)
|
||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||
local_params = {
|
||||
title: params[:message], #标题
|
||||
body: params[:content], #内容
|
||||
head: params[:new_branch], #源分支
|
||||
base: params[:branch], #目标分支
|
||||
milestone: 0 #里程碑,未与本地的里程碑关联
|
||||
|
||||
}
|
||||
requests_params = local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
assignees: [],
|
||||
labels: [],
|
||||
due_date: Time.now
|
||||
})
|
||||
|
||||
issue_params = {
|
||||
author_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
subject: params[:message],
|
||||
description: params[:content],
|
||||
assigned_to_id: nil,
|
||||
fixed_version_id: nil,
|
||||
issue_tags_value: nil,
|
||||
issue_classify: "pull_request",
|
||||
issue_type: "1",
|
||||
tracker_id: 2,
|
||||
status_id: 1,
|
||||
priority_id: params[:priority_id] || "2"
|
||||
}
|
||||
@pull_issue = Issue.new(issue_params)
|
||||
if @pull_issue.save!
|
||||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,14 +1,24 @@
|
|||
class SettingsController < ApplicationController
|
||||
def show
|
||||
@old_projects_url = nil
|
||||
get_navbar
|
||||
get_add_menu
|
||||
get_common_menu
|
||||
get_sub_competitions
|
||||
get_personal_menu
|
||||
get_third_party
|
||||
get_top_system_notification
|
||||
end
|
||||
|
||||
private
|
||||
def get_navbar
|
||||
@navbar = default_laboratory.navbar
|
||||
if User.current.logged?
|
||||
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
|
||||
@navbar << pernal_index
|
||||
end
|
||||
end
|
||||
|
||||
def get_add_menu
|
||||
@add = []
|
||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||
|
|
@ -20,6 +30,15 @@ class SettingsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def get_sub_competitions
|
||||
@sub_competitions = []
|
||||
Site.competition.pluck(:key).uniq.each do |key|
|
||||
hash = {"identifier": "#{key.to_s}"}
|
||||
hash.merge!("list": Site.competition.where(key: key).select(:id, :name, :url, :key).to_a.map(&:serializable_hash))
|
||||
@sub_competitions << hash
|
||||
end
|
||||
end
|
||||
|
||||
def get_common_menu
|
||||
@common = {}
|
||||
Site.common.select(:url, :key).each do |site|
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
class Traces::BaseController < ApplicationController
|
||||
|
||||
helper_method :observed_logged_user?, :observed_user
|
||||
|
||||
|
||||
def observed_user
|
||||
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||
end
|
||||
|
||||
def observed_logged_user?
|
||||
observed_user.id == User.current&.id
|
||||
end
|
||||
|
||||
protected
|
||||
def check_auth
|
||||
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
class Traces::ProjectsController < Traces::BaseController
|
||||
include OperateProjectAbilityAble
|
||||
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :authorizate_user_can_edit_project!, except: [:task_results]
|
||||
|
||||
def tasks
|
||||
branch_name = params[:branch_name]
|
||||
return render_error("无可用检测次数") if @project.user_trace_tasks.size >= 5
|
||||
return render_error("分支名不能为空!") if branch_name.blank?
|
||||
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||
code, data, error = Trace::CheckService.call(current_user.trace_token, @project, "1", branch_name)
|
||||
if code == 200
|
||||
UserTraceTask.create!(
|
||||
user_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
branch_tag: branch_name,
|
||||
task_id: data["task_id"]
|
||||
)
|
||||
render_ok
|
||||
else
|
||||
render_error("检测失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def task_results
|
||||
limit = params[:limit] || params[:per_page]
|
||||
limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
|
||||
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||
return render :json => {left_tasks_count: 5, data: []} if current_user.trace_user.nil?
|
||||
code, data, error = Trace::CheckResultService.call(current_user.trace_token, @project, nil, page, limit)
|
||||
if code == 200
|
||||
render :json => {left_tasks_count: 5 - @project.user_trace_tasks.size, data: data}
|
||||
else
|
||||
render_error("获取检测记录失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def reload_task
|
||||
return render_error("project_id错误") if params[:project_id].blank?
|
||||
branch_name = params[:branch_name]
|
||||
return render_error("分支名不能为空!") if branch_name.blank?
|
||||
@all_branches = Gitea::Repository::Branches::ListNameService.call(@project&.owner, @project.identifier)
|
||||
return render_error("请输入正确的分支名!") unless @all_branches["branch_name"].include?(branch_name)
|
||||
code, data, error = Trace::ReloadCheckService.call(current_user.trace_token, params[:project_id])
|
||||
if code == 200
|
||||
UserTraceTask.create!(
|
||||
user_id: current_user.id,
|
||||
project_id: @project.id,
|
||||
branch_tag: branch_name,
|
||||
task_id: data["task_id"]
|
||||
)
|
||||
render_ok
|
||||
else
|
||||
render_error("重新检测失败 Error:#{error}")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
|
||||
def task_pdf
|
||||
return render_error("task_id错误") if params[:task_id].blank?
|
||||
result = Trace::PdfReportService.call(current_user.trace_token, params[:task_id])
|
||||
if result.is_a?(Hash) && result[:code] == 200
|
||||
redirect_to result[:download_url]
|
||||
else
|
||||
render_error("下载报告失败!")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
class Traces::TraceUsersController < Traces::BaseController
|
||||
before_action :require_login
|
||||
|
||||
def create
|
||||
if current_user.trace_token.present?
|
||||
render_ok
|
||||
else
|
||||
render_error(-1, "代码溯源用户初始化失败")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
end
|
||||
|
|
@ -12,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
|
|||
@commit_data = []
|
||||
date_range.each do |date|
|
||||
@date_data << date.strftime("%Y.%m.%d")
|
||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
||||
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
|
||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
||||
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class Users::TemplateMessageSettingsController < Users::BaseController
|
|||
def get_current_setting
|
||||
@current_setting = @_observed_user.user_template_message_setting
|
||||
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
||||
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
|
||||
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
|
||||
end
|
||||
|
||||
def setting_params
|
||||
|
|
|
|||
|
|
@ -1,324 +1,399 @@
|
|||
class UsersController < ApplicationController
|
||||
include ApplicationHelper
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me list sync_user_info]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
before_action :convert_image!, only: [:update, :update_image]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
||||
def connect_to_ci_db(options={})
|
||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||
return
|
||||
end
|
||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||
connect_to_trustie_ci_database(options)
|
||||
else
|
||||
connect_to_ci_database(options)
|
||||
end
|
||||
end
|
||||
|
||||
def list
|
||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||
@total_count = scope.size
|
||||
@users = paginate(scope)
|
||||
end
|
||||
|
||||
def show
|
||||
#待办事项,现在未做
|
||||
if User.current.admin? || User.current.login == @user.login
|
||||
@waiting_applied_messages = @user.applied_messages.waiting
|
||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
else
|
||||
@waiting_applied_messages = AppliedMessage.none
|
||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||
@common_applied_projects = AppliedProject.none
|
||||
@undo_events = 0
|
||||
end
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||
@user_org_count = user_organizations.size
|
||||
normal_projects = Project.members_projects(@user.id).to_sql
|
||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
# 为了缓存活跃用户的基本信息,后续删除
|
||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||
if params[:search].present?
|
||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||
watchers = watchers.where(watchable_id: search_user_ids)
|
||||
end
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def fan_users
|
||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def hovercard
|
||||
end
|
||||
|
||||
def update
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||
@user.attributes = user_params.except(:image)
|
||||
unless @user.save
|
||||
render_error(-1, @user.errors.full_messages.join(", "))
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
Util.write_file(@image, avatar_path(@user))
|
||||
return render_ok({message: '头像修改成功'})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
render_error(-1, '头像修改失败!')
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
begin
|
||||
result = Notice::Read::CountService.call(current_user.id)
|
||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||
rescue
|
||||
@message_unread_total = 0
|
||||
end
|
||||
# TODO 等消息上线再打开注释
|
||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
missing_template
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def attachment_show
|
||||
file_name = params[:file_name]
|
||||
path = params[:path] || file_storage_directory
|
||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||
:type => 'game',
|
||||
:disposition => 'attachment' #inline can open in browser
|
||||
end
|
||||
|
||||
def html_show
|
||||
@contents = File.read("#{params[:path]}")
|
||||
respond_to do |format|
|
||||
format.html {render :layout => false}
|
||||
end
|
||||
end
|
||||
|
||||
# Redo: 消息总数缓存
|
||||
def get_navigation_info
|
||||
# @old_domain = edu_setting('old_edu_host')
|
||||
# @user = current_user
|
||||
# # 新消息数
|
||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||
#
|
||||
# @user_url = "/users/#{@user.login}"
|
||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||
end
|
||||
|
||||
# 用户回复功能
|
||||
def reply_message
|
||||
message = JournalsForMessage.new(reply_message_params)
|
||||
message.user_id = current_user.id
|
||||
message.save!
|
||||
|
||||
render_ok(id: message.id)
|
||||
end
|
||||
|
||||
# 搜索用户具有管理员角色的项目
|
||||
def search_user_projects
|
||||
projects = Project.where.not(status: 9)
|
||||
|
||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||
projects = projects.where(members: { user_id: current_user.id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
@projects = projects.select(:id, :name)
|
||||
end
|
||||
|
||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||
def homepage_info
|
||||
#待办事项,现在未做
|
||||
@undo_events = 10
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 10
|
||||
end
|
||||
|
||||
def brief_introduction
|
||||
content = params[:content].to_s.strip
|
||||
|
||||
current_user.user_extension.update!(brief_introduction: content)
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def attendance
|
||||
attendance = Users::AttendanceService.call(current_user)
|
||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||
rescue Users::AttendanceService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||
def sync_token
|
||||
return render_error('未找相关用户!') unless @user
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||
token.update_column(:value, params[:token])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def trustie_related_projects
|
||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||
projects_json = []
|
||||
domain_url = EduSetting.get('host_name')
|
||||
if projects.present?
|
||||
projects.each do |p|
|
||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||
pj = {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
is_public: p.is_public,
|
||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||
status: p.status,
|
||||
is_member: p.member?(current_user.try(:id)),
|
||||
owner: {
|
||||
name: p.owner.try(:show_real_name),
|
||||
login: p.owner.login
|
||||
},
|
||||
members_count: p&.members.size,
|
||||
issues_count: p.issues_count - p.pull_requests_count,
|
||||
commits_count: p&.project_score&.changeset_num.to_i,
|
||||
http_url: domain_url + project_url,
|
||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||
http_issues_url: domain_url + project_url + "/issues",
|
||||
http_commits_url: domain_url + project_url + "/commits",
|
||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||
}
|
||||
projects_json.push(pj)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||
end
|
||||
|
||||
def trustie_projects
|
||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||
projects = Project.visible
|
||||
|
||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
projects = projects.select(:id, :name).limit(10).as_json
|
||||
render json: { projects: projects }
|
||||
end
|
||||
|
||||
def projects
|
||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||
@total_count = scope.size
|
||||
@projects = paginate(scope)
|
||||
end
|
||||
|
||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||
def sync_gitea_pwd
|
||||
return render_error("未找到相关的用户") if @user.blank?
|
||||
|
||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||
flag ? render_ok : render_error('同步失败!')
|
||||
end
|
||||
|
||||
# TODO
|
||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||
def sync_salt
|
||||
user = User.find_by_login params[:login]
|
||||
return if user.blank?
|
||||
user.update_column(:salt, params[:salt])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:nickname, :image,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id, :province, :city,
|
||||
:custom_department, :identity, :student_id, :description,
|
||||
:show_email, :show_location, :show_department]
|
||||
)
|
||||
end
|
||||
|
||||
def reply_message_params
|
||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||
end
|
||||
|
||||
def check_user_exist
|
||||
return if @user.present?
|
||||
render_not_found
|
||||
end
|
||||
|
||||
end
|
||||
class UsersController < ApplicationController
|
||||
include ApplicationHelper
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me sync_user_info]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
before_action :convert_image!, only: [:update, :update_image]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
before_action :sso_login, only: [:get_user_info]
|
||||
|
||||
def connect_to_ci_db(options={})
|
||||
if !(current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification?)
|
||||
return
|
||||
end
|
||||
if current_user.ci_cloud_account.server_type == Ci::CloudAccount::SERVER_TYPE_TRUSTIE
|
||||
connect_to_trustie_ci_database(options)
|
||||
else
|
||||
connect_to_ci_database(options)
|
||||
end
|
||||
end
|
||||
|
||||
def list
|
||||
scope = User.active.recent.like(params[:search]).includes(:user_extension)
|
||||
@total_count = scope.size
|
||||
@users = paginate(scope)
|
||||
end
|
||||
|
||||
def show
|
||||
#待办事项,现在未做
|
||||
if User.current.admin? || User.current.login == @user.login
|
||||
@waiting_applied_messages = @user.applied_messages.waiting
|
||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||
@common_applied_projects = AppliedProject.where(project_id: @user.full_admin_projects).common
|
||||
#@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
@undo_events = @common_applied_transfer_projects.size + @common_applied_projects.size
|
||||
else
|
||||
@waiting_applied_messages = AppliedMessage.none
|
||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||
@common_applied_projects = AppliedProject.none
|
||||
@undo_events = 0
|
||||
end
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||
@user_org_count = user_organizations.size
|
||||
normal_projects = Project.members_projects(@user.id).to_sql
|
||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
# 为了缓存活跃用户的基本信息,后续删除
|
||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = Watcher.watching_users(@user.id).includes(:user).order("watchers.created_at desc")
|
||||
if params[:search].present?
|
||||
search_user_ids = User.where(id: watchers.pluck(:watchable_id)).like(params[:search]).pluck(:id)
|
||||
watchers = watchers.where(watchable_id: search_user_ids)
|
||||
end
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def fan_users
|
||||
watchers = @user.watchers.includes(:user).order("watchers.created_at desc")
|
||||
watchers = watchers.joins(:user).merge(User.like(params[:search]))
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def hovercard
|
||||
end
|
||||
|
||||
def update
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
Util.write_file(@image, avatar_path(@user)) if user_params[:image].present?
|
||||
@user.attributes = user_params.except(:image)
|
||||
unless @user.save
|
||||
render_error(-1, @user.errors.full_messages.join(", "))
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
Util.write_file(@image, avatar_path(@user))
|
||||
return render_ok({message: '头像修改成功'})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
render_error(-1, '头像修改失败!')
|
||||
end
|
||||
|
||||
def get_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
begin
|
||||
result = Notice::Read::CountService.call(current_user.id)
|
||||
@message_unread_total = result.nil? ? 0 : result[2]["unread_notification"]
|
||||
rescue
|
||||
@message_unread_total = 0
|
||||
end
|
||||
# TODO 等消息上线再打开注释
|
||||
#@tidding_count = unviewed_tiddings(current_user) if current_user.present?
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
missing_template
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def attachment_show
|
||||
file_name = params[:file_name]
|
||||
path = params[:path] || file_storage_directory
|
||||
send_file "#{path}/#{file_name}", :filename => "#{file_name}",
|
||||
:type => 'game',
|
||||
:disposition => 'attachment' #inline can open in browser
|
||||
end
|
||||
|
||||
def html_show
|
||||
@contents = File.read("#{params[:path]}")
|
||||
respond_to do |format|
|
||||
format.html {render :layout => false}
|
||||
end
|
||||
end
|
||||
|
||||
# Redo: 消息总数缓存
|
||||
def get_navigation_info
|
||||
# @old_domain = edu_setting('old_edu_host')
|
||||
# @user = current_user
|
||||
# # 新消息数
|
||||
# @new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
|
||||
#
|
||||
# @user_url = "/users/#{@user.login}"
|
||||
# @career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
|
||||
# @auth = User.current.ec_school.present? ? "#{@old_domain}/ecs/department?school_id=#{User.current.ec_school}" : nil
|
||||
end
|
||||
|
||||
# 用户回复功能
|
||||
def reply_message
|
||||
message = JournalsForMessage.new(reply_message_params)
|
||||
message.user_id = current_user.id
|
||||
message.save!
|
||||
|
||||
render_ok(id: message.id)
|
||||
end
|
||||
|
||||
# 搜索用户具有管理员角色的项目
|
||||
def search_user_projects
|
||||
projects = Project.where.not(status: 9)
|
||||
|
||||
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
|
||||
projects = projects.where(members: { user_id: current_user.id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
@projects = projects.select(:id, :name)
|
||||
end
|
||||
|
||||
#TODO 个人主页信息,forge上弃用-hs, 0602
|
||||
def homepage_info
|
||||
#待办事项,现在未做
|
||||
@undo_events = 10
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 10
|
||||
end
|
||||
|
||||
def brief_introduction
|
||||
content = params[:content].to_s.strip
|
||||
|
||||
current_user.user_extension.update!(brief_introduction: content)
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def attendance
|
||||
attendance = Users::AttendanceService.call(current_user)
|
||||
render_ok(grade: current_user.grade, next_gold: attendance.next_gold)
|
||||
rescue Users::AttendanceService::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||
def sync_token
|
||||
return render_error('未找相关用户!') unless @user
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||
token.update_column(:value, params[:token])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def trustie_related_projects
|
||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||
projects_json = []
|
||||
domain_url = EduSetting.get('host_name')
|
||||
if projects.present?
|
||||
projects.each do |p|
|
||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||
pj = {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
is_public: p.is_public,
|
||||
updated_on: p.updated_on.strftime("%Y-%m-%d"),
|
||||
status: p.status,
|
||||
is_member: p.member?(current_user.try(:id)),
|
||||
owner: {
|
||||
name: p.owner.try(:show_real_name),
|
||||
login: p.owner.login
|
||||
},
|
||||
members_count: p&.members.size,
|
||||
issues_count: p.issues_count - p.pull_requests_count,
|
||||
commits_count: p&.project_score&.changeset_num.to_i,
|
||||
http_url: domain_url + project_url,
|
||||
http_collaborator_url: domain_url + project_url + "/setting/collaborator",
|
||||
http_issues_url: domain_url + project_url + "/issues",
|
||||
http_commits_url: domain_url + project_url + "/commits",
|
||||
project_score: p&.project_score.present? ? p&.project_score&.as_json(:except=>[:created_at, :updated_at]).merge!(commit_time: format_time(p&.project_score&.commit_time)) : {}
|
||||
}
|
||||
projects_json.push(pj)
|
||||
end
|
||||
end
|
||||
Rails.logger.info("==========projects_json========+########{projects_json}")
|
||||
render json: { projects: projects_json.present? ? projects_json : {} }
|
||||
end
|
||||
|
||||
def trustie_projects
|
||||
user_id = User.select(:id, :login).where(login: params[:login])&.first&.id
|
||||
projects = Project.visible
|
||||
|
||||
projects = projects.joins(:members).where(members: { user_id: user_id })
|
||||
|
||||
search = params[:search].to_s.strip
|
||||
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
|
||||
|
||||
projects = projects.select(:id, :name).limit(10).as_json
|
||||
render json: { projects: projects }
|
||||
end
|
||||
|
||||
def projects
|
||||
is_current_admin_user = User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
scope = Projects::ListMyQuery.call(params, @user,is_current_admin_user)
|
||||
@total_count = scope.size
|
||||
@projects = paginate(scope)
|
||||
end
|
||||
|
||||
# TODO 其他平台登录时同步修改gitea平台对应用户的密码
|
||||
# 该方法主要用于:别的平台初次部署对接forge平台,同步用户后,gitea平台对应的用户密码与forge平台用户密码不一致是问题
|
||||
def sync_gitea_pwd
|
||||
return render_error("未找到相关的用户") if @user.blank?
|
||||
|
||||
flag = sync_pwd_to_gitea!(@user, {password: params[:password].to_s})
|
||||
flag ? render_ok : render_error('同步失败!')
|
||||
end
|
||||
|
||||
# TODO
|
||||
# 同步trusite平台用户的salt信息,只需同步一次,同步完成后,该方法可以删除
|
||||
def sync_salt
|
||||
user = User.find_by_login params[:login]
|
||||
return if user.blank?
|
||||
user.update_column(:salt, params[:salt])
|
||||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_ACTIVE)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def email_search
|
||||
return render_error('请输入email') if params[:email].blank?
|
||||
@user = User.find_by(mail: params[:email])
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:nickname, :image,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id, :province, :city,
|
||||
:custom_department, :identity, :student_id, :description,
|
||||
:show_super_description, :super_description,
|
||||
:show_email, :show_location, :show_department]
|
||||
)
|
||||
end
|
||||
|
||||
def reply_message_params
|
||||
normal_status(-1, "参数不对") if params[:journals_for_message][:jour_type].nil? || params[:journals_for_message][:jour_id].nil? ||
|
||||
params[:journals_for_message][:notes].nil? || params[:journals_for_message][:reply_id].nil?
|
||||
params.require(:journals_for_message).permit(:jour_type, :jour_id, :notes, :m_parent_id, :reply_id)
|
||||
end
|
||||
|
||||
def check_user_exist
|
||||
return if @user.present?
|
||||
render_not_found
|
||||
end
|
||||
|
||||
def sso_login
|
||||
if params[:login].present? && !current_user.logged? && params[:websiteName].present?
|
||||
user = User.where("login = ?", "#{params[:login].presence}").first
|
||||
# 已同步注册,直接登录
|
||||
if user.present?
|
||||
successful_authentication(user)
|
||||
else
|
||||
autologin_register_by_educoder(params[:login].presence)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 通过login参数查询头歌账号信息,注册并登录
|
||||
def autologin_register_by_educoder(edu_login)
|
||||
req_params = { "login" => "#{edu_login}", "private_token" => "hriEn3UwXfJs3PmyXnSH" }
|
||||
api_url= "https://data.educoder.net"
|
||||
client = Faraday.new(url: api_url)
|
||||
response = client.public_send("get", "/api/sources/get_user_info_by_login", req_params)
|
||||
result = JSON.parse(response.body)
|
||||
#查询
|
||||
return nil if result["status"].to_s != "0"
|
||||
|
||||
# login 邮箱 手机号 姓名 学校/单位
|
||||
user_info = result["data"]
|
||||
Rails.logger.info("user_info====== #{user_info}")
|
||||
login = user_info["login"]
|
||||
email = user_info["mail"]
|
||||
phone = user_info["phone"]
|
||||
real_name = user_info["username"]
|
||||
department_name = user_info["school"]
|
||||
password = "12345678"
|
||||
|
||||
# 没有用户时,新建用户并登录
|
||||
user = User.where("login = ? or phone = ? or mail = ? ", "#{login}", phone, email).first
|
||||
if user.present?
|
||||
# 手机号先记录,后续用
|
||||
user.update_column(:phone, "#{phone}") if phone.present?
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
email = "#{login}@gitlink.org.cn" if email.blank?
|
||||
user_params = { status: 1, type: 'User', login: "#{login}", lastname: "#{real_name}", mail: "#{email}",
|
||||
nickname: "#{real_name}", professional_certification: 0, certification: 0, grade: 0,
|
||||
password: "#{password}", phone: "#{phone}", profile_completed: 1 }
|
||||
user = User.create!(user_params)
|
||||
UserExtension.create!(user_id: user.id, gender: 1, custom_department: "#{department_name}")
|
||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
Rails.logger.info("Gitea::RegisterInteractor.call result====== #{gitea_user}")
|
||||
result = Gitea::User::GenerateTokenService.call(login, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
user.save!
|
||||
else
|
||||
Rails.logger.info("Gitea::RegisterInteractor.call error====== #{interactor.error}")
|
||||
end
|
||||
end
|
||||
end
|
||||
successful_authentication(user) if user.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class VersionReleasesController < ApplicationController
|
|||
def new
|
||||
#获取所有的分支
|
||||
@all_branches = []
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier), params[:branch_name]).call
|
||||
if get_all_branches && get_all_branches.size > 0
|
||||
get_all_branches.each do |b|
|
||||
@all_branches.push(b["name"])
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ includes:
|
|||
- users
|
||||
- projects
|
||||
- repositories
|
||||
- traces
|
||||
- pulls
|
||||
- issues
|
||||
- organizations
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ repo |是| |string |项目标识identifier
|
|||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,services:服务,activity:动态,setting:仓库设置
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
|
@ -408,7 +408,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
|
|||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,wiki:维基,resources:资源库,services:服务 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,217 @@
|
|||
# Traces
|
||||
|
||||
## 代码溯源初始化
|
||||
用户同意协议后请求的接口,创建代码溯源的账号
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
http://localhost:3000/api/traces/trace_users.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/traces/trace_users.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/traces/trace_users.json`
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 代码分析结果列表
|
||||
查询项目下代码分析的结果
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/task_results.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/task_results.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/task_results.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner|是|否|string | 项目所有者标识|
|
||||
repo|是 | 否|string | 项目标识 |
|
||||
page |否| 1 | int | 页码 |
|
||||
limit |否| 15 | int | 每页数量 |
|
||||
|
||||
### 返回字段说明(暂缺)
|
||||
<!-- 参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
total_count |int |总数 |
|
||||
public_keys.id |int |ID|
|
||||
public_keys.name |string|密钥标题|
|
||||
public_keys.content |string|密钥内容|
|
||||
public_keys.fingerprint |string|密钥标识|
|
||||
public_keys.created_time |string|密钥创建时间| -->
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"accuracy": "20",
|
||||
"code_type": "C",
|
||||
"depth": "2",
|
||||
"detect_flag": "快速-组件级",
|
||||
"detect_rule": "快速-组件级,2,20,,开源软件,50,10",
|
||||
"detect_startdate": "2022-05-10 15:59:46 ",
|
||||
"detect_status": "fail",
|
||||
"detectflag": "快速-组件级",
|
||||
"fail_reason": "Invalid package type",
|
||||
"file_name": "many_branch.zip",
|
||||
"license_process": "100",
|
||||
"licenseparam": "开源软件",
|
||||
"package_type": "",
|
||||
"product_name": "84727546110",
|
||||
"project_id": "6dbc3e42-5857-4ca4-a54d-58fd9dbf6dc5",
|
||||
"sim_process": "100",
|
||||
"similarity_process": "2",
|
||||
"task_id": "15139171-091b-4316-98b1-6068970efa44",
|
||||
"totalsize": 5,
|
||||
"uid": "78",
|
||||
"vuln_process": "",
|
||||
"vulnlevel": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
|
||||
## 新建分析
|
||||
用户选择仓库分支进行代码分析的接口
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/tasks.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/traces/:owner/:repo/tasks.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST api/traces/:owner/:repo/tasks.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
branch_name|是 | 否| string | 分支名称 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 重新扫描
|
||||
对代码分析结果进行再次分析
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/reload_task.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/reload_task.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/reload_task.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
project_id|是 | 否| string | 代码分析结果里的project_id |
|
||||
branch_name|是 | 否| string | 分支名称 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
|
||||
## 下载报告
|
||||
把代码分析的结果下载到本地
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/traces/yystopf/many_branch/task_pdf.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/traces/:owner/:repo/task_pdf.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/traces/:owner/:repo/task_pdf.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是 | 否 | string | 项目所有者标识 |
|
||||
repo |是 | 否 | string | 项目标识 |
|
||||
task_id|是 | 否| string | 代码分析结果里的task_id |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
Success — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
|
@ -91,10 +91,9 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
类型|说明
|
||||
--------- | -----------
|
||||
|IssueAssigned | 有新指派给我的疑修 |
|
||||
|IssueAssignerExpire | 我负责的疑修截止日期到达最后一天 |
|
||||
|IssueExpire | 我创建或负责的疑修截止日期到达最后一天 |
|
||||
|IssueAtme | 在疑修中@我 |
|
||||
|IssueChanged | 我创建或负责的疑修状态变更 |
|
||||
|IssueCreatorExpire | 我创建的疑修截止日期到达最后一天 |
|
||||
|IssueDeleted | 我创建或负责的疑修删除 |
|
||||
|IssueJournal | 我创建或负责的疑修有新的评论 |
|
||||
|LoginIpTip | 登录异常提示 |
|
||||
|
|
@ -109,6 +108,7 @@ await octokit.request('GET /api/users/:login/messages.json')
|
|||
|ProjectLeft | 账号被移出项目 |
|
||||
|ProjectMemberJoined | 我管理的仓库有成员加入 |
|
||||
|ProjectMemberLeft | 我管理的仓库有成员移出 |
|
||||
|ProjectMilestoneCompleted | 我管理的仓库有里程碑完成度100% |
|
||||
|ProjectMilestone | 我管理的仓库有新的里程碑 |
|
||||
|ProjectPraised | 我管理的仓库被点赞 |
|
||||
|ProjectPullRequest | 我管理/关注的仓库有新的合并请求 |
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class BaseForm
|
|||
|
||||
def check_verifi_code(verifi_code, code)
|
||||
code = strip(code)
|
||||
# return if code == "123123" # TODO 万能验证码,用于测试
|
||||
return if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
||||
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class Gitea::User::UpdateForm
|
|||
|
||||
attr_accessor :username, :email, :admin, :allow_create_organization, :allow_git_hook, :allow_import_local,
|
||||
:full_name, :location, :login_name, :max_repo_creation, :must_change_password, :password, :prohibit_login,
|
||||
:source_id, :website
|
||||
:source_id, :website, :new_name
|
||||
|
||||
validates :username, presence: true
|
||||
validates :email, presence: true, format: { with: EMAIL_REGEX, multiline: true }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
class Issues::CreateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
attr_accessor :subject, :description
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
|
||||
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
class Issues::UpdateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
attr_accessor :subject, :description
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class Journals::CreateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :notes
|
||||
|
||||
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
class Journals::UpdateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :notes
|
||||
|
||||
validates :notes, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
end
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
class Projects::UpdateForm < BaseForm
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private, :identifier, :user_id, :project_identifier, :project_name
|
||||
validates :name, presence: true
|
||||
validates :name, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
|
|
@ -10,6 +10,7 @@ class Projects::UpdateForm < BaseForm
|
|||
check_project_language(project_language_id)
|
||||
|
||||
check_repository_name(user_id, identifier) unless identifier.blank? || identifier == project_identifier
|
||||
check_project_name(user_id, name) unless name.blank? || name == project_name
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,28 +3,40 @@ module Register
|
|||
include ActiveModel::Model
|
||||
|
||||
private
|
||||
def check_login(login)
|
||||
def check_login(login, user=nil)
|
||||
login = strip(login)
|
||||
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
||||
|
||||
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
||||
raise LoginError, '登录名已被使用' if login_exist
|
||||
if user.present?
|
||||
raise LoginError, '登录名已被使用' if login_exist && login != user&.login
|
||||
else
|
||||
raise LoginError, '登录名已被使用' if login_exist
|
||||
end
|
||||
end
|
||||
|
||||
def check_mail(mail)
|
||||
def check_mail(mail, user=nil)
|
||||
mail = strip(mail)
|
||||
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
||||
|
||||
mail_exist = Owner.exists?(mail: mail)
|
||||
raise EmailError, '邮箱已被使用' if mail_exist
|
||||
if user.present?
|
||||
raise EmailError, '邮箱已被使用' if mail_exist && mail != user&.mail
|
||||
else
|
||||
raise EmailError, '邮箱已被使用' if mail_exist
|
||||
end
|
||||
end
|
||||
|
||||
def check_phone(phone)
|
||||
def check_phone(phone, user=nil)
|
||||
phone = strip(phone)
|
||||
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
||||
|
||||
phone_exist = Owner.exists?(phone: phone)
|
||||
raise PhoneError, '手机号已被使用' if phone_exist
|
||||
if user.present?
|
||||
raise PhoneError, '手机号已被使用' if phone_exist && phone != user&.phone
|
||||
else
|
||||
raise PhoneError, '手机号已被使用' if phone_exist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ module Register
|
|||
validate :check!
|
||||
|
||||
def check!
|
||||
Rails.logger.info "Register::Form params: code: #{code}; login: #{login};
|
||||
namespace: #{namespace}; password: #{password}; password_confirmation: #{password_confirmation}"
|
||||
|
||||
Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}"
|
||||
type = phone_mail_type(strip(login))
|
||||
db_verifi_code =
|
||||
db_verifi_code =
|
||||
if type == 1
|
||||
check_phone(login)
|
||||
VerificationCode.where(phone: login, code: code, code_type: 1).last
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
module Register
|
||||
class LoginCheckColumnsForm < Register::BaseForm
|
||||
attr_accessor :type, :value, :user
|
||||
|
||||
validates :type, presence: true, numericality: true
|
||||
validates :value, presence: true
|
||||
validate :check!
|
||||
|
||||
def check!
|
||||
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||
case strip(type).to_i
|
||||
when 1 then check_login(strip(value), user)
|
||||
when 2 then check_mail(strip(value), user)
|
||||
when 3 then check_phone(strip(value), user)
|
||||
else raise("type值无效")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,477 +1,486 @@
|
|||
# 所有的方法请按首字母的顺序依次列出
|
||||
module ApplicationHelper
|
||||
include Gitlink::I18n
|
||||
include GitHelper
|
||||
|
||||
ONE_MINUTE = 60 * 1000
|
||||
ONE_HOUR = 60 * ONE_MINUTE
|
||||
ONE_DAY = 24 * ONE_HOUR
|
||||
ONE_MONTH = 30 * ONE_DAY
|
||||
|
||||
ONE_YEAR = 12 * ONE_MONTH
|
||||
|
||||
# 全局参数配置
|
||||
def edu_setting name
|
||||
EduSetting.get(name)
|
||||
end
|
||||
|
||||
# xss共计问题
|
||||
def content_safe content
|
||||
tags = %w(
|
||||
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
||||
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
||||
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
||||
tfoot th thead time tr u ul var wbr div span
|
||||
)
|
||||
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
||||
sanitize content, tags: tags, attributes: attributes
|
||||
end
|
||||
|
||||
def graduation_navigation graduation
|
||||
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
||||
end
|
||||
|
||||
def graduation_navigation_id course
|
||||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||
end
|
||||
|
||||
# git用户
|
||||
# git用户命名规则:login+"@educoder.net"
|
||||
def git_username(email)
|
||||
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
||||
end
|
||||
|
||||
# 不同的类型扩展不同的目录
|
||||
def relative_path
|
||||
"avatars"
|
||||
end
|
||||
|
||||
def replace_bytes_to_b(size_string)
|
||||
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
||||
end
|
||||
|
||||
def storage_path
|
||||
File.join(Rails.root, "public", "images", relative_path)
|
||||
end
|
||||
|
||||
# 推荐实训
|
||||
def recommend_shixun(shixun)
|
||||
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
||||
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
||||
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
||||
|
||||
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
||||
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
||||
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
||||
|
||||
end
|
||||
|
||||
# shixun开启挑战对应的行为名及url
|
||||
def task_operation_url current_myshixun, shixun
|
||||
if current_myshixun.blank?
|
||||
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
||||
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
||||
else
|
||||
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
||||
if current_myshixun.status == 1
|
||||
name = "查看实战"
|
||||
else
|
||||
name = "继续挑战"
|
||||
end
|
||||
url = identifier
|
||||
end
|
||||
[name, url]
|
||||
end
|
||||
|
||||
# 获取当前时间
|
||||
def time_from_now(time)
|
||||
if String === time
|
||||
time = Time.parse(time)
|
||||
end
|
||||
|
||||
lastUpdateTime = time.to_i*1000
|
||||
|
||||
currentTime = Time.now.to_i*1000
|
||||
timePassed = currentTime - lastUpdateTime
|
||||
timeIntoFormat = 0
|
||||
updateAtValue = ""
|
||||
if timePassed < 0
|
||||
updateAtValue = "刚刚"
|
||||
elsif timePassed < ONE_MINUTE
|
||||
updateAtValue = "1分钟前"
|
||||
elsif timePassed < ONE_HOUR
|
||||
timeIntoFormat = timePassed / ONE_MINUTE
|
||||
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
||||
elsif (timePassed < ONE_DAY)
|
||||
timeIntoFormat = timePassed / ONE_HOUR
|
||||
updateAtValue = timeIntoFormat.to_s + "小时前"
|
||||
elsif (timePassed < ONE_MONTH)
|
||||
timeIntoFormat = timePassed / ONE_DAY
|
||||
updateAtValue = timeIntoFormat.to_s + "天前"
|
||||
elsif (timePassed < ONE_YEAR)
|
||||
timeIntoFormat = timePassed / ONE_MONTH
|
||||
updateAtValue = timeIntoFormat.to_s + "个月前"
|
||||
else
|
||||
timeIntoFormat = timePassed / ONE_YEAR
|
||||
updateAtValue = timeIntoFormat.to_s + "年前"
|
||||
end
|
||||
updateAtValue
|
||||
end
|
||||
|
||||
# 计算到结束还有多长时间 **天**小时**分
|
||||
def how_much_time(time)
|
||||
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
||||
''
|
||||
else
|
||||
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
||||
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
||||
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
||||
end
|
||||
end
|
||||
|
||||
def format_time(time)
|
||||
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
||||
end
|
||||
|
||||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
source.get_letter_avatar_url
|
||||
end
|
||||
end
|
||||
|
||||
# 主页banner图
|
||||
def banner_img(source_type)
|
||||
if File.exist?(disk_filename(source_type, "banner"))
|
||||
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
||||
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
||||
end
|
||||
end
|
||||
|
||||
def disk_filename(source_type,source_id,image_file=nil)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}")
|
||||
end
|
||||
|
||||
def disk_auth_filename(source_type, source_id, type)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def disk_real_name_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def auth_file_url(source_type, source_id, type)
|
||||
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def real_name_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def disk_professional_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def professional_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def shixun_url_to_avatar(shixun)
|
||||
if File.exist?(disk_filename(shixun.class, shixun.id))
|
||||
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
||||
else
|
||||
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
# 选用实训的学校情况
|
||||
def school_user_detail shixun
|
||||
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
||||
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
||||
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
||||
school_size = school_ids.size
|
||||
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
||||
end
|
||||
|
||||
# 普通/分组 作业作品状态数组
|
||||
def student_work_status homework, user_id, course, work
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting user_id, true
|
||||
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
||||
late_time = homework.late_time || course.end_date
|
||||
|
||||
if course.is_end && work && work.work_status > 0
|
||||
status << "查看作品"
|
||||
elsif !course.is_end
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
||||
# 作业未截止时
|
||||
if homework_setting.end_time > Time.now
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 补交阶段
|
||||
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 匿评阶段
|
||||
elsif work.work_status != 0
|
||||
if homework.homework_detail_manual.comment_status == 3
|
||||
work_ids = homework.student_works.has_committed.pluck(:id)
|
||||
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
||||
status << "匿评作品"
|
||||
end
|
||||
end
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commit_des_status work, homework
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting work.user_id
|
||||
|
||||
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
||||
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
||||
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
||||
work.description.present? ? status << "修改总结" : status << "提交总结"
|
||||
end
|
||||
end
|
||||
|
||||
def download_url attachment,options={}
|
||||
attachment_path(attachment,options)
|
||||
end
|
||||
|
||||
# 耗时:天、小时、分、秒
|
||||
# 小于1分钟则不显示
|
||||
def game_spend_time time
|
||||
day = time / 86400
|
||||
hour = time % (24*60*60) / (60*60)
|
||||
min = time % (24*60*60) % (60*60) / 60
|
||||
sec = time % (24*60*60) % (60*60) % 60
|
||||
if day < 1
|
||||
if hour < 1
|
||||
if min < 1
|
||||
if sec < 1
|
||||
time = "--"
|
||||
else
|
||||
time = "#{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
def absolute_path(file_path)
|
||||
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
||||
end
|
||||
|
||||
def file_root_directory
|
||||
Rails.root.to_s
|
||||
end
|
||||
|
||||
def file_storage_directory
|
||||
file_root_directory + edu_setting('attachment_folder')
|
||||
end
|
||||
|
||||
def local_path(file)
|
||||
File.join(file.disk_directory, file.disk_filename)
|
||||
end
|
||||
|
||||
def update_downloads(file)
|
||||
file.update_attributes(:downloads => file.downloads + 1)
|
||||
end
|
||||
|
||||
# 项目信息,
|
||||
def project_info work, current_user, course_identity
|
||||
project = work.project
|
||||
if project
|
||||
if project.status == 9
|
||||
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
||||
else
|
||||
project_score = project.project_score
|
||||
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
||||
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
else
|
||||
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
end
|
||||
end
|
||||
else
|
||||
{id: -1, name: "--", title: "--"}
|
||||
end
|
||||
end
|
||||
|
||||
def message_content(content)
|
||||
content = (strip_html content).strip
|
||||
content = content.gsub(/\s+/, " ")
|
||||
if content.gsub(" ", "") == ""
|
||||
content = "[非文本消息]"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def strip_html(text, len=0, endss="...")
|
||||
ss = ""
|
||||
if !text.nil? && text.length>0
|
||||
ss=text.gsub(/<\/?.*?>/, '').strip
|
||||
ss = ss.gsub(/ */, '')
|
||||
ss = ss.gsub(/\r\n/,'') #新增
|
||||
ss = ss.gsub(/\n/,'') #新增
|
||||
if len > 0 && ss.length > len
|
||||
ss = ss[0, len] + endss
|
||||
elsif len > 0 && ss.length <= len
|
||||
ss = ss
|
||||
#ss = truncate(ss, :length => len)
|
||||
end
|
||||
end
|
||||
ss
|
||||
end
|
||||
|
||||
def strip_export_title(content)
|
||||
con_ = ""
|
||||
if content.length > 0
|
||||
con_ = strip_tags(content)
|
||||
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
||||
end
|
||||
con_
|
||||
end
|
||||
|
||||
def pdf_load_sources(*arg)
|
||||
arr = arg.map do |path|
|
||||
content_tag(:script) do
|
||||
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
raw arr.join('')
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 导出pdf时,转化markdown为html
|
||||
def to_markdown(text,origin_url)
|
||||
return nil if text.blank?
|
||||
options = {
|
||||
:autolink => true,
|
||||
:no_intra_emphasis => true,
|
||||
:fenced_code_blocks => true,
|
||||
:lax_html_blocks => true,
|
||||
:strikethrough => true,
|
||||
:superscript => false,
|
||||
:tables => true
|
||||
}
|
||||
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
||||
m_t = markdown.render(text)
|
||||
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
||||
end
|
||||
|
||||
def shixun_status_class(shixun)
|
||||
case shixun.status
|
||||
when 0 then 'text-info'
|
||||
when 1 then 'text-warning'
|
||||
when 2 then 'text-success'
|
||||
when 3 then 'text-secondary'
|
||||
end
|
||||
end
|
||||
|
||||
def render_unix_time(date)
|
||||
date.to_time.to_i
|
||||
end
|
||||
|
||||
def find_user_by_login(login)
|
||||
User.find_by_login login
|
||||
end
|
||||
|
||||
def find_user_by_login_and_mail(login, mail)
|
||||
User.find_by(login: login, mail: mail)
|
||||
end
|
||||
|
||||
def find_user_by_gitea_uid(gitea_uid)
|
||||
User.find_by(gitea_uid: gitea_uid)
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache(login, email)
|
||||
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache_by_id(id)
|
||||
$redis_cache.hgetall("v2-owner-common:#{id}")
|
||||
end
|
||||
|
||||
def render_base64_decoded(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64 str
|
||||
end
|
||||
|
||||
def render_admin_statistics_item
|
||||
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
||||
|
||||
return if url.blank?
|
||||
content_tag(:li) do
|
||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||
end
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
def strip(str)
|
||||
str.to_s.strip.presence
|
||||
end
|
||||
|
||||
end
|
||||
# 所有的方法请按首字母的顺序依次列出
|
||||
module ApplicationHelper
|
||||
include Gitlink::I18n
|
||||
include GitHelper
|
||||
|
||||
ONE_MINUTE = 60 * 1000
|
||||
ONE_HOUR = 60 * ONE_MINUTE
|
||||
ONE_DAY = 24 * ONE_HOUR
|
||||
ONE_MONTH = 30 * ONE_DAY
|
||||
|
||||
ONE_YEAR = 12 * ONE_MONTH
|
||||
|
||||
# 全局参数配置
|
||||
def edu_setting name
|
||||
EduSetting.get(name)
|
||||
end
|
||||
|
||||
# xss共计问题
|
||||
def content_safe content
|
||||
tags = %w(
|
||||
a abbr b bdo blockquote br caption cite code col colgroup dd del dfn dl
|
||||
dt em figcaption figure h1 h2 h3 h4 h5 h6 hgroup i img ins kbd li mark
|
||||
ol p pre q rp rt ruby s samp small strike strong sub sup table tbody td
|
||||
tfoot th thead time tr u ul var wbr div span
|
||||
)
|
||||
attributes = %w(href src width height alt cite datetime title class name xml:lang abbr style)
|
||||
sanitize content, tags: tags, attributes: attributes
|
||||
end
|
||||
|
||||
def graduation_navigation graduation
|
||||
graduation.class.to_s == "GraduationTopic" ? "毕设选题" : "毕设任务"
|
||||
end
|
||||
|
||||
def graduation_navigation_id course
|
||||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||
end
|
||||
|
||||
# git用户
|
||||
# git用户命名规则:login+"@educoder.net"
|
||||
def git_username(email)
|
||||
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
|
||||
end
|
||||
|
||||
# 不同的类型扩展不同的目录
|
||||
def relative_path
|
||||
"avatars"
|
||||
end
|
||||
|
||||
def replace_bytes_to_b(size_string)
|
||||
return size_string.gsub("Bytes", "B").gsub("bytes", "B").gsub("字节", "B")
|
||||
end
|
||||
|
||||
def storage_path
|
||||
File.join(Rails.root, "public", "images", relative_path)
|
||||
end
|
||||
|
||||
# 推荐实训
|
||||
def recommend_shixun(shixun)
|
||||
tag_repertoire_id = shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0
|
||||
shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{tag_repertoire_id} and
|
||||
shixun_id != #{shixun.id}").pluck(:shixun_id)
|
||||
|
||||
shixun_id = shixun_id.blank? ? -1 : shixun_id.join(",")
|
||||
Shixun.select([:id, :name, :user_id, :challenges_count, :myshixuns_count, :trainee, :identifier]).where("id
|
||||
in(#{shixun_id})").unhidden.publiced.order("homepage_show asc, myshixuns_count desc").limit(3)
|
||||
|
||||
end
|
||||
|
||||
# shixun开启挑战对应的行为名及url
|
||||
def task_operation_url current_myshixun, shixun
|
||||
if current_myshixun.blank?
|
||||
name = shixun.status == 0 ? "模拟实战" : "开启挑战"
|
||||
url = "/shixuns/#{shixun.identifier}/shixun_exec"
|
||||
else
|
||||
identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
|
||||
if current_myshixun.status == 1
|
||||
name = "查看实战"
|
||||
else
|
||||
name = "继续挑战"
|
||||
end
|
||||
url = identifier
|
||||
end
|
||||
[name, url]
|
||||
end
|
||||
|
||||
# 获取当前时间
|
||||
def time_from_now(time)
|
||||
if String === time
|
||||
time = Time.parse(time)
|
||||
end
|
||||
|
||||
lastUpdateTime = time.to_i*1000
|
||||
|
||||
currentTime = Time.now.to_i*1000
|
||||
timePassed = currentTime - lastUpdateTime
|
||||
timeIntoFormat = 0
|
||||
updateAtValue = ""
|
||||
if timePassed < 0
|
||||
updateAtValue = "刚刚"
|
||||
elsif timePassed < ONE_MINUTE
|
||||
updateAtValue = "1分钟前"
|
||||
elsif timePassed < ONE_HOUR
|
||||
timeIntoFormat = timePassed / ONE_MINUTE
|
||||
updateAtValue = timeIntoFormat.to_s + "分钟前"
|
||||
elsif (timePassed < ONE_DAY)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_HOUR).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "小时前"
|
||||
elsif (timePassed < ONE_MONTH)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_DAY).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "天前"
|
||||
elsif (timePassed < ONE_YEAR)
|
||||
timeIntoFormat = (timePassed.to_f / ONE_MONTH).ceil
|
||||
updateAtValue = timeIntoFormat.to_s + "个月前"
|
||||
else
|
||||
timeIntoFormat = timePassed / ONE_YEAR
|
||||
updateAtValue = timeIntoFormat.to_s + "年前"
|
||||
end
|
||||
updateAtValue
|
||||
end
|
||||
|
||||
# 计算到结束还有多长时间 **天**小时**分
|
||||
def how_much_time(time)
|
||||
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
|
||||
''
|
||||
else
|
||||
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + " 天 "
|
||||
result += (((time - Time.now.to_i).to_i % (24*60*60)) / (60*60)).to_s + " 小时 "
|
||||
result + ((((time - Time.now.to_i).to_i % (24*60*60)) % (60*60)) / 60).to_s + " 分 "
|
||||
end
|
||||
end
|
||||
|
||||
def format_time(time)
|
||||
time.present? ? time.strftime("%Y-%m-%d %H:%M") : ''
|
||||
end
|
||||
|
||||
# 用户图像url,如果不存在的话,source为匿名用户,即默认使用匿名用户图像
|
||||
def url_to_avatar(source)
|
||||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
source.get_letter_avatar_url
|
||||
end
|
||||
end
|
||||
|
||||
def url_to_avatar_with_platform_url(source)
|
||||
platform_url = Rails.application.config_for(:configuration)['platform_url']
|
||||
if platform_url
|
||||
return Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(source).to_s
|
||||
else
|
||||
return url_to_avatar(source).to_s
|
||||
end
|
||||
end
|
||||
|
||||
# 主页banner图
|
||||
def banner_img(source_type)
|
||||
if File.exist?(disk_filename(source_type, "banner"))
|
||||
ctime = File.ctime(disk_filename(source_type, "banner")).to_i
|
||||
File.join("images/avatars", ["#{source_type}", "banner"]) + "?t=#{ctime}"
|
||||
end
|
||||
end
|
||||
|
||||
def disk_filename(source_type,source_id,image_file=nil)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}")
|
||||
end
|
||||
|
||||
def disk_auth_filename(source_type, source_id, type)
|
||||
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def disk_real_name_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def auth_file_url(source_type, source_id, type)
|
||||
File.join('/images', relative_path, source_type, "#{source_id}#{type}")
|
||||
end
|
||||
|
||||
def real_name_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'ID')
|
||||
end
|
||||
|
||||
def disk_professional_auth_filename(source_id)
|
||||
disk_auth_filename('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def professional_auth_file_url(source_id)
|
||||
auth_file_url('UserAuthentication', source_id, 'PRO')
|
||||
end
|
||||
|
||||
def shixun_url_to_avatar(shixun)
|
||||
if File.exist?(disk_filename(shixun.class, shixun.id))
|
||||
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
|
||||
else
|
||||
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
# 选用实训的学校情况
|
||||
def school_user_detail shixun
|
||||
user_ids = shixun.myshixuns.map(&:user_id).uniq # 走缓存取数据
|
||||
school_ids = UserExtension.where(user_id:user_ids).pluck(:school_id).uniq
|
||||
school_names = School.where(id: school_ids[0..1]).pluck(:name)
|
||||
school_size = school_ids.size
|
||||
str = school_size > 0 ? "#{school_names.join("、")}等 #{school_size}所" : "0所"
|
||||
end
|
||||
|
||||
# 普通/分组 作业作品状态数组
|
||||
def student_work_status homework, user_id, course, work
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting user_id, true
|
||||
work = work || StudentWork.create(homework_common_id: homework.id, user_id: user_id)
|
||||
late_time = homework.late_time || course.end_date
|
||||
|
||||
if course.is_end && work && work.work_status > 0
|
||||
status << "查看作品"
|
||||
elsif !course.is_end
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now
|
||||
# 作业未截止时
|
||||
if homework_setting.end_time > Time.now
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "提交作品"
|
||||
else
|
||||
status << "修改作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 补交阶段
|
||||
elsif homework.allow_late && (late_time.nil? || late_time > Time.now)
|
||||
if homework.homework_type == "group" && homework.homework_detail_group.base_on_project
|
||||
if work.project_id.nil? || work.project_id == 0
|
||||
status << "创建项目"
|
||||
status << "关联项目"
|
||||
elsif work.work_status == 0
|
||||
status << "取消关联"
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
else
|
||||
if work.work_status == 0
|
||||
status << "补交作品"
|
||||
else
|
||||
status << "补交附件"
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
|
||||
# 匿评阶段
|
||||
elsif work.work_status != 0
|
||||
if homework.homework_detail_manual.comment_status == 3
|
||||
work_ids = homework.student_works.has_committed.pluck(:id)
|
||||
if StudentWorksEvaluationDistribution.where(student_work_id: work_ids, user_id: user_id).size > 0
|
||||
status << "匿评作品"
|
||||
end
|
||||
end
|
||||
status << "查看作品"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def commit_des_status work, homework
|
||||
status = []
|
||||
homework_setting = homework.homework_group_setting work.user_id
|
||||
|
||||
# 作业已发布且作业未截止(补交未截止)且提交了作品才能提交或修改总结
|
||||
if homework_setting.publish_time && homework_setting.publish_time < Time.now && work.work_status > 0 &&
|
||||
((homework_setting.end_time && homework_setting.end_time > Time.now) ||
|
||||
(homework.allow_late && homework.late_time && homework.late_time > Time.now))
|
||||
work.description.present? ? status << "修改总结" : status << "提交总结"
|
||||
end
|
||||
end
|
||||
|
||||
def download_url attachment,options={}
|
||||
attachment_path(attachment,options)
|
||||
end
|
||||
|
||||
# 耗时:天、小时、分、秒
|
||||
# 小于1分钟则不显示
|
||||
def game_spend_time time
|
||||
day = time / 86400
|
||||
hour = time % (24*60*60) / (60*60)
|
||||
min = time % (24*60*60) % (60*60) / 60
|
||||
sec = time % (24*60*60) % (60*60) % 60
|
||||
if day < 1
|
||||
if hour < 1
|
||||
if min < 1
|
||||
if sec < 1
|
||||
time = "--"
|
||||
else
|
||||
time = "#{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
else
|
||||
time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒"
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
def absolute_path(file_path)
|
||||
file_root_directory + File.join(edu_setting('attachment_folder'), file_path)
|
||||
end
|
||||
|
||||
def file_root_directory
|
||||
Rails.root.to_s
|
||||
end
|
||||
|
||||
def file_storage_directory
|
||||
file_root_directory + edu_setting('attachment_folder')
|
||||
end
|
||||
|
||||
def local_path(file)
|
||||
File.join(file.disk_directory, file.disk_filename)
|
||||
end
|
||||
|
||||
def update_downloads(file)
|
||||
file.update_attributes(:downloads => file.downloads + 1)
|
||||
end
|
||||
|
||||
# 项目信息,
|
||||
def project_info work, current_user, course_identity
|
||||
project = work.project
|
||||
if project
|
||||
if project.status == 9
|
||||
{id: -1, name: "#{project.name}(已删除)", title: "该项目已删除", author: project.creator, member_count: project.project_members.count}
|
||||
else
|
||||
project_score = project.project_score
|
||||
if project.is_public || current_user.manager_of_project?(project) || course_identity < Course::STUDENT
|
||||
{id: project.id, name: project.name, author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
else
|
||||
{id: -1, name: "#{project.name}", title: "该项目是私有的", author: project.creator, member_count: project.project_members.count,
|
||||
all_score: project_score.all_score, code_score: project_score.code_score, issue_score: project_score.issue_score,
|
||||
attachment_score: project_score.attachment_score, message_score: project_score.message_score}
|
||||
end
|
||||
end
|
||||
else
|
||||
{id: -1, name: "--", title: "--"}
|
||||
end
|
||||
end
|
||||
|
||||
def message_content(content)
|
||||
content = (strip_html content).strip
|
||||
content = content.gsub(/\s+/, " ")
|
||||
if content.gsub(" ", "") == ""
|
||||
content = "[非文本消息]"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def strip_html(text, len=0, endss="...")
|
||||
ss = ""
|
||||
if !text.nil? && text.length>0
|
||||
ss=text.gsub(/<\/?.*?>/, '').strip
|
||||
ss = ss.gsub(/ */, '')
|
||||
ss = ss.gsub(/\r\n/,'') #新增
|
||||
ss = ss.gsub(/\n/,'') #新增
|
||||
if len > 0 && ss.length > len
|
||||
ss = ss[0, len] + endss
|
||||
elsif len > 0 && ss.length <= len
|
||||
ss = ss
|
||||
#ss = truncate(ss, :length => len)
|
||||
end
|
||||
end
|
||||
ss
|
||||
end
|
||||
|
||||
def strip_export_title(content)
|
||||
con_ = ""
|
||||
if content.length > 0
|
||||
con_ = strip_tags(content)
|
||||
con_ = con_.gsub(/\r\n/,'').gsub(/ */, '').strip
|
||||
end
|
||||
con_
|
||||
end
|
||||
|
||||
def pdf_load_sources(*arg)
|
||||
arr = arg.map do |path|
|
||||
content_tag(:script) do
|
||||
File.open(Rails.root.join('public', path)).read.to_s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
raw arr.join('')
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 导出pdf时,转化markdown为html
|
||||
def to_markdown(text,origin_url)
|
||||
return nil if text.blank?
|
||||
options = {
|
||||
:autolink => true,
|
||||
:no_intra_emphasis => true,
|
||||
:fenced_code_blocks => true,
|
||||
:lax_html_blocks => true,
|
||||
:strikethrough => true,
|
||||
:superscript => false,
|
||||
:tables => true
|
||||
}
|
||||
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
||||
m_t = markdown.render(text)
|
||||
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
|
||||
end
|
||||
|
||||
def shixun_status_class(shixun)
|
||||
case shixun.status
|
||||
when 0 then 'text-info'
|
||||
when 1 then 'text-warning'
|
||||
when 2 then 'text-success'
|
||||
when 3 then 'text-secondary'
|
||||
end
|
||||
end
|
||||
|
||||
def render_unix_time(date)
|
||||
date.to_time.to_i
|
||||
end
|
||||
|
||||
def find_user_by_login(login)
|
||||
User.find_by_login login
|
||||
end
|
||||
|
||||
def find_user_by_login_and_mail(login, mail)
|
||||
User.find_by(login: login, mail: mail)
|
||||
end
|
||||
|
||||
def find_user_by_gitea_uid(gitea_uid)
|
||||
User.find_by(gitea_uid: gitea_uid)
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache(login, email)
|
||||
$redis_cache.hgetall("v2-owner-common:#{login}-#{email}")
|
||||
end
|
||||
|
||||
def find_user_in_redis_cache_by_id(id)
|
||||
$redis_cache.hgetall("v2-owner-common:#{id}")
|
||||
end
|
||||
|
||||
def render_base64_decoded(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64 str
|
||||
end
|
||||
|
||||
def render_admin_statistics_item
|
||||
url = Rails.application.config_for(:configuration)["admin_statistics_url"]
|
||||
|
||||
return if url.blank?
|
||||
content_tag(:li) do
|
||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||
end
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
def strip(str)
|
||||
str.to_s.strip.presence
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module RepositoriesHelper
|
|||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
|
|
@ -22,7 +22,7 @@ module RepositoriesHelper
|
|||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase)
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
|
|
@ -36,7 +36,6 @@ module RepositoriesHelper
|
|||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
Rails.logger.info author_json['Email']
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
|
|
@ -45,36 +44,56 @@ module RepositoriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref)
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_images = ss + ss_src
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
if remove_title.length > 0
|
||||
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{r_content}&ref=#{ref}"].join
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
content = content.gsub(/#{r_content}/, new_r_content)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -84,6 +103,46 @@ module RepositoriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
|
||||
if image_type?(ext) || download_type(ext)
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub(s[0], "/#{s_content}")
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
def render_format_time_with_unix(unix_time)
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
|
|
@ -94,10 +153,21 @@ module RepositoriesHelper
|
|||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
readme_render_decode64_content(content, owner, repo, ref)
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
class Admins::NewImportUserFromExcel < BaseImportXlsx
|
||||
UserData = Struct.new(:login, :email, :password, :nickname)
|
||||
|
||||
def read_each(&block)
|
||||
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||
data = row.map(&method(:cell_value))[0..3]
|
||||
block.call UserData.new(*data)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def cell_value(obj)
|
||||
obj&.cell_value
|
||||
end
|
||||
end
|
||||
|
|
@ -13,7 +13,7 @@ module Gitea
|
|||
end
|
||||
|
||||
def success?
|
||||
@error.nil?
|
||||
@error.nil? && @result[:status].to_s == "success"
|
||||
end
|
||||
|
||||
def result
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ class CacheAsyncClearJob < ApplicationJob
|
|||
Cache::V2::ProjectCommonService.new(id).clear
|
||||
when "owner_common_service"
|
||||
Cache::V2::OwnnerCommonService.new(id).clear
|
||||
when "project_rank_service"
|
||||
Cache::V2::ProjectRankService.new(id).clear
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,8 +3,7 @@ class DelayExpiredIssueJob < ApplicationJob
|
|||
|
||||
def perform
|
||||
Issue.where(due_date: Date.today + 1.days).find_each do |issue|
|
||||
SendTemplateMessageJob.perform_later('IssueAssignerExpire', issue.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', issue.id) if Site.has_notice_menu?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,6 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueAssignerExpire'
|
||||
issue_id = args[0]
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue.present?
|
||||
receivers = User.where(id: issue&.assigned_to_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueAssignerExpire.get_message_content(receivers, issue)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
|
||||
when 'IssueAtme'
|
||||
receivers, operator_id, issue_id = args[0], args[1], args[2]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -52,13 +45,17 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::IssueChanged.get_email_message_content(receiver, operator, issue, change_params)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueCreatorExpire'
|
||||
when 'IssueExpire'
|
||||
issue_id = args[0]
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue.present?
|
||||
receivers = User.where(id: issue&.author_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue)
|
||||
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id])
|
||||
receivers_string, content, notification_url = MessageTemplate::IssueExpire.get_message_content(receivers, issue)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::IssueExpire.get_email_message_content(receiver, issue)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'IssueDeleted'
|
||||
operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -94,6 +91,14 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectForked'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
return unless operator.present? && project.present?
|
||||
receivers = project&.all_managers.where.not(id: operator&.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectForked.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectIssue'
|
||||
operator_id, issue_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -163,6 +168,37 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectMilestoneCompleted'
|
||||
milestone_id = args[0]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
return unless milestone.present? && milestone&.project.present?
|
||||
receivers = milestone&.project&.all_managers
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestoneCompleted.get_message_content(receivers, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestoneCompleted.get_email_message_content(receiver, milestone)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectMilestone'
|
||||
milestone_id, operator_id = args[0], args[1]
|
||||
milestone = Version.find_by_id(milestone_id)
|
||||
operator = User.find_by_id(operator_id)
|
||||
return unless milestone.present? && milestone&.project.present? && operator.present?
|
||||
receivers = milestone&.project&.all_managers.where.not(id: operator_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectMilestone.get_message_content(receivers, operator, milestone)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {milestone_id: milestone_id, operator_id: operator_id})
|
||||
receivers.find_each do |receiver|
|
||||
receivers_email_string, email_title, email_content = MessageTemplate::ProjectMilestone.get_email_message_content(receiver, operator, milestone)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'ProjectPraised'
|
||||
operator_id, project_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
project = Project.find_by_id(project_id)
|
||||
return unless operator.present? && project.present?
|
||||
receivers = project&.all_managers.where.not(id: operator&.id)
|
||||
receivers_string, content, notification_url = MessageTemplate::ProjectPraised.get_message_content(receivers, operator, project)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id})
|
||||
when 'ProjectPullRequest'
|
||||
operator_id, pull_request_id = args[0], args[1]
|
||||
operator = User.find_by_id(operator_id)
|
||||
|
|
@ -290,6 +326,30 @@ class SendTemplateMessageJob < ApplicationJob
|
|||
receivers_email_string, email_title, email_content = MessageTemplate::TeamLeft.get_email_message_content(receiver, organization, team)
|
||||
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
|
||||
end
|
||||
when 'CompetitionBegin'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionBegin.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
when 'CompetitionReview'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionReview.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
when 'CompetitionResult'
|
||||
user_id, competition_id = args[0], args[1]
|
||||
user = User.find_by_id(user_id)
|
||||
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
|
||||
return unless user.present? && project.present?
|
||||
receivers = User.where(id: user_id)
|
||||
receivers_string, content, notification_url = MessageTemplate::CompetitionResult.get_message_content(receivers, project.first)
|
||||
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
module CustomRegexp
|
||||
PHONE = /1\d{10}/
|
||||
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
||||
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]{4,15}\z/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
||||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||
|
|
@ -11,5 +11,5 @@ module CustomRegexp
|
|||
|
||||
URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i
|
||||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
|
||||
MD_REGEX = /^.+(\.[m|M][d|D])$/
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Notice
|
|||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
notice_config = config[:notice].symbolize_keys!
|
||||
raise 'notice config missing' if notice_config.blank?
|
||||
rescue => exception
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
module Trace
|
||||
class << self
|
||||
def trace_config
|
||||
trace_config = {}
|
||||
|
||||
begin
|
||||
config = Rails.application.config_for(:configuration).symbolize_keys!
|
||||
trace_config = config[:trace].symbolize_keys!
|
||||
raise 'trace config missing' if trace_config.blank?
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] gitea config or configuration.yml missing,
|
||||
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
|
||||
trace_config = {}
|
||||
end
|
||||
|
||||
trace_config
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,10 +5,10 @@ class Ci::Repo < Ci::RemoteBase
|
|||
has_one :perm, foreign_key: :perm_repo_uid
|
||||
has_many :builds, foreign_key: :build_repo_id, dependent: :destroy
|
||||
|
||||
def self.find_with_namespace(namespace_path, identifier)
|
||||
def self.find_with_namespace(namespace_path, identifier, user_login)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Ci::User.find_by_user_login namespace_path
|
||||
user_login = user_login || namespace_path
|
||||
user = Ci::User.find_by(user_login: user_login)
|
||||
repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first
|
||||
|
||||
[user, repo]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module Matchable
|
|||
scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? }
|
||||
scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? }
|
||||
scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) }
|
||||
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "%#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
class ForkUser < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id
|
||||
belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id
|
||||
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class Issue < ApplicationRecord
|
|||
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
|
||||
scope :closed, ->{where(status_id: 5)}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
after_update :change_versions_count
|
||||
after_save :change_versions_count, :send_update_message_to_notice_system
|
||||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
|
||||
|
||||
def incre_project_common
|
||||
|
|
@ -171,11 +171,25 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def change_versions_count
|
||||
if self.version.present? && self.saved_change_to_status_id?
|
||||
if self.saved_change_to_fixed_version_id?
|
||||
before_version = Version.find_by_id(self.fixed_version_id_before_last_save)
|
||||
Rails.logger.info self.fixed_version_id_before_last_save
|
||||
if before_version.present?
|
||||
Rails.logger.info self.status_id
|
||||
Rails.logger.info self.status_id_before_last_save
|
||||
# 更改前状态为完成 或者 更改前后都为完成状态
|
||||
if self.status_id_before_last_save == 5
|
||||
percent = before_version.issues_count == 0 ? 0.0 : ((before_version.closed_issues_count - 1).to_f / before_version.issues_count)
|
||||
before_version.update_attributes(closed_issues_count: (before_version.closed_issues_count - 1), percent: percent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.version.present? && (self.saved_change_to_status_id? || self.saved_change_to_fixed_version_id?)
|
||||
if self.status_id == 5
|
||||
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count + 1).to_f / self.version.issues_count)
|
||||
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count + 1), percent: percent)
|
||||
elsif self.status_id_before_last_save == 5
|
||||
elsif self.status_id_before_last_save == 5 && !self.saved_change_to_fixed_version_id?
|
||||
percent = self.version.issues_count == 0 ? 0.0 : ((self.version.closed_issues_count - 1).to_f / self.version.issues_count)
|
||||
self.version.update_attributes(closed_issues_count: (self.version.closed_issues_count - 1), percent: percent)
|
||||
end
|
||||
|
|
@ -183,7 +197,11 @@ class Issue < ApplicationRecord
|
|||
end
|
||||
|
||||
def update_closed_issues_count_in_project!
|
||||
self.project.decrement!(:closed_issues_count)
|
||||
self.project.decrement!(:closed_issues_count) if self.status_id == 5
|
||||
end
|
||||
|
||||
def send_update_message_to_notice_system
|
||||
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# journalized_id :integer default("0"), not null
|
||||
# journalized_type :string(30) default(""), not null
|
||||
# user_id :integer default("0"), not null
|
||||
# notes :text(65535)
|
||||
# notes :text(4294967295)
|
||||
# created_on :datetime not null
|
||||
# private_notes :boolean default("0"), not null
|
||||
# parent_id :integer
|
||||
|
|
|
|||
|
|
@ -13,61 +13,72 @@
|
|||
#
|
||||
|
||||
class MessageTemplate < ApplicationRecord
|
||||
PLATFORM = 'GitLink'
|
||||
|
||||
def self.build_init_data
|
||||
MessageTemplate::IssueAssignerExpire.destroy_all
|
||||
MessageTemplate::IssueCreatorExpire.destroy_all
|
||||
self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_assigned.html")
|
||||
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修')
|
||||
self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个疑修")
|
||||
self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在疑修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_changed.html")
|
||||
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的疑修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: 'GitLink: 疑修 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的疑修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', email: email_html, email_title: "#{PLATFORM}: 疑修 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/issue_expire.html")
|
||||
self.create(type: 'MessageTemplate::IssueExpire', sys_notice: '疑修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: 疑修截止日期到达最后一天")
|
||||
email_html = File.read("#{email_template_html_dir}/issue_deleted.html")
|
||||
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将疑修 <b>{title}</b> 删除', email: email_html, email_title: 'GitLink: 疑修 {title} 有状态变更', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将疑修 <b>{title}</b> 删除', email: email_html, email_title: "#{PLATFORM}: 疑修 {title} 有状态变更", notification_url: '')
|
||||
self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论疑修{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}')
|
||||
self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '')
|
||||
email_html = File.read("#{email_template_html_dir}/organization_joined.html")
|
||||
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {organization} 组织')
|
||||
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {organization} 组织")
|
||||
email_html = File.read("#{email_template_html_dir}/organization_left.html")
|
||||
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {organization} 组织')
|
||||
self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {organization} 组织")
|
||||
self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库 <b>{nickname2}/{repository}</b> 到 <b>{nickname1}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_issue.html")
|
||||
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 新建了一个疑修')
|
||||
self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建疑修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个疑修")
|
||||
email_html = File.read("#{email_template_html_dir}/project_joined.html")
|
||||
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: 你已加入 {repository} 项目')
|
||||
self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: 你已加入 {repository} 项目")
|
||||
email_html = File.read("#{email_template_html_dir}/project_left.html")
|
||||
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: 'GitLink: 你已被移出 {repository} 项目')
|
||||
self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: "#{PLATFORM}: 你已被移出 {repository} 项目")
|
||||
email_html = File.read("#{email_template_html_dir}/project_member_joined.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已加入项目 {nickname2}/{repository}')
|
||||
self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 已加入项目 {nickname2}/{repository}")
|
||||
email_html = File.read("#{email_template_html_dir}/project_member_left.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: 'GitLink: {nickname1} 已被移出项目 {nickname2}/{repository}')
|
||||
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}')
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 已被移出项目 {nickname2}/{repository}")
|
||||
email_html = File.read("#{email_template_html_dir}/project_milestone.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{name}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 新建了一个里程碑")
|
||||
email_html = File.read("#{email_template_html_dir}/project_milestone_completed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectMilestoneCompleted', sys_notice: '在 <b>{nickname}/{repository}</b> 仓库,里程碑 <b>{name}</b> 的完成度已达到100%', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}', email: email_html, email_title: "#{PLATFORM}: 仓库 {nickname}/{repository} 有里程碑已完成")
|
||||
self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname1}</b> 点赞了你管理的仓库 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_pull_request.html")
|
||||
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求')
|
||||
self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 提交了一个合并请求")
|
||||
email_html = File.read("#{email_template_html_dir}/project_role.html")
|
||||
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{nickname}/{repository}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: '#{PLATFORM}: 在 {nickname}/{repository} 项目你的账号有权限变更', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
email_html = File.read("#{email_template_html_dir}/project_setting_changed.html")
|
||||
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: 'GitLink: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改')
|
||||
self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifidentifier}更改项目标识为"<b>{identifier}</b>"{endidentifier}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: "#{PLATFORM}: 您管理的仓库 {nickname2}/{repository} 仓库设置已被更改")
|
||||
self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}')
|
||||
self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: 'GitLink: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求')
|
||||
self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}', email: email_html, email_title: "#{PLATFORM}: {nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求")
|
||||
self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_changed.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_closed.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '')
|
||||
self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '')
|
||||
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
|
||||
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: "#{PLATFORM}: 合并请求 {title} 有状态变更", notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
|
||||
email_html = File.read("#{email_template_html_dir}/team_joined.html")
|
||||
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
|
||||
email_html = File.read("#{email_template_html_dir}/team_left.html")
|
||||
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
|
||||
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
|
||||
|
||||
# 竞赛通知
|
||||
self.create(type: 'MessageTemplate::CompetitionBegin', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入比赛进行阶段,可在此期间提交作品', notification_url: '{to_url}')
|
||||
self.create(type: 'MessageTemplate::CompetitionResult', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入成绩公示阶段,可查看排行榜信息', notification_url: '{to_url}')
|
||||
self.create(type: 'MessageTemplate::CompetitionReview', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交', notification_url: '{to_url}')
|
||||
end
|
||||
|
||||
def self.sys_notice
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 报名的竞赛进入比赛进行阶段
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛已进入比赛进行阶段
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 已进入比赛进行阶段,可在此阶段提交作品
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 已进入比赛进行阶段,可在此期间提交作品
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionBegin < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.to_s.gsub('{competition_name}', competition&.name), notification_url.to_s.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
# rescue
|
||||
# return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 报名的竞赛进入成绩公示阶段
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛已进入成绩公示阶段
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 已进入成绩公示阶段,可查看排行榜信息
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 已进入成绩公示阶段,可查看排行榜信息
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionResult < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
rescue
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 报名的竞赛比赛结束时间临近
|
||||
# 触发场景
|
||||
# 赛队成员报名的竞赛阶段处于比赛进行中,且距比赛结束日期仅剩3天
|
||||
# 通知文案格式
|
||||
# 你报名的竞赛 xxx 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交
|
||||
# 时间:x分钟/小时/天/月前
|
||||
# 通知文案示例
|
||||
# 你报名的竞赛 代码审查大赛 距作品提交结束日期仅剩3天,若尚未提交参赛作品,请尽快提交
|
||||
# 时间:3小时前
|
||||
# 点击通知跳转页面
|
||||
# 点击此通知将跳转到代码审查大赛详情页:
|
||||
# http://117.50.100.12:8080/competitions/lgw7st/home
|
||||
class MessageTemplate::CompetitionReview < MessageTemplate
|
||||
|
||||
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
|
||||
def self.get_message_content(receivers, competition)
|
||||
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
|
||||
rescue
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -53,6 +53,7 @@ class MessageTemplate::IssueAssigned < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@ class MessageTemplate::IssueChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifduedate})(.*)({endduedate})/, '')
|
||||
end
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,29 +1,3 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我创建的疑修截止日期到达最后一天
|
||||
class MessageTemplate::IssueCreatorExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
def self.get_message_content(receivers, issue)
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{title}', issue&.subject)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::IssueDeleted < MessageTemplate
|
|||
content.gsub!('{login}', operator&.login)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue_title)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我创建或负责的疑修截止日期到达最后一天
|
||||
class MessageTemplate::IssueExpire < MessageTemplate
|
||||
|
||||
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
|
||||
def self.get_message_content(receivers, issue)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueExpire"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["CreateOrAssign::IssueExpire"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{title}', issue&.subject)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueExpire.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, issue)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["CreateOrAssign::IssueExpire"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["CreateOrAssign::IssueExpire"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = issue&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::IssueExpire.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::OrganizationJoined < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class MessageTemplate::OrganizationLeft < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class MessageTemplate::OrganizationRole < MessageTemplate
|
|||
content.gsub!('{login}', organization&.login)
|
||||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{role}', role)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,11 +12,21 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库被复刻
|
||||
# 我管理的仓库被复刻
|
||||
class MessageTemplate::ProjectForked < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectForked.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, user, project)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Forked"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Forked"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
|
||||
url = notification_url.gsub('{owner}', user&.login).gsub('{identifier}', project&.identifier)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}")
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class MessageTemplate::ProjectIssue < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', issue&.id.to_s)
|
||||
content.gsub!('{title}', issue&.subject)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class MessageTemplate::ProjectJoined < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{nickname}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class MessageTemplate::ProjectLeft < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{nickname}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class MessageTemplate::ProjectMemberJoined < MessageTemplate
|
|||
content.gsub!('{nickname1}', user&.real_name)
|
||||
content.gsub!('{nickname2}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class MessageTemplate::ProjectMemberLeft < MessageTemplate
|
|||
content.gsub!('{nickname1}', user&.real_name)
|
||||
content.gsub!('{nickname2}', project&.owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,14 +12,61 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库有新的里程碑
|
||||
# 我管理的仓库有新的里程碑
|
||||
class MessageTemplate::ProjectMilestone < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestone.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, operator, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Milestone"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestone.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, operator, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::Milestone"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::Milestone"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname1}', operator&.real_name)
|
||||
title.gsub!('{nickname2}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname1}', operator&.real_name)
|
||||
content.gsub!('{nickname2}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestone.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_templates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# sys_notice :text(65535)
|
||||
# email :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# notification_url :string(255)
|
||||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# 我管理的仓库有里程碑完成
|
||||
class MessageTemplate::ProjectMilestoneCompleted < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectMilestoneCompleted.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers, milestone)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneCompleted"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneCompleted"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
content = sys_notice.gsub('{nickname}', owner&.real_name).gsub('{repository}', project&.name).gsub('{name}', milestone&.name)
|
||||
url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', milestone&.id.to_s)
|
||||
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneCompleted.get_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
def self.get_email_message_content(receiver, milestone)
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneCompleted"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneCompleted"] : send_setting
|
||||
return '', '', '' unless send_setting
|
||||
project = milestone&.project
|
||||
owner = project&.owner
|
||||
title = email_title
|
||||
title.gsub!('{nickname}', owner&.real_name)
|
||||
title.gsub!('{repository}', project&.name)
|
||||
|
||||
content = email
|
||||
content.gsub!('{receiver}', receiver&.real_name)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{nickname}', owner&.real_name)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{login}', owner&.login)
|
||||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', milestone&.id.to_s)
|
||||
content.gsub!('{name}', milestone&.name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
return '', '', ''
|
||||
end
|
||||
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectMilestoneCompleted.get_email_message_content [ERROR] #{e}")
|
||||
return '', '', ''
|
||||
end
|
||||
end
|
||||
|
|
@ -12,11 +12,21 @@
|
|||
# email_title :string(255)
|
||||
#
|
||||
|
||||
# TODO 我管理的仓库被点赞
|
||||
# 我管理的仓库被点赞
|
||||
class MessageTemplate::ProjectPraised < MessageTemplate
|
||||
|
||||
# MessageTemplate::ProjectPraised.get_message_content(User.where(login: 'yystopf'))
|
||||
def self.get_message_content(receivers)
|
||||
def self.get_message_content(receivers, user, project)
|
||||
receivers.each do |receiver|
|
||||
if receiver.user_template_message_setting.present?
|
||||
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Praised"]
|
||||
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Praised"] : send_setting
|
||||
receivers = receivers.where.not(id: receiver.id) unless send_setting
|
||||
end
|
||||
end
|
||||
return '', '', '' if receivers.blank?
|
||||
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
|
||||
url = notification_url.gsub('{login}', user&.login)
|
||||
return receivers_string(receivers), content, url
|
||||
rescue => e
|
||||
Rails.logger.info("MessageTemplate::ProjectPraised.get_message_content [ERROR] #{e}")
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class MessageTemplate::ProjectPullRequest < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class MessageTemplate::ProjectRole < MessageTemplate
|
|||
content.gsub!('{identifier}', project&.identifier)
|
||||
content.gsub!('{repository}', project&.name)
|
||||
content.gsub!('{role}', role)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
navbar.gsub!('devops', '工作流')
|
||||
navbar.gsub!('versions', '里程碑')
|
||||
navbar.gsub!('resources', '资源库')
|
||||
navbar.gsub!('services', '服务')
|
||||
if change_count > 1
|
||||
content.sub!('{ifnavbar}', '<br/>')
|
||||
else
|
||||
|
|
@ -290,6 +291,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
navbar.gsub!('devops', '工作流')
|
||||
navbar.gsub!('versions', '里程碑')
|
||||
navbar.gsub!('resources', '资源库')
|
||||
navbar.gsub!('services', '服务')
|
||||
if change_count > 1
|
||||
content.sub!('{ifnavbar}', '<br/>')
|
||||
else
|
||||
|
|
@ -300,6 +302,7 @@ class MessageTemplate::ProjectSettingChanged < MessageTemplate
|
|||
else
|
||||
content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '')
|
||||
end
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class MessageTemplate::PullRequestAssigned < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ class MessageTemplate::PullRequestChanged < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
change_count = change_params.keys.size
|
||||
# 合并请求审查成员修改
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class MessageTemplate::PullRequestClosed < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class MessageTemplate::PullRequestMerged < MessageTemplate
|
|||
content.gsub!('{baseurl}', base_url)
|
||||
content.gsub!('{title}', pull_request&.title)
|
||||
content.gsub!('{id}', pull_request&.id.to_s)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class MessageTemplate::TeamJoined < MessageTemplate
|
|||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class MessageTemplate::TeamLeft < MessageTemplate
|
|||
content.gsub!('{organization}', organization&.real_name)
|
||||
content.gsub!('{team}', team&.nickname)
|
||||
content.gsub!('{role}', team&.authorize_name)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
|
||||
return receiver&.mail, title, content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ class Organization < Owner
|
|||
|
||||
after_save :reset_cache_data
|
||||
|
||||
def gitea_token
|
||||
team_users.joins(:team).where(teams: {authorize: "owner"}).take&.user&.gitea_token
|
||||
end
|
||||
|
||||
def reset_cache_data
|
||||
Cache::V2::OwnerCommonService.new(self.id).reset
|
||||
end
|
||||
|
|
|
|||
|
|
@ -124,9 +124,10 @@ class Project < ApplicationRecord
|
|||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members, :reset_cache_data
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
before_destroy :decre_project_common, :decre_forked_from_project_count
|
||||
after_destroy :decre_user_statistic, :decre_platform_statistic
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :description, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
|
|
@ -150,7 +151,7 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def reset_cache_data
|
||||
CacheAsyncResetJob.perform_later("project_common_service", self.id)
|
||||
CacheAsyncResetJob.set(wait: 5.seconds).perform_later("project_common_service", self.id)
|
||||
if changes[:user_id].present?
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1}, changes[:user_id].first)
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1}, changes[:user_id].last)
|
||||
|
|
@ -163,6 +164,14 @@ class Project < ApplicationRecord
|
|||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1})
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1})
|
||||
end
|
||||
if changes[:is_public].present?
|
||||
if changes[:is_public][0] && !changes[:is_public][1]
|
||||
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
|
||||
end
|
||||
if !changes[:is_public][0] && changes[:is_public][1]
|
||||
$redis_cache.srem("v2-project-rank-deleted", self.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
class ProjectUnit < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7}
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
|
||||
|
||||
validates :unit_type, uniqueness: { scope: :project_id}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# Table name: pull_requests
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# pull_request_id :integer
|
||||
# gpid :integer
|
||||
# gitea_id :integer
|
||||
# gitea_number :integer
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
# project_id :integer
|
||||
# title :string(255)
|
||||
# milestone :integer
|
||||
# body :text(65535)
|
||||
# body :text(4294967295)
|
||||
# head :string(255)
|
||||
# base :string(255)
|
||||
# issue_id :integer
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class Site < ApplicationRecord
|
|||
# add: 添加类链接
|
||||
# personal: 个人名下类链接,
|
||||
# common: 普通链接
|
||||
enum site_type: { add: 0, personal: 1, common: 2 }
|
||||
enum site_type: { add: 0, personal: 1, common: 2, competition: 3 }
|
||||
|
||||
scope :by_search, -> (keyword){ where("name LIKE :keyword OR url LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? }
|
||||
scope :by_site_type, -> (site_type){ where(site_type: strip_param(site_type)) unless strip_param(site_type).blank? }
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ class Team < ApplicationRecord
|
|||
has_many :team_units, dependent: :destroy
|
||||
has_many :team_users, dependent: :destroy
|
||||
|
||||
scope :like, lambda { |keywords|
|
||||
sql = "teams.nickname LIKE :search OR teams.name LIKE :search"
|
||||
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
validates :name, uniqueness: {scope: :organization_id}
|
||||
|
||||
enum authorize: {read: 1, write: 2, admin: 3, owner: 4}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class TeamUser < ApplicationRecord
|
|||
before_destroy :remove_project_member
|
||||
|
||||
def self.build(organization_id, user_id, team_id)
|
||||
self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id)
|
||||
self.find_or_create_by!(organization_id: organization_id, user_id: user_id, team_id: team_id)
|
||||
end
|
||||
|
||||
def remove_project_member
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class TemplateMessageSetting < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.build_init_data
|
||||
TemplateMessageSetting.destroy_all
|
||||
TemplateMessageSetting::CreateOrAssign.build_init_data
|
||||
TemplateMessageSetting::ManageProject.build_init_data
|
||||
TemplateMessageSetting::Normal.build_init_data
|
||||
|
|
|
|||
|
|
@ -27,5 +27,6 @@ class TemplateMessageSetting::CreateOrAssign < TemplateMessageSetting
|
|||
def self.build_init_data
|
||||
self.find_or_create_by(name: "疑修状态变更", key: "IssueChanged")
|
||||
self.find_or_create_by(name: "合并请求状态变更", key: "PullRequestChanged")
|
||||
self.find_or_create_by(name: "疑修截止日期到达最后一天", key: "IssueExpire", notification_disabled: false)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,5 +29,9 @@ class TemplateMessageSetting::ManageProject < TemplateMessageSetting
|
|||
self.find_or_create_by(name: "有新的合并请求", key: "PullRequest")
|
||||
self.find_or_create_by(name: "有成员变动", key: "Member")
|
||||
self.find_or_create_by(name: "仓库设置被更改", key: "SettingChanged")
|
||||
self.find_or_create_by(name: "被点赞", key: "Praised", notification_disabled: false, email_disabled: true)
|
||||
self.find_or_create_by(name: "被fork", key: "Forked", notification_disabled: false, email_disabled: true)
|
||||
self.find_or_create_by(name: "有新的里程碑", key: "Milestone", notification_disabled: false)
|
||||
self.find_or_create_by(name: "有里程碑已完成", key: "MilestoneCompleted", notification_disabled: false)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue