forked from Gitlink/forgeplus
Compare commits
188 Commits
standalone
...
dev_jk_ser
Author | SHA1 | Date |
---|---|---|
yystopf | e7af0e2e47 | |
yystopf | 04f2dbee9a | |
yystopf | 70d22f7c4f | |
yystopf | 25d0e784bb | |
yystopf | 5d45b24299 | |
yystopf | b6b8befde7 | |
yystopf | f33b9559cd | |
yystopf | f9bc2258ec | |
xiaoxiaoqiong | 74cbca2421 | |
xiaoxiaoqiong | 01bf13ddd9 | |
xiaoxiaoqiong | ea2de5910a | |
xiaoxiaoqiong | a5d4799a21 | |
xiaoxiaoqiong | 335d24bc8b | |
xiaoxiaoqiong | e97eacbbf6 | |
xiaoxiaoqiong | 2c17ae096e | |
xiaoxiaoqiong | 399f6c2a17 | |
xiaoxiaoqiong | fb335162fc | |
xiaoxiaoqiong | c7b40c1230 | |
xiaoxiaoqiong | 293121ab91 | |
yystopf | 43cccc5429 | |
yystopf | fcc5429bbd | |
yystopf | 1f8f2abcf6 | |
yystopf | a2140574cd | |
yystopf | ab47dd0524 | |
yystopf | 4310cc9f26 | |
yystopf | 9648afb0bb | |
yystopf | 557b6ccc13 | |
viletyy | d94b3ff2f4 | |
viletyy | 4a7878d16e | |
viletyy | 0a00a4bc0e | |
viletyy | b81d92af46 | |
jasder | ef6f2c7b42 | |
jasder | 689b24da8f | |
jasder | 369877da5f | |
jasder | 96c67d359e | |
jasder | 3e633ea6cc | |
jasder | 4fe3f88de6 | |
jasder | a5fd87a475 | |
jasder | e8bbc7d856 | |
jasder | 9a0d7aa02a | |
jasder | 25e1bf1565 | |
jasder | 574f6561d1 | |
jasder | eaddf52cbd | |
jasder | ef0a0e5ddd | |
jasder | ef81d61a0d | |
jasder | 071f913123 | |
jasder | 6096fdd7bf | |
jasder | 9ba297ccf6 | |
jasder | 66fd6a71e5 | |
jasder | 89bc20e540 | |
jasder | 184a6bf1bf | |
jasder | 8ee089b82d | |
jasder | abc21413ac | |
vilet.yy | ce89ce5169 | |
vilet.yy | b8a4c467fe | |
vilet.yy | 300658f8dd | |
vilet.yy | 9553740960 | |
vilet.yy | 1a8d9bb0ce | |
vilet.yy | 8c43f74b69 | |
vilet.yy | 3e7ae82258 | |
vilet.yy | 0aa75e077e | |
vilet.yy | 8aefcad510 | |
vilet.yy | 622dcbaf4f | |
jasder | 6570125a36 | |
jasder | d91e8dcbfe | |
jasder | 0c2507b1e9 | |
vilet.yy | 8d29c2bd50 | |
vilet.yy | 774f632d9a | |
vilet.yy | 2969afd333 | |
vilet.yy | cc978c8dea | |
vilet.yy | ce105b4c07 | |
vilet.yy | b5870b1020 | |
vilet.yy | 1edb3ce7ad | |
jasder | 59257b1caa | |
Jasder | b552e29aa3 | |
Jasder | 21424a23f2 | |
Jasder | a82af669bd | |
Jasder | 0f01abd45f | |
viletyy | 80002be670 | |
Jasder | f7e19cb3a4 | |
Jasder | 5cd6620413 | |
Jasder | f3a9124bdd | |
Jasder | d97a39a3a2 | |
Jasder | 987ff74690 | |
Jasder | 37be604e82 | |
viletyy | 83e2c1f889 | |
viletyy | 46a1c8877b | |
Jasder | 0aa39efe9b | |
Jasder | 15d562d7b1 | |
Jasder | 5b261d6e81 | |
viletyy | 4693e77e02 | |
viletyy | fbf22ff0df | |
Jasder | 0794f77a87 | |
Jasder | e5a46a242f | |
Jasder | 4902237bd7 | |
Jasder | 4ddc60a1c3 | |
viletyy | cfa14fff9d | |
viletyy | ef327f2994 | |
viletyy | bf91c5e382 | |
viletyy | 9b687f7885 | |
viletyy | a072162324 | |
viletyy | 8f1e0f39ea | |
viletyy | aaa6483958 | |
Jasder | bf730ca18f | |
Jasder | 132af875bc | |
viletyy | a862d994ab | |
Jasder | 604da93c5c | |
Jasder | 3f525f5779 | |
viletyy | 05d1e66ea9 | |
viletyy | 10c1cccf2c | |
viletyy | 27ec7ec7dd | |
Jasder | 43b4907565 | |
Jasder | cb90e1a13f | |
viletyy | 749cd058c4 | |
viletyy | 47cc70f2c5 | |
viletyy | 5447d54d30 | |
viletyy | 6c436dd631 | |
viletyy | 9eb7219b9a | |
viletyy | ad5fcb25c4 | |
viletyy | d42053ce0c | |
viletyy | 36bae71947 | |
Jasder | 837aa1ea9e | |
Sylor-huang | c283c7ed58 | |
sylor_huang@126.com | 4cf8588343 | |
sylor_huang@126.com | e75fad98f8 | |
sylor_huang@126.com | bc37c59f00 | |
sylor_huang@126.com | a6a745da93 | |
sylor_huang@126.com | 5bef80ee58 | |
sylor_huang@126.com | f9bcc7e02b | |
sylor_huang@126.com | d35faf3935 | |
sylor_huang@126.com | 8d7dc9cb60 | |
sylor_huang@126.com | 248d78d8c1 | |
sylor_huang@126.com | f632424f13 | |
sylor_huang@126.com | 95ede63220 | |
sylor_huang@126.com | 8fac294d04 | |
sylor_huang@126.com | d67c12beba | |
sylor_huang@126.com | a7e4b85352 | |
Jasder | 2ac2920399 | |
Jasder | 230b934de4 | |
sylor_huang@126.com | e0bedf175f | |
sylor_huang@126.com | c9a263e03c | |
Jasder | 2bd15d9746 | |
sylor_huang@126.com | fc9588fb63 | |
sylor_huang@126.com | e611b519ab | |
sylor_huang@126.com | 3dd3944ebd | |
sylor_huang@126.com | f417bf3308 | |
sylor_huang@126.com | 9c7c914d12 | |
sylor_huang@126.com | b088befae7 | |
sylor_huang@126.com | d3636e686b | |
sylor_huang@126.com | 88d98f0ac4 | |
sylor_huang@126.com | db6aa954b1 | |
sylor_huang@126.com | 04a611a4aa | |
sylor_huang@126.com | 9ecea83506 | |
sylor_huang@126.com | 82a9907fdc | |
sylor_huang@126.com | c56c98fd6e | |
sylor_huang@126.com | 2948ad2033 | |
sylor_huang@126.com | fc611140cf | |
sylor_huang@126.com | fcb5f58b69 | |
sylor_huang@126.com | 0f38a130f3 | |
sylor_huang@126.com | fc54632a08 | |
sylor_huang@126.com | 5963af5c7b | |
sylor_huang@126.com | c1f2f7f6e2 | |
sylor_huang@126.com | 271699daf1 | |
sylor_huang@126.com | 98da7ea34d | |
sylor_huang@126.com | 645e4a3586 | |
sylor_huang@126.com | 7beca24a05 | |
sylor_huang@126.com | d1368c7612 | |
sylor_huang@126.com | 28e762810e | |
sylor_huang@126.com | 0f60d0adc9 | |
sylor_huang@126.com | e634317675 | |
sylor_huang@126.com | 6b1a0a96c6 | |
sylor_huang@126.com | 298859bd10 | |
sylor_huang@126.com | d4d412ab40 | |
sylor_huang@126.com | 57d1a1474e | |
sylor_huang@126.com | 055b7dbac5 | |
sylor_huang@126.com | 30aad87e5a | |
sylor_huang@126.com | aecd68fe9a | |
sylor_huang@126.com | 998a6828d9 | |
sylor_huang@126.com | 12c04d02e5 | |
sylor_huang@126.com | d6ef3d8aa3 | |
sylor_huang@126.com | c7a89d1660 | |
sylor_huang@126.com | 1939c0d33f | |
Jasder | 561b9efd92 | |
Jasder | 6c0b87fdd1 | |
Jasder | 5d309d1dc4 | |
Jasder | 89c230c362 | |
Jasder | d4156a5582 | |
Jasder | ee8cbb8553 |
218
api_document.md
218
api_document.md
|
@ -329,6 +329,7 @@ http://localhost:3000/api/licenses/ | jq
|
|||
|licenses|array |返回数据|
|
||||
|-- id |int |id |
|
||||
|-- name |string|开源许可证名称|
|
||||
|-- is_secret |string|是否为特殊许可证|
|
||||
|
||||
|
||||
返回值
|
||||
|
@ -337,23 +338,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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -597,6 +608,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: 否 |
|
||||
|
||||
|
||||
|
||||
返回值
|
||||
|
@ -609,7 +622,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
|
||||
}
|
||||
```
|
||||
---
|
||||
|
@ -1189,6 +1203,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|项目创建者|
|
||||
|
@ -1199,6 +1214,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':审核通过|
|
||||
|
||||
|
||||
|
||||
返回值
|
||||
|
@ -1214,6 +1233,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": {
|
||||
|
@ -1227,7 +1247,13 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[
|
||||
{
|
||||
"id": 1,
|
||||
"status": "waiting"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
|
@ -1237,6 +1263,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": {
|
||||
|
@ -1250,7 +1277,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
|
@ -1260,6 +1288,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": {
|
||||
|
@ -1273,7 +1302,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
|
@ -1283,6 +1313,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": {
|
||||
|
@ -1296,7 +1327,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
|
@ -1306,6 +1338,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": {
|
||||
|
@ -1319,7 +1352,8 @@ http://localhost:3000/api/projects | jq
|
|||
"language": {
|
||||
"id": 2,
|
||||
"name": "C"
|
||||
}
|
||||
},
|
||||
"user_apply_signatures":[]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -5059,6 +5093,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|项目创建者|
|
||||
|
@ -5069,7 +5104,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
|
||||
|
@ -5084,6 +5121,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": {
|
||||
|
@ -5097,9 +5135,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 () {
|
||||
|
|
|
@ -13,12 +13,15 @@ class AccountsController < ApplicationController
|
|||
username = params[:username]&.gsub(/\s+/, "")
|
||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
phone = params[:phone]&.gsub(/\s+/, "")
|
||||
password = params[:password]
|
||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = autologin_register(username, email, password, platform)
|
||||
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])
|
||||
|
@ -251,9 +254,7 @@ class AccountsController < ApplicationController
|
|||
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)
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(user, autologin_cookie_name)
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.month.from_now,
|
||||
|
|
|
@ -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,12 +1,12 @@
|
|||
class Admins::ProjectsController < Admins::BaseController
|
||||
before_action :find_project, only: [:edit, :update]
|
||||
before_action :find_project, only: [:edit, :update, :sync_phenglei_user]
|
||||
|
||||
def index
|
||||
sort_by = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_on'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
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 edit ;end
|
||||
|
@ -43,6 +43,17 @@ class Admins::ProjectsController < Admins::BaseController
|
|||
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 find_project
|
||||
@project = Project.find_by_id(params[:id])
|
||||
|
|
|
@ -57,7 +57,50 @@ class Admins::UsersController < Admins::BaseController
|
|||
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 finder_user
|
||||
@user = User.find(params[:id])
|
||||
|
@ -68,4 +111,12 @@ class Admins::UsersController < Admins::BaseController
|
|||
mail phone location location_city school_id department_id admin business is_test
|
||||
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
|
||||
|
|
|
@ -309,7 +309,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_cookie_name)
|
||||
# start_user_session(user) if user # TODO 解决sso退出不同步的问题
|
||||
user
|
||||
end
|
||||
|
@ -735,7 +735,7 @@ class ApplicationController < ActionController::Base
|
|||
def avatar_path(object)
|
||||
ApplicationController.helpers.disk_filename(object.class, object.id)
|
||||
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
|
|
@ -51,6 +51,7 @@ class AttachmentsController < ApplicationController
|
|||
# 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
|
||||
|
||||
|
@ -88,8 +89,16 @@ class AttachmentsController < ApplicationController
|
|||
@attachment.digest = digest
|
||||
@attachment.author_id = current_user.id
|
||||
@attachment.disk_directory = month_folder
|
||||
@attachment.cloud_url = remote_path
|
||||
@attachment.save!
|
||||
# @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
|
||||
|
|
|
@ -179,7 +179,7 @@ module Ci::CloudAccountManageable
|
|||
|
||||
def drone_oauth_user!(url, state)
|
||||
logger.info "[drone] drone_oauth_user url: #{url}"
|
||||
conn = Faraday.new(url: url) do |req|
|
||||
conn = Faraday.new(url: "#{Gitea.gitea_config[:domain]}#{url}") do |req|
|
||||
req.request :url_encoded
|
||||
req.adapter Faraday.default_adapter
|
||||
req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}"
|
||||
|
@ -188,7 +188,8 @@ module Ci::CloudAccountManageable
|
|||
response = conn.get
|
||||
logger.info "[drone] response headers: #{response.headers}"
|
||||
|
||||
response.headers['location'].include?('error') ? false : true
|
||||
true
|
||||
# response.headers['location'].include?('error') ? false : true
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -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: Rails.application.config_for(:configuration)['platform_url'],
|
||||
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,12 @@ 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 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_cookie_name)
|
||||
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
|
|
@ -104,7 +104,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
|
||||
|
@ -136,6 +137,7 @@ class IssuesController < ApplicationController
|
|||
return normal_status(-1, "请输入正确的标记。")
|
||||
end
|
||||
end
|
||||
|
||||
if params[:assigned_to_id].present?
|
||||
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
|
||||
container_id: @issue.id, container_type: 'Issue',
|
||||
|
@ -164,11 +166,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
|
||||
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
|
||||
last_token = @issue.token
|
||||
last_status_id = @issue.status_id
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
|
@ -185,10 +188,6 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
issue_files = params[:attachment_ids]
|
||||
change_files = false
|
||||
issue_file_ids = []
|
||||
|
||||
if issue_files.present?
|
||||
change_files = true
|
||||
issue_files.each do |id|
|
||||
|
@ -201,6 +200,7 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# if params[:issue_tag_ids].present?
|
||||
# issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
|
||||
|
@ -269,6 +269,8 @@ class IssuesController < ApplicationController
|
|||
else
|
||||
normal_status(-1, "更新失败")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
|
@ -310,12 +312,11 @@ class IssuesController < ApplicationController
|
|||
Rails.logger.info("#########_______exception.message_________##########{exception.message}")
|
||||
normal_status(-1, "删除失败")
|
||||
else
|
||||
normal_status(-1, "删除失败")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def clean
|
||||
#批量删除,暂时只能删除未悬赏的
|
||||
issue_ids = params[:ids]
|
||||
issues = Issue.where(id: issue_ids, issue_type: "1")
|
||||
if issues.present?
|
||||
|
|
|
@ -74,7 +74,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, "评论的内容不能为空")
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -44,7 +44,7 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
if @organization.teams.count >= 50
|
||||
return render_forbidden("组织的团队数量已超过限制!")
|
||||
return tip_exception("组织的团队数量已超过限制!")
|
||||
else
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
|
|
|
@ -11,7 +11,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
|
||||
|
|
|
@ -34,7 +34,7 @@ class ProjectsController < ApplicationController
|
|||
# @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
|
||||
|
||||
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?
|
||||
|
@ -59,18 +59,23 @@ class ProjectsController < ApplicationController
|
|||
Projects::MigrateForm.new(mirror_params).validate!
|
||||
|
||||
@project =
|
||||
if enable_accelerator?(mirror_params[:clone_addr])
|
||||
# if enable_accelerator?(mirror_params[:clone_addr])
|
||||
# source_clone_url = mirror_params[:clone_addr]
|
||||
# uid_logger("########## 已动加速器 ##########")
|
||||
# result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||
# if result[:status] == :success
|
||||
# Rails.logger.info "########## 加速镜像成功 ########## "
|
||||
# Projects::MigrateService.call(current_user,
|
||||
# mirror_params.merge(source_clone_url: source_clone_url,
|
||||
# clone_addr: accelerator_url(mirror_params[:repository_name])))
|
||||
# else
|
||||
# Projects::MigrateService.call(current_user, mirror_params)
|
||||
# end
|
||||
if mirror_params[:clone_addr].include?("github.com")
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
uid_logger("########## 已动加速器 ##########")
|
||||
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||
if result[:status] == :success
|
||||
Rails.logger.info "########## 加速镜像成功 ########## "
|
||||
Projects::MigrateService.call(current_user,
|
||||
mirror_params.merge(source_clone_url: source_clone_url,
|
||||
clone_addr: accelerator_url(mirror_params[:repository_name])))
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
|
||||
uid_logger("########## 更改clone_addr ##########")
|
||||
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
|
@ -95,23 +100,14 @@ 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
|
||||
|
@ -220,7 +216,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,
|
||||
|
|
|
@ -134,8 +134,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)
|
||||
|
@ -228,7 +230,12 @@ class PullRequestsController < ApplicationController
|
|||
message: "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{can_merge.first.id}''>#{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
|
||||
|
@ -274,12 +281,12 @@ class PullRequestsController < ApplicationController
|
|||
base: params[:base], #目标分支
|
||||
milestone: 0, #里程碑,未与本地的里程碑关联
|
||||
}
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
@requests_params = @local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||
assignees: ["#{current_user.try(:login).to_s}"],
|
||||
labels: params[:issue_tag_ids],
|
||||
due_date: Time.now
|
||||
assignees: ["#{assignee_login.to_s}"],
|
||||
labels: params[:issue_tag_ids]
|
||||
# due_date: Time.now
|
||||
})
|
||||
@issue_params = {
|
||||
author_id: current_user.id,
|
||||
|
|
|
@ -259,6 +259,19 @@ class RepositoriesController < ApplicationController
|
|||
redirect_to file_path
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -196,8 +196,7 @@ class UsersController < ApplicationController
|
|||
# 其他平台登录后,必须将token同步到forge平台,实现sso登录功能
|
||||
def sync_token
|
||||
return render_error('未找相关用户!') unless @user
|
||||
|
||||
token = Token.get_or_create_permanent_login_token(@user, 'autologin')
|
||||
token = Token.get_or_create_permanent_login_token(@user, autologin_cookie_name)
|
||||
token.update_column(:value, params[:token])
|
||||
render_ok
|
||||
end
|
||||
|
|
|
@ -92,7 +92,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
|
||||
|
||||
|
@ -130,7 +130,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
|
||||
|
|
@ -144,6 +144,10 @@ module ApplicationHelper
|
|||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
source.get_letter_avatar_url
|
||||
elsif source.class.to_s == 'Subject'
|
||||
File.join("images","educoder", "index", "subject", "subject#{rand(17)}.jpg")
|
||||
elsif source.class.to_s == 'Shixun'
|
||||
File.join("images","educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ module ProjectsHelper
|
|||
open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?,
|
||||
type: project.numerical_for_project_type,
|
||||
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}},
|
||||
project_category_id: project.project_category_id,
|
||||
project_language_id: project.project_language_id,
|
||||
license_id: project.license_id,
|
||||
|
|
|
@ -11,7 +11,7 @@ module RepositoriesHelper
|
|||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
|
|
|
@ -54,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
|
||||
|
||||
|
|
|
@ -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, role_name)
|
||||
project.add_member!(collaborator.id, role_name, is_apply_signature)
|
||||
end
|
||||
fail!(nil)
|
||||
end
|
||||
|
@ -32,7 +33,7 @@ module Projects
|
|||
end
|
||||
|
||||
private
|
||||
attr_reader :owner, :project, :collaborator, :permission
|
||||
attr_reader :owner, :project, :collaborator, :permission, :is_apply_signature
|
||||
|
||||
def fail!(error)
|
||||
@error = error
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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("0")
|
||||
# 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
|
|
@ -44,7 +44,7 @@ class Attachment < ApplicationRecord
|
|||
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
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# == 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("0")
|
||||
# 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("0")
|
||||
# subtitle :string(255)
|
||||
# team_members_count :integer default("0")
|
||||
# limit_type :integer default("0")
|
||||
# show_top :integer default("0")
|
||||
# content :text(65535)
|
||||
#
|
||||
|
||||
class Competition < ApplicationRecord
|
||||
|
||||
enum status: {archived: 0, active: 1}
|
||||
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
|
||||
|
|
|
@ -20,7 +20,7 @@ module ProjectOperable
|
|||
add_member!(creator.id, "Manager")
|
||||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
def add_member!(user_id, role_name='Developer', is_apply_signature=false)
|
||||
if self.owner.is_a?(Organization)
|
||||
case role_name
|
||||
when 'Manager'
|
||||
|
@ -43,7 +43,7 @@ module ProjectOperable
|
|||
team_user = TeamUser.build(self.user_id, user_id, team.id)
|
||||
end
|
||||
end
|
||||
member = members.create!(user_id: user_id, team_user_id: team_user&.id)
|
||||
member = members.create!(user_id: user_id, team_user_id: team_user&.id, is_apply_signature: is_apply_signature)
|
||||
set_developer_role(member, role_name)
|
||||
end
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
class Issue < ApplicationRecord
|
||||
#issue_type 1为普通,2为悬赏
|
||||
include DunCheckAble
|
||||
belongs_to :project, counter_cache: true, touch: true
|
||||
belongs_to :tracker,optional: true
|
||||
has_many :project_trends, as: :trend, dependent: :destroy
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,9 +42,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}.gitlink.org.cn" : '.gitlink.org.cn'
|
||||
suffix = rails_env && rails_env != 'production' ? "39.105.176.215" : '39.105.176.215'
|
||||
|
||||
identifier ? "#{identifier}#{suffix}" : ''
|
||||
end
|
||||
|
|
|
@ -11,4 +11,6 @@
|
|||
|
||||
class License < ApplicationRecord
|
||||
include Projectable
|
||||
has_many :attachments, as: :container, dependent: :destroy
|
||||
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -123,6 +123,7 @@ class Project < ApplicationRecord
|
|||
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 :project_units, dependent: :destroy
|
||||
has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy
|
||||
has_many :pinned_projects, dependent: :destroy
|
||||
|
@ -137,6 +138,9 @@ class Project < ApplicationRecord
|
|||
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||
scope :pinned, -> {where(is_pinned: true)}
|
||||
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
|
||||
|
||||
delegate :content, to: :project_detail, allow_nil: true
|
||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||
|
|
|
@ -20,6 +20,14 @@ 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
|
||||
|
||||
def logo_url
|
||||
image_url('logo')
|
||||
end
|
||||
|
|
|
@ -12,4 +12,17 @@
|
|||
#
|
||||
|
||||
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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#
|
||||
|
||||
class PullRequest < ApplicationRecord
|
||||
include DunCheckAble
|
||||
#status 0 默认未合并, 1表示合并, 2表示请求拒绝(或已关闭)
|
||||
OPEN = 0
|
||||
MERGED = 1
|
||||
|
|
|
@ -70,7 +70,7 @@ class Token < ActiveRecord::Base
|
|||
|
||||
# Delete all expired tokens
|
||||
def self.destroy_expired
|
||||
Token.delete_all ["action NOT IN (?) AND created_on < ?", ['feeds', 'api', 'autologin'], Time.now - @@validity_time]
|
||||
Token.delete_all ["action NOT IN (?) AND created_on < ?", ['feeds', 'api', 'autologin', 'autologin_forge_military'], Time.now - @@validity_time]
|
||||
end
|
||||
|
||||
# Returns the active user who owns the key for the given action
|
||||
|
|
|
@ -117,7 +117,7 @@ class User < Owner
|
|||
|
||||
belongs_to :laboratory, optional: true
|
||||
has_one :user_extension, dependent: :destroy
|
||||
has_many :open_users, dependent: :destroy
|
||||
# has_many :open_users, dependent: :destroy
|
||||
has_one :wechat_open_user, class_name: 'OpenUsers::Wechat'
|
||||
has_one :qq_open_user, class_name: 'OpenUsers::QQ'
|
||||
accepts_nested_attributes_for :user_extension, update_only: true
|
||||
|
@ -159,6 +159,7 @@ class User < Owner
|
|||
# has_many :libraries, dependent: :destroy
|
||||
has_many :project_trends, dependent: :destroy
|
||||
has_many :oauths , dependent: :destroy
|
||||
has_many :apply_signatures, dependent: :destroy
|
||||
|
||||
has_many :organization_users, dependent: :destroy
|
||||
has_many :organizations, through: :organization_users
|
||||
|
@ -231,7 +232,7 @@ class User < Owner
|
|||
|
||||
# 删除自动登录的token,一旦退出下次会提示需要登录
|
||||
def delete_autologin_token(value)
|
||||
Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all
|
||||
Token.where(:user_id => id, :action => autologin_name, :value => value).delete_all
|
||||
end
|
||||
|
||||
def delete_session_token(value)
|
||||
|
@ -624,8 +625,8 @@ class User < Owner
|
|||
end
|
||||
|
||||
# Returns the user who matches the given autologin +key+ or nil
|
||||
def self.try_to_autologin(key)
|
||||
user = Token.find_active_user('autologin', key)
|
||||
def self.try_to_autologin(key,type)
|
||||
user = Token.find_active_user(type, key)
|
||||
user.update(last_login_on: Time.now) if user
|
||||
user
|
||||
end
|
||||
|
@ -793,6 +794,10 @@ class User < Owner
|
|||
raise("昵称包含敏感词汇,请重新输入") if nickname && !HarmoniousDictionary.clean?(nickname)
|
||||
end
|
||||
|
||||
def autologin_name
|
||||
EduSetting.get('autologin_cookie_name') || "autologin_forge_military"
|
||||
end
|
||||
|
||||
def set_laboratory
|
||||
return unless new_record?
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#
|
||||
|
||||
class Version < ApplicationRecord
|
||||
include DunCheckAble
|
||||
belongs_to :project, counter_cache: true, touch: true
|
||||
has_many :issues, class_name: "Issue", foreign_key: "fixed_version_id"
|
||||
belongs_to :user, optional: true
|
||||
|
|
|
@ -53,7 +53,7 @@ class Projects::ListMyQuery < ApplicationQuery
|
|||
|
||||
q = projects.ransack(name_or_identifier_cont: params[:search])
|
||||
|
||||
scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users)
|
||||
scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users, :members)
|
||||
|
||||
sort = Project.column_names.include?(params[:sort_by]) ? params[:sort_by] : "updated_on"
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : "desc"
|
||||
|
|
|
@ -60,6 +60,11 @@ class Projects::CreateService < ApplicationService
|
|||
# end
|
||||
|
||||
def repo_is_public
|
||||
params[:private].blank? ? true : !(ActiveModel::Type::Boolean.new.cast(params[:private]).nil? ? false : ActiveModel::Type::Boolean.new.cast(params[:private]))
|
||||
license = License.find_by_id(params[:license_id])
|
||||
if license&.is_secret
|
||||
false
|
||||
else
|
||||
params[:private].blank? ? true : !(ActiveModel::Type::Boolean.new.cast(params[:private]).nil? ? false : ActiveModel::Type::Boolean.new.cast(params[:private]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -125,7 +125,10 @@ class PullRequests::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def gitea_pull_request_params
|
||||
merge_original_pull_params.except(:milestone)
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
merge_original_pull_params.except(:milestone).merge(
|
||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||
assignees: ["#{assignee_login.to_s}"])
|
||||
end
|
||||
|
||||
def merge_original_pull_params
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
class Repositories::CompareService < ApplicationService
|
||||
attr_reader :owner, :project, :params
|
||||
|
||||
def initialize(owner, project, params)
|
||||
@owner = owner
|
||||
@project = project
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
compare!
|
||||
rescue => e
|
||||
raise Error, e.message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def compare!
|
||||
base, head = compare_params
|
||||
|
||||
# TODO: 处理fork的项目向源项目发送PR的base、head参数问题
|
||||
head.include?(":") ? gitea_compare(base, head) : gitea_compare(head, base)
|
||||
end
|
||||
|
||||
def compare_params
|
||||
base = Addressable::URI.unescape(params[:base])
|
||||
head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
|
||||
|
||||
[base, head]
|
||||
end
|
||||
|
||||
def gitea_compare(base, head)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
class SyncForgeProjectsRake
|
||||
# 运行示例: 检查哪些项目的repo不存在,bundle exec rails runner "SyncForgeProjectsRake.new.call(5)" -e production
|
||||
|
||||
def call(count)
|
||||
|
||||
url = "https://forgeplus.trustie.net/api/sync_forge/sync_range_projects" #trustie上的相关路由
|
||||
count_params = {
|
||||
sync_count: count || 10
|
||||
}
|
||||
Rails.logger.info("============begin to sync project,count: #{count_params} ===========")
|
||||
uri = URI.parse(url)
|
||||
http = Net::HTTP.new(uri.hostname, uri.port)
|
||||
http.use_ssl = true
|
||||
response = http.send_request('POST', uri.path, count_params.to_json, {'Content-Type' => 'application/json'})
|
||||
Rails.logger.info("============end to sync project, status: #{response.code} ===========")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('特殊许可申请列表') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box admin-list-container apply_signatures-list-container">
|
||||
<%= render partial: 'admins/apply_signatures/shared/list', locals: { apply_signatures: @apply_signatures } %>
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
$('.apply_signatures-list-container').html("<%= j( render partial: 'admins/apply_signatures/shared/list', locals: { apply_signatures: @apply_signatures } ) %>");
|
|
@ -0,0 +1,42 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="10%">序号</th>
|
||||
<th width="20%" class="text-left">项目名称</th>
|
||||
<th width="20%">申请人</th>
|
||||
<th width="25%">申请材料</th>
|
||||
<th width="25%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if apply_signatures.present? %>
|
||||
<% apply_signatures.each_with_index do |signature, index| %>
|
||||
<tr class="sinature-item-<%= signature.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td class="text-left">
|
||||
<%= link_to("#{signature&.project&.owner&.real_name}/#{signature&.project&.name}", "/projects/#{signature&.project&.owner&.login}/#{signature&.project&.identifier}", target: '_blank') %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to(signature&.user&.real_name, "/users/#{signature&.user&.login}", target: '_blank') %>
|
||||
</td>
|
||||
<td>
|
||||
<% if signature.attachments.present? %>
|
||||
<% signature.attachments.each do |attachment|%>
|
||||
<%= link_to "#{attachment.try(:filename)}",attachment_path(attachment), target: "_blank" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
</td>
|
||||
<td class="action-container">
|
||||
<%= link_to "同意", admins_apply_signature_path(signature.id, status: "passed"), method: :patch, class: "delete-project-action" %>
|
||||
<%= link_to "拒绝", admins_apply_signature_path(signature.id, status: "unpassed"), method: :patch, class: "delete-project-action" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: apply_signatures } %>
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<div class="box search-form-container laboratory-list-form">
|
||||
<%= form_tag(admins_laboratories_path(unsafe_params), method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-6 col-md-4 ml-3', placeholder: '单位名称/二级域名前缀检索') %>
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-6 col-md-4 ml-3', placeholder: '二级域名前缀检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<% end %>
|
||||
|
||||
|
@ -16,4 +16,4 @@
|
|||
</div>
|
||||
|
||||
<%= render 'admins/laboratories/shared/create_laboratory_modal' %>
|
||||
<%= render 'admins/laboratories/shared/add_laboratory_user_modal' %>
|
||||
<%= render 'admins/laboratories/shared/add_laboratory_user_modal' %>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<% school = laboratory&.school %>
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td class="text-left"><%= school&.name || '主站' %></td>
|
||||
<td class="text-left"><%= school&.name || '可控开源社区' %></td>
|
||||
<td class="text-left">
|
||||
<% if laboratory.identifier %>
|
||||
<%= link_to laboratory.site, "https://#{laboratory.site}", target: '_blank' %>
|
||||
<%= link_to laboratory.site, "http://#{laboratory.site}", target: '_blank' %>
|
||||
<% else %>
|
||||
--
|
||||
<% end %>
|
||||
|
|
|
@ -19,10 +19,14 @@
|
|||
maxlength: 15, class: 'form-control font-16',
|
||||
'onKeyUp': 'value=value.replace(/[^\w\-\/]/ig,"").toLowerCase()',
|
||||
style: 'text-transform:lowercase'%>
|
||||
<div class="input-group-append">
|
||||
<%
|
||||
=begin%>
|
||||
<div class="input-group-append">
|
||||
<% rails_env = EduSetting.get('rails_env') %>
|
||||
<span class="input-group-text font-14" id="site-prefix"><%= rails_env && rails_env != 'production' ? ".#{rails_env}.gitlink.org.cn" : '.gitlink.org.cn' %></span>
|
||||
</div>
|
||||
<%
|
||||
=end%>
|
||||
</div>
|
||||
<%# if @laboratory.errors && @laboratory.errors.key?(:identifier) %>
|
||||
<!-- <span id="identifier-error" class="danger text-danger">二级域名已被使用</span>-->
|
||||
|
@ -148,7 +152,7 @@
|
|||
|
||||
<div class="form-group px-2 setting-item">
|
||||
<div class="setting-item-head">
|
||||
<h6>导航设置
|
||||
<h6>导航设置
|
||||
<%= link_to "<i class='fa fa-plus-circle'></i>".html_safe,new_admins_laboratory_laboratory_setting_path, remote: true, class: "btn btn-primary btn-sm"%>
|
||||
</h6>
|
||||
</div>
|
||||
|
@ -199,8 +203,3 @@
|
|||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<script>
|
||||
function destroy_tr(that) {
|
||||
$(that).parent().parent("tr").remove()
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('风雷意向用户管理', admins_phenglei_users_path) %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container user-list-form">
|
||||
<%= form_tag(admins_phenglei_users_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '手机号检索') %>
|
||||
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<%= link_to "同步", sync_phenglei_user_admins_project_path(@phenglei_project.id), method: :get, data: {confirm: "确认同步吗?"}, class: "btn btn-primary pull-right ml-3", "data-disabled-with":"...同步" %>
|
||||
<% end %>
|
||||
<%= link_to "新增", new_admins_phenglei_user_path, remote: true, class: "btn btn-primary ml-3", "data-disabled-with":"...新增" %>
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container phenglei-users-list-container">
|
||||
<%= render partial: 'admins/phenglei_users/shared/list', locals: { phenglei_users: @phenglei_users } %>
|
||||
</div>
|
||||
<div id="phenglei-users-modals">
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
$('.phenglei-users-list-container').html("<%= j( render partial: 'admins/phenglei_users/shared/list', locals: { phenglei_users: @phenglei_users } ) %>");
|
|
@ -0,0 +1,2 @@
|
|||
$("#phenglei-users-modals").html("<%= j render(partial: 'admins/phenglei_users/shared/create_form_modal') %>")
|
||||
$(".phenglei-user-create-modal").modal('show');
|
|
@ -0,0 +1,21 @@
|
|||
<div class="modal fade phenglei-user-create-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">新增</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<%= form_for @phenglei_user, url: {controller: "phenglei_users", action: 'create'} do |p| %>
|
||||
<div class="modal-body">
|
||||
<%= p.text_field :phone, class: "form-control input-lg",placeholder: "手机号",required: true, maxlength: 64%>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,30 @@
|
|||
<table class="table table-hover users-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="4%">序号</th>
|
||||
<th width="10%">手机号码</th>
|
||||
<th width="12%">状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if phenglei_users.present? %>
|
||||
<% phenglei_users.each_with_index do |user, index| %>
|
||||
<tr class="user-item-<%= user.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= overflow_hidden_span display_text(user.phone), width: 100 %></td>
|
||||
<td>
|
||||
<% if user.register.present? %>
|
||||
<%= @phenglei_project.member?(user.register.id) ? "已同步" : "未同步" %>
|
||||
<% else %>
|
||||
未注册
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: phenglei_users } %>
|
|
@ -0,0 +1,50 @@
|
|||
<div class="modal fade platform-communicate-change-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><%= type == "create" ? "新增" : "编辑" %></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<%= form_for @communicate, url: {controller: "platform_communicates", action: "#{type}"} do |p| %>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
标题 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
内容 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_area :content,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
标签(多个请用,隔开) <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :tag_field,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
帖子ID <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.number_field :fake_id,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
排序等级 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.number_field :order_index,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,35 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="5%">序号</th>
|
||||
<th width="20%">标题</th>
|
||||
<th width="20%">内容</th>
|
||||
<th width="10%">帖子ID</th>
|
||||
<th width="20%">标签</th>
|
||||
<th width="20%">排序等级</th>
|
||||
<th width="25%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if communicates.present? %>
|
||||
<% communicates.each_with_index do |c, index| %>
|
||||
<tr class="platform-communicate-item-<%= c.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= c.title %></td>
|
||||
<td><%= c.content.truncate(50) %></td>
|
||||
<td><%= c.fake_id %></td>
|
||||
<td><%= c.tag_field %></td>
|
||||
<td><%= c.order_index %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to "编辑", edit_admins_platform_communicate_path(c), remote: true, class: "action" %>
|
||||
<%= link_to "删除", admins_platform_communicate_path(c), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: communicates } %>
|
|
@ -0,0 +1,2 @@
|
|||
$("#platform-communicate-modals").html("<%= j render(partial: 'admins/platform_communicates/form_modal', locals: {type: 'update'}) %>")
|
||||
$(".platform-communicate-change-modal").modal('show');
|
|
@ -0,0 +1,18 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('社区动态管理') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container platform-communicate-list-form">
|
||||
<%= form_tag(admins_platform_communicates_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||
<% end %>
|
||||
<%= link_to "新增", new_admins_platform_communicate_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container platform-communicate-list-container">
|
||||
<%= render partial: 'admins/platform_communicates/list', locals: { communicates: @communicates } %>
|
||||
</div>
|
||||
<div id="platform-communicate-modals">
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
$('.platform-communicate-list-container').html("<%= j( render partial: 'admins/platform_communicates/list', locals: { communicates: @communicates } ) %>");
|
|
@ -0,0 +1,2 @@
|
|||
$("#platform-communicate-modals").html("<%= j render(partial: 'admins/platform_communicates/form_modal', locals: {type: 'create'}) %>")
|
||||
$(".platform-communicate-change-modal").modal('show');
|
|
@ -0,0 +1,57 @@
|
|||
<div class="modal fade platform-person-change-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><%= type == "create" ? "新增" : "编辑" %></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<%= form_for @person, url: {controller: "platform_people", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
标题 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :name,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="logo-item">
|
||||
<% logo_img = @person.image %>
|
||||
<div class="logo-item-left mr-3 <%= logo_img ? 'has-img' : '' %>">
|
||||
<img class="logo-item-img nav-logo-img" src="<%= logo_img %>" style="<%= logo_img.present? ? '' : 'display: none' %>"/>
|
||||
<%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
|
||||
<label for="image" class="logo-item-upload" data-toggle="tooltip" data-title="选择图片"></label>
|
||||
</div>
|
||||
<div class="logo-item-right">
|
||||
<div class="logo-item-title flex-1">logo</div>
|
||||
<div>格式:PNG、JPG</div>
|
||||
<div>尺寸:高度38px以内,宽等比例缩放</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
个人宣言 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :announcement,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
内容 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_area :content,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
用户标识 <span class="ml10 color-orange mr20">*</span>
|
||||
</label>
|
||||
<%= p.text_field :fake_login,class: "form-control input-lg",required: true%>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,35 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="5%">序号</th>
|
||||
<th width="20%">名称</th>
|
||||
<th width="20%">头像</th>
|
||||
<th width="20%">个人宣言</th>
|
||||
<th width="20%">内容</th>
|
||||
<th width="10%">用户标识</th>
|
||||
<th width="25%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if people.present? %>
|
||||
<% people.each_with_index do |p, index| %>
|
||||
<tr class="platform-person-item-<%= p.id %>">
|
||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= p.name %></td>
|
||||
<td><img style="width:150px" src="<%= p.image %>" /></td>
|
||||
<td><%= p.announcement %></td>
|
||||
<td><%= p.content.truncate(50) %></td>
|
||||
<td><%= p.fake_login %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to "编辑", edit_admins_platform_person_path(p), remote: true, class: "action" %>
|
||||
<%= link_to "删除", admins_platform_person_path(p), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: people } %>
|
|
@ -0,0 +1,18 @@
|
|||
$("#platform-person-modals").html("<%= j render(partial: 'admins/platform_people/form_modal', locals: {type: 'update'}) %>")
|
||||
$(".platform-person-change-modal").modal('show');
|
||||
|
||||
$('.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 {
|
||||
}
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('论坛交流管理') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container platform-person-list-form">
|
||||
<%= form_tag(admins_platform_people_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
|
||||
<%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '名称检索') %>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||
<% end %>
|
||||
<%= link_to "新增", new_admins_platform_person_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||
</div>
|
||||
|
||||
<div class="box admin-list-container platform-person-list-container">
|
||||
<%= render partial: 'admins/platform_people/list', locals: { people: @people } %>
|
||||
</div>
|
||||
<div id="platform-person-modals">
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
$('.platform-person-list-container').html("<%= j( render partial: 'admins/platform_people/list', locals: { people: @people } ) %>");
|
|
@ -0,0 +1,18 @@
|
|||
$("#platform-person-modals").html("<%= j render(partial: 'admins/platform_people/form_modal', locals: {type: 'create'}) %>")
|
||||
$(".platform-person-change-modal").modal('show');
|
||||
|
||||
$('.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 {
|
||||
}
|
||||
});
|
|
@ -1,13 +1,12 @@
|
|||
<table class="table table-hover text-center subject-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="5%">序号</th>
|
||||
<th width="6%">ID</th>
|
||||
<th width="20%" class="text-left">项目名称</th>
|
||||
<th width="5%">公开</th>
|
||||
<th width="5%">精选</th>
|
||||
<th width="5%">推荐</th>
|
||||
<th width="5%">Issues</th>
|
||||
<th width="4%">序号</th>
|
||||
<th width="4%">ID</th>
|
||||
<th width="15%" class="text-left">项目名称</th>
|
||||
<th width="6%">公开</th>
|
||||
<th width="6%">特殊协议</th>
|
||||
<th width="5%">issue</th>
|
||||
<th width="5%">资源</th>
|
||||
<th width="5%">Pulls</th>
|
||||
<th width="6%">里程碑</th>
|
||||
|
@ -24,11 +23,10 @@
|
|||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||
<td><%= project.id %></td>
|
||||
<td class="text-left">
|
||||
<%= link_to(project.name, "/#{project&.owner&.login}/#{project.identifier}", target: '_blank') %>
|
||||
<%= link_to(project.name, "/projects/#{project.owner&.login}/#{project.identifier}", target: '_blank') %>
|
||||
</td>
|
||||
<td><%= project.is_public ? '√' : '' %></td>
|
||||
<td><%= project.is_pinned ? '√' : '' %></td>
|
||||
<td><%= project.recommend ? '√' : '' %></td>
|
||||
<td><%= project.is_secret ? '√' : '' %></td>
|
||||
<td><%= project.issues.size %></td>
|
||||
<td><%= project.attachments.size %></td>
|
||||
<td><%= project&.pull_requests_count %></td>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<li>
|
||||
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
|
||||
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
|
||||
<!-- <li><%= sidebar_item(admins_phenglei_users_path, '风雷意向用户列表', icon: 'user', controller: 'admins-phenglei_users') %></li> -->
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -26,17 +27,38 @@
|
|||
<li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories') %></li>
|
||||
<li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses') %></li>
|
||||
<li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li>
|
||||
<!-- <li><%= sidebar_item(admins_apply_signatures_path, '特殊许可申请列表', icon: 'git', controller: 'admins-apply_signatures') %></li> -->
|
||||
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_item_group('#homepage-submenu', '首页配置', icon: 'file') do %>
|
||||
<li><%= sidebar_item(admins_platform_communicates_path, '社区动态', icon: 'edit', controller: 'admins-platform_communicates') %></li>
|
||||
<li><%= sidebar_item(admins_platform_people_path, '论坛交流人物', icon: 'user', controller: 'admins-platform_people') %></li>
|
||||
<li>
|
||||
<a href="/task/taskAdmin">
|
||||
<i class="fa fa-bell fa-fw" data-toggle="tooltip" data-placement="right" data-boundary="window" title="" data-original-title="论坛交流人物"></i>
|
||||
<span>创客任务</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<%= Rails.application.config_for(:configuration)['web_site'] %>/admin/competitions/list">
|
||||
<i class="fa fa-wrench fa-fw" data-toggle="tooltip" data-placement="right" data-boundary="window" title="" data-original-title="论坛交流人物"></i>
|
||||
<span>开放竞赛</span>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li>
|
||||
<li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li>
|
||||
|
||||
<!--
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
|
||||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
||||
<% end %>
|
||||
</li>
|
||||
-->
|
||||
<li>
|
||||
<%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %>
|
||||
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li>
|
||||
|
|
|
@ -68,12 +68,12 @@
|
|||
<%= f.label :identity, label: '职业' %>
|
||||
<%= select_tag('user[identity]', [], class: 'form-control identity-select optional', 'data-value': @user.user_extension&.identity, 'data-first-title': '请选择') %>
|
||||
</div>
|
||||
<div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user.user_extension.student? ? 'display:none;' : '' %>">
|
||||
<div class="form-group technical-title-select-wrapper optional col-md-1" style="<%= @user.user_extension&.student? ? 'display:none;' : '' %>">
|
||||
<%= f.label :technical_title, label: '职称' %>
|
||||
<%= select_tag('user[technical_title]', [], class: 'form-control technical-title-select optional', 'data-value': @user.technical_title) %>
|
||||
</div>
|
||||
|
||||
<%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user.user_extension.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %>
|
||||
<%= f.input :student_id, as: :tel, label: '学号', wrapper_html: { class: 'col-md-2', style: @user.user_extension&.student? ? '' : 'display:none;' }, input_html: { class: 'student-id-input' } %>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
|
|
|
@ -16,16 +16,11 @@
|
|||
<%= select_tag(:identity, options_for_select(identity_options), class: 'form-control') %>
|
||||
</div>
|
||||
|
||||
<div class="form-group mr-2">
|
||||
<label for="identity">授权类型:</label>
|
||||
<% auto_trial_options = [['全部', ''], ['自动授权', 1], ['手动授权', 0]] %>
|
||||
<%= select_tag(:auto_trial, options_for_select(auto_trial_options), class: 'form-control') %>
|
||||
</div>
|
||||
|
||||
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'ID/姓名/邮箱/手机号检索') %>
|
||||
<%
|
||||
=begin%>
|
||||
<%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %>
|
||||
<%= text_field_tag(:school_name, params[:school_name], class: 'form-control col-sm-2', placeholder: '学校/单位检索') %>
|
||||
<%
|
||||
=end%>
|
||||
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<%
|
||||
define_admin_breadcrumbs do
|
||||
add_admin_breadcrumb('用户管理', admins_users_path)
|
||||
add_admin_breadcrumb('新增用户')
|
||||
end
|
||||
%>
|
||||
|
||||
<div class="box user-edit-container">
|
||||
<%= simple_form_for([:admins, User.new], url: admins_users_path ) do |f| %>
|
||||
<%= f.error_notification %>
|
||||
<div class="form-group px-2">
|
||||
<div class="form-row">
|
||||
<%= f.input :phone, as: :tel, label: '手机号', required: true, wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-sm-11', autocomplete: 'off' } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<%= f.input :password, as: :password, required: true, label: '密码', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-sm-11', autocomplete: 'new-password' } %>
|
||||
<%= f.input :password_confirmation, as: :password, required: true, label: '确认密码', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-sm-11', autocomplete: 'new-password' } %>
|
||||
</div>
|
||||
|
||||
<div class="form-row mt-4">
|
||||
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
|
||||
<%= link_to '取消', admins_users_path, class: 'btn btn-secondary px-4' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue