forked from Gitlink/forgeplus
Compare commits
206 Commits
master
...
dev_milita
| Author | SHA1 | Date |
|---|---|---|
|
|
a517d1df68 | |
|
|
6dfffb8a6d | |
|
|
1c5b42e01b | |
|
|
85302102d6 | |
|
|
316fb0ff58 | |
|
|
d475413fd6 | |
|
|
cd40efc760 | |
|
|
d1b5ead752 | |
|
|
972373a277 | |
|
|
f901ff8920 | |
|
|
00a4be2879 | |
|
|
90738a6117 | |
|
|
bd88870405 | |
|
|
fae11267f7 | |
|
|
2f06e89b54 | |
|
|
fda21d782c | |
|
|
4dadce904d | |
|
|
aa9006bfe5 | |
|
|
f8ef2d48a0 | |
|
|
0607a62b17 | |
|
|
1e1d07e697 | |
|
|
a72a0de2b9 | |
|
|
f0bc08cd47 | |
|
|
bcd5c6bee0 | |
|
|
cf0565ddb6 | |
|
|
cb184792cd | |
|
|
78cee5f7d1 | |
|
|
7ab87df7fc | |
|
|
78fd1d158f | |
|
|
9b91557bb6 | |
|
|
521a1a2c8a | |
|
|
01bf13ddd9 | |
|
|
a5d4799a21 | |
|
|
e97eacbbf6 | |
|
|
2c17ae096e | |
|
|
fb335162fc | |
|
|
c7b40c1230 | |
|
|
293121ab91 | |
|
|
43cccc5429 | |
|
|
fcc5429bbd | |
|
|
1f8f2abcf6 | |
|
|
a2140574cd | |
|
|
ab47dd0524 | |
|
|
4310cc9f26 | |
|
|
9648afb0bb | |
|
|
557b6ccc13 | |
|
|
d94b3ff2f4 | |
|
|
4a7878d16e | |
|
|
0a00a4bc0e | |
|
|
b81d92af46 | |
|
|
ef6f2c7b42 | |
|
|
689b24da8f | |
|
|
96c67d359e | |
|
|
3e633ea6cc | |
|
|
4fe3f88de6 | |
|
|
a5fd87a475 | |
|
|
e8bbc7d856 | |
|
|
9a0d7aa02a | |
|
|
25e1bf1565 | |
|
|
574f6561d1 | |
|
|
eaddf52cbd | |
|
|
ef0a0e5ddd | |
|
|
ef81d61a0d | |
|
|
071f913123 | |
|
|
6096fdd7bf | |
|
|
9ba297ccf6 | |
|
|
66fd6a71e5 | |
|
|
89bc20e540 | |
|
|
184a6bf1bf | |
|
|
8ee089b82d | |
|
|
abc21413ac | |
|
|
ce89ce5169 | |
|
|
b8a4c467fe | |
|
|
300658f8dd | |
|
|
9553740960 | |
|
|
1a8d9bb0ce | |
|
|
8c43f74b69 | |
|
|
3e7ae82258 | |
|
|
0aa75e077e | |
|
|
8aefcad510 | |
|
|
622dcbaf4f | |
|
|
6570125a36 | |
|
|
d91e8dcbfe | |
|
|
0c2507b1e9 | |
|
|
8d29c2bd50 | |
|
|
774f632d9a | |
|
|
2969afd333 | |
|
|
cc978c8dea | |
|
|
ce105b4c07 | |
|
|
b5870b1020 | |
|
|
1edb3ce7ad | |
|
|
59257b1caa | |
|
|
b552e29aa3 | |
|
|
21424a23f2 | |
|
|
a82af669bd | |
|
|
0f01abd45f | |
|
|
80002be670 | |
|
|
f7e19cb3a4 | |
|
|
5cd6620413 | |
|
|
f3a9124bdd | |
|
|
d97a39a3a2 | |
|
|
987ff74690 | |
|
|
37be604e82 | |
|
|
83e2c1f889 | |
|
|
46a1c8877b | |
|
|
0aa39efe9b | |
|
|
15d562d7b1 | |
|
|
5b261d6e81 | |
|
|
4693e77e02 | |
|
|
fbf22ff0df | |
|
|
0794f77a87 | |
|
|
e5a46a242f | |
|
|
4902237bd7 | |
|
|
4ddc60a1c3 | |
|
|
cfa14fff9d | |
|
|
ef327f2994 | |
|
|
bf91c5e382 | |
|
|
9b687f7885 | |
|
|
a072162324 | |
|
|
8f1e0f39ea | |
|
|
aaa6483958 | |
|
|
bf730ca18f | |
|
|
132af875bc | |
|
|
a862d994ab | |
|
|
604da93c5c | |
|
|
3f525f5779 | |
|
|
05d1e66ea9 | |
|
|
10c1cccf2c | |
|
|
27ec7ec7dd | |
|
|
43b4907565 | |
|
|
cb90e1a13f | |
|
|
749cd058c4 | |
|
|
47cc70f2c5 | |
|
|
5447d54d30 | |
|
|
6c436dd631 | |
|
|
9eb7219b9a | |
|
|
ad5fcb25c4 | |
|
|
d42053ce0c | |
|
|
36bae71947 | |
|
|
837aa1ea9e | |
|
|
c283c7ed58 | |
|
|
4cf8588343 | |
|
|
e75fad98f8 | |
|
|
bc37c59f00 | |
|
|
a6a745da93 | |
|
|
5bef80ee58 | |
|
|
f9bcc7e02b | |
|
|
d35faf3935 | |
|
|
8d7dc9cb60 | |
|
|
248d78d8c1 | |
|
|
f632424f13 | |
|
|
95ede63220 | |
|
|
8fac294d04 | |
|
|
d67c12beba | |
|
|
a7e4b85352 | |
|
|
2ac2920399 | |
|
|
230b934de4 | |
|
|
e0bedf175f | |
|
|
c9a263e03c | |
|
|
2bd15d9746 | |
|
|
fc9588fb63 | |
|
|
e611b519ab | |
|
|
3dd3944ebd | |
|
|
f417bf3308 | |
|
|
9c7c914d12 | |
|
|
b088befae7 | |
|
|
d3636e686b | |
|
|
88d98f0ac4 | |
|
|
db6aa954b1 | |
|
|
04a611a4aa | |
|
|
9ecea83506 | |
|
|
82a9907fdc | |
|
|
c56c98fd6e | |
|
|
2948ad2033 | |
|
|
fc611140cf | |
|
|
fcb5f58b69 | |
|
|
0f38a130f3 | |
|
|
fc54632a08 | |
|
|
5963af5c7b | |
|
|
c1f2f7f6e2 | |
|
|
271699daf1 | |
|
|
98da7ea34d | |
|
|
645e4a3586 | |
|
|
7beca24a05 | |
|
|
d1368c7612 | |
|
|
28e762810e | |
|
|
0f60d0adc9 | |
|
|
e634317675 | |
|
|
6b1a0a96c6 | |
|
|
298859bd10 | |
|
|
d4d412ab40 | |
|
|
57d1a1474e | |
|
|
055b7dbac5 | |
|
|
30aad87e5a | |
|
|
aecd68fe9a | |
|
|
998a6828d9 | |
|
|
12c04d02e5 | |
|
|
d6ef3d8aa3 | |
|
|
c7a89d1660 | |
|
|
1939c0d33f | |
|
|
561b9efd92 | |
|
|
6c0b87fdd1 | |
|
|
5d309d1dc4 | |
|
|
89c230c362 | |
|
|
d4156a5582 | |
|
|
ee8cbb8553 |
218
api_document.md
218
api_document.md
|
|
@ -284,6 +284,7 @@ http://localhost:3000/api/licenses/ | jq
|
|||
|licenses|array |返回数据|
|
||||
|-- id |int |id |
|
||||
|-- name |string|开源许可证名称|
|
||||
|-- is_secret |string|是否为特殊许可证|
|
||||
|
||||
|
||||
返回值
|
||||
|
|
@ -292,23 +293,33 @@ http://localhost:3000/api/licenses/ | jq
|
|||
"licenses": [
|
||||
{
|
||||
"id": 57,
|
||||
"name": "AFL-1.2"
|
||||
"name": "AFL-1.2",
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"id": 76,
|
||||
"name": "AFL-3.0"
|
||||
"name": "AFL-3.0",
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"id": 214,
|
||||
"name": "AFL-1.1"
|
||||
"name": "AFL-1.1",
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"id": 326,
|
||||
"name": "AFL-2.1"
|
||||
"name": "AFL-2.1",
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"id": 350,
|
||||
"name": "AFL-2.0"
|
||||
"name": "AFL-2.0",
|
||||
"is_secret": false
|
||||
},
|
||||
{
|
||||
"id": 359,
|
||||
"name": "PHengLEI",
|
||||
"is_secret": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -554,6 +565,8 @@ curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq
|
|||
|project_category_id |int|项目类别id|
|
||||
|project_language_id |int|项目语言id|
|
||||
|private |boolean|项目是否私有, true:为私有,false: 公开 |
|
||||
|is_secret |boolean|项目是否为特殊协议项目, true:是,false: 否 |
|
||||
|
||||
|
||||
|
||||
返回值
|
||||
|
|
@ -566,7 +579,8 @@ curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq
|
|||
"project_description": "my first project mirror_demo",
|
||||
"project_category_id": 1,
|
||||
"project_language_id": 2,
|
||||
"private": false
|
||||
"private": false,
|
||||
"is_secret": true
|
||||
}
|
||||
```
|
||||
---
|
||||
|
|
@ -1146,6 +1160,7 @@ http://localhost:3000/api/projects | jq
|
|||
|forked_count |int|被fork的数量|
|
||||
|praises_count |int|star数量|
|
||||
|is_public |boolean|是否公开, true:公开,false:未公开|
|
||||
|is_secret |boolean|是否为特殊许可证项目, true:是,false:否|
|
||||
|mirror_url |string|镜像url|
|
||||
|last_update_time|int|最后更新时间,为UNIX格式的时间戳|
|
||||
|author |object|项目创建者|
|
||||
|
|
@ -1156,6 +1171,10 @@ http://localhost:3000/api/projects | jq
|
|||
|language |object|项目语言|
|
||||
|-- id |int|项目语言id|
|
||||
|-- name |string|项目语言名称|
|
||||
|user_apply_signatures |object|用户创建的特殊许可申请|
|
||||
|-- id |int|用户创建的特殊许可申请id|
|
||||
|-- status |int|用户创建的特殊许可申请审核状态, 'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|
||||
|
||||
|
||||
|
||||
返回值
|
||||
|
|
@ -1171,6 +1190,7 @@ http://localhost:3000/api/projects | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"is_secret": true,
|
||||
"mirror_url": null,
|
||||
"last_update_time": 1577697461,
|
||||
"author": {
|
||||
|
|
@ -1184,7 +1204,13 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[
|
||||
{
|
||||
"id": 1,
|
||||
"status": "waiting"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
|
|
@ -1194,6 +1220,7 @@ http://localhost:3000/api/projects | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"is_secret": false,
|
||||
"mirror_url": null,
|
||||
"last_update_time": 1577697403,
|
||||
"author": {
|
||||
|
|
@ -1207,7 +1234,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
|
|
@ -1217,6 +1245,7 @@ http://localhost:3000/api/projects | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"is_secret": true,
|
||||
"mirror_url": null,
|
||||
"last_update_time": 1577415173,
|
||||
"author": {
|
||||
|
|
@ -1230,7 +1259,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
|
|
@ -1240,6 +1270,7 @@ http://localhost:3000/api/projects | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": false,
|
||||
"is_secret": true,
|
||||
"mirror_url": "https://gitea.com/CasperVector/slew.git",
|
||||
"last_update_time": 1577346228,
|
||||
"author": {
|
||||
|
|
@ -1253,7 +1284,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
|
|
@ -1263,6 +1295,7 @@ http://localhost:3000/api/projects | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"is_secret": true,
|
||||
"mirror_url": null,
|
||||
"last_update_time": 1577341572,
|
||||
"author": {
|
||||
|
|
@ -1276,7 +1309,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -5016,6 +5050,7 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|
|||
|forked_count |int|被fork的数量|
|
||||
|praises_count |int|star数量|
|
||||
|is_public |boolean|是否公开, true:公开,false:未公开|
|
||||
|is_secret |boolean|是否为特殊许可证项目, true:是,false:否|
|
||||
|mirror_url |string|镜像url|
|
||||
|last_update_time|int|最后更新时间,为UNIX格式的时间戳|
|
||||
|author |object|项目创建者|
|
||||
|
|
@ -5026,7 +5061,9 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|
|||
|language |object|项目语言|
|
||||
|-- id |int|项目语言id|
|
||||
|-- name |string|项目语言名称|
|
||||
|
||||
|user_apply_signatures |object|用户创建的特殊许可申请|
|
||||
|-- id |int|用户创建的特殊许可申请id|
|
||||
|-- status |int|用户创建的特殊许可申请审核状态, 'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|
||||
|
||||
返回值
|
||||
```json
|
||||
|
|
@ -5041,6 +5078,7 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|
|||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"is_public": true,
|
||||
"is_secret": false,
|
||||
"mirror_url": null,
|
||||
"last_update_time": 1577697461,
|
||||
"author": {
|
||||
|
|
@ -5054,9 +5092,163 @@ http://localhost:3000/api/users/Jason/projects.json | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[
|
||||
{
|
||||
"id": 1,
|
||||
"status": "waiting"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
#### 特殊许可证项目申请列表
|
||||
```
|
||||
GET /api/apply_signatures
|
||||
```
|
||||
*示例*
|
||||
```bash
|
||||
curl -X GET \
|
||||
-d "project_id=36" \
|
||||
-d "page=1" \
|
||||
-d "limit=5" \
|
||||
-d "search=16895620" \
|
||||
-d "status=waiting" \
|
||||
http://localhost:3000/api/apply_signatures | jq
|
||||
```
|
||||
*请求参数说明:*
|
||||
|
||||
|参数名|必选|类型|说明|
|
||||
|-|-|-|-|
|
||||
|project_id |是|int |项目id |
|
||||
|page |否|string |页数,第几页 |
|
||||
|limit |否|string |每页多少条数据,默认15条 |
|
||||
|search |否|string |用户名、登录名匹配搜索 |
|
||||
|status |否|string |状态匹配搜索,'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过 |
|
||||
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
|参数名|类型|说明|
|
||||
|-|-|-|
|
||||
|total_count |int |返回记录总条数 |
|
||||
|apply_signatures |array|特殊许可证项目申请信息|
|
||||
|-- id |int|特殊许可证项目申请id|
|
||||
|-- status |int|特殊许可证项目申请状态,'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|
||||
|user |object|用户|
|
||||
|-- id |int|用户id|
|
||||
|-- name |string|用户名称|
|
||||
|-- login |string|用户登录名/标识|
|
||||
|-- image_url |string|用户头像|
|
||||
|-- email |string|用户邮箱|
|
||||
|-- is_owner |boolean|是否是项目的拥有者,true:是, false:不是|
|
||||
|attachment |object|上传附件|
|
||||
|--filename |string|附件名称|
|
||||
|--path |string|附件地址|
|
||||
|
||||
|
||||
返回值
|
||||
```json
|
||||
{
|
||||
"total_count": 1,
|
||||
"apply_signatures": [
|
||||
{
|
||||
"id": 18,
|
||||
"status": "passed",
|
||||
"user": {
|
||||
"id": 3,
|
||||
"name": "16895620",
|
||||
"login": "16895620",
|
||||
"image_url": "avatars/User/boy.jpg",
|
||||
"email": "2456233122@qq.com",
|
||||
"is_owner": false
|
||||
},
|
||||
"attachment": {
|
||||
"filename": "PHengLEI软件开源协议.docx",
|
||||
"path": "/api/attachments/23"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
---
|
||||
#### 特殊许可证项目用户创建申请
|
||||
```
|
||||
POST /api/apply_signatures
|
||||
```
|
||||
|
||||
*示例*
|
||||
```bash
|
||||
curl -X POST \
|
||||
-d "project_id=8" \
|
||||
-d "attachment_id=4" \
|
||||
http://localhost:3000/api/apply_signatures.json | jq
|
||||
```
|
||||
|
||||
*请求参数说明:*
|
||||
|
||||
|参数名|必选|类型|说明|
|
||||
|-|-|-|-|
|
||||
|project_id |是|int |项目id |
|
||||
|attachment_id |是|int |上传的文件id |
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
|参数名|类型|说明|
|
||||
|-|-|-|
|
||||
|id |int|特殊许可证项目用户创建申请的id|
|
||||
|attachment |object|上传的文件|
|
||||
|--filename |string|上传的文件的文件名|
|
||||
|
||||
返回值
|
||||
```json
|
||||
{
|
||||
"id": 5,
|
||||
"attachment": {
|
||||
"filename": "timg.jpeg"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
#### 特殊许可证项目申请修改
|
||||
```
|
||||
PATCH /api/apply_signatures/:id
|
||||
```
|
||||
|
||||
*示例*
|
||||
```bash
|
||||
curl -X POST \
|
||||
-d "id=18" \
|
||||
-d "status=passed" \
|
||||
-d "project_id=36" \
|
||||
http://localhost:3000/api/apply_signatures/18 | jq
|
||||
```
|
||||
|
||||
*请求参数说明:*
|
||||
|
||||
|参数名|必选|类型|说明|
|
||||
|-|-|-|-|
|
||||
|id |是|int |特殊许可证项目申请id |
|
||||
|status |是|string |特殊许可证项目申请状态 ,'unpassed': 审核未通过,'waiting': 等待审核 'passed':审核通过|
|
||||
|project_id |是|int |项目id|
|
||||
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
|参数名|类型|说明|
|
||||
|-|-|-|
|
||||
|status |int |0:添加成功, -1: 更改失败, 1: 表示已经是该状态了 |
|
||||
|message |string|返回信息说明|
|
||||
|
||||
|
||||
返回值
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
---
|
||||
|
|
@ -71,6 +71,23 @@ $(document).on('turbolinks:load', function(){
|
|||
$('.admin-alert-container .alert.alert-danger').alert('close');
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
$('.logo-item-left').on("change", 'input[type="file"]', function () {
|
||||
var $fileInput = $(this);
|
||||
var file = this.files[0];
|
||||
var imageType = /image.*/;
|
||||
if (file && file.type.match(imageType)) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
var $box = $fileInput.parent();
|
||||
$box.find('img').attr('src', reader.result).css('display', 'block');
|
||||
$box.addClass('has-img');
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(document).on("turbolinks:before-cache", function () {
|
||||
|
|
|
|||
|
|
@ -58,3 +58,75 @@ input.form-control {
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.logo-item {
|
||||
display: flex;
|
||||
|
||||
&-img {
|
||||
display: block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: #e9ecef;
|
||||
}
|
||||
|
||||
&-upload {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: #e9ecef;
|
||||
border: 1px solid #ced4da;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 27px;
|
||||
left: 39px;
|
||||
width: 2px;
|
||||
height: 26px;
|
||||
background: #495057;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 39px;
|
||||
left: 27px;
|
||||
width: 26px;
|
||||
height: 2px;
|
||||
background: #495057;
|
||||
}
|
||||
}
|
||||
|
||||
&-left {
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
|
||||
&.has-img {
|
||||
.logo-item-upload {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.logo-item-upload {
|
||||
display: block;
|
||||
background: rgba(145, 145, 145, 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
color: #777777;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: #23272B;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,348 +1,349 @@
|
|||
class AccountsController < ApplicationController
|
||||
|
||||
#skip_before_action :check_account, :only => [:logout]
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
||||
# 其他平台同步注册的用户
|
||||
def remote_register
|
||||
username = params[:username]&.gsub(/\s+/, "")
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
password = params[:password]
|
||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = autologin_register(username, email, password, platform)
|
||||
if result[:message].blank?
|
||||
render_ok({user: result[:user]})
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台修改用户的信息,这边同步修改
|
||||
def remote_update
|
||||
ActiveRecord::Base.transaction do
|
||||
user_params = params[:user_params]
|
||||
user_extension_params = params[:user_extension_params]
|
||||
|
||||
u = User.find_by(login: params[:old_user_login])
|
||||
user_mail = u.try(:mail)
|
||||
|
||||
if u.present?
|
||||
ue = u.user_extension
|
||||
u.login = user_params["login"] if user_params["login"]
|
||||
u.mail = user_params["mail"] if user_params["mail"]
|
||||
u.lastname = user_params["lastname"] if user_params["lastname"]
|
||||
|
||||
ue.gender = user_extension_params["gender"]
|
||||
ue.school_id = user_extension_params["school_id"]
|
||||
ue.location = user_extension_params["location"]
|
||||
ue.location_city = user_extension_params["location_city"]
|
||||
ue.identity = user_extension_params["identity"]
|
||||
ue.technical_title = user_extension_params["technical_title"]
|
||||
ue.student_id = user_extension_params["student_id"]
|
||||
ue.description = user_extension_params["description"]
|
||||
ue.save!
|
||||
u.save!
|
||||
|
||||
sync_params = {}
|
||||
|
||||
if (user_params["mail"] && user_params["mail"] != user_mail)
|
||||
sync_params = sync_params.merge(email: user_params["mail"])
|
||||
end
|
||||
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
||||
if interactor.success?
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台同步登录
|
||||
def remote_login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
if @user
|
||||
successful_authentication(@user)
|
||||
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
||||
else
|
||||
render_error("用户不存在")
|
||||
end
|
||||
end
|
||||
|
||||
#修改密码
|
||||
def remote_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 用户注册
|
||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||
# params[:login] 邮箱或者手机号
|
||||
# params[:code] 验证码
|
||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||
# 本地forge注册入口
|
||||
def register
|
||||
begin
|
||||
# 查询验证码是否正确;type只可能是1或者8
|
||||
type = phone_mail_type(params[:login].strip)
|
||||
# code = params[:code].strip
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = params[:login]
|
||||
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
||||
# TODO: 暂时限定邮箱注册
|
||||
return normal_status(-1, '只支持邮箱注册')
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = params[:login]
|
||||
phone = nil
|
||||
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
|
||||
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
|
||||
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
||||
end
|
||||
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
||||
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
|
||||
# todo 上线前请删除万能验证码"513231"
|
||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
|
||||
|
||||
code = generate_identifier User, 8, pre
|
||||
login = pre + code
|
||||
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User")
|
||||
@user.password = params[:password]
|
||||
# 现在因为是验证码,所以在注册的时候就可以激活
|
||||
@user.activate
|
||||
# 必须要用save操作,密码的保存是在users中
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
|
||||
@user.gitea_token = result['sha1']
|
||||
@user.gitea_uid = gitea_user[:body]['id']
|
||||
if @user.save!
|
||||
UserExtension.create!(user_id: @user.id)
|
||||
successful_authentication(@user)
|
||||
normal_status("注册成功")
|
||||
end
|
||||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
# 用户登录
|
||||
def login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||
# user is already in local database
|
||||
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
||||
|
||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
||||
|
||||
password_ok = @user.check_password?(params[:password].to_s)
|
||||
unless password_ok
|
||||
if login_control.remain_times-1 == 0
|
||||
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
||||
else
|
||||
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
||||
end
|
||||
login_control.increment!
|
||||
return
|
||||
end
|
||||
|
||||
successful_authentication(@user)
|
||||
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
||||
|
||||
# session[:user_id] = @user.id
|
||||
end
|
||||
|
||||
# 忘记密码
|
||||
def reset_password
|
||||
begin
|
||||
code = params[:code]
|
||||
login_type = phone_mail_type(params[:login].strip)
|
||||
# 获取验证码
|
||||
if login_type == 1
|
||||
phone = params[:login]
|
||||
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last
|
||||
user = User.find_by_phone(phone)
|
||||
else
|
||||
email = params[:login]
|
||||
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
|
||||
user = User.find_by_mail(email) #这里有问题,应该是为email,而不是mail 6.13-hs
|
||||
end
|
||||
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
|
||||
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
|
||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
|
||||
|
||||
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
||||
ActiveRecord::Base.transaction do
|
||||
user.save!
|
||||
LimitForbidControl::UserLogin.new(user).clear
|
||||
end
|
||||
sucess_status
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def successful_authentication(user)
|
||||
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
||||
# Valid user
|
||||
self.logged_user = user
|
||||
# generate a key and set cookie if autologin
|
||||
|
||||
set_autologin_cookie(user)
|
||||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||
user.update_column(:last_login_on, Time.now)
|
||||
session[:"#{default_yun_session}"] = user.id
|
||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||
# 注册完成后有一天的试用申请(先去掉)
|
||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
:path => '/',
|
||||
:secure => false,
|
||||
:httponly => true
|
||||
}
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||
end
|
||||
cookies[autologin_cookie_name] = cookie_options
|
||||
cookies.signed[:user_id] ||= user.id
|
||||
|
||||
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
||||
end
|
||||
|
||||
def logout
|
||||
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
||||
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
||||
logout_user
|
||||
render :json => {status: 1, message: "退出成功!"}
|
||||
end
|
||||
|
||||
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
||||
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
||||
def valid_email_and_phone
|
||||
check_mail_and_phone_valid(params[:login], params[:type])
|
||||
end
|
||||
|
||||
# 发送验证码
|
||||
# params[:login] 手机号或者邮箱号
|
||||
# params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||
def get_verification_code
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
value = params[:login]
|
||||
type = params[:type].strip.to_i
|
||||
login_type = phone_mail_type(value)
|
||||
send_type = verify_type(login_type, type)
|
||||
verification_code = code.sample(6).join
|
||||
|
||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||
|
||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||
|
||||
# 记录验证码
|
||||
check_verification_code(verification_code, send_type, value)
|
||||
sucess_status
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||
# login_type 1:手机类型 2:邮箱类型
|
||||
def verify_type login_type, type
|
||||
case type
|
||||
when 1
|
||||
login_type == 1 ? 1 : 8
|
||||
when 2
|
||||
login_type == 1 ? 2 : 3
|
||||
when 3
|
||||
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
||||
when 4
|
||||
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
||||
when 5
|
||||
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
|
||||
end
|
||||
end
|
||||
|
||||
def generate_login(login)
|
||||
type = phone_mail_type(login.strip)
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = login
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = login
|
||||
phone = nil
|
||||
end
|
||||
code = generate_identifier User, 8, pre
|
||||
|
||||
{ login: pre + code, email: email, phone: phone }
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
||||
end
|
||||
class AccountsController < ApplicationController
|
||||
|
||||
#skip_before_action :check_account, :only => [:logout]
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
||||
# 其他平台同步注册的用户
|
||||
def remote_register
|
||||
username = params[:username]&.gsub(/\s+/, "")
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
phone = params[:phone]&.gsub(/\s+/, "")
|
||||
password = params[:password]
|
||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
return render_error("该手机号已注册") if phone.present? && User.where(phone: phone).exists?
|
||||
result = autologin_register(username, email, password, platform, phone)
|
||||
if result[:message].blank?
|
||||
PlatformStatistic.data.increment!(:users_count)
|
||||
render_ok({user: result[:user]})
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台修改用户的信息,这边同步修改
|
||||
def remote_update
|
||||
ActiveRecord::Base.transaction do
|
||||
user_params = params[:user_params]
|
||||
user_extension_params = params[:user_extension_params]
|
||||
|
||||
u = User.find_by(login: params[:old_user_login])
|
||||
user_mail = u.try(:mail)
|
||||
|
||||
if u.present?
|
||||
ue = u.user_extension
|
||||
u.login = user_params["login"] if user_params["login"]
|
||||
u.mail = user_params["mail"] if user_params["mail"]
|
||||
u.lastname = user_params["lastname"] if user_params["lastname"]
|
||||
|
||||
ue.gender = user_extension_params["gender"]
|
||||
ue.school_id = user_extension_params["school_id"]
|
||||
ue.location = user_extension_params["location"]
|
||||
ue.location_city = user_extension_params["location_city"]
|
||||
ue.identity = user_extension_params["identity"]
|
||||
ue.technical_title = user_extension_params["technical_title"]
|
||||
ue.student_id = user_extension_params["student_id"]
|
||||
ue.description = user_extension_params["description"]
|
||||
ue.save!
|
||||
u.save!
|
||||
|
||||
sync_params = {}
|
||||
|
||||
if (user_params["mail"] && user_params["mail"] != user_mail)
|
||||
sync_params = sync_params.merge(email: user_params["mail"])
|
||||
end
|
||||
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(u.login, sync_params)
|
||||
if interactor.success?
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台同步登录
|
||||
def remote_login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
if @user
|
||||
successful_authentication(@user)
|
||||
render_ok({user: {id: @user.id, token: @user.gitea_token}})
|
||||
else
|
||||
render_error("用户不存在")
|
||||
end
|
||||
end
|
||||
|
||||
#修改密码
|
||||
def remote_password
|
||||
@user = User.find_by(login: params[:login])
|
||||
return render_error("未找到相关用户!") if @user.blank?
|
||||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
if interactor.success?
|
||||
@user.update_attribute(:password, params[:password])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 用户注册
|
||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||
# params[:login] 邮箱或者手机号
|
||||
# params[:code] 验证码
|
||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||
# 本地forge注册入口
|
||||
def register
|
||||
begin
|
||||
# 查询验证码是否正确;type只可能是1或者8
|
||||
type = phone_mail_type(params[:login].strip)
|
||||
# code = params[:code].strip
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = params[:login]
|
||||
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
||||
# TODO: 暂时限定邮箱注册
|
||||
return normal_status(-1, '只支持邮箱注册')
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = params[:login]
|
||||
phone = nil
|
||||
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
|
||||
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
|
||||
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
||||
end
|
||||
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
||||
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
|
||||
# todo 上线前请删除万能验证码"513231"
|
||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
|
||||
|
||||
code = generate_identifier User, 8, pre
|
||||
login = pre + code
|
||||
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User")
|
||||
@user.password = params[:password]
|
||||
# 现在因为是验证码,所以在注册的时候就可以激活
|
||||
@user.activate
|
||||
# 必须要用save操作,密码的保存是在users中
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
|
||||
@user.gitea_token = result['sha1']
|
||||
@user.gitea_uid = gitea_user[:body]['id']
|
||||
if @user.save!
|
||||
UserExtension.create!(user_id: @user.id)
|
||||
successful_authentication(@user)
|
||||
normal_status("注册成功")
|
||||
end
|
||||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
# 用户登录
|
||||
def login
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||
# user is already in local database
|
||||
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
|
||||
|
||||
login_control = LimitForbidControl::UserLogin.new(@user)
|
||||
return normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码") if login_control.forbid?
|
||||
|
||||
password_ok = @user.check_password?(params[:password].to_s)
|
||||
unless password_ok
|
||||
if login_control.remain_times-1 == 0
|
||||
normal_status(-2, "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码")
|
||||
else
|
||||
normal_status(-2, "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会")
|
||||
end
|
||||
login_control.increment!
|
||||
return
|
||||
end
|
||||
|
||||
successful_authentication(@user)
|
||||
sync_pwd_to_gitea!(@user, {password: params[:password].to_s}) # TODO用户密码未同步
|
||||
|
||||
# session[:user_id] = @user.id
|
||||
end
|
||||
|
||||
# 忘记密码
|
||||
def reset_password
|
||||
begin
|
||||
code = params[:code]
|
||||
login_type = phone_mail_type(params[:login].strip)
|
||||
# 获取验证码
|
||||
if login_type == 1
|
||||
phone = params[:login]
|
||||
verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 2).last
|
||||
user = User.find_by_phone(phone)
|
||||
else
|
||||
email = params[:login]
|
||||
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
|
||||
user = User.find_by_mail(email) #这里有问题,应该是为email,而不是mail 6.13-hs
|
||||
end
|
||||
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
|
||||
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
|
||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:new_password] =~ CustomRegexp::PASSWORD
|
||||
|
||||
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
||||
ActiveRecord::Base.transaction do
|
||||
user.save!
|
||||
LimitForbidControl::UserLogin.new(user).clear
|
||||
end
|
||||
sucess_status
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def successful_authentication(user)
|
||||
uid_logger("Successful authentication start: '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}")
|
||||
# Valid user
|
||||
self.logged_user = user
|
||||
# generate a key and set cookie if autologin
|
||||
|
||||
set_autologin_cookie(user)
|
||||
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
|
||||
user.update_column(:last_login_on, Time.now)
|
||||
session[:"#{default_yun_session}"] = user.id
|
||||
Rails.logger.info("#########_____session_default_yun_session__________###############{default_yun_session}")
|
||||
# 注册完成后有一天的试用申请(先去掉)
|
||||
# UserDayCertification.create(user_id: user.id, status: 1)
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, autologin_action)
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
:path => '/',
|
||||
:secure => false,
|
||||
:httponly => true
|
||||
}
|
||||
if edu_setting('cookie_domain').present?
|
||||
cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain'))
|
||||
end
|
||||
cookies[autologin_cookie_name] = cookie_options
|
||||
cookies.signed[:user_id] ||= user.id
|
||||
|
||||
logger.info("cookies is #{cookies} ======> #{cookies.signed[:user_id]} =====> #{cookies[autologin_cookie_name]}")
|
||||
end
|
||||
|
||||
def logout
|
||||
Rails.logger.info("########___logout_current_user____________########{current_user.try(:id)}")
|
||||
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
|
||||
logout_user
|
||||
render :json => {status: 1, message: "退出成功!"}
|
||||
end
|
||||
|
||||
# 检验邮箱是否已被注册及邮箱或者手机号是否合法
|
||||
# 参数type为事件类型 1:注册;2:忘记密码;3:绑定
|
||||
def valid_email_and_phone
|
||||
check_mail_and_phone_valid(params[:login], params[:type])
|
||||
end
|
||||
|
||||
# 发送验证码
|
||||
# params[:login] 手机号或者邮箱号
|
||||
# params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||
def get_verification_code
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
value = params[:login]
|
||||
type = params[:type].strip.to_i
|
||||
login_type = phone_mail_type(value)
|
||||
send_type = verify_type(login_type, type)
|
||||
verification_code = code.sample(6).join
|
||||
|
||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||
|
||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||
|
||||
# 记录验证码
|
||||
check_verification_code(verification_code, send_type, value)
|
||||
sucess_status
|
||||
end
|
||||
|
||||
# 1 手机类型;0 邮箱类型
|
||||
# 注意新版的login是自动名生成的
|
||||
def phone_mail_type value
|
||||
value =~ /^1\d{10}$/ ? 1 : 0
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||
# login_type 1:手机类型 2:邮箱类型
|
||||
def verify_type login_type, type
|
||||
case type
|
||||
when 1
|
||||
login_type == 1 ? 1 : 8
|
||||
when 2
|
||||
login_type == 1 ? 2 : 3
|
||||
when 3
|
||||
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
|
||||
when 4
|
||||
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
|
||||
when 5
|
||||
login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
|
||||
end
|
||||
end
|
||||
|
||||
def generate_login(login)
|
||||
type = phone_mail_type(login.strip)
|
||||
|
||||
if type == 1
|
||||
uid_logger("start register by phone: type is #{type}")
|
||||
pre = 'p'
|
||||
email = nil
|
||||
phone = login
|
||||
else
|
||||
uid_logger("start register by email: type is #{type}")
|
||||
pre = 'm'
|
||||
email = login
|
||||
phone = nil
|
||||
end
|
||||
code = generate_identifier User, 8, pre
|
||||
|
||||
{ login: pre + code, email: email, phone: phone }
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
class Admins::ApplySignaturesController < Admins::BaseController
|
||||
|
||||
def index
|
||||
sort_by = params[:sort_by] ||= 'created_on'
|
||||
sort_direction = params[:sort_direction] ||= 'desc'
|
||||
|
||||
@apply_signatures = paginate ApplySignature.waiting.includes(:attachments)
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
apply_signature = ApplySignature.find_by!(id: params[:id])
|
||||
apply_signature.update_attributes!(apply_signatures_params)
|
||||
if apply_signature.status == "passed"
|
||||
Projects::AddMemberInteractor.call(apply_signature.project.owner, apply_signature.project, apply_signature.user, "read", true)
|
||||
end
|
||||
redirect_to admins_apply_signatures_path
|
||||
flash[:success] = "更新成功"
|
||||
rescue => e
|
||||
raise ActiveRecord::Rollback
|
||||
redirect_to admins_apply_signatures_path
|
||||
flash[:danger] = "更新失败"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def apply_signatures_params
|
||||
params.permit(:status)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
class Admins::PhengleiUsersController < Admins::BaseController
|
||||
before_action :phenglei_project, only: [:index]
|
||||
|
||||
def index
|
||||
if params[:keyword].present?
|
||||
@phenglei_users = PhengleiUser.ransack(phone_cont: params[:keyword]).result
|
||||
else
|
||||
@phenglei_users = PhengleiUser
|
||||
end
|
||||
@phenglei_users = @phenglei_users.page(page).per(per_page)
|
||||
end
|
||||
|
||||
def new
|
||||
@phenglei_user = PhengleiUser.new
|
||||
end
|
||||
|
||||
def create
|
||||
@phenglei_user = PhengleiUser.new(phenglei_user_params)
|
||||
if @phenglei_user.save
|
||||
redirect_to admins_phenglei_users_path
|
||||
flash[:success] = "创建成功"
|
||||
else
|
||||
redirect_to admins_phenglei_users_path
|
||||
flash[:error] = "创建失败"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def phenglei_project
|
||||
@phenglei_project = Project.find_by_id(EduSetting.get("sync_phenglei_user_project"))
|
||||
end
|
||||
|
||||
def phenglei_user_params
|
||||
params.require(:phenglei_user).permit(:phone)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
class Admins::PlatformCommunicatesController < Admins::BaseController
|
||||
before_action :get_communicate, only: [:edit, :update, :destroy]
|
||||
def index
|
||||
sort_by = PlatformCommunicate.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'order_index'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
q = PlatformCommunicate.ransack(title_cont: params[:search])
|
||||
communicates = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
|
||||
@communicates = kaminari_paginate(communicates)
|
||||
end
|
||||
|
||||
def new
|
||||
@communicate = PlatformCommunicate.new
|
||||
end
|
||||
|
||||
def create
|
||||
@communicate = PlatformCommunicate.new(communicate_params)
|
||||
if @communicate.save
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:success] = '创建社区动态成功'
|
||||
else
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:danger] = "创建社区动态失败"
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
|
||||
end
|
||||
|
||||
def update
|
||||
@communicate.attributes = communicate_params
|
||||
if @communicate.save
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:success] = '更新社区动态成功'
|
||||
else
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:danger] = '更新社区动态失败'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @communicate.destroy
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:success] = '删除社区动态成功'
|
||||
else
|
||||
redirect_to admins_platform_communicates_path
|
||||
flash[:danger] = '删除社区动态失败'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def get_communicate
|
||||
@communicate = PlatformCommunicate.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def communicate_params
|
||||
params.require(:platform_communicate).permit!
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
class Admins::PlatformPeopleController < Admins::BaseController
|
||||
before_action :get_person, only: [:edit, :update, :destroy]
|
||||
def index
|
||||
sort_by = PlatformPerson.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
q = PlatformPerson.ransack(name_cont: params[:search])
|
||||
people = q.result(distinct: true).order("#{sort_by} #{sort_direction}")
|
||||
@people = kaminari_paginate(people)
|
||||
end
|
||||
|
||||
def new
|
||||
@person = PlatformPerson.new
|
||||
end
|
||||
|
||||
def create
|
||||
@person = PlatformPerson.new(person_params)
|
||||
if @person.save
|
||||
save_image_file(params[:image], @person)
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:success] = '创建论坛动态成功'
|
||||
else
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:danger] = "创建论坛动态失败"
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
|
||||
end
|
||||
|
||||
def update
|
||||
@person.attributes = person_params
|
||||
if @person.save
|
||||
save_image_file(params[:image], @person)
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:success] = '更新论坛动态成功'
|
||||
else
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:danger] = '更新论坛动态失败'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @person.destroy
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:success] = '删除论坛动态成功'
|
||||
else
|
||||
redirect_to admins_platform_people_path
|
||||
flash[:danger] = '删除论坛动态失败'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def get_person
|
||||
@person = PlatformPerson.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def person_params
|
||||
params.require(:platform_person).permit!
|
||||
end
|
||||
|
||||
def save_image_file(file, topic)
|
||||
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
|
||||
|
||||
file_path = Util::FileManage.source_disk_filename(topic, 'image')
|
||||
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
|
||||
Util.write_file(file, file_path)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
class Admins::ProjectsController < Admins::BaseController
|
||||
before_action :load_project, only: [:sync_phenglei_user]
|
||||
|
||||
def index
|
||||
sort_by = params[:sort_by] ||= 'created_on'
|
||||
|
|
@ -6,7 +7,7 @@ class Admins::ProjectsController < Admins::BaseController
|
|||
|
||||
search = params[:search].to_s.strip
|
||||
projects = Project.where("name like ?", "%#{search}%").order("#{sort_by} #{sort_direction}")
|
||||
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score)
|
||||
@projects = paginate projects.includes(:owner, :members, :issues, :versions, :attachments, :project_score, :license)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
@ -22,4 +23,20 @@ class Admins::ProjectsController < Admins::BaseController
|
|||
redirect_to admins_projects_path
|
||||
flash[:danger] = "删除失败"
|
||||
end
|
||||
|
||||
def sync_phenglei_user
|
||||
if @project.is_secret
|
||||
SyncPhengleiUserJob.perform_later(@project.id)
|
||||
redirect_to admins_phenglei_users_path
|
||||
flash[:success] = "已开启后台同步任务"
|
||||
else
|
||||
redirect_to admins_phenglei_users_path
|
||||
flash[:danger] = "非风雷协议项目"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_project
|
||||
@project = Project.find_by!(id: params[:id])
|
||||
end
|
||||
end
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
class Admins::UsersController < Admins::BaseController
|
||||
before_action :finder_user, except: [:index]
|
||||
|
||||
def index
|
||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||
|
|
@ -8,12 +10,9 @@ class Admins::UsersController < Admins::BaseController
|
|||
end
|
||||
|
||||
def edit
|
||||
@user = User.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find(params[:id])
|
||||
|
||||
Admins::UpdateUserService.call(@user, update_params)
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_user_path(@user)
|
||||
|
|
@ -26,43 +25,94 @@ class Admins::UsersController < Admins::BaseController
|
|||
end
|
||||
|
||||
def destroy
|
||||
User.find(params[:id]).destroy!
|
||||
@user.destroy!
|
||||
Gitea::User::DeleteService.call(@user.login)
|
||||
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
def lock
|
||||
User.find(params[:id]).lock!
|
||||
@user.lock!
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def unlock
|
||||
User.find(params[:id]).activate!
|
||||
@user.activate!
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def reward_grade
|
||||
user = User.find(params[:user_id])
|
||||
return render_unprocessable_entity('金币数量必须大于0') if params[:grade].to_i <= 0
|
||||
|
||||
RewardGradeService.call(user, container_id: user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
||||
RewardGradeService.call(@user, container_id: @user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
||||
|
||||
render_ok(grade: user.grade)
|
||||
render_ok(grade: @user.grade)
|
||||
end
|
||||
|
||||
def reset_login_times
|
||||
User.find(params[:id]).reset_login_times!
|
||||
@user.reset_login_times!
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def new
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
def create
|
||||
Users::AdminCreateUserForm.new(validate_create_params).validate!
|
||||
|
||||
user = User.new(create_params)
|
||||
login = User.generate_login("p")
|
||||
|
||||
user.type = 'User'
|
||||
user.login = login
|
||||
user.mail = "#{login}@example.org"
|
||||
ActiveRecord::Base.transaction do
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: create_params[:password]})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(user.login, create_params[:password])
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
user.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to admins_users_path
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
logger.info "------------ #{e.message}"
|
||||
puts e.message
|
||||
flash.now[:danger] = e.message
|
||||
render 'new'
|
||||
rescue Exception => ex
|
||||
flash.now[:danger] = ex.message
|
||||
render 'new'
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def finder_user
|
||||
@user = User.find(params[:id])
|
||||
end
|
||||
|
||||
def update_params
|
||||
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
|
||||
mail phone location location_city school_id department_id admin business is_test
|
||||
password professional_certification authentication])
|
||||
password professional_certification authentication login])
|
||||
end
|
||||
|
||||
def create_params
|
||||
params.require(:user).permit(%i[nickname gender mail phone location location_city password professional_certification])
|
||||
end
|
||||
|
||||
def validate_create_params
|
||||
create_params.slice(:phone, :password)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class ApplicationController < ActionController::Base
|
|||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
|
||||
|
||||
helper_method :current_user
|
||||
helper_method :current_user, :base_url
|
||||
|
||||
# 所有请求必须合法签名
|
||||
def check_sign
|
||||
|
|
@ -330,21 +330,21 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
# if !User.current.logged? && Rails.env.development?
|
||||
# User.current = User.find 1
|
||||
# end
|
||||
if !User.current.logged? && Rails.env.development?
|
||||
User.current = User.find 1
|
||||
end
|
||||
|
||||
|
||||
# 测试版前端需求
|
||||
logger.info("subdomain:#{request.subdomain}")
|
||||
if request.subdomain != "www"
|
||||
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
User.current = User.find 81403
|
||||
User.current = User.find 6
|
||||
elsif params[:debug] == 'student'
|
||||
User.current = User.find 8686
|
||||
User.current = User.find 7
|
||||
elsif params[:debug] == 'admin'
|
||||
logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
user = User.find 36480
|
||||
user = User.find 1
|
||||
User.current = user
|
||||
cookies.signed[:user_id] = user.id
|
||||
end
|
||||
|
|
@ -374,7 +374,7 @@ class ApplicationController < ActionController::Base
|
|||
# auto-login feature starts a new session
|
||||
user = nil
|
||||
Rails.logger.info("111111111111111111#{default_yun_session}, session is #{session[:"#{default_yun_session}"]} ")
|
||||
user = User.try_to_autologin(cookies[autologin_cookie_name])
|
||||
user = User.try_to_autologin(cookies[autologin_cookie_name], autologin_action)
|
||||
# start_user_session(user) if user # TODO 解决sso退出不同步的问题
|
||||
user
|
||||
end
|
||||
|
|
@ -770,6 +770,10 @@ class ApplicationController < ActionController::Base
|
|||
@repository ||= load_project&.repository
|
||||
end
|
||||
|
||||
def base_url
|
||||
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
||||
end
|
||||
|
||||
private
|
||||
def object_not_found
|
||||
uid_logger("Missing template or cant't find record, responding with 404")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
class ApplySignaturesController < ApplicationController
|
||||
include ApplicationHelper
|
||||
before_action :find_project, only: [:index, :create, :update]
|
||||
before_action :require_owner, only: [:update]
|
||||
before_action :find_apply_signature, only: [:update]
|
||||
|
||||
def index
|
||||
search = params[:search].to_s.downcase
|
||||
@apply_signatures = @project.apply_signatures.with_status(status).includes(user: :user_extension)
|
||||
@apply_signatures = @apply_signatures.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
|
||||
@apply_signatures = kaminari_paginate(@apply_signatures)
|
||||
end
|
||||
|
||||
def template_file
|
||||
license = License.find_by_name("PHengLEI")
|
||||
file = license.attachments.take
|
||||
normal_status(-1, "文件不存在") if file.blank?
|
||||
send_file(absolute_path(local_path(file)), filename: file.title,stream:false, type: file.content_type.presence || 'application/octet-stream')
|
||||
end
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
@signature = current_user.apply_signatures.find_or_create_by!(project_id: params[:project_id])
|
||||
@signature.status = 0
|
||||
@signature.attachments = Attachment.none
|
||||
@attachment = Attachment.find_by_id(params[:attachment_id])
|
||||
@attachment.container = @signature
|
||||
@signature.save!
|
||||
@attachment.save!
|
||||
rescue Exception => e
|
||||
tip_exception("#{e}")
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
render_json
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@apply_signature.update_attributes!(apply_signature_params)
|
||||
if @apply_signature.status == "passed"
|
||||
Projects::AddMemberInteractor.call(@apply_signature.project.owner, @apply_signature.project, @apply_signature.user, "read", true)
|
||||
else
|
||||
Projects::DeleteMemberInteractor.call(@apply_signature.project.owner, @apply_signature.project, @apply_signature.user)
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def find_project
|
||||
@project = Project.find_by_id(params[:project_id])
|
||||
normal_status(-1, "项目不存在") unless @project.present?
|
||||
end
|
||||
|
||||
def find_apply_signature
|
||||
@apply_signature = ApplySignature.find_by_id(params[:id])
|
||||
normal_status(-1, "特殊许可申请不存在") unless @apply_signature.present?
|
||||
normal_status(1, "已经是该状态了") if @apply_signature.status == params[:status]
|
||||
end
|
||||
|
||||
def apply_signature_params
|
||||
params.permit(:status)
|
||||
end
|
||||
|
||||
def status
|
||||
params.fetch(:status, "all")
|
||||
end
|
||||
|
||||
def require_owner
|
||||
normal_status(403, "") unless @project.owner?(current_user)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,252 +1,261 @@
|
|||
#coding=utf-8
|
||||
#
|
||||
# 文件上传
|
||||
class AttachmentsController < ApplicationController
|
||||
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
||||
before_action :find_file, only: %i[show destroy]
|
||||
before_action :attachment_candown, only: [:show]
|
||||
skip_before_action :check_sign, only: [:show, :create]
|
||||
|
||||
include ApplicationHelper
|
||||
|
||||
def show
|
||||
# 1. 优先跳到cdn
|
||||
# 2. 如果没有cdn,send_file
|
||||
if @file.cloud_url.present?
|
||||
update_downloads(@file)
|
||||
redirect_to @file.cloud_url and return
|
||||
end
|
||||
|
||||
type_attachment = params[:disposition] || "attachment"
|
||||
if type_attachment == "inline"
|
||||
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
||||
elsif type_attachment == "MP4"
|
||||
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
||||
else
|
||||
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
||||
end
|
||||
update_downloads(@file)
|
||||
end
|
||||
|
||||
|
||||
def get_file
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||
response = Faraday.get(url)
|
||||
filename = params[:download_url].to_s.split("/").pop()
|
||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||
end
|
||||
|
||||
def create
|
||||
# 1. 本地存储
|
||||
# 2. 上传到云
|
||||
begin
|
||||
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
||||
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
||||
raise "未上传文件" unless upload_file
|
||||
|
||||
folder = file_storage_directory
|
||||
raise "存储目录未定义" unless folder.present?
|
||||
|
||||
month_folder = current_month_folder
|
||||
save_path = File.join(folder, month_folder)
|
||||
|
||||
ext = file_ext(upload_file.original_filename)
|
||||
|
||||
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
||||
|
||||
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
||||
|
||||
# remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
|
||||
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
||||
|
||||
logger.info "local_path: #{local_path}"
|
||||
logger.info "remote_path: #{remote_path}"
|
||||
|
||||
|
||||
disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||
#存数据库
|
||||
#
|
||||
@attachment = Attachment.where(disk_filename: disk_filename,
|
||||
author_id: current_user.id,
|
||||
cloud_url: remote_path).first
|
||||
if @attachment.blank?
|
||||
@attachment = Attachment.new
|
||||
@attachment.filename = upload_file.original_filename
|
||||
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||
@attachment.filesize = upload_file.tempfile.size
|
||||
@attachment.content_type = content_type
|
||||
@attachment.digest = digest
|
||||
@attachment.author_id = current_user.id
|
||||
@attachment.disk_directory = month_folder
|
||||
@attachment.cloud_url = remote_path
|
||||
@attachment.save!
|
||||
else
|
||||
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
||||
end
|
||||
|
||||
render_json
|
||||
rescue => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
@file_path = absolute_path(local_path(@file))
|
||||
#return normal_status(403, "") unless @file.author == current_user
|
||||
@file.destroy!
|
||||
|
||||
delete_file(@file_path)
|
||||
normal_status("删除成功")
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
# 附件为视频时,点击播放
|
||||
def preview_attachment
|
||||
attachment = Attachment.find_by(id: params[:id])
|
||||
dir_path = "#{Rails.root}/public/preview"
|
||||
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
||||
if params[:status] == "preview"
|
||||
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
||||
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
else
|
||||
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
||||
normal_status(1, "操作成功")
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_file
|
||||
@file =
|
||||
if params[:type] == 'history'
|
||||
AttachmentHistory.find params[:id]
|
||||
else
|
||||
Attachment.find params[:id]
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file(file_path)
|
||||
File.delete(file_path) if File.exist?(file_path)
|
||||
end
|
||||
|
||||
def current_month_folder
|
||||
date = Time.now
|
||||
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
||||
end
|
||||
|
||||
def file_ext(file_name)
|
||||
ext = ''
|
||||
exts = file_name.split(".")
|
||||
if exts.size > 1
|
||||
ext = ".#{exts.last}"
|
||||
end
|
||||
ext
|
||||
end
|
||||
|
||||
def file_save_to_local(save_path, temp_file, ext)
|
||||
unless Dir.exists?(save_path)
|
||||
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
||||
end
|
||||
|
||||
digest = md5_file(temp_file)
|
||||
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
||||
local_file_path = File.join(save_path, digest) + ext
|
||||
save_temp_file(temp_file, local_file_path)
|
||||
|
||||
[local_file_path, digest]
|
||||
end
|
||||
|
||||
def save_temp_file(temp_file, save_file_path)
|
||||
File.open(save_file_path, 'wb') do |f|
|
||||
temp_file.rewind
|
||||
while (buffer = temp_file.read(8192))
|
||||
f.write(buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def md5_file(temp_file)
|
||||
md5 = Digest::MD5.new
|
||||
temp_file.rewind
|
||||
while (buffer = temp_file.read(8192))
|
||||
md5.update(buffer)
|
||||
end
|
||||
md5.hexdigest
|
||||
end
|
||||
|
||||
def file_save_to_ucloud(path, file, content_type)
|
||||
ufile = Educoder::Ufile.new(
|
||||
ucloud_public_key: edu_setting('public_key'),
|
||||
ucloud_private_key: edu_setting('private_key'),
|
||||
ucloud_public_read: true,
|
||||
ucloud_public_bucket: edu_setting('public_bucket'),
|
||||
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
||||
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
||||
)
|
||||
File.open(file) do |f|
|
||||
ufile.put(path, f, 'Content-Type' => content_type)
|
||||
end
|
||||
edu_setting('public_cdn_host') + "/" + path
|
||||
end
|
||||
|
||||
def attachment_candown
|
||||
unless current_user.admin? || current_user.business?
|
||||
candown = true
|
||||
unless params[:type] == 'history'
|
||||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user)
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user)
|
||||
else
|
||||
course = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_file_with_range(path, options = {})
|
||||
logger.info("########request.headers: #{request.headers}")
|
||||
logger.info("########request.headers: #{File.exist?(path)}")
|
||||
|
||||
if File.exist?(path)
|
||||
size = File.size(path)
|
||||
logger.info("########request.headers: #{request.headers}")
|
||||
if !request.headers["Range"]
|
||||
status_code = 200 # 200 OK
|
||||
offset = 0
|
||||
length = File.size(path)
|
||||
else
|
||||
status_code = 206 # 206 Partial Content
|
||||
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
||||
offset = bytes.begin
|
||||
length = bytes.end - bytes.begin
|
||||
end
|
||||
response.header["Accept-Ranges"] = "bytes"
|
||||
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
||||
response.header["status"] = status_code
|
||||
|
||||
send_data IO.binread(path, length, offset), options
|
||||
else
|
||||
raise ActionController::MissingFile, "Cannot read file #{path}."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
#coding=utf-8
|
||||
#
|
||||
# 文件上传
|
||||
class AttachmentsController < ApplicationController
|
||||
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
||||
before_action :find_file, only: %i[show destroy]
|
||||
before_action :attachment_candown, only: [:show]
|
||||
skip_before_action :check_sign, only: [:show, :create]
|
||||
|
||||
include ApplicationHelper
|
||||
|
||||
def show
|
||||
# 1. 优先跳到cdn
|
||||
# 2. 如果没有cdn,send_file
|
||||
if @file.cloud_url.present?
|
||||
update_downloads(@file)
|
||||
redirect_to @file.cloud_url and return
|
||||
end
|
||||
|
||||
type_attachment = params[:disposition] || "attachment"
|
||||
if type_attachment == "inline"
|
||||
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
||||
elsif type_attachment == "MP4"
|
||||
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
||||
else
|
||||
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
||||
end
|
||||
update_downloads(@file)
|
||||
end
|
||||
|
||||
|
||||
def get_file
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||
response = Faraday.get(url)
|
||||
filename = params[:download_url].to_s.split("/").pop()
|
||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||
end
|
||||
|
||||
def create
|
||||
# 1. 本地存储
|
||||
# 2. 上传到云
|
||||
begin
|
||||
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
||||
dun_check_file = upload_file.dup
|
||||
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
||||
raise "未上传文件" unless upload_file
|
||||
|
||||
folder = file_storage_directory
|
||||
raise "存储目录未定义" unless folder.present?
|
||||
|
||||
month_folder = current_month_folder
|
||||
save_path = File.join(folder, month_folder)
|
||||
|
||||
ext = file_ext(upload_file.original_filename)
|
||||
|
||||
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
||||
|
||||
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
||||
|
||||
# remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
|
||||
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
||||
|
||||
logger.info "local_path: #{local_path}"
|
||||
logger.info "remote_path: #{remote_path}"
|
||||
|
||||
|
||||
disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||
#存数据库
|
||||
#
|
||||
@attachment = Attachment.where(disk_filename: disk_filename,
|
||||
author_id: current_user.id,
|
||||
cloud_url: remote_path).first
|
||||
if @attachment.blank?
|
||||
@attachment = Attachment.new
|
||||
@attachment.filename = upload_file.original_filename
|
||||
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||
@attachment.filesize = upload_file.tempfile.size
|
||||
@attachment.content_type = content_type
|
||||
@attachment.digest = digest
|
||||
@attachment.author_id = current_user.id
|
||||
@attachment.disk_directory = month_folder
|
||||
@attachment.cloud_url = remote_path
|
||||
@attachment.save!
|
||||
# if @attachment.save!
|
||||
# check_result = Attachment.check_image_able(dun_check_file)
|
||||
# if check_result[:status].to_i == -1
|
||||
# @attachment.destroy
|
||||
# raise "上传失败,#{check_result[:message]}"
|
||||
# # return render json: {status: -1, message: "上传失败,#{check_result[:message]}" }
|
||||
# end
|
||||
# end
|
||||
else
|
||||
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
||||
end
|
||||
|
||||
render_json
|
||||
rescue => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
@file_path = absolute_path(local_path(@file))
|
||||
#return normal_status(403, "") unless @file.author == current_user
|
||||
@file.destroy!
|
||||
|
||||
delete_file(@file_path)
|
||||
normal_status("删除成功")
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
# 附件为视频时,点击播放
|
||||
def preview_attachment
|
||||
attachment = Attachment.find_by(id: params[:id])
|
||||
dir_path = "#{Rails.root}/public/preview"
|
||||
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
||||
if params[:status] == "preview"
|
||||
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
||||
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
else
|
||||
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
||||
normal_status(1, "操作成功")
|
||||
else
|
||||
normal_status(-1, "出现错误,请稍后重试")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_file
|
||||
@file =
|
||||
if params[:type] == 'history'
|
||||
AttachmentHistory.find params[:id]
|
||||
else
|
||||
Attachment.find params[:id]
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file(file_path)
|
||||
File.delete(file_path) if File.exist?(file_path)
|
||||
end
|
||||
|
||||
def current_month_folder
|
||||
date = Time.now
|
||||
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
||||
end
|
||||
|
||||
def file_ext(file_name)
|
||||
ext = ''
|
||||
exts = file_name.split(".")
|
||||
if exts.size > 1
|
||||
ext = ".#{exts.last}"
|
||||
end
|
||||
ext
|
||||
end
|
||||
|
||||
def file_save_to_local(save_path, temp_file, ext)
|
||||
unless Dir.exists?(save_path)
|
||||
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
||||
end
|
||||
|
||||
digest = md5_file(temp_file)
|
||||
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
||||
local_file_path = File.join(save_path, digest) + ext
|
||||
save_temp_file(temp_file, local_file_path)
|
||||
|
||||
[local_file_path, digest]
|
||||
end
|
||||
|
||||
def save_temp_file(temp_file, save_file_path)
|
||||
File.open(save_file_path, 'wb') do |f|
|
||||
temp_file.rewind
|
||||
while (buffer = temp_file.read(8192))
|
||||
f.write(buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def md5_file(temp_file)
|
||||
md5 = Digest::MD5.new
|
||||
temp_file.rewind
|
||||
while (buffer = temp_file.read(8192))
|
||||
md5.update(buffer)
|
||||
end
|
||||
md5.hexdigest
|
||||
end
|
||||
|
||||
def file_save_to_ucloud(path, file, content_type)
|
||||
ufile = Educoder::Ufile.new(
|
||||
ucloud_public_key: edu_setting('public_key'),
|
||||
ucloud_private_key: edu_setting('private_key'),
|
||||
ucloud_public_read: true,
|
||||
ucloud_public_bucket: edu_setting('public_bucket'),
|
||||
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
||||
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
||||
)
|
||||
File.open(file) do |f|
|
||||
ufile.put(path, f, 'Content-Type' => content_type)
|
||||
end
|
||||
edu_setting('public_cdn_host') + "/" + path
|
||||
end
|
||||
|
||||
def attachment_candown
|
||||
unless current_user.admin? || current_user.business?
|
||||
candown = true
|
||||
unless params[:type] == 'history'
|
||||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user)
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user)
|
||||
else
|
||||
course = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_file_with_range(path, options = {})
|
||||
logger.info("########request.headers: #{request.headers}")
|
||||
logger.info("########request.headers: #{File.exist?(path)}")
|
||||
|
||||
if File.exist?(path)
|
||||
size = File.size(path)
|
||||
logger.info("########request.headers: #{request.headers}")
|
||||
if !request.headers["Range"]
|
||||
status_code = 200 # 200 OK
|
||||
offset = 0
|
||||
length = File.size(path)
|
||||
else
|
||||
status_code = 206 # 206 Partial Content
|
||||
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
||||
offset = bytes.begin
|
||||
length = bytes.end - bytes.begin
|
||||
end
|
||||
response.header["Accept-Ranges"] = "bytes"
|
||||
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
||||
response.header["status"] = status_code
|
||||
|
||||
send_data IO.binread(path, length, offset), options
|
||||
else
|
||||
raise ActionController::MissingFile, "Cannot read file #{path}."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
class CompetitionInfosController < ApplicationController
|
||||
include ApplicationHelper
|
||||
before_action :find_competition, only: [:show, :update, :enroll, :upload, :enroll_status, :statistics, :enroll_list]
|
||||
before_action :require_admin, only: [:index, :new, :edit, :create]
|
||||
before_action :check_competition_manager, only: [:update]
|
||||
|
||||
def index
|
||||
@competition_infos = CompetitionInfo.all
|
||||
end
|
||||
|
||||
# GET /competition_infos/new
|
||||
def new
|
||||
@competition_info = CompetitionInfo.new
|
||||
end
|
||||
|
||||
# GET /competition_infos/1/edit
|
||||
def edit
|
||||
@competition_info = CompetitionInfo.find params[:id]
|
||||
end
|
||||
|
||||
# POST /competition_infos.json
|
||||
def create
|
||||
@competition_info = CompetitionInfo.new(competition_info_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @competition_info.save
|
||||
format.html { redirect_to competition_infos_path, notice: '创建成功.' }
|
||||
format.json { render :show, status: :created, location: @competition_info }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @competition_info.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /competition_infos/1.json
|
||||
def update
|
||||
# @competition_info = CompetitionInfo.find params[:id]
|
||||
respond_to do |format|
|
||||
if @competition_info.update(competition_info_params)
|
||||
format.html { redirect_to competition_infos_path, notice: '更新成功.' }
|
||||
format.json { render :show, status: :ok, location: @competition_info }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @competition_info.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def enroll_list
|
||||
competition_users = CompetitionUser.where(competition_info: @competition_info.id).order("updated_at desc")
|
||||
zones = @competition_info.manager_zones(current_user)
|
||||
if params[:zone].present?
|
||||
competition_users = zones.include?(params[:zone].to_s) ? competition_users.where(zone: params[:zone].to_s) : competition_users.where(zone: [])
|
||||
else
|
||||
competition_users = current_user.admin? ? competition_users : competition_users.where(zone: zones)
|
||||
end
|
||||
if params[:sub_competition].present?
|
||||
competition_users = competition_users.where(sub_competition: params[:sub_competition].to_s)
|
||||
end
|
||||
if params[:upload].to_s == "true"
|
||||
competition_users = competition_users.joins("join attachments on attachments.container_type='CompetitionUser' and attachments.container_id = competition_users.id")
|
||||
end
|
||||
@competition_users_count = competition_users.count
|
||||
competition_users = competition_users.select("DISTINCT competition_users.*")
|
||||
@competition_users = paginate(competition_users)
|
||||
respond_to do |format|
|
||||
format.json
|
||||
#导出功能
|
||||
format.xlsx {
|
||||
set_export_cookies
|
||||
@table_columns = %w(参赛单位 参赛负责人 职务 军衔 电话 赛区 赛项 课题来源 成员)
|
||||
@table_columns = @table_columns + %w(作品下载链接) if params[:upload].to_s == "true"
|
||||
@export_infos = []
|
||||
competition_users.each do |u|
|
||||
info_array = [u.org_name, u.leader, u.org_job, u.org_rank, u.phone, u.zone, u.sub_competition, u.subject_source_type == 0 ? "自主提报" : u.subject_source_name,
|
||||
u.members_to_string
|
||||
]
|
||||
if params[:upload].to_s == "true"
|
||||
info_array = info_array + [u.attachments.blank? ? "" : "#{EduSetting.get('host_name')}/#{download_url(u.attachments.first)}"]
|
||||
end
|
||||
@export_infos.push(info_array)
|
||||
end
|
||||
export_name = "竞赛报名列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
|
||||
export_name = "竞赛作品列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}" if params[:upload].to_s == "true"
|
||||
render xlsx: "#{export_name.strip}", template: "competition_infos/enroll_list.xlsx.axlsx", locals: {table_columns: @table_columns, export_infos: @export_infos}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def enroll
|
||||
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
|
||||
tip_exception "您已经报名!" if competition_user.present?
|
||||
competition_user = CompetitionUser.new(enroll_params)
|
||||
competition_user.competition_info = @competition_info
|
||||
competition_user.user = current_user
|
||||
competition_user.members = params[:members]
|
||||
competition_user.save
|
||||
render_ok
|
||||
end
|
||||
|
||||
def enroll_status
|
||||
@competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
|
||||
end
|
||||
|
||||
def upload
|
||||
competition_user = CompetitionUser.find_by(competition_info: @competition_info.id, user_id: current_user.id)
|
||||
tip_exception "未报名,请先报名" if competition_user.blank?
|
||||
tip_exception "附件参数attachment_ids不能为空" if params[:attachment_ids].blank?
|
||||
# tip_exception "您已经提交作品!" if competition_user.present? && competition_user.attachments.present?
|
||||
competition_user.attachments.update_all(container_id: nil, container_type: nil)
|
||||
params[:attachment_ids].each do |id|
|
||||
attachment = Attachment.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = competition_user
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
#赛事风采
|
||||
def statistics
|
||||
@competition_users = @competition_info.competition_users
|
||||
@upload_count = @competition_users.joins("join attachments on attachments.container_type='CompetitionUser' and attachments.container_id = competition_users.id").count
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def enroll_params
|
||||
params.permit(:org_name, :org_job, :org_rank, :leader, :zone, :sub_competition, :phone,
|
||||
:subject_source_type, :subject_source_name)
|
||||
end
|
||||
|
||||
def competition_info_params
|
||||
params.require(:competition_info).permit(:title, :zones, :zones_local, :sub_competitions, :identifier, :content,
|
||||
:video_url, :is_local, :manager_ids, :upload_date, :enroll_date, :guide, :about_us, :banner_url)
|
||||
end
|
||||
|
||||
def find_competition
|
||||
if CompetitionInfo.where(:identifier => params[:id]).exists?
|
||||
@competition_info = CompetitionInfo.where(:identifier => params[:id]).first
|
||||
else
|
||||
@competition_info = CompetitionInfo.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
def manager_competition_zones
|
||||
if current_user.admin?
|
||||
@competition_info.competition_zones
|
||||
else
|
||||
@competition_info.manager_zones(current_user)
|
||||
end
|
||||
end
|
||||
|
||||
def check_competition_manager
|
||||
unless @competition_info.is_manager?(current_user)
|
||||
tip_exception(403, "你没有权限操作!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
class CompetitionNoticesController < ApplicationController
|
||||
include ApplicationHelper
|
||||
before_action :find_competition, only: [:show, :index, :update, :destroy, :create]
|
||||
# before_action :require_admin, only: [:show, :index, :update, :destroy, :create]
|
||||
before_action :manager_competition_zones, only: [:enroll_list]
|
||||
|
||||
def index
|
||||
competition_notices = CompetitionNotice.where(competition_info_id: @competition_info.id).order("created_at desc")
|
||||
@competition_notices_count = competition_notices.size
|
||||
@competition_notices = paginate(competition_notices)
|
||||
end
|
||||
|
||||
def create
|
||||
@competition_notice = CompetitionNotice.new(competition_notice_params)
|
||||
@competition_notice.user = current_user
|
||||
@competition_notice.competition_info = @competition_info
|
||||
@competition_notice.save
|
||||
if params[:attachment_ids].present?
|
||||
params[:attachment_ids].each do |id|
|
||||
attachment = Attachment.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @competition_notice
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
end
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
# PATCH/PUT /competition_infos/1.json
|
||||
def update
|
||||
@competition_notice = CompetitionNotice.find params[:id]
|
||||
@competition_notice.update(competition_notice_params)
|
||||
@competition_notice.attachments.update_all(container_id: nil, container_type: nil)
|
||||
if params[:attachment_ids].present?
|
||||
params[:attachment_ids].each do |id|
|
||||
attachment = Attachment.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @competition_notice
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
end
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
def show
|
||||
@competition_notice = CompetitionNotice.find params[:id]
|
||||
end
|
||||
|
||||
def upload
|
||||
competition_user = CompetitionUser.find_by(competition_info: @competition_notice.id, user_id: current_user.id)
|
||||
tip_exception "未报名,请先报名" if competition_user.blank?
|
||||
tip_exception "附件参数attachment_ids不能为空" if params[:attachment_ids].blank?
|
||||
# tip_exception "您已经提交作品!" if competition_user.present? && competition_user.attachments.present?
|
||||
competition_user.attachments.update_all(container_id: nil, container_type: nil)
|
||||
|
||||
render_ok
|
||||
end
|
||||
|
||||
def destroy
|
||||
@competition_notice = CompetitionNotice.find params[:id]
|
||||
@competition_notice.destroy
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def competition_notice_params
|
||||
params.permit(:title, :content)
|
||||
end
|
||||
|
||||
def find_competition
|
||||
if CompetitionInfo.where(:identifier => params[:competition_info_id]).exists?
|
||||
@competition_info = CompetitionInfo.where(:identifier => params[:competition_info_id]).first
|
||||
else
|
||||
@competition_info = CompetitionInfo.find(params[:competition_info_id])
|
||||
end
|
||||
end
|
||||
|
||||
def manager_competition_zones
|
||||
if current_user.admin?
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,6 +8,9 @@ module LaboratoryHelper
|
|||
helper_method :default_setting
|
||||
helper_method :default_yun_session
|
||||
helper_method :default_course_links
|
||||
helper_method :manager_main_site_url
|
||||
helper_method :main_web_site_url
|
||||
helper_method :current_main_site_url
|
||||
end
|
||||
|
||||
def current_laboratory
|
||||
|
|
@ -32,18 +35,29 @@ module LaboratoryHelper
|
|||
end
|
||||
|
||||
def default_course_links
|
||||
# my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
|
||||
|
||||
{
|
||||
new_syllabuses: "https://www.trustie.net/syllabuses/new",
|
||||
new_course: "https://www.trustie.net/courses/new",
|
||||
edit_account: "https://www.trustie.net/my/account",
|
||||
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
||||
my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
||||
default_url: "https://www.trustie.net/",
|
||||
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
|
||||
register_url: "https://www.trustie.net/login?login=false"
|
||||
# new_syllabuses: "https://www.trustie.net/syllabuses/new",
|
||||
# new_course: "https://www.trustie.net/courses/new",
|
||||
# edit_account: "https://www.trustie.net/my/account",
|
||||
# my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
||||
# my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||
# my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
||||
# default_url: "https://www.trustie.net/",
|
||||
tiding_url: "#{main_web_site_url}/users/#{current_user.try(:login)}/user_tidings",
|
||||
register_url: "#{main_web_site_url}/user_join"
|
||||
}
|
||||
end
|
||||
|
||||
def manager_main_site_url
|
||||
{name: '管理', link: "#{main_web_site_url}/managements"}
|
||||
end
|
||||
|
||||
def main_web_site_url
|
||||
EduSetting.get('host_main_site')
|
||||
end
|
||||
|
||||
def current_main_site_url
|
||||
EduSetting.get('host_name')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,14 +6,16 @@ module LoginHelper
|
|||
end
|
||||
|
||||
def autologin_cookie_name
|
||||
edu_setting('autologin_cookie_name').presence || 'autologin'
|
||||
edu_setting('autologin_cookie_name').presence || 'autologin_forge_military'
|
||||
end
|
||||
|
||||
def autologin_action
|
||||
EduSetting.get('autologin_action').presence || 'autologin'
|
||||
end
|
||||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
|
||||
Rails.logger.info("set_cookie_user_id is=======> #{user.id}")
|
||||
token = Token.get_or_create_permanent_login_token(user, autologin_action)
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
module RegisterHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def autologin_register(username, email, password, platform= 'forge')
|
||||
def autologin_register(username, email, password, platform = 'forge', phone = nil)
|
||||
result = {message: nil, user: nil}
|
||||
email = email.blank? ? "#{username}@example.org" : email
|
||||
|
||||
user = User.find_by(login: username)
|
||||
user = User.find_by(phone: phone) if user.blank? && phone.present?
|
||||
user ||= User.new(admin: false, login: username, mail: email, type: "User")
|
||||
|
||||
user = User.new(admin: false, login: username, mail: email, type: "User")
|
||||
user.password = password
|
||||
user.platform = platform
|
||||
user.phone = phone if phone.present?
|
||||
user.activate
|
||||
|
||||
return unless user.valid?
|
||||
|
|
@ -18,7 +23,7 @@ module RegisterHelper
|
|||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
UserExtension.create!(user_id: user.id) if user.user_extension.blank?
|
||||
result[:user] = {id: user.id, token: user.gitea_token}
|
||||
end
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
class Home::CompetitionsController < ApplicationController
|
||||
|
||||
def index
|
||||
@competitions = Competition.active.order(start_time: :desc).limit(3)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class Home::PlatformCommunicatesController < ApplicationController
|
||||
|
||||
def index
|
||||
scope = PlatformCommunicate.order(order_index: :desc)
|
||||
@communicates = kaminari_paginate(scope)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class Home::PlatformPeopleController < ApplicationController
|
||||
|
||||
def index
|
||||
scope = PlatformPerson.order(created_at: :desc)
|
||||
@people = kaminari_paginate(scope)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class Home::PlatformStatisticsController < ApplicationController
|
||||
|
||||
def index
|
||||
@platform_statistic = PlatformStatistic.data
|
||||
@project_statistic = ProjectStatistic.data
|
||||
@platform_statistic.increment!(:visits)
|
||||
@tasks_count = ActiveRecord::Base.connection.exec_query("SELECT COUNT(*) FROM tasks").rows[0][0]
|
||||
@memos_count = ActiveRecord::Base.connection.exec_query("SELECT COUNT(*) FROM memos").rows[0][0]
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,6 @@ class IssuesController < ApplicationController
|
|||
before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen, :close_issue]
|
||||
|
||||
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :close_issue, :lock_issue]
|
||||
before_action :check_token_enough, only: [:create, :update]
|
||||
|
||||
include ApplicationHelper
|
||||
include TagChosenHelper
|
||||
|
|
@ -96,7 +95,8 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@issue_chosen = get_associated_data(@project)
|
||||
# @all_branches = get_branches
|
||||
@issue_chosen = issue_left_chosen(@project, nil)
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
@ -132,15 +132,10 @@ class IssuesController < ApplicationController
|
|||
tiding_type: 'issue', status: 0)
|
||||
end
|
||||
|
||||
#为悬赏任务时, 扣除当前用户的积分
|
||||
if params[:issue_type].to_s == "2"
|
||||
post_to_chain("minus", params[:token].to_i, current_user.try(:login))
|
||||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||
else
|
||||
normal_status(-1, "创建失败")
|
||||
normal_status(-1, @issue.errors.messages.values[0][0])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -149,13 +144,12 @@ class IssuesController < ApplicationController
|
|||
|
||||
def edit
|
||||
# @issue_chosen = issue_left_chosen(@project, @issue.id)
|
||||
@cannot_edit_tags = @issue.issue_type=="2" && @issue.status_id == 5 #悬赏任务已解决且关闭的状态下,不能修改
|
||||
@issue_attachments = @issue.attachments
|
||||
end
|
||||
|
||||
def update
|
||||
last_token = @issue.token
|
||||
last_status_id = @issue.status_id
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
return normal_status(-1, "您没有权限修改token") if @issue.will_save_change_to_token? && @issue.user_id != current_user&.id
|
||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
|
|
@ -163,22 +157,23 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
issue_files = params[:attachment_ids]
|
||||
change_files = false
|
||||
issue_file_ids = []
|
||||
if @issue.update_attributes(issue_params)
|
||||
issue_files = params[:attachment_ids]
|
||||
change_files = false
|
||||
issue_file_ids = []
|
||||
|
||||
if issue_files.present?
|
||||
change_files = true
|
||||
issue_files.each do |id|
|
||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @issue
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
if issue_files.present?
|
||||
change_files = true
|
||||
issue_files.each do |id|
|
||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @issue
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# if params[:issue_tag_ids].present?
|
||||
# issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
|
||||
|
|
@ -194,35 +189,15 @@ class IssuesController < ApplicationController
|
|||
# end
|
||||
# end
|
||||
|
||||
if @issue.issue_type.to_s == "2" && params[:status_id].to_i == 5 && @issue.author_id != current_user.try(:id)
|
||||
normal_status(-1, "不允许修改为关闭状态")
|
||||
else
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
|
||||
if @issue.update_attributes(issue_params)
|
||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
@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))
|
||||
else
|
||||
post_to_chain("add", @issue.token, @issue.user.try(:login))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if @issue.issue_type.to_s == "2" && @issue.status_id != 5 && @issue.saved_change_to_attribute("token")
|
||||
#表示修改token值
|
||||
change_token = last_token - @issue.token
|
||||
change_type = change_token > 0 ? "add" : "minus"
|
||||
post_to_chain(change_type, change_token.abs, current_user.try(:login))
|
||||
end
|
||||
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
normal_status(-1, "更新失败")
|
||||
if params[:status_id].to_i == 5
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
#@issue.update_closed_issues_count_in_project!
|
||||
end
|
||||
|
||||
@issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
normal_status(-1, @issue.errors.messages.values[0][0])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -243,32 +218,17 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
begin
|
||||
issue_type = @issue.issue_type
|
||||
status_id = @issue.status_id
|
||||
token = @issue.token
|
||||
login = @issue.user.try(:login)
|
||||
if @issue.destroy
|
||||
if issue_type == "2" && status_id != 5
|
||||
post_to_chain("add", token, login)
|
||||
end
|
||||
normal_status(0, "删除成功")
|
||||
else
|
||||
normal_status(-1, "删除失败")
|
||||
end
|
||||
rescue => exception
|
||||
Rails.logger.info("#########_______exception.message_________##########{exception.message}")
|
||||
normal_status(-1, "删除失败")
|
||||
if @issue.destroy
|
||||
normal_status(0, "删除成功")
|
||||
else
|
||||
normal_status(-1, "删除失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def clean
|
||||
#批量删除,暂时只能删除未悬赏的
|
||||
issue_ids = params[:ids]
|
||||
if issue_ids.present?
|
||||
if Issue.where(id: issue_ids, issue_type: "1").destroy_all
|
||||
if Issue.where(id: issue_ids).destroy_all
|
||||
normal_status(0, "删除成功")
|
||||
else
|
||||
normal_status(-1, "删除失败")
|
||||
|
|
@ -460,32 +420,4 @@ class IssuesController < ApplicationController
|
|||
project_id: @project.id
|
||||
}
|
||||
end
|
||||
|
||||
def post_to_chain(type, amount,login)
|
||||
change_params = {
|
||||
type: type,
|
||||
chain_params: {
|
||||
amount: amount,
|
||||
reponame: @project.try(:identifier),
|
||||
username: login
|
||||
}
|
||||
}
|
||||
PostChainJob.perform_later(change_params)
|
||||
end
|
||||
|
||||
def check_token_enough
|
||||
if params[:issue_type].to_s == "2" && (@issue.blank? || (@issue.present? && @issue.author_id == current_user.try(:id)))
|
||||
return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0
|
||||
query_params = {
|
||||
type: "query",
|
||||
chain_params: {
|
||||
reponame: @project.try(:identifier),
|
||||
username: current_user.try(:login)
|
||||
}
|
||||
}
|
||||
response = Gitea::Chain::ChainGetService.new(query_params).call
|
||||
return normal_status(-1, "获取token失败,请稍后重试") if response.status != 200
|
||||
return normal_status(-1, "您的token值不足") if JSON.parse(response.body)["balance"].to_i < params[:token].to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class JournalsController < ApplicationController
|
|||
render :json => { status: 0, message: "评论成功", id: journal.id}
|
||||
# normal_status(0, "评论成功")
|
||||
else
|
||||
normal_status(-1, "评论失败")
|
||||
normal_status(-1, journal.errors.messages.values[0][0])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -70,7 +70,7 @@ class JournalsController < ApplicationController
|
|||
if @journal.update_attribute(:notes, content)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
normal_status(-1, "更新失败")
|
||||
normal_status(-1, @journal.errors.messages.values[0][0])
|
||||
end
|
||||
else
|
||||
normal_status(-1, "评论的内容不能为空")
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class MembersController < ApplicationController
|
|||
scope = @project.members.includes(:roles, user: :user_extension)
|
||||
search = params[:search].to_s.downcase
|
||||
role = params[:role].to_s
|
||||
scope = scope.joins(:user).where("LOWER(concat(users.lastname, users.firstname, users.login, users.mail)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
|
||||
scope = scope.joins(:user).where("LOWER(CONCAT_WS(users.lastname, users.firstname, users.login, users.mail, users.nickname)) LIKE ?", "%#{search.split(" ").join('|')}%") if search.present?
|
||||
scope = scope.joins(:roles).where("roles.name LIKE ?", "%#{role}%") if role.present?
|
||||
|
||||
@total_count = scope.size
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class Oauth::EducoderController < Oauth::BaseController
|
|||
|
||||
::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate!
|
||||
|
||||
open_user= OpenUsers::Educoder.find_by(uid: login) || OpenUsers::Educoder.find_by(uid: mail)
|
||||
open_user= OpenUsers::Educoder.find_by(uid: login)
|
||||
|
||||
if open_user.present? && open_user.user.present? && open_user.user.email_binded?
|
||||
Rails.logger.info "######## open_user exist and open_user.user exsit and email is binded ok"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,5 @@ class ProjectCategoriesController < ApplicationController
|
|||
|
||||
def group_list
|
||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
||||
# projects = Project.no_anomory_projects.visible
|
||||
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ class ProjectsController < ApplicationController
|
|||
include OperateProjectAbilityAble
|
||||
include ProjectsHelper
|
||||
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about]
|
||||
before_action :load_project, except: %i[index group_type_list migrate create recommend]
|
||||
before_action :load_repository, except: %i[index group_type_list migrate create recommend]
|
||||
before_action :authorizate_user_can_edit_project!, only: %i[update]
|
||||
before_action :project_public?, only: %i[fork_users praise_users watch_users]
|
||||
|
||||
def index
|
||||
PlatformStatistic.data.increment!(:visits)
|
||||
scope = Projects::ListQuery.call(params)
|
||||
|
||||
# @projects = kaminari_paginate(scope)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner)
|
||||
@projects = kaminari_paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :apply_signatures, :members, :owner)
|
||||
|
||||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
@total_count = @projects.total_count
|
||||
if category_id.blank?
|
||||
ps = ProjectStatistic.first
|
||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
|
|
@ -48,33 +49,24 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def group_type_list
|
||||
project_statics = ProjectStatistic.first
|
||||
|
||||
@project_statics_list = [
|
||||
{
|
||||
project_type: 'common',
|
||||
name: '开源托管项目',
|
||||
projects_count: project_statics&.common_projects_count || 0
|
||||
},
|
||||
{
|
||||
project_type: 'mirror',
|
||||
name: '开源镜像项目',
|
||||
projects_count: project_statics&.mirror_projects_count || 0
|
||||
}
|
||||
]
|
||||
|
||||
# projects = Project.no_anomory_projects.visible
|
||||
# @project_group_list = projects.group(:project_type).size
|
||||
# if current_user&.logged?
|
||||
# projects = Project.list_user_projects(current_user.id)
|
||||
# else
|
||||
# projects = Project.visible
|
||||
# end
|
||||
projects = Project.no_anomory_projects.secret_and_visible
|
||||
language_lists = projects.joins(:project_language).group("project_languages.name", "project_languages.id").size.keys.sort.to_h
|
||||
@project_group_list = language_lists.delete_if { |k, v| k.blank? }
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
# Projects::CreateForm.new(project_params).validate!
|
||||
private = params[:private]
|
||||
private = params[:private] || @project.is_public
|
||||
gitea_params = {
|
||||
private: private,
|
||||
default_branch: params[:default_branch]
|
||||
}
|
||||
}.compact
|
||||
if [true, false].include? private
|
||||
new_project_params = project_params.except(:private).merge(is_public: !private)
|
||||
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
|
||||
|
|
@ -147,7 +139,6 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
if @project_detail.save!
|
||||
attachment_ids = Array(params[:attachment_ids])
|
||||
logger.info "=============> #{Array(params[:attachment_ids])}"
|
||||
@attachments = Attachment.where(id: attachment_ids)
|
||||
@attachments.update_all(
|
||||
container_id: @project_detail.id,
|
||||
|
|
|
|||
|
|
@ -104,8 +104,10 @@ class PullRequestsController < ApplicationController
|
|||
normal_status(-1, "PullRequest更新失败")
|
||||
end
|
||||
else
|
||||
normal_status(-1, "PullRequest更新失败")
|
||||
normal_status(-1, @pull_request.errors.messages.values[0][0])
|
||||
end
|
||||
else
|
||||
normal_status(-1, @issue.errors.messages.values[0][0])
|
||||
end
|
||||
rescue => e
|
||||
normal_status(-1, e.message)
|
||||
|
|
@ -180,7 +182,12 @@ class PullRequestsController < ApplicationController
|
|||
message: "在这些分支之间的合并请求已存在:<a href='/projects/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}/Messagecount''>#{can_merge.first.try(:title)}</a>",
|
||||
}
|
||||
else
|
||||
normal_status(0, "可以合并")
|
||||
compare_result = Repositories::CompareService.call(@owner, @project, params)
|
||||
if compare_result['Diff'].blank?
|
||||
normal_status(0, "可以合并")
|
||||
else
|
||||
normal_status(-2, "分支内容相同,无需创建合并请求")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
before_action :require_login, only: %i[edit update create_file update_file delete_file sync_mirror]
|
||||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit]
|
||||
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]
|
||||
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]
|
||||
|
||||
|
|
@ -157,6 +157,19 @@ class RepositoriesController < ApplicationController
|
|||
render json: languages_precentagable
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_project
|
||||
|
|
@ -231,7 +244,7 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
# uploadPushInfo
|
||||
end
|
||||
|
||||
|
||||
def create_new_pr(params)
|
||||
if params[:new_branch].present? && params[:new_branch] != params[:branch]
|
||||
local_params = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
class SettingsController < ApplicationController
|
||||
def show
|
||||
@old_projects_url = nil
|
||||
@old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -309,12 +309,12 @@ class SyncForgeController < ApplicationController
|
|||
# end
|
||||
# end
|
||||
|
||||
# def check_token
|
||||
# sync_params = params[:sync_params]
|
||||
# unless sync_params[:token] && sync_params[:token] == get_token
|
||||
# render json: {message: "token_errors"}
|
||||
# end
|
||||
# end
|
||||
# # def check_token
|
||||
# # sync_params = params[:sync_params]
|
||||
# # unless sync_params[:token] && sync_params[:token] == get_token
|
||||
# # render json: {message: "token_errors"}
|
||||
# # end
|
||||
# # end
|
||||
|
||||
# def get_token
|
||||
# "34c82f51e0b699d9d16d70fd6497c9b1e4821d6ea3e872558a6537a091076b8e"
|
||||
|
|
|
|||
|
|
@ -1,261 +1,260 @@
|
|||
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]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users]
|
||||
before_action :require_login, only: %i[me list]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
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
|
||||
#待办事项,现在未做
|
||||
@undo_events = 0
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
@user_org_count = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)).size + @user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).size : @user.organizations.with_visibility("common").size
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.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
|
||||
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).where("LOWER(concat(users.lastname, users.firstname, users.login)) LIKE ?", "%#{params[:search].split(" ").join('|')}%") if params[:search].present?
|
||||
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find params[:id]
|
||||
@user.update!(user_params)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
# 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') + '/projects'
|
||||
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
|
||||
|
||||
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, :lastname, :show_realname,:login,:mail,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id,:identity, :student_id, :description]
|
||||
)
|
||||
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]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users]
|
||||
before_action :require_login, only: %i[me list]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
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
|
||||
#待办事项,现在未做
|
||||
@undo_events = 0
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
@user_org_count = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)).size + @user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).size : @user.organizations.with_visibility("common").size
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.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
|
||||
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).where("LOWER(concat(users.lastname, users.firstname, users.login)) LIKE ?", "%#{params[:search].split(" ").join('|')}%") if params[:search].present?
|
||||
|
||||
@watchers_count = watchers.size
|
||||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find params[:id]
|
||||
@user.update!(user_params)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# 贴吧获取用户信接口
|
||||
def get_user_info
|
||||
begin
|
||||
@user = current_user
|
||||
# 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_action)
|
||||
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') + '/projects'
|
||||
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
|
||||
|
||||
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, :lastname, :show_realname,:login,:mail,
|
||||
user_extension_attributes: [
|
||||
:gender, :location, :location_city,
|
||||
:occupation, :technical_title,
|
||||
:school_id, :department_id,:identity, :student_id, :description]
|
||||
)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class VersionsController < ApplicationController
|
|||
if version.save
|
||||
normal_status(0, "里程碑创建成功")
|
||||
else
|
||||
normal_status(-1, "里程碑创建失败")
|
||||
normal_status(-1, version.errors.messages.values[0][0])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ class VersionsController < ApplicationController
|
|||
if @version.update_attributes(tag_params)
|
||||
normal_status(0, "里程碑更新成功")
|
||||
else
|
||||
normal_status(-1, "里程碑更新失败")
|
||||
normal_status(-1, version.errors.messages.values[0][0])
|
||||
end
|
||||
end
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,13 +1,24 @@
|
|||
class Contents::CreateForm < BaseForm
|
||||
attr_accessor :filepath, :branch, :new_branch
|
||||
attr_accessor :filepath, :branch, :new_branch, :content
|
||||
|
||||
validates :filepath, presence: true
|
||||
|
||||
validate :check_branch
|
||||
|
||||
# validate :dun_content_check 敏感词过滤
|
||||
|
||||
def check_branch
|
||||
raise "branch和new_branch必须存在一个 " if branch.blank? && new_branch.blank?
|
||||
# raise "branch和new_branch只能存在一个" if !branch.blank? && !new_branch.blank?
|
||||
end
|
||||
|
||||
def dun_content_check
|
||||
if content.present?
|
||||
check_result = DunCheck::TextCheck.new({title: "", content: content}).call
|
||||
if check_result[:status].to_i == -1
|
||||
raise "内容含有:#{check_result[:extra_params][:infos]},请修改"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
class Users::AdminCreateUserForm
|
||||
include ActiveModel::Model
|
||||
|
||||
|
||||
attr_accessor :phone, :password
|
||||
|
||||
validates :phone, presence: true, format: { with: CustomRegexp::PHONE, message: "手机号格式错误" }
|
||||
validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位密码,支持字母数字和符号" }
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ module ApplicationHelper
|
|||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g"
|
||||
str = source.user_extension.try(:gender).to_i == 0 ? "boy.jpg" : "girl.jpg"
|
||||
File.join(relative_path, "#{source.class}", str)
|
||||
elsif source.class.to_s == 'Subject'
|
||||
File.join("images","educoder", "index", "subject", "subject#{rand(17)}.jpg")
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ module ProjectsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def render_zip_url(project, archive_name)
|
||||
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.zip"].join('/')
|
||||
def render_zip_url(owner, repository, archive)
|
||||
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.zip")].join
|
||||
end
|
||||
|
||||
def render_tar_url(project, archive_name)
|
||||
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.tar.gz"].join('/')
|
||||
def render_tar_url(owner, repository, archive)
|
||||
[base_url, archive_repositories_path(owner&.login, repository, "#{archive}.tar.gz")].join
|
||||
end
|
||||
|
||||
def render_http_url(project)
|
||||
|
|
@ -50,7 +50,10 @@ module ProjectsHelper
|
|||
repo_id: repo.id,
|
||||
open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?,
|
||||
type: project.numerical_for_project_type,
|
||||
author: render_owner(project)
|
||||
author: render_owner(project),
|
||||
is_secret: project.is_secret,
|
||||
is_member: project.member?(user.id),
|
||||
user_apply_signatures: project.apply_signatures.with_user_id(user.id).collect{|s| {id: s.id, status: s.status}}
|
||||
}).compact
|
||||
|
||||
render json: tmp_json
|
||||
|
|
|
|||
|
|
@ -24,8 +24,14 @@ module Gitea
|
|||
|
||||
def run
|
||||
Contents::CreateForm.new(valid_params).validate!
|
||||
response = Gitea::Repository::Entries::CreateService.new(token, owner, @params[:identifier], @params[:filepath], file_params).call
|
||||
render_result(response)
|
||||
result = Gitea::Repository::Entries::CreateService.call(token,
|
||||
owner, @params[:identifier], @params[:filepath], file_params)
|
||||
|
||||
if result[:status] == :success
|
||||
@result = result[:body]
|
||||
else
|
||||
fail!(result[:message])
|
||||
end
|
||||
rescue Exception => exception
|
||||
Rails.logger.info "Exception ===========> #{exception.message}"
|
||||
fail!(exception.message)
|
||||
|
|
@ -48,7 +54,8 @@ module Gitea
|
|||
{
|
||||
filepath: @params[:filepath],
|
||||
branch: @params[:branch],
|
||||
new_branch: @params[:new_branch]
|
||||
new_branch: @params[:new_branch],
|
||||
content: @params[:content]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -56,7 +63,7 @@ module Gitea
|
|||
file_params = {}
|
||||
file_params = file_params.merge(branch: @params[:branch]) unless @params[:branch].blank?
|
||||
file_params = file_params.merge(new_branch: @params[:new_branch]) unless @params[:new_branch].blank?
|
||||
file_params = file_params.merge(content: Base64.encode64(@params[:content]))
|
||||
file_params = file_params.merge(content: Base64.encode64(@params[:content] || ""))
|
||||
file_params = file_params.merge(message: @params[:message]) unless @params[:message].blank?
|
||||
file_params = file_params.merge(committer: @params[:committer])
|
||||
file_params
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
module Projects
|
||||
class AddMemberInteractor
|
||||
def self.call(owner, project, collaborator, permission="write")
|
||||
interactor = new(owner, project, collaborator, permission)
|
||||
def self.call(owner, project, collaborator, permission="write", is_apply_signature=false)
|
||||
interactor = new(owner, project, collaborator, permission, is_apply_signature)
|
||||
interactor.run
|
||||
interactor
|
||||
end
|
||||
|
||||
attr_reader :error, :result
|
||||
|
||||
def initialize(owner, project, collaborator, permission)
|
||||
@owner = owner
|
||||
@project = project
|
||||
@collaborator = collaborator
|
||||
@permission = permission
|
||||
def initialize(owner, project, collaborator, permission, is_apply_signature)
|
||||
@owner = owner
|
||||
@project = project
|
||||
@collaborator = collaborator
|
||||
@permission = permission
|
||||
@is_apply_signature = is_apply_signature
|
||||
end
|
||||
|
||||
def success?
|
||||
|
|
@ -23,7 +24,7 @@ module Projects
|
|||
ActiveRecord::Base.transaction do
|
||||
gitea_result = Gitea::Repository::Members::AddService.new(owner, project.identifier, collaborator.login, permission).call
|
||||
if gitea_result.status == 204
|
||||
project.add_member!(collaborator.id)
|
||||
project.add_member!(collaborator.id, set_member_role, is_apply_signature)
|
||||
end
|
||||
fail!(nil)
|
||||
end
|
||||
|
|
@ -32,11 +33,20 @@ module Projects
|
|||
end
|
||||
|
||||
private
|
||||
attr_reader :owner, :project, :collaborator, :permission
|
||||
attr_reader :owner, :project, :collaborator, :permission, :is_apply_signature
|
||||
|
||||
def fail!(error)
|
||||
@error = error
|
||||
end
|
||||
|
||||
def set_member_role
|
||||
@role ||=
|
||||
case @permission
|
||||
when "write" then "Developer"
|
||||
when "read" then "Reporter"
|
||||
else "Developer"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
class SyncForgeProjectJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(sync_parmas)
|
||||
# sync_parmas.permit!
|
||||
Rails.logger.info("=======begin to sync forge projects, and sync_parmas: #{sync_parmas}")
|
||||
get_rand_user = rand_user
|
||||
project_params = sync_parmas[:project]
|
||||
repository_params = sync_parmas[:repository]
|
||||
project_socre_params = sync_parmas[:project_socre]
|
||||
begin
|
||||
unless Project.select(:identifier).exists?(identifier: project_params[:identifier])
|
||||
project_params = project_params.merge({user_id: get_rand_user.id })
|
||||
project = Project.new(project_params)
|
||||
if project.save
|
||||
repository_params = {
|
||||
hidden: false,
|
||||
identifier: repository_params[:identifier],
|
||||
mirror_url: repository_params[:url].to_s.gsub("https://gitea.", "https://git."),
|
||||
user_id: get_rand_user.id,
|
||||
login: get_rand_user.login,
|
||||
password: "",
|
||||
is_mirror: false
|
||||
}
|
||||
Repositories::MigrateService.new(get_rand_user, project, repository_params).call
|
||||
project_score = ProjectScore.new(project_socre_params.merge({project_id: project.id}))
|
||||
project_score.save
|
||||
end
|
||||
end
|
||||
Rails.logger.info("=======end to sync forge projects")
|
||||
rescue => e
|
||||
Rails.logger.info("=======sync forge projects has errors: #{e}")
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rand_user
|
||||
user_ids = User.select(:id, :type, :gitea_token, :gitea_uid).where("gitea_token is not null and gitea_uid is not null and type = ?", "User").pluck(:id)
|
||||
range_user_id = user_ids[rand(user_ids.length-1)]
|
||||
rand_sync_user = User.find_by_id(range_user_id) #生成随机用户
|
||||
unless rand_sync_user.present?
|
||||
rand_user
|
||||
end
|
||||
rand_sync_user
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,7 @@ class SyncMirroredRepositoryJob < ApplicationJob
|
|||
repo = Repository.find_by(id: repo_id)
|
||||
current_user = User.find_by(id: user_id)
|
||||
return if repo.blank? || current_user.blank?
|
||||
result = Gitea::Repository::SyncMirroredService.new(repo.owner.login, repo.identifier, token: current_user.gitea_token).call
|
||||
repo&.mirror.set_status! if result[:status] === 200
|
||||
result = Gitea::Repository::SyncMirroredService.new(repo.user.login, repo.identifier, token: current_user.gitea_token).call
|
||||
repo&.mirror&.set_status! if result[:status] == 200 && repo.mirror.present?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
class SyncPhengleiUserJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(project_id=nil)
|
||||
project_id ||= EduSetting.get("sync_phenglei_user_project")
|
||||
project = Project.find_by_id(project_id)
|
||||
return if project.nil?
|
||||
member_count, success_count, error_count, not_exsit_count = 0, 0, 0, 0
|
||||
Rails.logger.info("======begin to sync phenglei user to project#{project.owner.login + "/" + project.identifier}")
|
||||
PhengleiUser.find_each do |i|
|
||||
puts "======开始处理#{i.phone}"
|
||||
user = User.find_by(phone: i.phone)
|
||||
if user.present?
|
||||
if project.member?(user.id)
|
||||
puts "======#{i.phone}用户已经是外围贡献者了"
|
||||
member_count += 1
|
||||
else
|
||||
interactor = Projects::AddMemberInteractor.call(project.owner, project, user, "read", true)
|
||||
if interactor.error.nil?
|
||||
puts "========用户#{i.phone}成功添加为项目的外围贡献者======="
|
||||
success_count += 1
|
||||
else
|
||||
puts "========用户#{i.phone}添加失败"
|
||||
error_count += 1
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "=====#{i.phone}用户不存在"
|
||||
not_exsit_count += 1
|
||||
next
|
||||
end
|
||||
end
|
||||
Rails.logger.info("======已存在外围贡献者数量#{member_count}, 成功添加用户数量#{success_count}, 添加失败用户数量#{error_count}, 找不到用户数量#{not_exsit_count}")
|
||||
Rails.logger.info("======end to sync phenglei user to project#{project.owner.login + "/" + project.identifier}")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
class DunCheck::ImageCheck
|
||||
|
||||
#检测结果,0:通过,1:嫌疑,2:不通过
|
||||
# include ActionView::Helpers::LoopTextsHelper
|
||||
|
||||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
def initialize(image_params)
|
||||
@image_params = image_params
|
||||
end
|
||||
|
||||
def call
|
||||
begin
|
||||
Rails.logger.info("==========@image_params===========#{@image_params}")
|
||||
dun_params = check_dun_params(@image_params)
|
||||
|
||||
api_url = EduSetting.get("dun_image_api")
|
||||
|
||||
uri = URI.parse(api_url)
|
||||
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
if api_url.include?("https://")
|
||||
http.use_ssl = true
|
||||
end
|
||||
dun_params_str = URI.encode_www_form(dun_params)
|
||||
|
||||
header = {'content-type':'application/x-www-form-urlencoded'}
|
||||
response = http.post(uri.path, dun_params_str, header)
|
||||
|
||||
response_body = JSON.parse(response.body)
|
||||
if response_body["code"].to_i == 200
|
||||
response_body_result = response_body["antispam"]
|
||||
response_lables = response_body_result[0]["labels"]
|
||||
return_sub_lable = ""
|
||||
if response_lables.present?
|
||||
return_sub_lable = get_sub_labels(response_lables)
|
||||
end
|
||||
render_status = response_body_result[0]["action"].to_i == 0 ? 1 : -1
|
||||
tip_status(render_status, return_sub_lable.present? ? "图片含有: #{return_sub_lable}" : response_body["msg"] )
|
||||
else
|
||||
tip_status(-1, response_body["msg"])
|
||||
end
|
||||
rescue Exception => ex
|
||||
Rails.logger.info "*** transaction abored!"
|
||||
Rails.logger.info "*** errors: #{ex.message}"
|
||||
tip_status(-1, "检测失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_dun_params(image_params)
|
||||
|
||||
dun_public_params = DunCheck::PublicParams.new("image")
|
||||
check_params = {
|
||||
version: "v4",
|
||||
images: image_params.to_json
|
||||
}
|
||||
check_params.merge!(dun_public_params.call)
|
||||
dun_params = dun_public_params.generate_sign(check_params)
|
||||
|
||||
return dun_params
|
||||
end
|
||||
|
||||
def tip_status(status, message, msg_params={})
|
||||
return {status: status, message: message, extra_params: msg_params}
|
||||
end
|
||||
|
||||
def get_sub_labels(labels)
|
||||
_sub_labels = []
|
||||
labels.each do |label|
|
||||
error_label = label["subLabels"].present? ? label["subLabels"][0]["subLabel"] : ""
|
||||
if error_label.present?
|
||||
_sub_labels.push(sub_lables[:"#{error_label.to_s}"])
|
||||
end
|
||||
end
|
||||
return _sub_labels.present? ? _sub_labels.join(",") : ""
|
||||
end
|
||||
|
||||
def sub_lables
|
||||
{
|
||||
"10000": "色情",
|
||||
"10001": "女下体",
|
||||
"10002": "女胸",
|
||||
"10003": "男下体",
|
||||
"10004": "性行为",
|
||||
"10005": "臀部",
|
||||
"10006": "口交",
|
||||
"10007": "卡通色情",
|
||||
"10008": "色情人物",
|
||||
"10009": "儿童色情",
|
||||
"11000": "性感低俗",
|
||||
"11001": "亲吻",
|
||||
"11002": "腿部特写",
|
||||
"11003": "非漏点赤膊",
|
||||
"11004": "胸部",
|
||||
"100001": "色情文字-色情其他",
|
||||
"100002": "色情文字-色情传播",
|
||||
"100003": "色情文字-色情性器官",
|
||||
"100004": "色情文字-色情挑逗",
|
||||
"100005": "色情文字-色情低俗段子",
|
||||
"100006": "色情文字-色情性行为",
|
||||
"100007": "色情文字-色情舆情事件",
|
||||
"100008": "色情文字-色情交友类",
|
||||
"20000": "广告",
|
||||
"20001": "广告带文字",
|
||||
"200009": "广告文字-商业推广",
|
||||
"200010": "广告文字-广告法",
|
||||
"200011": "刷量行为",
|
||||
"200012": "广告其他",
|
||||
"260052": "广告文字-广告法-涉医疗用语",
|
||||
"260053": "广告文字-广告法-迷信用语",
|
||||
"260054": "广告文字-广告法-需要凭证",
|
||||
"260055": "广告文字-广告法-限时性用语",
|
||||
"260056": "广告文字-广告法-涉嫌诱导消费者",
|
||||
"260057": "广告文字-广告法-涉嫌欺诈消费者",
|
||||
"260058": "广告文字-广告法-法律风险较高",
|
||||
"260059": "广告文字-广告法-极限词",
|
||||
"21000": "二维码",
|
||||
"30000": "暴恐",
|
||||
"30001": "暴恐图集",
|
||||
"30002": "暴恐旗帜",
|
||||
"30003": "暴恐人物",
|
||||
"30004": "暴恐标识",
|
||||
"30005": "暴恐场景",
|
||||
"300016": "暴恐文字-暴恐其他",
|
||||
"40000": "违禁",
|
||||
"40001": "违禁图集",
|
||||
"40002": "违禁品",
|
||||
"40003": "特殊标识",
|
||||
"40004": "血腥模型",
|
||||
"40005": "公职服饰",
|
||||
"40006": "不文明",
|
||||
"40007": "违禁人物",
|
||||
"40008": "违禁场景",
|
||||
"40009": "火焰",
|
||||
"40010": "骷髅",
|
||||
"40011": "货币",
|
||||
"40012": "毒品",
|
||||
"400017": "违禁文字-违禁其他",
|
||||
"600018": "违禁文字-谩骂其他",
|
||||
"50000": "涉政",
|
||||
"50001": "涉政图集",
|
||||
"50002": "中国地图",
|
||||
"50003": "涉政人物",
|
||||
"50004": "涉政旗帜",
|
||||
"50005": "涉政标识",
|
||||
"50006": "涉政场景",
|
||||
"500013": "涉政文字-涉政其他",
|
||||
"500014": "涉政文字-敏感专项",
|
||||
"500015": "涉政文字-严格涉政",
|
||||
"500039": "涉政文字-时事报道",
|
||||
"500040": "涉政文字-领导人相关",
|
||||
"500041": "涉政文字-英雄烈士相关",
|
||||
"500042": "涉政文字-邪教迷信",
|
||||
"500043": "涉政文字-落马官员相关",
|
||||
"500044": "涉政文字-热点舆情",
|
||||
"500045": "涉政文字-涉政综合",
|
||||
"90000": "其他",
|
||||
"90002": "自定义用户名单",
|
||||
"90003": "自定义IP名单",
|
||||
"900020": "文字违规-其他"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
class DunCheck::PublicParams
|
||||
def initialize(type)
|
||||
@type = type
|
||||
end
|
||||
|
||||
def call
|
||||
|
||||
public_params = {
|
||||
secretId: EduSetting.get("dun_secret_id"),
|
||||
businessId: EduSetting.get("dun_#{@type}_businessId"),
|
||||
timestamp: DateTime.current.strftime('%Q').to_i,
|
||||
nonce: rand(10 ** 11).to_i
|
||||
}
|
||||
return public_params
|
||||
end
|
||||
|
||||
def generate_sign(params)
|
||||
secretkey = EduSetting.get("dun_secrect_key")
|
||||
sort_params = params.sort.to_h
|
||||
sign_str = ""
|
||||
sort_params.each do |k,v|
|
||||
sign_str += "#{k.to_s}#{v.to_s}"
|
||||
end
|
||||
sign_str += secretkey
|
||||
md5_sign = Digest::MD5.hexdigest(sign_str.to_s.force_encoding("UTF-8"))
|
||||
return sort_params.merge!(signature: md5_sign)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
class DunCheck::TextCheck
|
||||
|
||||
# include DunCheck::PublicParams
|
||||
#text_params = {
|
||||
# content: "ccc", #内容
|
||||
# ip: "xxx", #用户ip
|
||||
# account: "xxx", #登录login
|
||||
# nickname: "xxx", #用户姓名
|
||||
# title: "xxx", #帖子的标题
|
||||
# }
|
||||
|
||||
#检测结果,0:通过,1:嫌疑,2:不通过
|
||||
# include ActionView::Helpers::LoopTextsHelper
|
||||
|
||||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
def initialize(text_params)
|
||||
@text_params = text_params
|
||||
end
|
||||
|
||||
def call
|
||||
new_text_params = @text_params
|
||||
text_long_array = []
|
||||
check_content = new_text_params[:content]
|
||||
format_text(check_content,text_long_array)
|
||||
(1..text_long_array.size).each do |i|
|
||||
new_text_params.merge!(content: text_long_array[i-1])
|
||||
check_result = check_text(new_text_params)
|
||||
if check_result[:status].to_i == -1
|
||||
return check_result
|
||||
break
|
||||
else
|
||||
if i == text_long_array.size
|
||||
return check_result
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check_text(text_params)
|
||||
begin
|
||||
dun_params = check_dun_params(text_params)
|
||||
|
||||
# api_url = Redmine::Configuration['dun']['text_api']
|
||||
api_url = EduSetting.get("dun_text_api")
|
||||
uri = URI.parse(api_url)
|
||||
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
if api_url.include?("https://")
|
||||
http.use_ssl = true
|
||||
end
|
||||
dun_params_str = URI.encode_www_form(dun_params)
|
||||
header = {'content-type':'application/x-www-form-urlencoded'}
|
||||
response = http.post(uri.path, dun_params_str, header)
|
||||
response_body = eval(response.body)
|
||||
Rails.logger.info("======response========#{response_body}")
|
||||
|
||||
if response_body[:code].to_i == 200
|
||||
response_body_result = response_body[:result]
|
||||
response_body_labels = response_body_result[:labels].present? ? response_body_result[:labels][0] : []
|
||||
extra_params = {
|
||||
action: response_body_result[:action],
|
||||
taskId: response_body_result[:taskId],
|
||||
infos: response_body_labels.present? ? sub_lables[:"#{response_body_labels[:subLabels][0][:subLabel]}"] : ""
|
||||
}
|
||||
render_status = response_body_result[:action].to_i == 0 ? 1 : -1
|
||||
tip_status(render_status, response_body[:msg], extra_params)
|
||||
else
|
||||
tip_status(-1, response_body[:msg])
|
||||
end
|
||||
rescue Exception => ex
|
||||
Rails.logger.info "*** transaction abored!"
|
||||
Rails.logger.info "*** errors: #{ex.message}"
|
||||
tip_status(-1, "检测失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_dun_params(text_params)
|
||||
dun_public_params = DunCheck::PublicParams.new("text")
|
||||
rand_data_id = random_dataId
|
||||
check_params = {
|
||||
dataId: rand_data_id,
|
||||
version: "v3.1",
|
||||
callback: rand_data_id
|
||||
}.merge(text_params)
|
||||
|
||||
check_params.merge!(dun_public_params.call)
|
||||
dun_params = dun_public_params.generate_sign(check_params)
|
||||
return dun_params
|
||||
end
|
||||
|
||||
def format_text(text_long, text_long_array)
|
||||
slice_content = text_long.slice(0..4998)
|
||||
last_slice_content = text_long.slice(4999..-1)
|
||||
text_long_array.push(slice_content)
|
||||
if last_slice_content.present?
|
||||
if last_slice_content.length > 4999
|
||||
format_text(last_slice_content, text_long_array)
|
||||
else
|
||||
text_long_array.push(last_slice_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def random_dataId
|
||||
Digest::MD5.hexdigest(rand(100000000).to_s)
|
||||
end
|
||||
|
||||
def check_labels
|
||||
# 100:色情,200:广告,260:广告法,300:暴恐,400:违禁,500:涉政,600:谩骂,700:灌水
|
||||
%w(100 200 260 300 400 500 600 700).join(",")
|
||||
end
|
||||
|
||||
def tip_status(status, message, msg_params={})
|
||||
return {status: status, message: message, extra_params: msg_params}
|
||||
end
|
||||
|
||||
def sub_lables
|
||||
{
|
||||
"100001": "色情其他",
|
||||
"100002": "色情传播",
|
||||
"100003": "色情性器官",
|
||||
"100004": "色情挑逗",
|
||||
"100005": "色情低俗段子",
|
||||
"100006": "色情性行为",
|
||||
"100007": "色情舆情事件",
|
||||
"100008": "色情交友类",
|
||||
"200009": "商业推广",
|
||||
"200010": "广告法",
|
||||
"200011": "刷量行为",
|
||||
"200012": "广告其他",
|
||||
"260052": "广告法-涉医疗用语(非药品禁止宣传药效)",
|
||||
"260053": "广告法-迷信用语",
|
||||
"260054": "广告法-需要凭证(可以写但需要凭证证明)",
|
||||
"260055": "广告法-限时性用语(可以写但必须有具体时间)",
|
||||
"260056": "广告法-涉嫌诱导消费者",
|
||||
"260057": "广告法-涉嫌欺诈消费者",
|
||||
"260058": "广告法-法律风险较高",
|
||||
"260059": "广告法-极限词(用语绝对化)",
|
||||
"300016": "暴恐其他",
|
||||
"400017": "违禁其他",
|
||||
"400021": "违禁网监要求",
|
||||
"500013": "涉政其他",
|
||||
"500014": "敏感专项",
|
||||
"500015": "严格涉政",
|
||||
"500039": "时事报道",
|
||||
"500040": "领导人相关",
|
||||
"500041": "英雄烈士相关",
|
||||
"500042": "邪教迷信",
|
||||
"500043": "落马官员相关",
|
||||
"500044": "热点舆情",
|
||||
"500045": "涉政综合",
|
||||
"600018": "谩骂其他",
|
||||
"700019": "灌水其他",
|
||||
"900020": "其他",
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
# user_id :integer
|
||||
# applied_id :integer
|
||||
# applied_type :string(255)
|
||||
# viewed :integer default("0")
|
||||
# status :integer default("0")
|
||||
# viewed :integer default(0)
|
||||
# status :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# name :string(255)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
# id :integer not null, primary key
|
||||
# project_id :integer not null
|
||||
# user_id :integer not null
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# role :integer default(0)
|
||||
# status :integer default(0)
|
||||
#
|
||||
|
||||
class AppliedProject < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -2,52 +2,46 @@
|
|||
#
|
||||
# Table name: apply_actions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# reason :string(255)
|
||||
# container_id :integer
|
||||
# container_type :string(255)
|
||||
# dealer_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# status :integer default("0")
|
||||
# apply_reason :text(65535)
|
||||
# noticed :boolean default("0")
|
||||
# ip_addr :string(255)
|
||||
# reject_description :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_apply_actions_on_user_id (user_id)
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# reason :string(255)
|
||||
# container_id :integer
|
||||
# container_type :string(255)
|
||||
# dealer_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# status :integer default(0)
|
||||
# apply_reason :text(65535)
|
||||
# noticed :boolean default(FALSE)
|
||||
#
|
||||
|
||||
# 申请消息
|
||||
class ApplyAction < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
has_many :tidings, :as => :container, :dependent => :destroy
|
||||
after_create :send_tiding
|
||||
|
||||
def status_text
|
||||
I18n.t!("apply_action.status.#{status}")
|
||||
rescue I18n::MissingTranslationData
|
||||
nil
|
||||
end
|
||||
|
||||
def send_tiding
|
||||
if container_type == 'TrialAuthorization' && status == 1
|
||||
tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System',
|
||||
parent_container_id: container_id, parent_container_type: container_type,
|
||||
belong_container_id: container_id, belong_container_type: 'User')
|
||||
elsif %w(ApplyShixun ApplySubject TrialAuthorization).include?(container_type)
|
||||
belong_container_type = if container_type == 'TrialAuthorization'
|
||||
'User'
|
||||
else
|
||||
container_type == 'ApplyShixun' ? 'Shixun' : 'Subject'
|
||||
end
|
||||
tidings.create(user_id: '1', trigger_user_id: user_id, status: 0, viewed: 0, tiding_type: 'Apply',
|
||||
parent_container_id: container_id, parent_container_type: container_type,
|
||||
belong_container_id: container_id, belong_container_type: belong_container_type)
|
||||
end
|
||||
end
|
||||
# 申请消息
|
||||
class ApplyAction < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
has_many :tidings, :as => :container, :dependent => :destroy
|
||||
after_create :send_tiding
|
||||
|
||||
def status_text
|
||||
I18n.t!("apply_action.status.#{status}")
|
||||
rescue I18n::MissingTranslationData
|
||||
nil
|
||||
end
|
||||
|
||||
def send_tiding
|
||||
if container_type == 'TrialAuthorization' && status == 1
|
||||
tidings.create(user_id: user_id, trigger_user_id: 0, status: 1, viewed: 0, tiding_type: 'System',
|
||||
parent_container_id: container_id, parent_container_type: container_type,
|
||||
belong_container_id: container_id, belong_container_type: 'User')
|
||||
elsif %w(ApplyShixun ApplySubject TrialAuthorization).include?(container_type)
|
||||
belong_container_type = if container_type == 'TrialAuthorization'
|
||||
'User'
|
||||
else
|
||||
container_type == 'ApplyShixun' ? 'Shixun' : 'Subject'
|
||||
end
|
||||
tidings.create(user_id: '1', trigger_user_id: user_id, status: 0, viewed: 0, tiding_type: 'Apply',
|
||||
parent_container_id: container_id, parent_container_type: container_type,
|
||||
belong_container_id: container_id, belong_container_type: belong_container_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: apply_signatures
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# status :integer default("waiting")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_apply_signatures_on_project_id (project_id)
|
||||
# index_apply_signatures_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class ApplySignature < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
|
||||
scope :with_user_id, -> (user_id) {where(user_id: user_id)}
|
||||
scope :with_status, -> (status) {where(status: status) if status.present? && status != "all"}
|
||||
|
||||
validates :project_id, uniqueness: {scope: :user_id}
|
||||
|
||||
enum status: {unpassed: -1, waiting: 0, passed: 1}
|
||||
end
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
# deal_time :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# is_delete :boolean default("0")
|
||||
# is_delete :boolean default(FALSE)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -2,184 +2,179 @@
|
|||
#
|
||||
# Table name: attachments
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(30)
|
||||
# filename :string(255) default(""), not null
|
||||
# disk_filename :string(255) default(""), not null
|
||||
# filesize :integer default("0"), not null
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default(""), not null
|
||||
# downloads :integer default("0"), not null
|
||||
# author_id :integer default("0"), not null
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer default("1")
|
||||
# is_public :integer default("1")
|
||||
# copy_from :integer
|
||||
# quotes :integer default("0")
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :datetime
|
||||
# resource_bank_id :integer
|
||||
# unified_setting :boolean default("1")
|
||||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
# id :integer not null, primary key
|
||||
# container_id :integer
|
||||
# container_type :string(30)
|
||||
# filename :string(255) default(""), not null
|
||||
# disk_filename :string(255) default(""), not null
|
||||
# filesize :integer default(0), not null
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default(""), not null
|
||||
# downloads :integer default(0), not null
|
||||
# author_id :integer default(0), not null
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
# disk_directory :string(255)
|
||||
# attachtype :integer default(1)
|
||||
# is_public :integer default(1)
|
||||
# copy_from :integer
|
||||
# quotes :integer
|
||||
# is_publish :integer default("published")
|
||||
# publish_time :datetime
|
||||
# memo_image :boolean default(FALSE)
|
||||
# extra_type :integer default(0)
|
||||
# cloud_url :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachments_on_author_id (author_id)
|
||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
#
|
||||
|
||||
class Attachment < ApplicationRecord
|
||||
include BaseModel
|
||||
include Publicable
|
||||
include Publishable
|
||||
include Lockable
|
||||
|
||||
belongs_to :container, polymorphic: true, optional: true
|
||||
belongs_to :author, class_name: "User", foreign_key: :author_id
|
||||
# belongs_to :course, foreign_key: :container_id, optional: true
|
||||
# has_many :attachment_group_settings, :dependent => :destroy
|
||||
# has_many :attachment_histories, -> { order(version: :desc) }, :dependent => :destroy
|
||||
# 二级目录
|
||||
# belongs_to :course_second_category, optional: true
|
||||
|
||||
scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(concat(users.lastname, users.firstname)) LIKE :search",
|
||||
:search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
|
||||
scope :by_keywords, -> (keywords) { where("filename LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
|
||||
scope :ordered, -> (opts = {}) { order("#{opts[:sort_type]} #{opts[:sort] == 1 ? 'asc': 'desc'}") }
|
||||
scope :by_course_second_category_id, -> (course_second_category_id = 0) { where(course_second_category_id: course_second_category_id) }
|
||||
scope :contains_only_course, -> { where(container_type: 'Course') }
|
||||
scope :contains_only_project, -> { where(container_type: 'Project') }
|
||||
scope :contains_course_and_project, -> { contains_only_course.or(contains_only_project) }
|
||||
scope :mine, -> (author_id) { where(author_id: author_id) }
|
||||
scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type, :container_type, :container_id) }
|
||||
scope :search_by_container, -> (ids) {where(container_id: ids)}
|
||||
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
|
||||
|
||||
validates_length_of :description, maximum: 100, message: "不能超过100个字符"
|
||||
|
||||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
|
||||
def diskfile
|
||||
File.join(File.join(Rails.root, "files"), disk_directory.to_s, disk_filename.to_s)
|
||||
end
|
||||
|
||||
def relative_path_filename
|
||||
File.join(disk_directory.to_s, disk_filename.to_s)
|
||||
end
|
||||
|
||||
def title
|
||||
filename
|
||||
# title = filename
|
||||
# if container && container.is_a?(StudentWork) && author_id != User.current.id
|
||||
# course = container&.homework_common&.course
|
||||
# unless User.current.teacher_of_course?(course)
|
||||
# title = "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{DCODES.sample(8).join}" + File.extname(filename)
|
||||
# end
|
||||
# end
|
||||
# title
|
||||
end
|
||||
|
||||
def downloads_count
|
||||
downloads
|
||||
end
|
||||
|
||||
def quotes_count
|
||||
quotes.nil? ? 0 : quotes
|
||||
end
|
||||
|
||||
def self.associate_container(ids, container_id, container_type, attachtype=1)
|
||||
return false if ids.blank? || !ids.is_a?(Array)
|
||||
ids.each do |id|
|
||||
attachment = Attachment.find id
|
||||
attachment.update_attributes(container_id: container_id, container_type: container_type, attachtype: attachtype)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an unsaved copy of the attachment
|
||||
def copy(attributes=nil)
|
||||
copy = self.class.new
|
||||
copy.attributes = self.attributes.dup.except("id", "downloads", "quotes")
|
||||
copy.attributes = attributes if attributes
|
||||
copy
|
||||
end
|
||||
|
||||
def set_publish_time(publish_time)
|
||||
self.unified_setting = 1
|
||||
if publish_time.blank?
|
||||
self.publish_time = Time.now
|
||||
self.is_publish = 1
|
||||
else
|
||||
self.is_publish = publish_time.to_s > (format_time Time.now).to_s ? 0 : 1
|
||||
self.publish_time = publish_time.to_s > (format_time Time.now).to_s ? publish_time : Time.now
|
||||
end
|
||||
end
|
||||
|
||||
def set_course_group_publish_time(course, course_group_publish_times)
|
||||
self.unified_setting = 0
|
||||
min_publish_time = ""
|
||||
course_group_publish_times.each do |obj|
|
||||
if obj && obj[:course_group_id]
|
||||
publish_time = obj[:publish_time]
|
||||
if !publish_time.blank? && publish_time < min_publish_time
|
||||
min_publish_time = publish_time
|
||||
elsif publish_time.blank?
|
||||
publish_time = Time.now
|
||||
end
|
||||
attachment_group_setting = self.attachment_group_settings.where(course_group_id: obj[:course_group_id], course_id: course.id).first
|
||||
if attachment_group_setting.present?
|
||||
attachment_group_setting.update_columns(publish_time: publish_time)
|
||||
else
|
||||
self.attachment_group_settings.create(
|
||||
:course_group_id => obj[:course_group_id],
|
||||
:course_id => course.id,
|
||||
:publish_time => publish_time
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.is_publish = min_publish_time > (format_time Time.now).to_s ? 0 : 1
|
||||
self.publish_time = min_publish_time > (format_time Time.now).to_s ? min_publish_time : self.created_on
|
||||
end
|
||||
|
||||
def become_history
|
||||
history = self.attachment_histories.first
|
||||
new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id", "delay_publish").merge(
|
||||
attachment_id: self.id,
|
||||
version: history.nil? ? 1 : history.version + 1,
|
||||
))
|
||||
new_attachment_history
|
||||
end
|
||||
|
||||
def copy_attributes_from_new_attachment(new_attachment)
|
||||
self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time', "delay_publish")
|
||||
end
|
||||
|
||||
def set_public(is_public)
|
||||
if is_public == true
|
||||
is_public = 1
|
||||
elsif is_public == false
|
||||
is_public = 0
|
||||
end
|
||||
end
|
||||
|
||||
#判断是否为pdf文件
|
||||
def is_pdf?
|
||||
is_pdf = false
|
||||
file_content_type = content_type
|
||||
file_ext_type = File.extname(filename).strip.downcase[1..-1]
|
||||
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
|
||||
is_pdf = true
|
||||
end
|
||||
is_pdf
|
||||
end
|
||||
|
||||
end
|
||||
class Attachment < ApplicationRecord
|
||||
include BaseModel
|
||||
include Publicable
|
||||
include Publishable
|
||||
include Lockable
|
||||
include DunCheckImageAble
|
||||
belongs_to :container, polymorphic: true, optional: true
|
||||
belongs_to :author, class_name: "User", foreign_key: :author_id
|
||||
# belongs_to :course, foreign_key: :container_id, optional: true
|
||||
# has_many :attachment_group_settings, :dependent => :destroy
|
||||
# has_many :attachment_histories, -> { order(version: :desc) }, :dependent => :destroy
|
||||
# 二级目录
|
||||
# belongs_to :course_second_category, optional: true
|
||||
|
||||
scope :by_filename_or_user_name, -> (keywords) { joins(:author).where("filename like :search or LOWER(concat(users.lastname, users.firstname)) LIKE :search",
|
||||
:search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
|
||||
scope :by_keywords, -> (keywords) { where("filename LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank? }
|
||||
scope :ordered, -> (opts = {}) { order("#{opts[:sort_type]} #{opts[:sort] == 1 ? 'asc': 'desc'}") }
|
||||
scope :by_course_second_category_id, -> (course_second_category_id = 0) { where(course_second_category_id: course_second_category_id) }
|
||||
scope :contains_only_course, -> { where(container_type: 'Course') }
|
||||
scope :contains_only_project, -> { where(container_type: 'Project') }
|
||||
scope :contains_course_and_project, -> { contains_only_course.or(contains_only_project) }
|
||||
scope :mine, -> (author_id) { where(author_id: author_id) }
|
||||
scope :simple_columns, -> { select(:id, :filename, :filesize, :created_on, :cloud_url, :author_id, :content_type, :container_type, :container_id) }
|
||||
scope :search_by_container, -> (ids) {where(container_id: ids)}
|
||||
scope :unified_setting, -> {where("unified_setting = ? ", 1)}
|
||||
|
||||
validates_length_of :description, maximum: 100, message: "不能超过100个字符"
|
||||
|
||||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
|
||||
def diskfile
|
||||
File.join(File.join(Rails.root, "files"), disk_directory.to_s, disk_filename.to_s)
|
||||
end
|
||||
|
||||
def relative_path_filename
|
||||
File.join(disk_directory.to_s, disk_filename.to_s)
|
||||
end
|
||||
|
||||
def title
|
||||
filename
|
||||
# title = filename
|
||||
# if container && container.is_a?(StudentWork) && author_id != User.current.id
|
||||
# course = container&.homework_common&.course
|
||||
# unless User.current.teacher_of_course?(course)
|
||||
# title = "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{DCODES.sample(8).join}" + File.extname(filename)
|
||||
# end
|
||||
# end
|
||||
# title
|
||||
end
|
||||
|
||||
def downloads_count
|
||||
downloads
|
||||
end
|
||||
|
||||
def quotes_count
|
||||
quotes.nil? ? 0 : quotes
|
||||
end
|
||||
|
||||
def self.associate_container(ids, container_id, container_type, attachtype=1)
|
||||
return false if ids.blank? || !ids.is_a?(Array)
|
||||
ids.each do |id|
|
||||
attachment = Attachment.find id
|
||||
attachment.update_attributes(container_id: container_id, container_type: container_type, attachtype: attachtype)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an unsaved copy of the attachment
|
||||
def copy(attributes=nil)
|
||||
copy = self.class.new
|
||||
copy.attributes = self.attributes.dup.except("id", "downloads", "quotes")
|
||||
copy.attributes = attributes if attributes
|
||||
copy
|
||||
end
|
||||
|
||||
def set_publish_time(publish_time)
|
||||
self.unified_setting = 1
|
||||
if publish_time.blank?
|
||||
self.publish_time = Time.now
|
||||
self.is_publish = 1
|
||||
else
|
||||
self.is_publish = publish_time.to_s > (format_time Time.now).to_s ? 0 : 1
|
||||
self.publish_time = publish_time.to_s > (format_time Time.now).to_s ? publish_time : Time.now
|
||||
end
|
||||
end
|
||||
|
||||
def set_course_group_publish_time(course, course_group_publish_times)
|
||||
self.unified_setting = 0
|
||||
min_publish_time = ""
|
||||
course_group_publish_times.each do |obj|
|
||||
if obj && obj[:course_group_id]
|
||||
publish_time = obj[:publish_time]
|
||||
if !publish_time.blank? && publish_time < min_publish_time
|
||||
min_publish_time = publish_time
|
||||
elsif publish_time.blank?
|
||||
publish_time = Time.now
|
||||
end
|
||||
attachment_group_setting = self.attachment_group_settings.where(course_group_id: obj[:course_group_id], course_id: course.id).first
|
||||
if attachment_group_setting.present?
|
||||
attachment_group_setting.update_columns(publish_time: publish_time)
|
||||
else
|
||||
self.attachment_group_settings.create(
|
||||
:course_group_id => obj[:course_group_id],
|
||||
:course_id => course.id,
|
||||
:publish_time => publish_time
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.is_publish = min_publish_time > (format_time Time.now).to_s ? 0 : 1
|
||||
self.publish_time = min_publish_time > (format_time Time.now).to_s ? min_publish_time : self.created_on
|
||||
end
|
||||
|
||||
def become_history
|
||||
history = self.attachment_histories.first
|
||||
new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id", "delay_publish").merge(
|
||||
attachment_id: self.id,
|
||||
version: history.nil? ? 1 : history.version + 1,
|
||||
))
|
||||
new_attachment_history
|
||||
end
|
||||
|
||||
def copy_attributes_from_new_attachment(new_attachment)
|
||||
self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time', "delay_publish")
|
||||
end
|
||||
|
||||
def set_public(is_public)
|
||||
if is_public == true
|
||||
is_public = 1
|
||||
elsif is_public == false
|
||||
is_public = 0
|
||||
end
|
||||
end
|
||||
|
||||
#判断是否为pdf文件
|
||||
def is_pdf?
|
||||
is_pdf = false
|
||||
file_content_type = content_type
|
||||
file_ext_type = File.extname(filename).strip.downcase[1..-1]
|
||||
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
|
||||
is_pdf = true
|
||||
end
|
||||
is_pdf
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
# container_type :string(255)
|
||||
# filename :string(255) default("")
|
||||
# disk_filename :string(255) default("")
|
||||
# filesize :integer default("0")
|
||||
# filesize :integer default(0)
|
||||
# content_type :string(255) default("")
|
||||
# digest :string(60) default("")
|
||||
# downloads :integer default("0")
|
||||
# digest :string(40) default("")
|
||||
# downloads :integer default(0)
|
||||
# author_id :integer
|
||||
# created_on :datetime
|
||||
# description :text(65535)
|
||||
|
|
@ -21,41 +21,42 @@
|
|||
# quotes :integer
|
||||
# version :integer
|
||||
# attachment_id :integer
|
||||
# is_publish :integer default("1")
|
||||
# is_publish :integer default("published")
|
||||
# publish_time :date
|
||||
# cloud_url :string(255) default("")
|
||||
# memo_image :boolean default(FALSE)
|
||||
# extra_type :integer default(0)
|
||||
#
|
||||
|
||||
class AttachmentHistory < ApplicationRecord
|
||||
include Publishable
|
||||
include Publicable
|
||||
|
||||
belongs_to :attachment, foreign_key: 'attachment_id'
|
||||
|
||||
def title
|
||||
filename
|
||||
end
|
||||
|
||||
def downloads_count
|
||||
downloads
|
||||
end
|
||||
|
||||
def quotes_count
|
||||
quotes.nil? ? 0 : quotes
|
||||
end
|
||||
|
||||
def public?
|
||||
is_public == 1
|
||||
end
|
||||
|
||||
def is_history_pdf?
|
||||
is_pdf = false
|
||||
file_content_type = content_type
|
||||
file_ext_type = File.extname(filename).strip.downcase[1..-1]
|
||||
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
|
||||
is_pdf = true
|
||||
end
|
||||
is_pdf
|
||||
end
|
||||
|
||||
end
|
||||
class AttachmentHistory < ApplicationRecord
|
||||
include Publishable
|
||||
include Publicable
|
||||
|
||||
belongs_to :attachment, foreign_key: 'attachment_id'
|
||||
|
||||
def title
|
||||
filename
|
||||
end
|
||||
|
||||
def downloads_count
|
||||
downloads
|
||||
end
|
||||
|
||||
def quotes_count
|
||||
quotes.nil? ? 0 : quotes
|
||||
end
|
||||
|
||||
def public?
|
||||
is_public == 1
|
||||
end
|
||||
|
||||
def is_history_pdf?
|
||||
is_pdf = false
|
||||
file_content_type = content_type
|
||||
file_ext_type = File.extname(filename).strip.downcase[1..-1]
|
||||
if (file_content_type.present? && file_content_type.downcase.include?("pdf")) || (file_ext_type.present? && file_ext_type.include?("pdf"))
|
||||
is_pdf = true
|
||||
end
|
||||
is_pdf
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ci_user_id :integer
|
||||
# server_type :integer default("0")
|
||||
# server_type :integer default(0)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# id :integer not null, primary key
|
||||
# name :string(255) not null
|
||||
# content :text(65535) not null
|
||||
# usage_amount :integer default("0")
|
||||
# usage_amount :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# cover_id :integer
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# login :string(255)
|
||||
# sync :integer default("0"), not null
|
||||
# sync :integer default(0), not null
|
||||
# identifier :string(255)
|
||||
# branch :string(255)
|
||||
# event :string(255)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# stage_name :string(255) not null
|
||||
# stage_type :string(255) not null
|
||||
# pipeline_id :integer not null
|
||||
# show_index :integer default("0"), not null
|
||||
# show_index :integer default(0), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
# stage_id :integer not null
|
||||
# template_id :integer
|
||||
# content :text(65535)
|
||||
# show_index :integer default("0"), not null
|
||||
# show_index :integer default(0), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
# firstname :string(30) default(""), not null
|
||||
# lastname :string(255) default(""), not null
|
||||
# mail :string(60)
|
||||
# admin :boolean default("0"), not null
|
||||
# status :integer default("1"), not null
|
||||
# admin :boolean default(FALSE), not null
|
||||
# status :integer default(1), not null
|
||||
# last_login_on :datetime
|
||||
# language :string(5) default("")
|
||||
# auth_source_id :integer
|
||||
|
|
@ -20,32 +20,35 @@
|
|||
# mail_notification :string(255) default(""), not null
|
||||
# salt :string(64)
|
||||
# gid :integer
|
||||
# visits :integer default("0")
|
||||
# excellent_teacher :integer default("0")
|
||||
# excellent_student :integer default("0")
|
||||
# visits :integer default(0)
|
||||
# excellent_teacher :integer default(0)
|
||||
# excellent_student :integer default(0)
|
||||
# phone :string(255)
|
||||
# authentication :boolean default("0")
|
||||
# grade :integer default("0")
|
||||
# experience :integer default("0")
|
||||
# authentication :boolean default(FALSE)
|
||||
# grade :integer default(0)
|
||||
# experience :integer default(0)
|
||||
# nickname :string(255)
|
||||
# show_realname :boolean default("1")
|
||||
# professional_certification :boolean default("0")
|
||||
# show_realname :boolean default(TRUE)
|
||||
# professional_certification :boolean default(FALSE)
|
||||
# ID_number :string(255)
|
||||
# certification :integer default("0")
|
||||
# homepage_teacher :boolean default("0")
|
||||
# homepage_engineer :boolean default("0")
|
||||
# is_test :integer default("0")
|
||||
# ecoder_user_id :integer default("0")
|
||||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# certification :integer default(0)
|
||||
# homepage_teacher :boolean default(FALSE)
|
||||
# homepage_engineer :boolean default(FALSE)
|
||||
# is_test :integer default(0)
|
||||
# ecoder_user_id :integer default(0)
|
||||
# business :boolean default(FALSE)
|
||||
# profile_completed :boolean default(FALSE)
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
# is_shixun_marker :boolean default(FALSE)
|
||||
# is_sync_pwd :boolean default(TRUE)
|
||||
# watchers_count :integer default(0)
|
||||
# enterprise_certification :boolean default(FALSE)
|
||||
# admin_role :integer default(0)
|
||||
# devops_step :integer default(0)
|
||||
# company_name :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: competitions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# title :string(255)
|
||||
# start_time :datetime
|
||||
# end_time :datetime
|
||||
# identifier :string(255)
|
||||
# available :boolean default(FALSE)
|
||||
# online_time :datetime
|
||||
# visits :integer default(0)
|
||||
# competition_lists_count :integer default(0)
|
||||
# min_num :integer default(1)
|
||||
# max_num :integer default(1)
|
||||
# enroll_end_time :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# status :integer default("archived")
|
||||
# subtitle :string(255)
|
||||
# team_members_count :integer default(0)
|
||||
# limit_type :integer default(0)
|
||||
# show_top :integer default(0)
|
||||
# content :text(65535)
|
||||
# enroll_begin_time :datetime
|
||||
# review_time :datetime
|
||||
# result_time :datetime
|
||||
# org_name :string(255)
|
||||
# show_banner :boolean default(FALSE)
|
||||
# is_expert_audit :boolean default(FALSE)
|
||||
# outer_url :string(255)
|
||||
#
|
||||
|
||||
class Competition < ApplicationRecord
|
||||
|
||||
enum status: {archived: 0, active: 1}
|
||||
end
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: competition_infos
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# identifier :string(255)
|
||||
# title :string(255)
|
||||
# content :text(4294967295)
|
||||
# video_url :string(255)
|
||||
# manager_ids :string(255)
|
||||
# zones :string(255)
|
||||
# sub_competitions :string(255)
|
||||
# is_local :boolean default(FALSE)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# enroll_date :datetime
|
||||
# upload_date :datetime
|
||||
# zones_local :string(255)
|
||||
# guide :text(65535)
|
||||
# about_us :text(65535)
|
||||
# banner_url :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_competition_infos_on_identifier (identifier) UNIQUE
|
||||
#
|
||||
|
||||
class CompetitionInfo < ApplicationRecord
|
||||
has_many :competition_users
|
||||
|
||||
def competition_zones
|
||||
self.is_local? ? self.zones_local.to_s.split(",") : self.zones.to_s.split(",")
|
||||
end
|
||||
|
||||
def competition_subs
|
||||
self.sub_competitions.to_s.split(",")
|
||||
end
|
||||
|
||||
# 管理员配置方式:id:赛区名称,id:赛区名称
|
||||
def manager_zones(user)
|
||||
return self.competition_zones if user.admin?
|
||||
return [] if self.manager_ids.blank?
|
||||
zones = []
|
||||
managers = manager_ids.split(",")
|
||||
managers.each do |u|
|
||||
zones.push(u.split(":")[1]) if u.split(":")[0].to_s == user.id.to_s
|
||||
end
|
||||
zones
|
||||
end
|
||||
|
||||
# 管理员配置方式:id:赛区名称,id:赛区名称
|
||||
def is_manager?(user)
|
||||
return true if user.admin?
|
||||
managers = manager_ids.split(",")
|
||||
managers.select { |u| u.split(":")[0].to_s == user.id.to_s }.size > 0
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: competition_notices
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# competition_info_id :integer
|
||||
# user_id :integer
|
||||
# title :string(255)
|
||||
# content :text(4294967295)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_competition_notices_on_competition_info_id (competition_info_id)
|
||||
# index_competition_notices_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class CompetitionNotice < ApplicationRecord
|
||||
belongs_to :competition_info
|
||||
belongs_to :user
|
||||
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: competition_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# competition_info_id :integer
|
||||
# user_id :integer
|
||||
# leader :string(255)
|
||||
# org_name :string(255)
|
||||
# org_job :string(255)
|
||||
# org_rank :string(255)
|
||||
# zone :string(255)
|
||||
# sub_competition :string(255)
|
||||
# subject_source_type :integer
|
||||
# subject_source_name :string(255)
|
||||
# phone :string(255)
|
||||
# members :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_competition_users_on_competition_info_id (competition_info_id)
|
||||
# index_competition_users_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class CompetitionUser < ApplicationRecord
|
||||
belongs_to :competition_info
|
||||
belongs_to :user
|
||||
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
|
||||
serialize :members, JSON
|
||||
|
||||
# %i[real_name org_name org_job org_rank].each do |method_name|
|
||||
# define_method method_name do
|
||||
# members&.[](method_name.to_s)
|
||||
# end
|
||||
#
|
||||
# define_method "#{method_name}=" do |value|
|
||||
# self.config ||= {}
|
||||
# members.[]=(method_name.to_s, value)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def members_to_string
|
||||
return "" if members.blank?
|
||||
str = []
|
||||
members.each do |m|
|
||||
str.push("#{m["real_name"]} #{m["org_name"]} #{m["org_job"]} #{m["org_rank"]} ")
|
||||
end
|
||||
str.join(";")
|
||||
end
|
||||
end
|
||||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
class Compose < ApplicationRecord
|
||||
#组织
|
||||
belongs_to :user
|
||||
has_many :compose_projects
|
||||
has_many :compose_users
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
module DunCheckAble
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# validate :check_text_able # 敏感词过滤
|
||||
end
|
||||
|
||||
def check_text_able
|
||||
dun_check_params = get_model
|
||||
if dun_check_params[:is_change]
|
||||
dun_check_params.delete(:is_change)
|
||||
check_result = DunCheck::TextCheck.new(dun_check_params).call
|
||||
if check_result[:status].to_i == -1
|
||||
errors.add(:base, "内容含有:#{check_result[:extra_params][:infos]},请修改")
|
||||
# raise ActiveRecord::RecordInvalid.new(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_model
|
||||
dun_model = self.class.name
|
||||
case dun_model
|
||||
when "Issue"
|
||||
check_params = {
|
||||
title: self.subject,
|
||||
content: self.description,
|
||||
is_change: (self.subject_changed? || self.description_changed?) && self.subject.present? && self.description.present?
|
||||
}
|
||||
when "PullRequest"
|
||||
check_params = {
|
||||
title: "",
|
||||
content: self.body,
|
||||
is_change: self.body_changed? && self.body.present?
|
||||
}
|
||||
when "Journal"
|
||||
check_params = {
|
||||
title: "",
|
||||
content: self.notes,
|
||||
is_change: self.notes_changed? && self.notes.present?
|
||||
}
|
||||
when "Version"
|
||||
check_params = {
|
||||
title: self.name,
|
||||
content: self.description,
|
||||
is_change: (self.name_changed? || self.description_changed?) && self.name.present? && self.description.present?
|
||||
}
|
||||
end
|
||||
return check_params
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
module DunCheckImageAble
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
def self.check_image_able(file)
|
||||
original_filename = file.original_filename
|
||||
file_extention = original_filename.split(".").last
|
||||
check_include = %w(jpg png bmp gif webp tiff jpeg)
|
||||
|
||||
if file_extention && check_include.include?(file_extention)
|
||||
base64_file = Base64.encode64(file.open.read.force_encoding(Encoding::UTF_8))
|
||||
check_params = [
|
||||
{
|
||||
name: original_filename,
|
||||
type: 2,
|
||||
data: base64_file,
|
||||
}
|
||||
]
|
||||
check_result = DunCheck::ImageCheck.new(check_params).call
|
||||
if check_result[:status].to_i == -1
|
||||
return {status: -1, message: check_result[:message]}
|
||||
else
|
||||
return {status: 1}
|
||||
end
|
||||
else
|
||||
return {status: 1}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -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("projects.name like :search or projects.identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ module ProjectAbility
|
|||
|
||||
def can_read_project?(project)
|
||||
return true if self.admin?
|
||||
return true if project.is_secret
|
||||
return false if !project.is_public? && !project.member?(self.id)
|
||||
true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ module ProjectOperable
|
|||
has_many :team_projects, dependent: :destroy
|
||||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
member = members.create!(user_id: user_id)
|
||||
def add_member!(user_id, role_name='Developer', is_apply_signature=false)
|
||||
member = members.create!(user_id: user_id, is_apply_signature: is_apply_signature)
|
||||
set_developer_role(member, role_name)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
# img_type :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# position :integer
|
||||
#
|
||||
|
||||
class CooImg < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -1,5 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: forge_activities
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# forge_act_id :integer
|
||||
# forge_act_type :string(255)
|
||||
# org_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# forge_act_index (project_id,forge_act_id,created_at,forge_act_type)
|
||||
# index_forge_activities_on_forge_act_id (forge_act_id)
|
||||
#
|
||||
|
||||
class ForgeActivity < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :forge_act, polymorphic: true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: helps
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# about_us :text(65535)
|
||||
# agreement :text(65535)
|
||||
# status :text(65535)
|
||||
# help_center :text(65535)
|
||||
#
|
||||
|
||||
class Help < ApplicationRecord
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,19 +17,19 @@
|
|||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# start_date :date
|
||||
# done_ratio :integer default("0"), not null
|
||||
# done_ratio :integer default(0), not null
|
||||
# estimated_hours :float(24)
|
||||
# parent_id :integer
|
||||
# root_id :integer
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# is_private :boolean default("0"), not null
|
||||
# is_private :boolean default(FALSE), not null
|
||||
# closed_on :datetime
|
||||
# project_issues_index :integer
|
||||
# issue_type :string(255)
|
||||
# token :integer default("0")
|
||||
# token :integer default(0)
|
||||
# issue_tags_value :string(255)
|
||||
# is_lock :boolean default("0")
|
||||
# is_lock :boolean default(FALSE)
|
||||
# issue_classify :string(255)
|
||||
# ref_name :string(255)
|
||||
# branch_name :string(255)
|
||||
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
class Issue < ApplicationRecord
|
||||
#issue_type 1为普通,2为悬赏
|
||||
include DunCheckAble
|
||||
belongs_to :project, :counter_cache => true
|
||||
belongs_to :tracker,optional: true
|
||||
has_many :project_trends, as: :trend, dependent: :destroy
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(30) default(""), not null
|
||||
# is_closed :boolean default("0"), not null
|
||||
# is_default :boolean default("0"), not null
|
||||
# position :integer default("1")
|
||||
# is_closed :boolean default(FALSE), not null
|
||||
# is_default :boolean default(FALSE), not null
|
||||
# position :integer default(1)
|
||||
# default_done_ratio :integer
|
||||
#
|
||||
# Indexes
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
# color :string(255)
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# issues_count :integer default("0")
|
||||
# issues_count :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# gid :integer
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
# Table name: journals
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# journalized_id :integer default("0"), not null
|
||||
# journalized_id :integer default(0), not null
|
||||
# journalized_type :string(30) default(""), not null
|
||||
# user_id :integer default("0"), not null
|
||||
# user_id :integer default(0), not null
|
||||
# notes :text(65535)
|
||||
# created_on :datetime not null
|
||||
# private_notes :boolean default("0"), not null
|
||||
# private_notes :boolean default(FALSE), not null
|
||||
# parent_id :integer
|
||||
# comments_count :integer default("0")
|
||||
# comments_count :integer default(0)
|
||||
# reply_id :integer
|
||||
#
|
||||
# Indexes
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#
|
||||
|
||||
class Journal < ApplicationRecord
|
||||
include DunCheckAble
|
||||
belongs_to :user
|
||||
belongs_to :issue, foreign_key: :journalized_id, :touch => true
|
||||
has_many :journal_details, :dependent => :delete_all
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# Table name: journal_details
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# journal_id :integer default("0"), not null
|
||||
# journal_id :integer default(0), not null
|
||||
# property :string(30) default(""), not null
|
||||
# prop_key :string(30) default(""), not null
|
||||
# old_value :text(65535)
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
# m_reply_count :integer
|
||||
# m_reply_id :integer
|
||||
# is_comprehensive_evaluation :integer
|
||||
# private :integer default("0")
|
||||
# private :integer default(0)
|
||||
# root_id :integer
|
||||
# hidden :boolean default("0")
|
||||
# praises_count :integer default("0")
|
||||
# hidden :boolean default(FALSE)
|
||||
# praises_count :integer default(0)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -27,83 +27,83 @@
|
|||
# index_journals_for_messages_on_root_id (root_id)
|
||||
#
|
||||
|
||||
class JournalsForMessage < ApplicationRecord
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :parent, class_name: "JournalsForMessage", foreign_key: "m_parent_id",
|
||||
counter_cache: :m_reply_count, optional: true
|
||||
|
||||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
#scope :children, -> {where(m_parent_id: self.id).includes(:user).reorder("created_on asc")}
|
||||
#scope :children, -> (discuss_id){ where(parent_id: discuss_id).includes(:user).reorder("created_at asc") }
|
||||
|
||||
scope :parent_comment, -> { where(m_parent_id: nil)}
|
||||
scope :search_by_jour_type, lambda{|type,ids| where(jour_type:type,jour_id: ids)}
|
||||
has_many :tidings, as: :container, dependent: :destroy
|
||||
|
||||
# "jour_type", # 留言所属类型
|
||||
# "jour_id", # 留言所属类型的id
|
||||
# "notes", # 留言内容
|
||||
# "reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
# "status", # 留言是否被查看(弃用)
|
||||
# "user_id", # 留言者的id
|
||||
# "m_parent_id", # 留言信息的父留言id
|
||||
# "is_readed", # 留言是否已读
|
||||
# "m_reply_count", # 留言的回复数量
|
||||
# "m_reply_id" , # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
# "is_comprehensive_evaluation", # 1 教师评论、2 匿评、3 留言
|
||||
# "hidden", 隐藏、
|
||||
|
||||
validates :notes, length: { maximum: 2000, too_long: "不能超过2000个字符" }
|
||||
|
||||
after_create :send_tiding
|
||||
|
||||
|
||||
# course_identity 课堂用户身份
|
||||
def contents_show course_identity
|
||||
if self.hidden && course_identity >= Course::STUDENT
|
||||
nil
|
||||
else
|
||||
self.notes
|
||||
end
|
||||
end
|
||||
|
||||
def can_delete course_identity
|
||||
course_identity < Course::STUDENT
|
||||
end
|
||||
|
||||
def created_at
|
||||
self.created_on
|
||||
end
|
||||
|
||||
def children page, limit
|
||||
JournalsForMessage.includes(:user).where(m_parent_id: self.id).page(page).per(limit).reorder("created_on asc")
|
||||
end
|
||||
|
||||
|
||||
def send_tiding
|
||||
# 回复和@同一个人时:只发@的消息(因@的消息先创建)
|
||||
case self.jour_type
|
||||
# 用户留言当做私信处理 不发消息
|
||||
when "Principal"
|
||||
=begin
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour_id
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour_id, :belong_container_type => "User", :viewed => 0, :tiding_type => self.m_parent_id.present? ? "Comment" : "Journal")
|
||||
end
|
||||
=end
|
||||
when "HomeworkCommon", "GraduationTopic"
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : (self.jour_type == "HomeworkCommon" ? self.jour.user_id : self.jour.tea_id)
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour.course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
|
||||
end
|
||||
when "StudentWorksScore"
|
||||
course_id = self.jour.try(:student_work).try(:homework_common).try(:course_id)
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour.user_id
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
class JournalsForMessage < ApplicationRecord
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :parent, class_name: "JournalsForMessage", foreign_key: "m_parent_id",
|
||||
counter_cache: :m_reply_count, optional: true
|
||||
|
||||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
#scope :children, -> {where(m_parent_id: self.id).includes(:user).reorder("created_on asc")}
|
||||
#scope :children, -> (discuss_id){ where(parent_id: discuss_id).includes(:user).reorder("created_at asc") }
|
||||
|
||||
scope :parent_comment, -> { where(m_parent_id: nil)}
|
||||
scope :search_by_jour_type, lambda{|type,ids| where(jour_type:type,jour_id: ids)}
|
||||
has_many :tidings, as: :container, dependent: :destroy
|
||||
|
||||
# "jour_type", # 留言所属类型
|
||||
# "jour_id", # 留言所属类型的id
|
||||
# "notes", # 留言内容
|
||||
# "reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
# "status", # 留言是否被查看(弃用)
|
||||
# "user_id", # 留言者的id
|
||||
# "m_parent_id", # 留言信息的父留言id
|
||||
# "is_readed", # 留言是否已读
|
||||
# "m_reply_count", # 留言的回复数量
|
||||
# "m_reply_id" , # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
# "is_comprehensive_evaluation", # 1 教师评论、2 匿评、3 留言
|
||||
# "hidden", 隐藏、
|
||||
|
||||
validates :notes, length: { maximum: 2000, too_long: "不能超过2000个字符" }
|
||||
|
||||
after_create :send_tiding
|
||||
|
||||
|
||||
# course_identity 课堂用户身份
|
||||
def contents_show course_identity
|
||||
if self.hidden && course_identity >= Course::STUDENT
|
||||
nil
|
||||
else
|
||||
self.notes
|
||||
end
|
||||
end
|
||||
|
||||
def can_delete course_identity
|
||||
course_identity < Course::STUDENT
|
||||
end
|
||||
|
||||
def created_at
|
||||
self.created_on
|
||||
end
|
||||
|
||||
def children page, limit
|
||||
JournalsForMessage.includes(:user).where(m_parent_id: self.id).page(page).per(limit).reorder("created_on asc")
|
||||
end
|
||||
|
||||
|
||||
def send_tiding
|
||||
# 回复和@同一个人时:只发@的消息(因@的消息先创建)
|
||||
case self.jour_type
|
||||
# 用户留言当做私信处理 不发消息
|
||||
when "Principal"
|
||||
=begin
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour_id
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour_id, :belong_container_type => "User", :viewed => 0, :tiding_type => self.m_parent_id.present? ? "Comment" : "Journal")
|
||||
end
|
||||
=end
|
||||
when "HomeworkCommon", "GraduationTopic"
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : (self.jour_type == "HomeworkCommon" ? self.jour.user_id : self.jour.tea_id)
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour.course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
|
||||
end
|
||||
when "StudentWorksScore"
|
||||
course_id = self.jour.try(:student_work).try(:homework_common).try(:course_id)
|
||||
user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour.user_id
|
||||
if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,9 +7,14 @@
|
|||
# identifier :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# sync_course :boolean default("0")
|
||||
# sync_subject :boolean default("0")
|
||||
# sync_shixun :boolean default("0")
|
||||
# sync_course :boolean default(FALSE)
|
||||
# sync_subject :boolean default(FALSE)
|
||||
# sync_shixun :boolean default(FALSE)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_laboratories_on_identifier (identifier) UNIQUE
|
||||
# index_laboratories_on_school_id (school_id)
|
||||
#
|
||||
|
||||
class Laboratory < ApplicationRecord
|
||||
|
|
@ -36,9 +41,10 @@ class Laboratory < ApplicationRecord
|
|||
|
||||
delegate :name, :navbar, :footer, :login_logo_url, :nav_logo_url, :tab_logo_url, :default_navbar, to: :laboratory_setting
|
||||
|
||||
# TODO 域名申请后更改
|
||||
def site
|
||||
rails_env = EduSetting.get('rails_env')
|
||||
suffix = rails_env && rails_env != 'production' ? ".#{rails_env}.trustie.net" : '.trustie.net'
|
||||
suffix = rails_env && rails_env != 'production' ? "39.105.176.215" : '39.105.176.215'
|
||||
|
||||
identifier ? "#{identifier}#{suffix}" : ''
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
# laboratory_id :integer
|
||||
# config :text(65535)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_laboratory_settings_on_laboratory_id (laboratory_id)
|
||||
#
|
||||
|
||||
class LaboratorySetting < ApplicationRecord
|
||||
belongs_to :laboratory
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# is_secret :boolean default("0")
|
||||
# is_secret :boolean default(FALSE)
|
||||
#
|
||||
|
||||
class License < ApplicationRecord
|
||||
include Projectable
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
# Table name: members
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer default("0"), not null
|
||||
# project_id :integer default("0")
|
||||
# user_id :integer default(0), not null
|
||||
# project_id :integer default(0)
|
||||
# created_on :datetime
|
||||
# mail_notification :boolean default("0"), not null
|
||||
# course_id :integer default("-1")
|
||||
# course_group_id :integer default("0")
|
||||
# is_collect :integer default("1")
|
||||
# graduation_group_id :integer default("0")
|
||||
# is_apply_signature :boolean default("0")
|
||||
# mail_notification :boolean default(FALSE), not null
|
||||
# course_id :integer default(-1)
|
||||
# course_group_id :integer default(0)
|
||||
# is_collect :integer default(1)
|
||||
# graduation_group_id :integer default(0)
|
||||
# is_apply_signature :boolean default(FALSE)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -21,14 +21,14 @@
|
|||
# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE
|
||||
#
|
||||
|
||||
class Member < ApplicationRecord
|
||||
belongs_to :user
|
||||
# belongs_to :course, optional: true
|
||||
belongs_to :project, optional: true
|
||||
|
||||
has_many :member_roles, dependent: :destroy
|
||||
has_many :roles, through: :member_roles
|
||||
|
||||
validates :user_id, :project_id, presence: true
|
||||
|
||||
end
|
||||
class Member < ApplicationRecord
|
||||
belongs_to :user
|
||||
# belongs_to :course, optional: true
|
||||
belongs_to :project, optional: true
|
||||
|
||||
has_many :member_roles, dependent: :destroy
|
||||
has_many :roles, through: :member_roles
|
||||
|
||||
validates :user_id, :project_id, presence: true
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# member_id :integer not null
|
||||
# role_id :integer not null
|
||||
# inherited_from :integer
|
||||
# is_current :integer default("1")
|
||||
# is_current :integer default(1)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
# index_member_roles_on_role_id (role_id)
|
||||
#
|
||||
|
||||
class MemberRole < ApplicationRecord
|
||||
belongs_to :role
|
||||
belongs_to :member
|
||||
|
||||
validates :member_id, :role_id, presence: true
|
||||
end
|
||||
class MemberRole < ApplicationRecord
|
||||
belongs_to :role
|
||||
belongs_to :member
|
||||
|
||||
validates :member_id, :role_id, presence: true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#
|
||||
# id :integer not null, primary key
|
||||
# repo_id :integer
|
||||
# status :integer default("0"), not null
|
||||
# status :integer default("succeeded"), not null
|
||||
# interval :integer
|
||||
# next_update_time :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# sync_num :integer default("1")
|
||||
# sync_num :integer default(1)
|
||||
#
|
||||
|
||||
class Mirror < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
# token_expires_in :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# user_id :integer default("0")
|
||||
# user_id :integer default(0)
|
||||
# gitea_oauth_id :integer
|
||||
# project_id :integer
|
||||
#
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_onclick_times_on_user_id (user_id)
|
||||
# index_onclick_times_on_onclick_time (onclick_time)
|
||||
#
|
||||
|
||||
class OnclickTime < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
end
|
||||
class OnclickTime < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
# firstname :string(30) default(""), not null
|
||||
# lastname :string(255) default(""), not null
|
||||
# mail :string(60)
|
||||
# admin :boolean default("0"), not null
|
||||
# status :integer default("1"), not null
|
||||
# admin :boolean default(FALSE), not null
|
||||
# status :integer default(1), not null
|
||||
# last_login_on :datetime
|
||||
# language :string(5) default("")
|
||||
# auth_source_id :integer
|
||||
|
|
@ -20,32 +20,35 @@
|
|||
# mail_notification :string(255) default(""), not null
|
||||
# salt :string(64)
|
||||
# gid :integer
|
||||
# visits :integer default("0")
|
||||
# excellent_teacher :integer default("0")
|
||||
# excellent_student :integer default("0")
|
||||
# visits :integer default(0)
|
||||
# excellent_teacher :integer default(0)
|
||||
# excellent_student :integer default(0)
|
||||
# phone :string(255)
|
||||
# authentication :boolean default("0")
|
||||
# grade :integer default("0")
|
||||
# experience :integer default("0")
|
||||
# authentication :boolean default(FALSE)
|
||||
# grade :integer default(0)
|
||||
# experience :integer default(0)
|
||||
# nickname :string(255)
|
||||
# show_realname :boolean default("1")
|
||||
# professional_certification :boolean default("0")
|
||||
# show_realname :boolean default(TRUE)
|
||||
# professional_certification :boolean default(FALSE)
|
||||
# ID_number :string(255)
|
||||
# certification :integer default("0")
|
||||
# homepage_teacher :boolean default("0")
|
||||
# homepage_engineer :boolean default("0")
|
||||
# is_test :integer default("0")
|
||||
# ecoder_user_id :integer default("0")
|
||||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# certification :integer default(0)
|
||||
# homepage_teacher :boolean default(FALSE)
|
||||
# homepage_engineer :boolean default(FALSE)
|
||||
# is_test :integer default(0)
|
||||
# ecoder_user_id :integer default(0)
|
||||
# business :boolean default(FALSE)
|
||||
# profile_completed :boolean default(FALSE)
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
# is_shixun_marker :boolean default(FALSE)
|
||||
# is_sync_pwd :boolean default(TRUE)
|
||||
# watchers_count :integer default(0)
|
||||
# enterprise_certification :boolean default(FALSE)
|
||||
# admin_role :integer default(0)
|
||||
# devops_step :integer default(0)
|
||||
# company_name :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
# description :string(255)
|
||||
# website :string(255)
|
||||
# location :string(255)
|
||||
# repo_admin_change_team_access :boolean default("0")
|
||||
# visibility :integer default("0")
|
||||
# max_repo_creation :integer default("-1")
|
||||
# repo_admin_change_team_access :boolean default(FALSE)
|
||||
# visibility :integer default("common")
|
||||
# max_repo_creation :integer default(-1)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# num_projects :integer default("0")
|
||||
# num_users :integer default("0")
|
||||
# num_teams :integer default("0")
|
||||
# num_projects :integer default(0)
|
||||
# num_users :integer default(0)
|
||||
# num_teams :integer default(0)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: phenglei_users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# phone :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class PhengleiUser < ApplicationRecord
|
||||
|
||||
validates :phone, uniqueness: true
|
||||
|
||||
def register
|
||||
User.find_by(phone: self.phone)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: platform_communicates
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# title :string(255)
|
||||
# content :text(65535)
|
||||
# tag_field :text(65535)
|
||||
# fake_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# order_index :integer default(0)
|
||||
#
|
||||
|
||||
class PlatformCommunicate < ApplicationRecord
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: platform_people
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# announcement :string(255)
|
||||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# fake_login :string(255)
|
||||
#
|
||||
|
||||
class PlatformPerson < ApplicationRecord
|
||||
|
||||
def image
|
||||
image_url('image')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def image_url(type)
|
||||
return nil unless Util::FileManage.exists?(self, type)
|
||||
Util::FileManage.source_disk_file_url(self, type)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: platform_statistics
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# visits :integer default(0)
|
||||
# users_count :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class PlatformStatistic < ApplicationRecord
|
||||
|
||||
def self.data
|
||||
data = self.last
|
||||
if data.present?
|
||||
return data
|
||||
else
|
||||
return PlatformStatistic.create(users_count: User.count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
# user_id :integer not null
|
||||
# praise_tread_object_id :integer
|
||||
# praise_tread_object_type :string(255)
|
||||
# praise_or_tread :integer default("1")
|
||||
# praise_or_tread :integer default(1)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
@ -15,29 +15,29 @@
|
|||
# praise_tread (praise_tread_object_id,praise_tread_object_type)
|
||||
#
|
||||
|
||||
class PraiseTread < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :praise_tread_object, polymorphic: true, counter_cache: :praises_count
|
||||
has_many :tidings, :as => :container, :dependent => :destroy
|
||||
|
||||
after_create :send_tiding
|
||||
|
||||
def send_tiding
|
||||
case self.praise_tread_object_type
|
||||
when "Memo","Message","Issue"
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.author_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
|
||||
when "Discuss","Challenge","HomeworkCommon","JournalsForMessage","Journal","GraduationTopic","GraduationTask", "Hack"
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.user_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_object_by_type_and_id(id, type)
|
||||
type.constantize find_by_id id
|
||||
end
|
||||
|
||||
# 用户是否点赞
|
||||
def self.user_praise?(user)
|
||||
self.select{|pt| pt.user_id == user.id}.length > 0
|
||||
end
|
||||
|
||||
end
|
||||
class PraiseTread < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :praise_tread_object, polymorphic: true, counter_cache: :praises_count
|
||||
has_many :tidings, :as => :container, :dependent => :destroy
|
||||
|
||||
after_create :send_tiding
|
||||
|
||||
def send_tiding
|
||||
case self.praise_tread_object_type
|
||||
when "Memo","Message","Issue"
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.author_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
|
||||
when "Discuss","Challenge","HomeworkCommon","JournalsForMessage","Journal","GraduationTopic","GraduationTask", "Hack"
|
||||
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.user_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_object_by_type_and_id(id, type)
|
||||
type.constantize find_by_id id
|
||||
end
|
||||
|
||||
# 用户是否点赞
|
||||
def self.user_praise?(user)
|
||||
self.select{|pt| pt.user_id == user.id}.length > 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,52 +6,53 @@
|
|||
# name :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# homepage :string(255) default("")
|
||||
# is_public :boolean default("1"), not null
|
||||
# is_public :boolean default(TRUE), not null
|
||||
# parent_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# identifier :string(255)
|
||||
# status :integer default("1"), not null
|
||||
# status :integer default(1), not null
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# inherit_members :boolean default("0"), not null
|
||||
# project_type :integer default("0")
|
||||
# hidden_repo :boolean default("0"), not null
|
||||
# attachmenttype :integer default("1")
|
||||
# inherit_members :boolean default(FALSE), not null
|
||||
# project_type :integer default("common")
|
||||
# hidden_repo :boolean default(FALSE), not null
|
||||
# attachmenttype :integer default(1)
|
||||
# user_id :integer
|
||||
# dts_test :integer default("0")
|
||||
# dts_test :integer default(0)
|
||||
# enterprise_name :string(255)
|
||||
# organization_id :integer
|
||||
# project_new_type :integer
|
||||
# gpid :integer
|
||||
# forked_from_project_id :integer
|
||||
# forked_count :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# hot :integer default("0")
|
||||
# forked_count :integer default(0)
|
||||
# publish_resource :integer default(0)
|
||||
# visits :integer default(0)
|
||||
# hot :integer default(0)
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# qrcode_expiretime :integer default(0)
|
||||
# script :text(65535)
|
||||
# training_status :integer default("0")
|
||||
# training_status :integer default(0)
|
||||
# rep_identifier :string(255)
|
||||
# project_category_id :integer
|
||||
# project_language_id :integer
|
||||
# license_id :integer
|
||||
# ignore_id :integer
|
||||
# praises_count :integer default("0")
|
||||
# watchers_count :integer default("0")
|
||||
# issues_count :integer default("0")
|
||||
# pull_requests_count :integer default("0")
|
||||
# praises_count :integer default(0)
|
||||
# watchers_count :integer default(0)
|
||||
# issues_count :integer default(0)
|
||||
# pull_requests_count :integer default(0)
|
||||
# language :string(255)
|
||||
# versions_count :integer default("0")
|
||||
# issue_tags_count :integer default("0")
|
||||
# closed_issues_count :integer default("0")
|
||||
# open_devops :boolean default("0")
|
||||
# versions_count :integer default(0)
|
||||
# issue_tags_count :integer default(0)
|
||||
# closed_issues_count :integer default(0)
|
||||
# open_devops :boolean default(FALSE)
|
||||
# gitea_webhook_id :integer
|
||||
# open_devops_count :integer default("0")
|
||||
# recommend :boolean default("0")
|
||||
# platform :integer default("0")
|
||||
# open_devops_count :integer default(0)
|
||||
# recommend :boolean default(FALSE)
|
||||
# platform :integer default("forge")
|
||||
# order_index :integer default(0)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -68,224 +69,228 @@
|
|||
# index_projects_on_updated_on (updated_on)
|
||||
#
|
||||
|
||||
|
||||
|
||||
class Project < ApplicationRecord
|
||||
include Matchable
|
||||
include Publicable
|
||||
include Watchable
|
||||
include ProjectOperable
|
||||
|
||||
# common:开源托管项目
|
||||
# mirror:普通镜像项目,没有定时同步功能
|
||||
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
|
||||
#
|
||||
enum project_type: { sync_mirror: 2, mirror: 1, common: 0 }
|
||||
|
||||
# forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台
|
||||
enum platform: { forge: 0, educoder: 1 }
|
||||
|
||||
belongs_to :ignore, optional: true
|
||||
belongs_to :license, optional: true
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
||||
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
|
||||
belongs_to :project_category, optional: true , :counter_cache => true
|
||||
belongs_to :project_language, optional: true , :counter_cache => true
|
||||
has_many :project_trends, dependent: :destroy
|
||||
has_many :watchers, as: :watchable, dependent: :destroy
|
||||
has_many :fork_users, dependent: :destroy
|
||||
has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy
|
||||
has_one :project_educoder, dependent: :destroy
|
||||
|
||||
has_one :project_score, dependent: :destroy
|
||||
has_one :repository, dependent: :destroy
|
||||
has_many :pull_requests, dependent: :destroy
|
||||
has_many :issue_tags, -> { order("issue_tags.created_at DESC") }, dependent: :destroy
|
||||
has_many :issues, dependent: :destroy
|
||||
# has_many :user_grades, dependent: :destroy
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
has_one :project_score, dependent: :destroy
|
||||
has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy
|
||||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||
has_one :project_detail, dependent: :destroy
|
||||
has_many :team_projects, dependent: :destroy
|
||||
|
||||
after_save :check_project_members
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||
|
||||
|
||||
|
||||
def self.search_project(search)
|
||||
ransack(name_or_identifier_cont: search)
|
||||
end
|
||||
# 创建者
|
||||
def creator
|
||||
User.find(user_id).full_name
|
||||
end
|
||||
|
||||
def members_user_infos
|
||||
members.joins(:roles).where("roles.name in ('Manager', 'Developer', 'Reporter')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User")
|
||||
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")
|
||||
# .pluck("users.id", "users.login","users.lastname", "users.firstname")
|
||||
end
|
||||
|
||||
def to_param
|
||||
self.identifier.parameterize
|
||||
end
|
||||
|
||||
def get_issues_count(status_id)
|
||||
if status_id.present?
|
||||
self&.issues.issue_issue.select(:id, :status_id).where(status_id: status_id)&.pluck(:id).size
|
||||
else
|
||||
self&.issues.issue_issue.select(:id)&.pluck(:id).size
|
||||
end
|
||||
end
|
||||
|
||||
def get_pull_requests_count(status_id)
|
||||
if status_id.present?
|
||||
self&.pull_requests.select(:id, :status).where(status: status_id)&.pluck(:id).size
|
||||
else
|
||||
self&.pull_requests.select(:id)&.pluck(:id).size
|
||||
end
|
||||
end
|
||||
|
||||
#创建项目管理员
|
||||
def check_project_members
|
||||
unless members.present? && members.exists?(user_id: self.user_id)
|
||||
member_params = {
|
||||
user_id: self.user_id,
|
||||
project_id: self.id
|
||||
}
|
||||
user_member = Member.new(member_params)
|
||||
if user_member.save
|
||||
role_id = Role.select(:id,:position).where(position: 3)&.first&.id
|
||||
MemberRole.create!(member_id: user_member.id ,role_id: role_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.init_bluck_repository
|
||||
Project.includes(:repository).find_each do |project|
|
||||
puts project.id
|
||||
next if project.owner.blank?
|
||||
if project.repository.blank?
|
||||
puts "########### start create repositoy #############"
|
||||
Repository.create!(project_id: project.id, identifier: Project.generate_identifier, user_id: project&.owner&.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.generate_identifier
|
||||
str_arr = (("a".."z").to_a + ("A".."Z").to_a)
|
||||
|
||||
str = str_arr.shuffle[0..8].join
|
||||
while Repository.exists?(identifier: str)
|
||||
str = str_arr.shuffle[0..8].join
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
def self.list_user_projects(user_id)
|
||||
projects = Project.is_private.select(:id,:user_id)
|
||||
user_not_show_1 = projects.where("user_id != ?",user_id).pluck(:id).uniq
|
||||
|
||||
user_show_2 = projects.joins(:members).where("members.user_id = ?", user_id).pluck(:id).uniq
|
||||
Project.where.not(id: (user_not_show_1 - user_show_2).uniq)
|
||||
end
|
||||
|
||||
def members_count
|
||||
members.select(:id).size
|
||||
end
|
||||
|
||||
|
||||
def can_visited?
|
||||
is_public? || User.current.admin? || member?(User.current)
|
||||
end
|
||||
|
||||
def releases_size(current_user_id, type)
|
||||
if current_user_id == self.user_id && type.to_s == "all"
|
||||
self.repository.version_releases_count
|
||||
else
|
||||
self.repository.version_releases.releases_size
|
||||
end
|
||||
end
|
||||
|
||||
def contributor_users
|
||||
self.pull_requests.select(:user_id).pluck(:user_id).uniq.size
|
||||
end
|
||||
|
||||
def open_issues_count
|
||||
issues_count - closed_issues_count
|
||||
end
|
||||
|
||||
def numerical_for_project_type
|
||||
self.class.name.constantize.project_types["#{self.project_type}"]
|
||||
end
|
||||
|
||||
def watched_by? user
|
||||
watchers.pluck(:user_id).include? user&.id
|
||||
end
|
||||
|
||||
def praised_by? user
|
||||
praise_treads.pluck(:user_id).include? user&.id
|
||||
end
|
||||
|
||||
def get_premission user
|
||||
permission = "Reporter"
|
||||
member = members.find_by(user: user)
|
||||
|
||||
member&.roles&.last&.name || permission
|
||||
end
|
||||
|
||||
def fork_project
|
||||
Project.find_by(id: self.forked_from_project_id)
|
||||
end
|
||||
|
||||
def self.members_projects(member_user_id)
|
||||
joins(:members).where(members: { user_id: member_user_id})
|
||||
end
|
||||
|
||||
def self.find_with_namespace(namespace_path, identifier)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Owner.find_by_login namespace_path
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
return nil if project.blank?
|
||||
|
||||
[project, user]
|
||||
end
|
||||
|
||||
def ci_reactivate?
|
||||
open_devops_count > 0
|
||||
end
|
||||
|
||||
def ci_reactivate!(ci_repo)
|
||||
ci_repo.update_column(:repo_active, 1)
|
||||
update_column(:open_devops, true)
|
||||
increment!(:open_devops_count)
|
||||
end
|
||||
|
||||
def self.sync_educoder_shixun(url, private_token, page, per_page)
|
||||
SyncEducoderShixunJob.perform_later(url, private_token, page, per_page)
|
||||
end
|
||||
|
||||
def self.update_common_projects_count!
|
||||
ps = ProjectStatistic.first
|
||||
ps.increment!(:common_projects_count) unless ps.blank?
|
||||
end
|
||||
|
||||
def self.update_mirror_projects_count!
|
||||
ps = ProjectStatistic.first
|
||||
ps.increment!(:mirror_projects_count) unless ps.blank?
|
||||
end
|
||||
|
||||
def set_updated_on(time)
|
||||
return if time.blank?
|
||||
update_column(:updated_on, time)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Project < ApplicationRecord
|
||||
include Matchable
|
||||
include Publicable
|
||||
include Watchable
|
||||
include ProjectOperable
|
||||
|
||||
# common:开源托管项目
|
||||
# mirror:普通镜像项目,没有定时同步功能
|
||||
# sync_mirror:同步镜像项目,有系统定时同步功能,且用户可手动同步操作
|
||||
#
|
||||
enum project_type: { sync_mirror: 2, mirror: 1, common: 0 }
|
||||
|
||||
# forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台
|
||||
enum platform: { forge: 0, educoder: 1 }
|
||||
|
||||
belongs_to :ignore, optional: true
|
||||
belongs_to :license, optional: true
|
||||
belongs_to :owner, class_name: 'Owner', foreign_key: :user_id, optional: true
|
||||
belongs_to :organization_extension, foreign_key: :user_id, primary_key: :organization_id, optional: true, counter_cache: :num_projects
|
||||
belongs_to :project_category, optional: true , :counter_cache => true
|
||||
belongs_to :project_language, optional: true , :counter_cache => true
|
||||
has_many :project_trends, dependent: :destroy
|
||||
has_many :watchers, as: :watchable, dependent: :destroy
|
||||
has_many :fork_users, dependent: :destroy
|
||||
has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy
|
||||
has_one :project_educoder, dependent: :destroy
|
||||
|
||||
has_one :project_score, dependent: :destroy
|
||||
has_one :repository, dependent: :destroy
|
||||
has_many :pull_requests, dependent: :destroy
|
||||
has_many :issue_tags, -> { order("issue_tags.created_at DESC") }, dependent: :destroy
|
||||
has_many :issues, dependent: :destroy
|
||||
# has_many :user_grades, dependent: :destroy
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
has_one :project_score, dependent: :destroy
|
||||
has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy
|
||||
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
|
||||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||
has_one :project_detail, dependent: :destroy
|
||||
has_many :apply_signatures, dependent: :destroy
|
||||
has_many :team_projects, dependent: :destroy
|
||||
|
||||
after_save :check_project_members
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||
|
||||
scope :secret_and_visible, -> {left_outer_joins(:license).where("licenses.is_secret = TRUE OR projects.is_public = TRUE")}
|
||||
|
||||
delegate :is_secret, to: :license, allow_nil: true
|
||||
|
||||
|
||||
def self.search_project(search)
|
||||
ransack(name_or_identifier_cont: search)
|
||||
end
|
||||
# 创建者
|
||||
def creator
|
||||
User.find(user_id).full_name
|
||||
end
|
||||
|
||||
def members_user_infos
|
||||
members.joins(:roles).where("roles.name in ('Manager', 'Developer', 'Reporter')").joins("left join users on members.user_id = users.id ").includes(:user).where("users.type = ?", "User")
|
||||
# members.joins("left join users on members.user_id = users.id").select("users.id", "users.login","users.firstname","users.lastname")
|
||||
# .pluck("users.id", "users.login","users.lastname", "users.firstname")
|
||||
end
|
||||
|
||||
def to_param
|
||||
self.identifier.parameterize
|
||||
end
|
||||
|
||||
def get_issues_count(status_id)
|
||||
if status_id.present?
|
||||
self&.issues.issue_issue.select(:id, :status_id).where(status_id: status_id)&.pluck(:id).size
|
||||
else
|
||||
self&.issues.issue_issue.select(:id)&.pluck(:id).size
|
||||
end
|
||||
end
|
||||
|
||||
def get_pull_requests_count(status_id)
|
||||
if status_id.present?
|
||||
self&.pull_requests.select(:id, :status).where(status: status_id)&.pluck(:id).size
|
||||
else
|
||||
self&.pull_requests.select(:id)&.pluck(:id).size
|
||||
end
|
||||
end
|
||||
|
||||
#创建项目管理员
|
||||
def check_project_members
|
||||
unless members.present? && members.exists?(user_id: self.user_id)
|
||||
member_params = {
|
||||
user_id: self.user_id,
|
||||
project_id: self.id
|
||||
}
|
||||
user_member = Member.new(member_params)
|
||||
if user_member.save
|
||||
role_id = Role.select(:id,:position).where(position: 3)&.first&.id
|
||||
MemberRole.create!(member_id: user_member.id ,role_id: role_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.init_bluck_repository
|
||||
Project.includes(:repository).find_each do |project|
|
||||
puts project.id
|
||||
next if project.owner.blank?
|
||||
if project.repository.blank?
|
||||
puts "########### start create repositoy #############"
|
||||
Repository.create!(project_id: project.id, identifier: Project.generate_identifier, user_id: project&.owner&.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.generate_identifier
|
||||
str_arr = (("a".."z").to_a + ("A".."Z").to_a)
|
||||
|
||||
str = str_arr.shuffle[0..8].join
|
||||
while Repository.exists?(identifier: str)
|
||||
str = str_arr.shuffle[0..8].join
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
def self.list_user_projects(user_id)
|
||||
projects = Project.is_private.select(:id,:user_id)
|
||||
user_not_show_1 = projects.where("user_id != ?",user_id).pluck(:id).uniq
|
||||
|
||||
user_show_2 = projects.joins(:members).where("members.user_id = ?", user_id).pluck(:id).uniq
|
||||
Project.where.not(id: (user_not_show_1 - user_show_2).uniq)
|
||||
end
|
||||
|
||||
def members_count
|
||||
members.select(:id).size
|
||||
end
|
||||
|
||||
|
||||
def can_visited?
|
||||
is_public? || User.current.admin? || member?(User.current)
|
||||
end
|
||||
|
||||
def releases_size(current_user_id, type)
|
||||
if current_user_id == self.user_id && type.to_s == "all"
|
||||
self.repository.version_releases_count
|
||||
else
|
||||
self.repository.version_releases.releases_size
|
||||
end
|
||||
end
|
||||
|
||||
def contributor_users
|
||||
self.pull_requests.select(:user_id).pluck(:user_id).uniq.size
|
||||
end
|
||||
|
||||
def open_issues_count
|
||||
issues_count - closed_issues_count
|
||||
end
|
||||
|
||||
def numerical_for_project_type
|
||||
self.class.name.constantize.project_types["#{self.project_type}"]
|
||||
end
|
||||
|
||||
def watched_by? user
|
||||
watchers.pluck(:user_id).include? user&.id
|
||||
end
|
||||
|
||||
def praised_by? user
|
||||
praise_treads.pluck(:user_id).include? user&.id
|
||||
end
|
||||
|
||||
def get_premission user
|
||||
permission = "Reporter"
|
||||
member = members.find_by(user: user)
|
||||
|
||||
member&.roles&.last&.name || permission
|
||||
end
|
||||
|
||||
def fork_project
|
||||
Project.find_by(id: self.forked_from_project_id)
|
||||
end
|
||||
|
||||
def self.members_projects(member_user_id)
|
||||
joins(:members).where(members: { user_id: member_user_id})
|
||||
end
|
||||
|
||||
def self.find_with_namespace(namespace_path, identifier)
|
||||
logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} "
|
||||
|
||||
user = Owner.find_by_login namespace_path
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
return nil if project.blank?
|
||||
|
||||
[project, user]
|
||||
end
|
||||
|
||||
def ci_reactivate?
|
||||
open_devops_count > 0
|
||||
end
|
||||
|
||||
def ci_reactivate!(ci_repo)
|
||||
ci_repo.update_column(:repo_active, 1)
|
||||
update_column(:open_devops, true)
|
||||
increment!(:open_devops_count)
|
||||
end
|
||||
|
||||
def self.sync_educoder_shixun(url, private_token, page, per_page)
|
||||
SyncEducoderShixunJob.perform_later(url, private_token, page, per_page)
|
||||
end
|
||||
|
||||
def self.update_common_projects_count!
|
||||
ps = ProjectStatistic.first
|
||||
ps.increment!(:common_projects_count) unless ps.blank?
|
||||
end
|
||||
|
||||
def self.update_mirror_projects_count!
|
||||
ps = ProjectStatistic.first
|
||||
ps.increment!(:mirror_projects_count) unless ps.blank?
|
||||
end
|
||||
|
||||
def set_updated_on(time)
|
||||
return if time.blank?
|
||||
update_column(:updated_on, time)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# position :integer
|
||||
# projects_count :integer default("0")
|
||||
# projects_count :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ancestry :string(255)
|
||||
|
|
@ -19,4 +19,12 @@ class ProjectCategory < ApplicationRecord
|
|||
include Projectable
|
||||
has_ancestry
|
||||
|
||||
def self.descendants
|
||||
where.not(ancestry: [nil, ""])
|
||||
end
|
||||
|
||||
def self.get_children(target_id)
|
||||
where(ancestry: target_id).pluck(:id,:name)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
# project_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# commit_count :integer default("0")
|
||||
# forked_count :integer default("0")
|
||||
# commit_count :integer default(0)
|
||||
# forked_count :integer default(0)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# position :integer
|
||||
# projects_count :integer default("0")
|
||||
# projects_count :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
|
|||
|
|
@ -7,44 +7,44 @@
|
|||
# score :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# issue_num :integer default("0")
|
||||
# issue_journal_num :integer default("0")
|
||||
# news_num :integer default("0")
|
||||
# documents_num :integer default("0")
|
||||
# changeset_num :integer default("0")
|
||||
# board_message_num :integer default("0")
|
||||
# board_num :integer default("0")
|
||||
# attach_num :integer default("0")
|
||||
# issue_num :integer default(0)
|
||||
# issue_journal_num :integer default(0)
|
||||
# news_num :integer default(0)
|
||||
# documents_num :integer default(0)
|
||||
# changeset_num :integer default(0)
|
||||
# board_message_num :integer default(0)
|
||||
# board_num :integer default(0)
|
||||
# attach_num :integer default(0)
|
||||
# commit_time :datetime
|
||||
# pull_request_num :integer default("0")
|
||||
# pull_request_num :integer default(0)
|
||||
#
|
||||
|
||||
class ProjectScore < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
def all_score
|
||||
self.issue_num * 4 + self.issue_journal_num + (self.changeset_num||0) * 4 + self.board_num * 2 +
|
||||
self.board_message_num + self.attach_num * 5
|
||||
end
|
||||
|
||||
# 代码提交得分
|
||||
def code_score
|
||||
(self.changeset_num||0) * 4
|
||||
end
|
||||
|
||||
# issues得分
|
||||
def issue_score
|
||||
self.issue_num * 4 + self.issue_journal_num
|
||||
end
|
||||
|
||||
# 资源得分
|
||||
def attachment_score
|
||||
self.attach_num * 5
|
||||
end
|
||||
|
||||
# 帖子得分
|
||||
def message_score
|
||||
self.board_message_num
|
||||
end
|
||||
|
||||
end
|
||||
class ProjectScore < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
def all_score
|
||||
self.issue_num * 4 + self.issue_journal_num + (self.changeset_num||0) * 4 + self.board_num * 2 +
|
||||
self.board_message_num + self.attach_num * 5
|
||||
end
|
||||
|
||||
# 代码提交得分
|
||||
def code_score
|
||||
(self.changeset_num||0) * 4
|
||||
end
|
||||
|
||||
# issues得分
|
||||
def issue_score
|
||||
self.issue_num * 4 + self.issue_journal_num
|
||||
end
|
||||
|
||||
# 资源得分
|
||||
def attachment_score
|
||||
self.attach_num * 5
|
||||
end
|
||||
|
||||
# 帖子得分
|
||||
def message_score
|
||||
self.board_message_num
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,13 +3,26 @@
|
|||
# Table name: project_statistics
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# common_projects_count :integer default("0")
|
||||
# mirror_projects_count :integer default("0")
|
||||
# sync_mirror_projects_count :integer default("0")
|
||||
# commits_total_count :integer default("0")
|
||||
# common_projects_count :integer default(0)
|
||||
# mirror_projects_count :integer default(0)
|
||||
# sync_mirror_projects_count :integer default(0)
|
||||
# commits_total_count :integer default(0)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class ProjectStatistic < ApplicationRecord
|
||||
|
||||
def self.data
|
||||
data = self.last
|
||||
if data.present?
|
||||
return data
|
||||
else
|
||||
common_projects_count = Project.common.count
|
||||
mirror_projects_count = Project.mirror.count
|
||||
sync_mirror_projects_count = Project.sync_mirror.count
|
||||
return ProjectStatistic.create(common_projects_count: common_projects_count, mirror_projects_count: mirror_projects_count, sync_mirror_projects_count: sync_mirror_projects_count)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@
|
|||
# id :integer not null, primary key
|
||||
# repo_id :integer
|
||||
# branch_name :string(255) default("")
|
||||
# can_push :boolean default("0"), not null
|
||||
# enable_whitelist :boolean default("0")
|
||||
# can_push :boolean default(FALSE), not null
|
||||
# enable_whitelist :boolean default(FALSE)
|
||||
# whitelist_user_i_ds :text(65535)
|
||||
# whitelist_team_i_ds :text(65535)
|
||||
# enable_merge_whitelist :boolean default("0"), not null
|
||||
# whitelist_deploy_keys :boolean default("0"), not null
|
||||
# enable_merge_whitelist :boolean default(FALSE), not null
|
||||
# whitelist_deploy_keys :boolean default(FALSE), not null
|
||||
# merge_whitelist_user_i_ds :text(65535)
|
||||
# merge_whitelist_team_i_ds :text(65535)
|
||||
# enable_status_check :boolean default("0"), not null
|
||||
# enable_status_check :boolean default(FALSE), not null
|
||||
# status_check_contexts :text(65535)
|
||||
# approvals_whitelist_user_i_ds :text(65535)
|
||||
# approvals_whitelist_team_i_ds :text(65535)
|
||||
# required_approvals :integer default("0")
|
||||
# enable_approvals_whitelist :boolean default("0"), not null
|
||||
# block_on_rejected_reviews :boolean default("0"), not null
|
||||
# dismiss_stale_approvals :boolean default("0"), not null
|
||||
# require_signed_commits :boolean default("0"), not null
|
||||
# required_approvals :integer default(0)
|
||||
# enable_approvals_whitelist :boolean default(FALSE), not null
|
||||
# block_on_rejected_reviews :boolean default(FALSE), not null
|
||||
# dismiss_stale_approvals :boolean default(FALSE), not null
|
||||
# require_signed_commits :boolean default(FALSE), not null
|
||||
# protected_file_patterns :text(65535)
|
||||
# block_on_outdated_branch :boolean default("0"), not null
|
||||
# block_on_outdated_branch :boolean default(FALSE), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue