forked from Gitlink/forgeplus
Compare commits
197 Commits
dev_ms_mil
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
86f03ffafc | |
|
|
9f837c62fb | |
|
|
d768e81afd | |
|
|
8341c177b6 | |
|
|
5c9702b308 | |
|
|
f470807225 | |
|
|
51597335a4 | |
|
|
eba8a3553d | |
|
|
e490ddb1f5 | |
|
|
c96dacbf88 | |
|
|
b162b3357a | |
|
|
c67686bdf5 | |
|
|
1021731d2b | |
|
|
fc5876fc32 | |
|
|
411c10e8f3 | |
|
|
d867823f01 | |
|
|
604c2595d3 | |
|
|
1c111e83b3 | |
|
|
4643d2387c | |
|
|
3ca629d47d | |
|
|
a9c0d18a5f | |
|
|
b22330d146 | |
|
|
b2e338732d | |
|
|
d71272146f | |
|
|
c56f0ca7fc | |
|
|
744f857f20 | |
|
|
f222cc6e4f | |
|
|
e87413f8a0 | |
|
|
0133ec24ca | |
|
|
03e54f9b3d | |
|
|
1277e717ff | |
|
|
1a7b323120 | |
|
|
fffe57a211 | |
|
|
b673747475 | |
|
|
a4555e2d10 | |
|
|
c920994274 | |
|
|
c14c92ac11 | |
|
|
8bf02b1ee5 | |
|
|
9876e84c17 | |
|
|
ea42b0d6ed | |
|
|
660a48b257 | |
|
|
65d51e8578 | |
|
|
c3d9e38e05 | |
|
|
7d612ea6b3 | |
|
|
120a33bc8a | |
|
|
b68c9945e5 | |
|
|
01360de423 | |
|
|
5bd33c033c | |
|
|
0d828ead1f | |
|
|
1a22491e36 | |
|
|
95a355b87c | |
|
|
13768f9778 | |
|
|
220ca96669 | |
|
|
28c8761f32 | |
|
|
1d81548eb6 | |
|
|
96238c2e13 | |
|
|
d532dc7cf5 | |
|
|
8b7b1b7a4e | |
|
|
1e081b5a3e | |
|
|
8c71a72fce | |
|
|
ee7acaaa82 | |
|
|
c1d4df6e06 | |
|
|
55f7beb22d | |
|
|
aa314c141c | |
|
|
37e1704897 | |
|
|
ddacf2a733 | |
|
|
d07543111a | |
|
|
908cda56f3 | |
|
|
841778900c | |
|
|
6a3d297b30 | |
|
|
002c773746 | |
|
|
45f05c9fc4 | |
|
|
84e48d25c1 | |
|
|
37d8a5426f | |
|
|
df3bf621ce | |
|
|
da98efe04f | |
|
|
2976742b29 | |
|
|
55e081ba2b | |
|
|
a3c49b3d5f | |
|
|
5a9f29c25f | |
|
|
f75827bcf0 | |
|
|
f0c4d1226b | |
|
|
3a47c61010 | |
|
|
1f0388c1a1 | |
|
|
de6ae5b720 | |
|
|
8a55e84372 | |
|
|
f055fed7d0 | |
|
|
21befb6486 | |
|
|
b6e8a135f0 | |
|
|
9cddda7fd4 | |
|
|
002ae9f327 | |
|
|
8055ae2c07 | |
|
|
01f32ae2d7 | |
|
|
1c6982d15b | |
|
|
9300483c1a | |
|
|
1920cb5ce3 | |
|
|
5a20842edb | |
|
|
506ab1722d | |
|
|
07d11737e9 | |
|
|
1fe9ea126a | |
|
|
dcd4457cf5 | |
|
|
0bd6621821 | |
|
|
04a1376820 | |
|
|
c3a1fb78ea | |
|
|
cf224bc9fe | |
|
|
d6c3bcfaf1 | |
|
|
a66e5b876d | |
|
|
b11fd350da | |
|
|
c417fa7369 | |
|
|
e9a4370adc | |
|
|
e6b8435037 | |
|
|
c175fa1339 | |
|
|
6ce4b26047 | |
|
|
e022e429d4 | |
|
|
50fb8d3983 | |
|
|
02d26df172 | |
|
|
254718e390 | |
|
|
0b6ebb7b36 | |
|
|
e638dccfa5 | |
|
|
b89501822f | |
|
|
5f5b380514 | |
|
|
d2293a2778 | |
|
|
7d0b05f975 | |
|
|
9393ceb8b7 | |
|
|
860b46685a | |
|
|
62b99c517e | |
|
|
3869529620 | |
|
|
9394d15752 | |
|
|
8952f6a944 | |
|
|
ffa2782637 | |
|
|
d0a65775aa | |
|
|
d7a459bad2 | |
|
|
fc522be5ea | |
|
|
9195d43a34 | |
|
|
a866415990 | |
|
|
69bf30d482 | |
|
|
c4560ebb66 | |
|
|
0211d6152e | |
|
|
12f1aba07e | |
|
|
63d91919ae | |
|
|
06c851d22f | |
|
|
ad4617288d | |
|
|
7c0a2aa89e | |
|
|
e1d7b0b881 | |
|
|
7f28f07665 | |
|
|
3be5c013a8 | |
|
|
70c7b1da0c | |
|
|
66608b3baa | |
|
|
9ee42e805b | |
|
|
15f9004f63 | |
|
|
0f67944911 | |
|
|
8b656fd409 | |
|
|
815b364428 | |
|
|
18ae3853d7 | |
|
|
ce18cc380a | |
|
|
cbc6f4e7d1 | |
|
|
aa23762b2f | |
|
|
5c864acb64 | |
|
|
8bbfea2079 | |
|
|
8c2a543e61 | |
|
|
2932866198 | |
|
|
0d8ddc34cc | |
|
|
0909223867 | |
|
|
c07c570061 | |
|
|
223755a965 | |
|
|
f1ed61c687 | |
|
|
553a584121 | |
|
|
04288a734e | |
|
|
db2ba95e24 | |
|
|
39f0811f0a | |
|
|
495de925dd | |
|
|
f18c56129e | |
|
|
6a7ef2a1a7 | |
|
|
25186b4e81 | |
|
|
a627ab4d82 | |
|
|
187ad1d263 | |
|
|
8f98a83379 | |
|
|
a14459da50 | |
|
|
f17e436d62 | |
|
|
34d95451b5 | |
|
|
b43926f69f | |
|
|
bd46d2dcc7 | |
|
|
6063c7c414 | |
|
|
af289d1f5e | |
|
|
899e7ccab8 | |
|
|
d3df04fb97 | |
|
|
50928f82c0 | |
|
|
33984e16d0 | |
|
|
8942c694c4 | |
|
|
d3a3c645c8 | |
|
|
3b5d971964 | |
|
|
61e5b9132a | |
|
|
d7bc309d49 | |
|
|
cb90dc1f51 | |
|
|
347af1a8ad | |
|
|
11350bb76f | |
|
|
50d81b2490 |
|
|
@ -36,6 +36,7 @@ public/react/yarn.lock
|
|||
/.idea/*
|
||||
|
||||
# Ignore react node_modules
|
||||
public/system/*
|
||||
public/react/*
|
||||
/public/react/.cache
|
||||
/public/react/node_modules/
|
||||
|
|
@ -82,4 +83,5 @@ docker/
|
|||
educoder.sql
|
||||
redis_data/
|
||||
Dockerfile
|
||||
dump.rdb
|
||||
dump.rdb
|
||||
.tags*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
# Changelog
|
||||
|
||||
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
|
||||
|
||||
* BUGFIXES
|
||||
* Fix 解决易修标题过长导致的排版问题(45469)
|
||||
* Fix 解决合并请求详情页面排版错误的问题(45457)
|
||||
* FIX 解决转移仓库界面专有名词描述错误的问题(45455)
|
||||
* Fix 解决markdown格式文件自动生成数字排序的问题(45454)
|
||||
* Fix 解决镜像项目源地址不显示的问题(45403)
|
||||
* Fix 解决镜像项目导航显示错误问题(45398)
|
||||
* Fix 解决其他相关bug
|
||||
|
||||
* ENHANCEMENTS
|
||||
* UPDATE 用户注册时,账号和密码正则匹配调整(45336) (45318) (45290)
|
||||
* ADD 创建组织各属性添加规则匹配功能(45313) (45289)
|
||||
* ADD 创建团建各属性添加规则匹配功能(45334) (45325) (45287)
|
||||
* ADD 仓库转移功能(45017) (45015)
|
||||
|
||||
## [v3.0.2](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-04-23
|
||||
|
||||
* BUGFIXES
|
||||
* Fix 解决部分用户头像不显示问题
|
||||
* Fix 解决代码库模块中最左侧目录中的文件定位加载不准确的问题
|
||||
* FIX 解决团队管理页面中项目链接错误问题
|
||||
* Fix 解决markdown格式文件显示问题
|
||||
* Fix 解决组织名下创建项目报错的问题
|
||||
* Fix 解决组织名下的项目,创建issue报错的问题
|
||||
* Fix 解决组织名下创建团队提示信息信息显示错误问题
|
||||
* Fix 解决点击组织图片时,链接加载错误问题
|
||||
* Fix 修复查询版本库信息安全漏洞
|
||||
* Fix 解决修复团队成员操作访问组织仓库报403错误的问题
|
||||
* Fix 解决owners团队成员对仓库添加成功失败的问题
|
||||
|
||||
* ENHANCEMENTS
|
||||
* ADD 自动生产用户头像功能
|
||||
* ADD 创建组织支持中文名称
|
||||
* ADD 创建团建支持中文名称
|
||||
* ADD 组织名称统一显示中文名
|
||||
* ADD 团队名称统一显示中文名
|
||||
* ADD 用户头像悬浮时展示相关信息
|
||||
* ADD 项目详情页添加实践课程链接入口
|
||||
* ADD README文件页面添加添加目录导航功能
|
||||
* UPDATE 升级改版底部footer信息
|
||||
* UPDATE 升级用户操作版本库权限
|
||||
|
||||
## [v3.0.1](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-03-19
|
||||
|
||||
* BUGFIXES
|
||||
* Fix pull reqeust模块中用户头像显示问题
|
||||
* Fix 解决issue模块中,指派用户的问题
|
||||
* Fix 解决合并请求失败的后显示message信息不正确
|
||||
* Fix 代码目录页面,readme文件提供单独的api
|
||||
|
||||
* ENHANCEMENTS
|
||||
* 重构项目详情页面
|
||||
|
||||
## [v3.0.0](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2020-12-29
|
||||
|
||||
* BUGFIXES
|
||||
* Fix pull reqeust的访问权限问题 (#14156) (#14171)
|
||||
* Fix 部分页面访问403的问题
|
||||
* Fix 合并请求失败的问题
|
||||
* Fix 代码目录页面,文件夹和文件图片不显示的问题
|
||||
* Fix Issue列表中按‘负责人’过滤筛选时,部分项目成员不在搜索范围没的问题
|
||||
* Fix 项目更新时间不同步的问题, 添加了定时任务
|
||||
* ENHANCEMENTS
|
||||
* 提升获取版本库目录代码查询速度 (#43296)
|
||||
* tag 列表慢查询速度问题 (#43332)
|
||||
* API builder 模版中 render partial builder的性能问题
|
||||
2
Gemfile
2
Gemfile
|
|
@ -126,3 +126,5 @@ gem 'request_store'
|
|||
gem 'harmonious_dictionary', '~> 0.0.1'
|
||||
|
||||
gem 'parallel', '~> 1.19', '>= 1.19.1'
|
||||
|
||||
gem 'letter_avatar'
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ GEM
|
|||
activerecord
|
||||
kaminari-core (= 1.2.0)
|
||||
kaminari-core (1.2.0)
|
||||
letter_avatar (0.3.8)
|
||||
listen (3.1.5)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
|
|
@ -456,6 +457,7 @@ DEPENDENCIES
|
|||
jbuilder (~> 2.5)
|
||||
jquery-rails
|
||||
kaminari (~> 1.1, >= 1.1.1)
|
||||
letter_avatar
|
||||
listen (>= 3.0.5, < 3.2)
|
||||
mysql2 (>= 0.4.4, < 0.6.0)
|
||||
oauth2
|
||||
|
|
|
|||
99
README.md
99
README.md
|
|
@ -11,13 +11,32 @@ Trustie (确实)是一个以大众化协同开发、开放式资源共享、
|
|||
## 部署
|
||||
|
||||
|
||||
### 1. 安装依赖包
|
||||
### Depends Versions
|
||||
|
||||
```bash
|
||||
bundle install
|
||||
* Ruby 2.4.5
|
||||
|
||||
* Rails ~> 5.2
|
||||
|
||||
* MySql ~> 5.6
|
||||
|
||||
* Redis 5+
|
||||
|
||||
* imagemagick
|
||||
|
||||
### Steps
|
||||
|
||||
#### 1. 克隆稳定版本
|
||||
```
|
||||
git clone -b standalone https://git.trustie.net/jasder/forgeplus.git
|
||||
```
|
||||
|
||||
### 2. 配置初始化文件
|
||||
#### 2. 安装依赖包
|
||||
|
||||
```bash
|
||||
cd forgeplus && bundle install
|
||||
```
|
||||
|
||||
#### 3. 配置初始化文件
|
||||
进入项目根目录执行一下命令:
|
||||
|
||||
```bash
|
||||
|
|
@ -27,12 +46,26 @@ touch config/redis.yml
|
|||
touch config/elasticsearch.yml
|
||||
```
|
||||
|
||||
### 3. 配置gitea服务(可选)
|
||||
#### 4. 配置数据库
|
||||
数据库配置信息请查看/config/database.yml文件,
|
||||
项目默认采用mysql数据库, 如需更改,请自行修改配置信息,
|
||||
默认配置如下:
|
||||
|
||||
```bash
|
||||
default: &default
|
||||
adapter: mysql2
|
||||
host: 127.0.0.1
|
||||
encoding: utf8
|
||||
username: root
|
||||
password: 123456
|
||||
```
|
||||
|
||||
#### 5. 配置gitea服务(可选)
|
||||
**如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/**
|
||||
|
||||
**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary
|
||||
**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/Trustie/gitea-binary**
|
||||
|
||||
#### 配置gitea服务步骤
|
||||
**配置gitea服务步骤**
|
||||
1. 部署gitea服务,并注册root账户
|
||||
2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如:
|
||||
|
||||
|
|
@ -44,75 +77,93 @@ gitea:
|
|||
base_url: '/api/v1'
|
||||
```
|
||||
|
||||
### 4. 安装redis环境
|
||||
#### 6. 安装redis环境
|
||||
**请自行搜索各平台如何安装部署redis环境**
|
||||
|
||||
|
||||
### 5. 创建数据库
|
||||
|
||||
#### 7. 安装imagemagick插件
|
||||
- Mac OS X
|
||||
```bash
|
||||
rails db:create
|
||||
brew install imagemagick ghostscript
|
||||
```
|
||||
|
||||
### 6. 导入数据表结构
|
||||
- Linux
|
||||
```bash
|
||||
sudo apt-get install -y imagemagick
|
||||
```
|
||||
|
||||
#### 8. 创建数据库
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
rails db:create RAILS_ENV=development
|
||||
```
|
||||
|
||||
#### 9. 导入数据表结构
|
||||
|
||||
```bash
|
||||
bundle exec rake sync_table_structure:import_csv
|
||||
```
|
||||
|
||||
### 7. 执行migrate迁移文件
|
||||
#### 10. 执行migrate迁移文件
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
rails db:migrate RAILS_ENV=development
|
||||
```
|
||||
|
||||
### 8. 启动redis(此处已mac系统为例)
|
||||
#### 11. clone前端代码
|
||||
**将前端代码克隆到public/react目录下,目录结构应该是: public/react/build**
|
||||
```bash
|
||||
git clone -b standalone https://git.trustie.net/jasder/build.git
|
||||
```
|
||||
|
||||
#### 12. 启动redis(此处已mac系统为例)
|
||||
```bash
|
||||
redis-server&
|
||||
```
|
||||
|
||||
### 9. 启动sidekiq
|
||||
#### 13. 启动sidekiq
|
||||
**开发环境为development, 生成环境为production**
|
||||
```bash
|
||||
bundle exec sidekiq -C config/sidekiq.yml -e production -d
|
||||
```
|
||||
|
||||
### 10. 启动rails服务
|
||||
#### 14. 启动rails服务
|
||||
```bash
|
||||
rails s
|
||||
```
|
||||
|
||||
### 11. 浏览器访问
|
||||
#### 15. 浏览器访问
|
||||
在浏览器中输入如下地址访问:
|
||||
```bash
|
||||
http://localhost:3000/
|
||||
```
|
||||
|
||||
#### 16. 其他说明
|
||||
通过页面注册都第一个用户为平台管理员用户
|
||||
|
||||
## 页面展示
|
||||
|
||||
- 代码库
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
- 任务管理
|
||||

|
||||

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

|
||||

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

|
||||

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

|
||||

|
||||
|
||||
### API
|
||||
- [API](api_document.md)
|
||||
- [API文档](https://forgeplus.trustie.net/docs/api)
|
||||
- [API](showdoc.com.cn)
|
||||
账号:forgeplus@admin.com 密码:forge123
|
||||
|
||||
|
|
|
|||
127
api_document.md
127
api_document.md
|
|
@ -1,4 +1,3 @@
|
|||
---
|
||||
|
||||
|
||||
# API文档
|
||||
|
|
@ -19,7 +18,6 @@
|
|||
|
||||
|
||||
### API接口
|
||||
---
|
||||
|
||||
#### 用户注册(通过其他平台)
|
||||
```
|
||||
|
|
@ -4830,8 +4828,133 @@ curl --location --request DELETE 'http://localhost:3000/api/ci/templates/10'
|
|||
|
||||
------
|
||||
|
||||
#### 参数列表查询
|
||||
|
||||
```
|
||||
GET /api/ci/secrets/secrets?owner={owner}&repo={repo}
|
||||
```
|
||||
|
||||
*示例*
|
||||
|
||||
```bash
|
||||
curl --location --request GET 'http://localhost:3000/api/ci/secrets?owner=test&repo=test'
|
||||
```
|
||||
|
||||
*请求参数说明:*
|
||||
|
||||
| 参数名 | 必选 | 类型 | 说明 |
|
||||
| ------ | ---- | ------ | ---------- |
|
||||
| owner | 是 | string | 仓库所有人 |
|
||||
| repo | 是 | string | 仓库名 |
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ------ | ------ | ------ |
|
||||
| name | string | 参数名 |
|
||||
| data | string | 参数值 |
|
||||
| repo | string | 仓库 |
|
||||
|
||||
返回值
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "test",
|
||||
"data": "test",
|
||||
"repo": "test"
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
#### 参数新增/更新
|
||||
|
||||
```
|
||||
POST /api/ci/secrets?owner={owner}&repo={repo}
|
||||
```
|
||||
|
||||
*示例*
|
||||
|
||||
```bash
|
||||
curl --location --request POST 'http://localhost:3000/api/ci/secrets?owner=test&repo=test' \
|
||||
--data-raw ' {
|
||||
"name": "ip",
|
||||
"data": "1.1.1.1",
|
||||
"id": 21
|
||||
}'
|
||||
```
|
||||
|
||||
*请求参数说明:*
|
||||
|
||||
| 参数名 | 必选 | 类型 | 说明 |
|
||||
| ------ | ---- | ------ | ------------ |
|
||||
| owner | 是 | string | 仓库拥有者 |
|
||||
| repo | 是 | string | 仓库名 |
|
||||
| name | 是 | string | 参数名 |
|
||||
| data | 是 | string | 参数值 |
|
||||
| id | 否 | int | id,更新时传 |
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ------- | ------ | ------------ |
|
||||
| status | int | 状态码 0成功 |
|
||||
| message | string | 消息 |
|
||||
|
||||
返回值
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
#### 参数删除
|
||||
|
||||
```
|
||||
DELETE /api/ci/secrets/{id}?name={name}&owner={owner}&repo={repo}
|
||||
```
|
||||
|
||||
*示例*
|
||||
|
||||
```bash
|
||||
curl --location --request DELETE 'http://localhost:3000/api/ci/secrets/1?name=p1&owner=victor&repo=trustieTest' \
|
||||
```
|
||||
|
||||
*请求参数说明:*
|
||||
|
||||
| 参数名 | 必选 | 类型 | 说明 |
|
||||
| ------ | ---- | ------ | ------ |
|
||||
| name | 是 | string | 参数名 |
|
||||
| id | 是 | int | 参数id |
|
||||
|
||||
*返回参数说明:*
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ------- | ------ | ------------ |
|
||||
| status | int | 状态码 0成功 |
|
||||
| message | string | 返回消息 |
|
||||
|
||||
返回值
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
|
||||
|
||||
|
||||
#### 解除CI服务器绑定
|
||||
```
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ class AccountsController < ApplicationController
|
|||
|
||||
# 用户登录
|
||||
def login
|
||||
Users::LoginForm.new(account_params).validate!
|
||||
@user = User.try_to_login(params[:login], params[:password])
|
||||
|
||||
return normal_status(-2, "错误的账号或密码") if @user.blank?
|
||||
|
|
@ -345,4 +346,7 @@ class AccountsController < ApplicationController
|
|||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
||||
def account_params
|
||||
params.require(:account).permit(:login, :password)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class ApplicationController < ActionController::Base
|
|||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
|
||||
|
||||
helper_method :current_user
|
||||
helper_method :current_user, :base_url
|
||||
|
||||
# 所有请求必须合法签名
|
||||
def check_sign
|
||||
|
|
@ -770,6 +770,11 @@ class ApplicationController < ActionController::Base
|
|||
@repository ||= load_project&.repository
|
||||
end
|
||||
|
||||
def base_url
|
||||
request.base_url
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def object_not_found
|
||||
uid_logger("Missing template or cant't find record, responding with 404")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
class Ci::SecretsController < Ci::BaseController
|
||||
|
||||
before_action :load_repo
|
||||
|
||||
# 参数列表
|
||||
def index
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], nil).secrets
|
||||
@secrets = result
|
||||
end
|
||||
|
||||
#新增、更新参数
|
||||
def create
|
||||
options = {
|
||||
name: params[:name],
|
||||
data: params[:data]
|
||||
}
|
||||
id = params[:id]
|
||||
if id
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).update_secret
|
||||
if result["id"]
|
||||
render_ok
|
||||
else
|
||||
render_error(result["message"])
|
||||
end
|
||||
else
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
||||
if result["id"]
|
||||
render_ok
|
||||
else
|
||||
render_error(result["message"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#删除参数
|
||||
def destroy
|
||||
name = params[:name]
|
||||
if !name.blank?
|
||||
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
||||
render_ok
|
||||
else
|
||||
render_error("参数名不能为空")
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_ok
|
||||
end
|
||||
|
||||
def ci_drone_url
|
||||
user = User.find_by(login: params[:owner])
|
||||
user&.ci_cloud_account.drone_url
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
module Acceleratorable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def enable_accelerator?(clone_addr)
|
||||
clone_addr.include?(github_domain) || clone_addr.include?(gitlab_domain)
|
||||
end
|
||||
|
||||
def accelerator_url(repo_name)
|
||||
[accelerator_domain, accelerator_username, "#{repo_name}.git"].join('/')
|
||||
end
|
||||
|
||||
def github_domain
|
||||
'github.com'
|
||||
end
|
||||
|
||||
def gitlab_domain
|
||||
'gitlab.com'
|
||||
end
|
||||
|
||||
def accelerator_domain
|
||||
Gitea.gitea_config[:accelerator]["domain"]
|
||||
end
|
||||
|
||||
def accelerator_username
|
||||
Gitea.gitea_config[:accelerator]["access_key_id"]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -8,6 +8,8 @@ module RegisterHelper
|
|||
user.password = password
|
||||
user.platform = platform
|
||||
user.activate
|
||||
|
||||
return unless user.valid?
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
||||
if interactor.success?
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ module Repository::LanguagesPercentagable
|
|||
hash.transform_values { |v|
|
||||
ActionController::Base.helpers
|
||||
.number_to_percentage((v * 100.0 / total_byte_size), precision: 1)
|
||||
}
|
||||
}.select{|k,v| v != "0.0%"}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class IssuesController < ApplicationController
|
|||
include TagChosenHelper
|
||||
|
||||
def index
|
||||
return render_not_found unless @project.has_menu_permission("issues")
|
||||
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
|
||||
issues = @project.issues.issue_issue.issue_index_includes
|
||||
issues = issues.where(is_private: false) unless @user_admin_or_member
|
||||
|
|
@ -100,51 +101,46 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
if params[:subject].blank?
|
||||
normal_status(-1, "标题不能为空")
|
||||
elsif params[:subject].to_s.size > 255
|
||||
normal_status(-1, "标题不能超过255个字符")
|
||||
else
|
||||
issue_params = issue_send_params(params)
|
||||
|
||||
@issue = Issue.new(issue_params)
|
||||
if @issue.save!
|
||||
if params[:attachment_ids].present?
|
||||
params[:attachment_ids].each do |id|
|
||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @issue
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
issue_params = issue_send_params(params)
|
||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
||||
@issue = Issue.new(issue_params)
|
||||
if @issue.save!
|
||||
if params[:attachment_ids].present?
|
||||
params[:attachment_ids].each do |id|
|
||||
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
|
||||
unless attachment.blank?
|
||||
attachment.container = @issue
|
||||
attachment.author_id = current_user.id
|
||||
attachment.description = ""
|
||||
attachment.save
|
||||
end
|
||||
end
|
||||
if params[:issue_tag_ids].present?
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
end
|
||||
if params[:issue_tag_ids].present?
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
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',
|
||||
parent_container_id: @project.id, parent_container_type: "Project",
|
||||
tiding_type: 'issue', status: 0)
|
||||
end
|
||||
|
||||
#为悬赏任务时, 扣除当前用户的积分
|
||||
if params[:issue_type].to_s == "2"
|
||||
post_to_chain("minus", params[:token].to_i, current_user.try(:login))
|
||||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||
else
|
||||
normal_status(-1, "创建失败")
|
||||
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',
|
||||
parent_container_id: @project.id, parent_container_type: "Project",
|
||||
tiding_type: 'issue', status: 0)
|
||||
end
|
||||
|
||||
end
|
||||
#为悬赏任务时, 扣除当前用户的积分
|
||||
if params[:issue_type].to_s == "2"
|
||||
post_to_chain("minus", params[:token].to_i, current_user.try(:login))
|
||||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||
else
|
||||
normal_status(-1, "创建失败")
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
@ -198,7 +194,7 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "不允许修改为关闭状态")
|
||||
else
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
|
||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
||||
if @issue.update_attributes(issue_params)
|
||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
|
|
@ -224,6 +220,9 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "更新失败")
|
||||
end
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class MembersController < ApplicationController
|
|||
end
|
||||
|
||||
def member_exists?
|
||||
@project.member?(params[:user_id])
|
||||
@project.members.exists?(params[:user_id])
|
||||
end
|
||||
|
||||
def operate!
|
||||
|
|
@ -59,6 +59,6 @@ class MembersController < ApplicationController
|
|||
end
|
||||
|
||||
def check_member_not_exists!
|
||||
return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
|
||||
return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless @project.member?(params[:user_id])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@ class Organizations::BaseController < ApplicationController
|
|||
end
|
||||
|
||||
def org_privacy_condition
|
||||
return false if current_user.admin?
|
||||
@organization.organization_extension.privacy? && @organization.organization_users.where(user_id: current_user.id).blank?
|
||||
end
|
||||
|
||||
def team_not_found_condition
|
||||
@team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id)
|
||||
!current_user&.admin? && @team.team_users.where(user_id: current_user.id).blank? && !@organization.is_owner?(current_user.id)
|
||||
end
|
||||
|
||||
def user_mark
|
||||
|
|
@ -31,4 +32,4 @@ class Organizations::BaseController < ApplicationController
|
|||
def project_mark
|
||||
params[:repo_name] || params[:id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
end
|
||||
|
|
@ -35,9 +36,12 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
login = @organization.login
|
||||
@organization.update!(login: organization_params[:name]) if organization_params[:name].present?
|
||||
@organization.organization_extension.update_attributes!(organization_params.except(:name))
|
||||
@organization.login = organization_params[:name] if organization_params[:name].present?
|
||||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||
@organization.save!
|
||||
@organization.organization_extension.update_attributes!(organization_params.except(:name, :nickname))
|
||||
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
end
|
||||
|
|
@ -82,7 +86,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
def organization_params
|
||||
params.permit(:name, :description, :website, :location,
|
||||
:repo_admin_change_team_access, :visibility,
|
||||
:max_repo_creation)
|
||||
:max_repo_creation, :nickname)
|
||||
end
|
||||
|
||||
def password
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
end
|
||||
|
||||
def create
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def update
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::UpdateService.call(current_user, @team, team_params)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
@ -60,7 +64,7 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
|
||||
private
|
||||
def team_params
|
||||
params.permit(:name, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => [])
|
||||
params.permit(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types => [])
|
||||
end
|
||||
|
||||
def load_organization
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
class Projects::AppliedTransferProjectsController < Projects::BaseController
|
||||
before_action :check_auth
|
||||
|
||||
def organizations
|
||||
@organizations = Organization.includes(:organization_extension).joins(team_users: :team).where(team_users: {user_id: current_user.id}, teams: {authorize: %w(admin owner)})
|
||||
end
|
||||
|
||||
def create
|
||||
@applied_transfer_project = Projects::ApplyTransferService.call(current_user, @project, params)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def cancel
|
||||
@applied_transfer_project = Projects::CancelTransferService.call(current_user, @project)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def check_auth
|
||||
return render_forbidden unless current_user.admin? ||@project.owner?(current_user)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
class Projects::ProjectUnitsController < Projects::BaseController
|
||||
def index
|
||||
@project_units = @project.project_units
|
||||
end
|
||||
|
||||
def create
|
||||
if current_user.admin? || @project.manager?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
ProjectUnit.update_by_unit_types!(@project, unit_types)
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
render_forbidden('你没有权限操作')
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def unit_types
|
||||
params.fetch(:unit_types, [])
|
||||
end
|
||||
end
|
||||
|
|
@ -2,16 +2,34 @@ class ProjectsController < ApplicationController
|
|||
include ApplicationHelper
|
||||
include OperateProjectAbilityAble
|
||||
include ProjectsHelper
|
||||
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about]
|
||||
include Acceleratorable
|
||||
|
||||
before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list]
|
||||
before_action :load_project, except: %i[index group_type_list migrate create recommend]
|
||||
before_action :authorizate_user_can_edit_project!, only: %i[update]
|
||||
before_action :project_public?, only: %i[fork_users praise_users watch_users]
|
||||
|
||||
def menu_list
|
||||
menu = []
|
||||
|
||||
menu.append(menu_hash_by_name("home"))
|
||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
|
||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
|
||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
|
||||
menu.append(menu_hash_by_name("activity"))
|
||||
menu.append(menu_hash_by_name("setting")) if current_user.admin? || @project.manager?(current_user)
|
||||
|
||||
render json: menu
|
||||
end
|
||||
|
||||
def index
|
||||
scope = Projects::ListQuery.call(params)
|
||||
|
||||
# @projects = kaminari_paginate(scope)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner)
|
||||
@projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, :owner, :project_units)
|
||||
|
||||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
|
|
@ -37,14 +55,33 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def migrate
|
||||
Projects::MigrateForm.new(mirror_params).validate!
|
||||
@project = Projects::MigrateService.new(current_user, mirror_params).call
|
||||
|
||||
@project =
|
||||
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
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def branches
|
||||
@branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : []
|
||||
return @branches = [] unless @project.forge?
|
||||
|
||||
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def group_type_list
|
||||
|
|
@ -69,18 +106,20 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
# Projects::CreateForm.new(project_params).validate!
|
||||
private = params[:private]
|
||||
Projects::UpdateForm.new(project_params).validate!
|
||||
private = params[:private] || false
|
||||
|
||||
new_project_params = project_params.except(:private).merge(is_public: !private)
|
||||
@project.update_attributes!(new_project_params)
|
||||
gitea_params = {
|
||||
private: private,
|
||||
default_branch: params[:default_branch]
|
||||
default_branch: @project.default_branch,
|
||||
website: @project.website
|
||||
}
|
||||
if [true, false].include? private
|
||||
new_project_params = project_params.except(:private).merge(is_public: !private)
|
||||
Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params)
|
||||
@project.repository.update_column(:hidden, private)
|
||||
end
|
||||
@project.update_attributes!(new_project_params)
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
@ -91,7 +130,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
if current_user.admin? || @project.owner?(current_user)
|
||||
if current_user.admin? || @project.manager?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
||||
@project.destroy!
|
||||
|
|
@ -128,7 +167,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def recommend
|
||||
@projects = Project.recommend.includes(:repository, :project_category, :owner).limit(5)
|
||||
@projects = Project.recommend.includes(:repository, :project_category, :owner).order(id: :desc).limit(5)
|
||||
end
|
||||
|
||||
def about
|
||||
|
|
@ -162,7 +201,7 @@ class ProjectsController < ApplicationController
|
|||
|
||||
private
|
||||
def project_params
|
||||
params.permit(:user_id, :name, :description, :repository_name,
|
||||
params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url,
|
||||
:project_category_id, :project_language_id, :license_id, :ignore_id, :private)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
|
||||
def index
|
||||
return render_not_found unless @project.has_menu_permission("pulls")
|
||||
# @issues = Gitea::PullRequest::ListService.new(@user,@repository.try(:identifier)).call #通过gitea获取
|
||||
issues = @project.issues.issue_pull_request.issue_index_includes.includes(pull_request: :user)
|
||||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||
|
|
@ -139,7 +140,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def pr_merge
|
||||
return render_forbidden("你没有权限操作.") if @project.reporter?(current_user)
|
||||
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
|
||||
|
||||
if params[:do].blank?
|
||||
normal_status(-1, "请选择合并方式")
|
||||
|
|
@ -148,12 +149,12 @@ class PullRequestsController < ApplicationController
|
|||
begin
|
||||
result = PullRequests::MergeService.call(@owner, @repository, @pull_request, current_user, params)
|
||||
|
||||
if result && @pull_request.merge!
|
||||
if result.status == 200 && @pull_request.merge!
|
||||
@pull_request.project_trend_status!
|
||||
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
||||
normal_status(1, "合并成功")
|
||||
else
|
||||
normal_status(-1, "合并失败")
|
||||
normal_status(-1, result.message)
|
||||
end
|
||||
rescue => e
|
||||
normal_status(-1, e.message)
|
||||
|
|
@ -214,7 +215,7 @@ class PullRequestsController < ApplicationController
|
|||
def get_relatived
|
||||
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
|
||||
@project_versions = @project.versions&.select(:id,:name, :status).as_json
|
||||
@project_members = @project.members_user_infos
|
||||
@project_members = @project.all_developers
|
||||
@project_priories = IssuePriority&.select(:id,:name, :position).as_json
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,29 @@ class RepositoriesController < ApplicationController
|
|||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
@result = Repositories::DetailService.call(@owner, @repository, @user)
|
||||
@project_fork_id = @project.try(:forked_from_project_id)
|
||||
if @project_fork_id.present?
|
||||
@fork_project = Project.find_by(id: @project_fork_id)
|
||||
@fork_project_user = @fork_project.owner
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
@repo = @project.repository
|
||||
|
|
@ -84,7 +103,13 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def tags
|
||||
@tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
|
||||
def contributors
|
||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
@ -187,7 +212,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def get_ref
|
||||
@ref = params[:ref] || "master"
|
||||
@ref = params[:ref] || @project&.default_branch
|
||||
end
|
||||
|
||||
def get_latest_commit
|
||||
|
|
|
|||
|
|
@ -1,6 +1,57 @@
|
|||
class SettingsController < ApplicationController
|
||||
def show
|
||||
@old_projects_url = nil
|
||||
@old_projects_url = "https://www.trustie.net/users/#{current_user.try(:login)}/projects" if User.current.logged?
|
||||
@old_projects_url = nil
|
||||
get_add_menu
|
||||
get_common_menu
|
||||
get_personal_menu
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
def get_add_menu
|
||||
@add = []
|
||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||
hash = {}
|
||||
site.each {|k, v|
|
||||
hash.merge!("#{k}": get_site_url(k, v))
|
||||
}
|
||||
@add << hash
|
||||
end
|
||||
end
|
||||
|
||||
def get_common_menu
|
||||
@common = {}
|
||||
Site.common.select(:url, :key).each do |site|
|
||||
next if site["url"].to_s.include?("current_user") && !User.current.logged?
|
||||
@common.merge!("#{site["key"]}": append_http(reset_site_url(site["url"])))
|
||||
end
|
||||
end
|
||||
|
||||
def get_personal_menu
|
||||
@personal = []
|
||||
if User.current.logged?
|
||||
Site.personal.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||
hash = {}
|
||||
site.each {|k, v|
|
||||
hash.merge!("#{k}": get_site_url(k, v))
|
||||
}
|
||||
@personal << hash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_site_url(key, value)
|
||||
key.to_s === "url" ? append_http(reset_site_url(value)) : reset_site_url(value)
|
||||
end
|
||||
|
||||
def reset_site_url(url)
|
||||
return url unless url.to_s.include?("current_user")
|
||||
|
||||
split_arr = url.split('current_user')
|
||||
split_arr.length > 1 ? split_arr.join(current_user&.login) : (split_arr << current_user&.login).join('')
|
||||
end
|
||||
|
||||
def append_http(url)
|
||||
url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
class Users::AppliedMessagesController < Users::BaseController
|
||||
before_action :check_auth
|
||||
after_action :view_messages, only: [:index]
|
||||
|
||||
def index
|
||||
@applied_messages = @_observed_user.applied_messages.order(viewed: :asc, created_at: :desc)
|
||||
@applied_messages = paginate @applied_messages
|
||||
end
|
||||
|
||||
private
|
||||
def check_auth
|
||||
return render_forbidden unless observed_logged_user?
|
||||
end
|
||||
|
||||
def view_messages
|
||||
@applied_messages.update_all(viewed: 'viewed')
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
class Users::AppliedTransferProjectsController < Users::BaseController
|
||||
before_action :check_auth
|
||||
before_action :find_applied_transfer_project, except: [:index]
|
||||
before_action :find_project, except: [:index]
|
||||
|
||||
def index
|
||||
user_collection_sql = AppliedTransferProject.where(owner_id: @_observed_user.id).to_sql
|
||||
org_collection_sql = AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @_observed_user.id}, teams: {authorize: %w(admin owner)} )).to_sql
|
||||
@applied_transfer_projects = AppliedTransferProject.from("( #{ user_collection_sql } UNION #{ org_collection_sql } ) AS applied_transfer_projects")
|
||||
@applied_transfer_projects = paginate @applied_transfer_projects.order("created_at desc")
|
||||
end
|
||||
|
||||
# 接受迁移
|
||||
def accept
|
||||
@applied_transfer_project = Projects::AcceptTransferService.call(current_user, @project)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
# 拒绝迁移
|
||||
def refuse
|
||||
@applied_transfer_project = Projects::RefuseTransferService.call(current_user, @project)
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
private
|
||||
def check_auth
|
||||
return render_forbidden unless observed_logged_user?
|
||||
end
|
||||
|
||||
def find_applied_transfer_project
|
||||
@applied_transfer_project = AppliedTransferProject.find_by_id params[:id]
|
||||
end
|
||||
|
||||
def find_project
|
||||
@project = @applied_transfer_project.project
|
||||
end
|
||||
end
|
||||
|
|
@ -2,9 +2,9 @@ class UsersController < ApplicationController
|
|||
include ApplicationHelper
|
||||
include Ci::DbConnectable
|
||||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users]
|
||||
before_action :require_login, only: %i[me list]
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me list sync_user_info]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
||||
|
|
@ -27,12 +27,24 @@ class UsersController < ApplicationController
|
|||
|
||||
def show
|
||||
#待办事项,现在未做
|
||||
@undo_events = 0
|
||||
if User.current.login == @user.login
|
||||
@waiting_applied_messages = @user.applied_messages.waiting
|
||||
@common_applied_transfer_projects = AppliedTransferProject.where(owner_id: @user.id).common + AppliedTransferProject.where(owner_id: Organization.joins(team_users: :team).where(team_users: {user_id: @user.id}, teams: {authorize: %w(admin owner)} )).common
|
||||
@undo_events = @waiting_applied_messages.size + @common_applied_transfer_projects.size
|
||||
else
|
||||
@waiting_applied_messages = AppliedMessage.none
|
||||
@common_applied_transfer_projects = AppliedTransferProject.none
|
||||
@undo_events = 0
|
||||
end
|
||||
#用户的组织数量
|
||||
# @user_composes_count = @user.composes.size
|
||||
@user_composes_count = 0
|
||||
@user_org_count = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)).size + @user.organizations.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).size : @user.organizations.with_visibility("common").size
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible
|
||||
user_organizations = User.current.logged? ? @user.organizations.with_visibility(%w(common limited)) + @user.organizations.with_visibility("privacy").joins(:team_users).where(team_users: {user_id: current_user.id}) : @user.organizations.with_visibility("common")
|
||||
@user_org_count = user_organizations.size
|
||||
normal_projects = Project.members_projects(@user.id).to_sql
|
||||
org_projects = Project.joins(team_projects: [team: :team_users]).where(team_users: {user_id: @user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? projects : projects.visible
|
||||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
|
|
@ -56,6 +68,9 @@ class UsersController < ApplicationController
|
|||
@watchers = paginate(watchers)
|
||||
end
|
||||
|
||||
def hovercard
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find params[:id]
|
||||
@user.update!(user_params)
|
||||
|
|
@ -233,6 +248,26 @@ class UsersController < ApplicationController
|
|||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class VersionReleasesController < ApplicationController
|
|||
version_releases = Gitea::Versions::ListService.new(@user.gitea_token, @user.try(:login), @repository.try(:identifier)).call
|
||||
@version_releases = version_releases
|
||||
@user_permission = current_user.present? && (current_user == @user || current_user.admin?)
|
||||
@forge_releases = @repository.version_releases.select(:id,:version_gid).includes(:attachments)
|
||||
@forge_releases = @repository.version_releases.select(:id,:version_gid, :created_at).includes(:attachments)
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ class VersionsController < ApplicationController
|
|||
before_action :set_version, only: [:edit, :update, :destroy, :show,:update_status]
|
||||
|
||||
def index
|
||||
return render_not_found unless @project.has_menu_permission("versions")
|
||||
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||
order_name = params[:order_name] || "created_on"
|
||||
order_type = params[:order_type] || "desc"
|
||||
|
|
|
|||
|
|
@ -168,6 +168,55 @@ Remember — a happy kitten is an authenticated kitten!
|
|||
</aside>
|
||||
|
||||
|
||||
## 项目导航
|
||||
获取项目导航信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/yystopf/ceshi/menu_list | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/menu_list')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/:owner/:repo/menu_list`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是| |string |用户登录名
|
||||
repo |是| |string |项目标识identifier
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"menu_name": "home"
|
||||
},
|
||||
{
|
||||
"menu_name": "code"
|
||||
},
|
||||
{
|
||||
"menu_name": "pulls"
|
||||
},
|
||||
{
|
||||
"menu_name": "activity"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## 项目主页
|
||||
获取项目主页信息
|
||||
|
||||
|
|
@ -212,6 +261,84 @@ attachments |array|附件
|
|||
Remember — a happy kitten is an authenticated kitten!
|
||||
</aside>
|
||||
|
||||
## 项目模块信息
|
||||
项目模块信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/yystopf/ceshi/project_units.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/project_units')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/yystopf/ceshi/project_units`
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|type |string|模块名称 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "code"
|
||||
},
|
||||
{
|
||||
"type": "pulls"
|
||||
},
|
||||
{
|
||||
"type": "issues"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 更改项目模块展示
|
||||
更改项目模块展示
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
-H "accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{ \"unit_typs\": [\"code\", \"pulls\"]}" \
|
||||
http://localhost:3000/api/yystopf/ceshi/project_units.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/ceshi/project_units')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/yystopf/ceshi/project_units`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|status |int|返回状态, 0: 表示操作成功 |
|
||||
|message |string|返回信息说明|
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
## 创建项目
|
||||
创建项目
|
||||
|
|
@ -399,3 +526,241 @@ await octokit.request('POST /api/jaser/jasder_test/forks.json')
|
|||
"identifier": "newadm"
|
||||
}
|
||||
```
|
||||
|
||||
## 用户管理的组织列表
|
||||
用户管理的组织列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json | jq
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/:owner/:repo/applied_transfer_projects/organizations')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/:owner/:repo/applied_transfer_projects/organizations`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
owner |是| |string |用户登录名
|
||||
repo |是| |string |项目标识identifier
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
name |string|组织标识
|
||||
nickname |string|组织名称
|
||||
description|string|组织描述
|
||||
avatar_url|string|组织头像
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_count": 3,
|
||||
"organizations": [
|
||||
{
|
||||
"id": 9,
|
||||
"name": "ceshi_org",
|
||||
"nickname": "测试组织",
|
||||
"description": "测试组织",
|
||||
"avatar_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"name": "ceshi",
|
||||
"nickname": "测试组织哈哈哈",
|
||||
"description": "23212312",
|
||||
"avatar_url": "images/avatars/Organization/51?t=1618800723"
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"name": "ceshi1",
|
||||
"nickname": "身份卡手动阀",
|
||||
"description": "1231手动阀是的",
|
||||
"avatar_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 迁移项目
|
||||
迁移项目,edit接口is_transfering为true表示正在迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/:owner/:repo/applied_transfer_projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/applied_transfer_projects.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|owner_name|是| |string |迁移对象标识 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |项目id |
|
||||
|status |string |项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |项目迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 9,
|
||||
"type": "Organization",
|
||||
"name": "测试组织",
|
||||
"login": "ceshi_org",
|
||||
"image_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
"id": 4,
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
||||
|
||||
## 取消迁移项目
|
||||
迁移项目,edit接口is_transfering为true表示正在迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/applied_transfer_projects/cancel.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |迁移id |
|
||||
|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 9,
|
||||
"type": "Organization",
|
||||
"name": "测试组织",
|
||||
"login": "ceshi_org",
|
||||
"image_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
"id": 4,
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
||||
|
|
@ -97,6 +97,182 @@ await octokit.request('GET /api/jasder/jasder_test/simple.json')
|
|||
}
|
||||
```
|
||||
|
||||
## 仓库详情(新版)
|
||||
仓库详情
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/ceshi/detail.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/detail.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/detail`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|content |string |仓库简介 |
|
||||
|website |string |仓库网址 |
|
||||
|readme |string |readme文件|
|
||||
|identifier |string |项目标识 |
|
||||
|name |string |项目名称 |
|
||||
|issues_count |int |项目issue数量|
|
||||
|pull_requests_count |int |项目合并请求数量|
|
||||
|project_identifier |int |项目标识|
|
||||
|praises_count |int |项目点赞数量|
|
||||
|forked_count |int |项目复刻数量|
|
||||
|watchers_count |int |项目关注数量|
|
||||
|versions_count |int |项目里程碑数量|
|
||||
|version_releases_count |int |项目发行版数量|
|
||||
|version_releasesed_count |int |项目发行版已发行数量|
|
||||
|permission |string |项目权限|
|
||||
|mirror_url |string |镜像地址|
|
||||
|mirror |bool |是否为镜像项目|
|
||||
|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目|
|
||||
|open_devops |int |是否开启devops|
|
||||
|watched |bool |是否关注|
|
||||
|praised |bool |是否点赞|
|
||||
|status |int |项目状态|
|
||||
|forked_from_project_id |int |fork项目id|
|
||||
|fork_info |object |fork项目信息|
|
||||
|size |string |仓库大小|
|
||||
|ssh_url |string |项目ssh地址|
|
||||
|clone_url |string |项目克隆地址|
|
||||
|default_branch |string |仓库默认分支|
|
||||
|empty |bool |仓库是否为空|
|
||||
|full_name |string |仓库全称|
|
||||
|private |bool |仓库是否为私有项目|
|
||||
|license_name |string |许可证名称|
|
||||
|release_versions.list.name |string |项目issue数量|
|
||||
|release_versions.list.tag_name |string |发行版标签名称|
|
||||
|release_versions.list.created_at |string |发行版创建时间|
|
||||
|release_versions.total_count |int |发行版数量|
|
||||
|branches.list.name |string |分支名称|
|
||||
|branches.total_count |int |分支数量|
|
||||
|tags.list.name |string |标签名称|
|
||||
|tags.total_count |int |标签数量|
|
||||
|contributors.list.contributions|int |贡献数量|
|
||||
|contributors.list.login |string |贡献者登录名|
|
||||
|contributors.list.name |string |贡献者用户名称|
|
||||
|contributors.list.image_url |string |贡献者头像|
|
||||
|languages |object |项目语言占比|
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "仓库简介",
|
||||
"website": "仓库网址",
|
||||
"readme": {
|
||||
"type": "file",
|
||||
"encoding": "base64",
|
||||
"size": 9,
|
||||
"name": "README.md",
|
||||
"path": "README.md",
|
||||
"content": "# ceshi\n\n",
|
||||
"sha": ""
|
||||
},
|
||||
"identifier": "ceshi",
|
||||
"name": "测试项目",
|
||||
"project_id": 2,
|
||||
"repo_id": 2,
|
||||
"issues_count": 0,
|
||||
"pull_requests_count": 0,
|
||||
"project_identifier": "ceshi",
|
||||
"praises_count": 0,
|
||||
"forked_count": 0,
|
||||
"watchers_count": 0,
|
||||
"versions_count": 0,
|
||||
"version_releases_count": 0,
|
||||
"version_releasesed_count": 0,
|
||||
"permission": "Reporter",
|
||||
"mirror_url": null,
|
||||
"mirror": false,
|
||||
"type": 0,
|
||||
"open_devops": false,
|
||||
"watched": false,
|
||||
"praised": false,
|
||||
"status": 1,
|
||||
"forked_from_project_id": 1,
|
||||
"fork_info": {
|
||||
"fork_form_name": "测试项目",
|
||||
"fork_project_user_login": "ceshi_org",
|
||||
"fork_project_identifier": "ceshi",
|
||||
"fork_project_user_name": "ceshi_org"
|
||||
},
|
||||
"size": "25.0 KB",
|
||||
"ssh_url": "virus@localhost:yystopf/ceshi.git",
|
||||
"clone_url": "http://localhost:10080/yystopf/ceshi.git",
|
||||
"default_branch": "master",
|
||||
"empty": false,
|
||||
"full_name": "yystopf/ceshi",
|
||||
"private": false,
|
||||
"license_name": "gnu-javamail-exception",
|
||||
"release_versions": {
|
||||
"list": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "vvvv",
|
||||
"tag_name": "v1.1",
|
||||
"created_at": "2019-07-18 10:16"
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
},
|
||||
"branches": {
|
||||
"list": [
|
||||
{
|
||||
"name": "master"
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
},
|
||||
"tags": {
|
||||
"list": [
|
||||
{
|
||||
"name": "v1.1"
|
||||
},
|
||||
{
|
||||
"name": "v1.0"
|
||||
}
|
||||
],
|
||||
"total_count": 2
|
||||
},
|
||||
"contributors": {
|
||||
"list": [
|
||||
{
|
||||
"contributions": 1,
|
||||
"gid": 2,
|
||||
"login": "yystopf",
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"image_url": "avatars/User/b"
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
},
|
||||
"languages": {
|
||||
"HTML": "50.9%",
|
||||
"Ruby": "25.6%",
|
||||
"JavaScript": "21.4%",
|
||||
"CSS": "1.3%",
|
||||
"CoffeeScript": "0.7%",
|
||||
"Shell": "0.1%"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 编辑仓库信息
|
||||
编辑仓库信息
|
||||
|
|
@ -463,6 +639,78 @@ await octokit.request('GET /api/jasder/jasder_test/collaborators.json')
|
|||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 获取仓库所有文件
|
||||
获取仓库所有文件
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
-d "ref=develop" \
|
||||
http://localhost:3000/api/yystopf/ceshi/files.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/files.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/files`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|search |否| |string |文件搜索关键词 |
|
||||
|ref |是| |string |分支名,默认为仓库默认分支 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|name |string |文件名称|
|
||||
|path |string |文件路径|
|
||||
|sha |string |文件标识|
|
||||
|type |string |文件类型|
|
||||
|size |int |文件大小|
|
||||
|url |string |文件地址|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": ".gitignore",
|
||||
"path": ".gitignore",
|
||||
"sha": "f83922d01ae60f6e637a1a2b9f08871b4f87dfc8",
|
||||
"type": "file",
|
||||
"size": 63,
|
||||
"url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/.gitignore?ref=master",
|
||||
"html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/.gitignore"
|
||||
},
|
||||
{
|
||||
"name": "LICENSE",
|
||||
"path": "LICENSE",
|
||||
"sha": "8f3b9ab0d08afd3a624d822e3971a2f42b3bc2b9",
|
||||
"type": "file",
|
||||
"size": 341,
|
||||
"url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/LICENSE?ref=master",
|
||||
"html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/LICENSE"
|
||||
},
|
||||
{
|
||||
"name": "README.md",
|
||||
"path": "README.md",
|
||||
"sha": "1bc8a60ac6ddc876ebc4b60fc68991435bfad93e",
|
||||
"type": "file",
|
||||
"size": 9,
|
||||
"url": "http://localhost:10080/api/v1/repos/yystopf/ceshi/contents/README.md?ref=master",
|
||||
"html_url": "http://localhost:10080/yystopf/ceshi/src/branch/master/README.md"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## 获取仓库代码目录
|
||||
获取仓库代码目录
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
<!--
|
||||
* @Date: 2021-03-01 10:35:21
|
||||
* @LastEditors: viletyy
|
||||
* @LastEditTime: 2021-04-26 10:47:30
|
||||
* @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md
|
||||
-->
|
||||
# Users
|
||||
|
||||
## 获取当前登陆用户信息
|
||||
|
|
@ -40,3 +46,390 @@ await octokit.request('GET /api/users/me.json')
|
|||
<aside class="success">
|
||||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 待办事项-用户通知信息
|
||||
待办事项-用户通知信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/users/:login/applied_messages.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/users/:login/applied_messages.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login |string |用户标识 |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|applied |object |通知主体 |
|
||||
|applied.id |int |通知主体的迁移id |
|
||||
|applied.status |string |通知主体的迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|applied.time_ago |string |通知主体的迁移创建的时间 |
|
||||
|applied.project.id |int |通知主体的迁移项目的id |
|
||||
|applied.project.identifier |string |通知主体的迁移项目的标识 |
|
||||
|applied.project.name |string |通知主体的迁移项目的名称 |
|
||||
|applied.project.description |string |通知主体的迁移项目的描述 |
|
||||
|applied.project.is_public |bool |通知主体的迁移项目是否公开 |
|
||||
|applied.project.owner.id |bool |通知主体的迁移项目拥有者id |
|
||||
|applied.project.owner.type |string |通知主体的迁移项目拥有者类型 |
|
||||
|applied.project.owner.name |string |通知主体的迁移项目拥有者昵称 |
|
||||
|applied.project.owner.login |string |通知主体的迁移项目拥有者标识 |
|
||||
|applied.project.owner.image_url |string |通知主体的迁移项目拥有者头像 |
|
||||
|applied.user.id |int |通知主体的迁移创建者的id |
|
||||
|applied.user.type |string |通知主体的迁移创建者的类型 |
|
||||
|applied.user.name |string |通知主体的迁移创建者的名称 |
|
||||
|applied.user.login |string |通知主体的迁移创建者的标识 |
|
||||
|applied.user.image_url |string |通知主体的迁移创建者头像 |
|
||||
|applied.owner.id |int |通知主体的迁移接受者的id |
|
||||
|applied.owner.type |string |通知主体的迁移接受者的类型 |
|
||||
|applied.owner.name |string |通知主体的迁移接受者的名称 |
|
||||
|applied.owner.login |string |通知主体的迁移接受者的标识 |
|
||||
|applied.owner.image_url |string |通知主体的迁移接受者头像 |
|
||||
|applied_type |string |通知类型 |
|
||||
|name |string | 通知内容 |
|
||||
|viewed |string|是否已读,waiting:未读,viewed:已读|
|
||||
|status |string|通知状态, canceled:已取消,common: 正常,successed:成功,failure:失败|
|
||||
|time_ago |string|通知时间|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_count": 5,
|
||||
"applied_messages": [
|
||||
{
|
||||
"applied": {
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 9,
|
||||
"type": "Organization",
|
||||
"name": "测试组织",
|
||||
"login": "ceshi_org",
|
||||
"image_url": "images/avatars/Organization/9?t=1612706073"
|
||||
},
|
||||
"id": 4,
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "35分钟前"
|
||||
},
|
||||
"applied_user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"applied_type": "AppliedTransferProject",
|
||||
"name": "正在将【测试项目啊1】仓库转移给【测试组织】",
|
||||
"viewed": "viewed",
|
||||
"status": "common",
|
||||
"created_at": "2021-04-26 09:54",
|
||||
"time_ago": "35分钟前"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 待办事项-接受仓库
|
||||
待办事项-接受仓库
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/users/:login/applied_transfer_projects.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login |string |用户标识 |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |迁移id |
|
||||
|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_count": 4,
|
||||
"applied_transfer_projects": [
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
},
|
||||
"id": 1,
|
||||
"status": "canceled",
|
||||
"created_at": "2021-04-25 18:06",
|
||||
"time_ago": "16小时前"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 用户接受迁移
|
||||
用户接受迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/users/:login/applied_transfer_projects/:id/accept.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login |string |用户标识 |
|
||||
|id |int |迁移id |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |迁移id |
|
||||
|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
},
|
||||
"id": 1,
|
||||
"status": "canceled",
|
||||
"created_at": "2021-04-25 18:06",
|
||||
"time_ago": "16小时前"
|
||||
}
|
||||
```
|
||||
|
||||
## 用户拒绝迁移
|
||||
用户拒绝迁移
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/users/:login/applied_transfer_projects/:id/refuse.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login |string |用户标识 |
|
||||
|id |int |迁移id |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |迁移id |
|
||||
|status |string |迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝|
|
||||
|time_ago |string |迁移创建的时间 |
|
||||
|project.id |int |迁移项目的id |
|
||||
|project.identifier |string |迁移项目的标识 |
|
||||
|project.name |string |迁移项目的名称 |
|
||||
|project.description |string |迁移项目的描述 |
|
||||
|project.is_public |bool |迁移项目是否公开 |
|
||||
|project.owner.id |bool |迁移项目拥有者id |
|
||||
|project.owner.type |string |迁移项目拥有者类型 |
|
||||
|project.owner.name |string |迁移项目拥有者昵称 |
|
||||
|project.owner.login |string |迁移项目拥有者标识 |
|
||||
|project.owner.image_url |string |迁移项目拥有者头像 |
|
||||
|user.id |int |迁移创建者的id |
|
||||
|user.type |string |迁移创建者的类型 |
|
||||
|user.name |string |迁移创建者的名称 |
|
||||
|user.login |string |迁移创建者的标识 |
|
||||
|user.image_url |string |迁移创建者头像 |
|
||||
|owner.id |int |迁移接受者的id |
|
||||
|owner.type |string |迁移接受者的类型 |
|
||||
|owner.name |string |迁移接受者的名称 |
|
||||
|owner.login |string |迁移接受者的标识 |
|
||||
|owner.image_url |string |迁移接受者头像 |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"project": {
|
||||
"id": 86,
|
||||
"identifier": "ceshi_repo1",
|
||||
"name": "测试项目啊1",
|
||||
"description": "二十多",
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"id": 6,
|
||||
"type": "User",
|
||||
"name": "yystopf",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
|
||||
},
|
||||
"owner": {
|
||||
"id": 52,
|
||||
"type": "Organization",
|
||||
"name": "身份卡手动阀",
|
||||
"login": "ceshi1",
|
||||
"image_url": "images/avatars/Organization/52?t=1618805056"
|
||||
},
|
||||
"id": 1,
|
||||
"status": "canceled",
|
||||
"created_at": "2021-04-25 18:06",
|
||||
"time_ago": "16小时前"
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class Issues::CreateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class Issues::UpdateForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :subject
|
||||
|
||||
validates :subject, presence: { message: "不能为空" }
|
||||
|
||||
validates :subject, length: { maximum: 80, too_long: "不能超过80个字符" }
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class Organizations::CreateForm < BaseForm
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :name, :description, :website, :location, :repo_admin_change_team_access, :visibility, :max_repo_creation, :nickname
|
||||
|
||||
validates :name, :nickname, :visibility, presence: true
|
||||
validates :name, :nickname, length: { maximum: 100 }
|
||||
validates :location, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class Organizations::CreateTeamForm < BaseForm
|
||||
NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project, :unit_types
|
||||
|
||||
validates :name, :nickname, presence: true
|
||||
validates :name, :nickname, length: { maximum: 100 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validates :name, format: { with: NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
end
|
||||
|
|
@ -2,11 +2,15 @@ class Projects::CreateForm < BaseForm
|
|||
REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||
attr_accessor :user_id, :name, :description, :repository_name, :project_category_id,
|
||||
:project_language_id, :ignore_id, :license_id, :private, :owner
|
||||
|
||||
|
||||
validates :user_id, :name, :description,:repository_name,
|
||||
:project_category_id, :project_language_id, presence: true
|
||||
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
|
||||
|
||||
validates :name, length: { maximum: 50 }
|
||||
validates :repository_name, length: { maximum: 100 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
|
||||
validate :check_ignore, :check_license, :check_owner, :check_max_repo_creation
|
||||
validate do
|
||||
check_project_category(project_category_id)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
class Projects::UpdateForm < BaseForm
|
||||
attr_reader :name, :description, :repository_name, :project_category_id
|
||||
attr_accessor :name, :description, :project_category_id, :project_language_id, :private
|
||||
validates :name, :description, :project_category_id, :project_language_id, presence: true
|
||||
validates :name, length: { maximum: 50 }
|
||||
validates :description, length: { maximum: 200 }
|
||||
validate do
|
||||
check_project_category(project_category_id)
|
||||
check_project_language(project_language_id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
class Users::LoginForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :password, :login
|
||||
|
||||
validates :login, presence: true
|
||||
validates :password, presence: true, length: { minimum: 8, maximum: 16 }, format: { with: CustomRegexp::PASSWORD, message: "8~16位,支持字母数字和符号" }
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
class Users::UpdateInfoForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :email, :password, :login
|
||||
|
||||
validates :email, presence: true, format: { with: CustomRegexp::EMAIL }
|
||||
validates :password, presence: true
|
||||
validates :login, presence: true
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
module Admins::ProjectsHelper
|
||||
|
||||
def link_to_project(project)
|
||||
owner = project.owner
|
||||
|
||||
if owner.is_a?(User)
|
||||
link_to(project.owner&.real_name, "/users/#{project&.owner&.login}", target: '_blank')
|
||||
elsif owner.is_a?(Organization)
|
||||
link_to(project.owner&.real_name, "/organize/#{project&.owner&.login}", target: '_blank')
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -35,12 +35,6 @@ module ApplicationHelper
|
|||
course.course_modules.find_by(module_type: "graduation").try(:id)
|
||||
end
|
||||
|
||||
# 是否关注
|
||||
# from_user_id为被关注的用户
|
||||
def follow?(from_user_id, user_id)
|
||||
Watcher.where(watchable_type: 'Principal', watchable_id: from_user_id, user_id: user_id).exists?
|
||||
end
|
||||
|
||||
# git用户
|
||||
# git用户命名规则:login+"@educoder.net"
|
||||
def git_username(email)
|
||||
|
|
@ -144,17 +138,12 @@ module ApplicationHelper
|
|||
if File.exist?(disk_filename(source&.class, source&.id))
|
||||
ctime = File.ctime(disk_filename(source.class, source.id)).to_i
|
||||
if %w(User Organization).include?(source.class.to_s)
|
||||
File.join(relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
File.join("images", relative_path, ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
else
|
||||
File.join("images/avatars", ["#{source.class}", "#{source.id}"]) + "?t=#{ctime}"
|
||||
end
|
||||
elsif source.class.to_s == 'User'
|
||||
str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g"
|
||||
File.join(relative_path, "#{source.class}", str)
|
||||
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")
|
||||
source.get_letter_avatar_url
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
module ProjectsHelper
|
||||
def menu_hash_by_name(name)
|
||||
{
|
||||
menu_name: name
|
||||
}
|
||||
end
|
||||
|
||||
def render_zh_project_type(project_type)
|
||||
case project_type
|
||||
|
|
@ -29,15 +34,14 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def json_response(project, user)
|
||||
# repo = project.repository
|
||||
repo = Repository.includes(:mirror).select(:id, :mirror_url).find_by(project: project)
|
||||
repo = Repository.includes(:mirror).select(:id, :mirror_url, :source_clone_url).find_by(project: project)
|
||||
|
||||
tmp_json = {}
|
||||
unless project.common?
|
||||
tmp_json = tmp_json.merge({
|
||||
mirror_status: repo.mirror_status,
|
||||
mirror_num: repo.mirror_num,
|
||||
mirror_url: repo.mirror_url,
|
||||
mirror_url: repo.remote_mirror_url,
|
||||
first_sync: repo.first_sync?
|
||||
})
|
||||
end
|
||||
|
|
@ -85,8 +89,4 @@ module ProjectsHelper
|
|||
def render_educoder_avatar_url(project_educoder)
|
||||
[Rails.application.config_for(:configuration)['educoder']['cdn_url'], project_educoder&.image_url].join('/')
|
||||
end
|
||||
|
||||
def render_avatar_url(owner)
|
||||
['images', url_to_avatar(owner)].join('/')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
return "Owner" if user === project.owner
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
|
|
@ -28,39 +27,43 @@ module RepositoriesHelper
|
|||
|
||||
def render_commit_author(author_json)
|
||||
return nil if author_json.blank?
|
||||
find_user_by_login author_json['login']
|
||||
find_user_by_login author_json['name']
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, path)
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_images = ss + ss_src
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
if remove_title.length > 0
|
||||
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_images = ss + ss_src
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
if remove_title.length > 0
|
||||
r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
end
|
||||
if r_content.include?("?")
|
||||
new_r_content = r_content + "&raw=true"
|
||||
else
|
||||
new_r_content = r_content + "?raw=true"
|
||||
end
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
new_r_content = "#{path}" + new_r_content
|
||||
end
|
||||
content = content.gsub(/#{r_content}/, new_r_content)
|
||||
end
|
||||
if r_content.include?("?")
|
||||
new_r_content = r_content + "&raw=true"
|
||||
else
|
||||
new_r_content = r_content + "?raw=true"
|
||||
end
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
new_r_content = "#{path}" + new_r_content
|
||||
end
|
||||
content = content.gsub(/#{r_content}/, new_r_content)
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
|
|
|
|||
|
|
@ -124,14 +124,13 @@ module TagChosenHelper
|
|||
end
|
||||
|
||||
def render_cache_collaborators(project)
|
||||
cache_key = "all_collaborators/#{project.members.maximum('created_on')}"
|
||||
|
||||
cache_key = "all_collaborators/#{project.all_collaborators.maximum('created_on')}"
|
||||
Rails.cache.fetch(cache_key) do
|
||||
project.members.includes(:user).collect do |event|
|
||||
project.all_collaborators.order(created_on: :desc).collect do |user|
|
||||
{
|
||||
id: event.user&.id,
|
||||
name: event.user&.show_real_name,
|
||||
avatar_url: url_to_avatar(event.user),
|
||||
id: user&.id,
|
||||
name: user&.show_real_name,
|
||||
avatar_url: url_to_avatar(user),
|
||||
is_chosen: '0'
|
||||
}
|
||||
end
|
||||
|
|
@ -171,10 +170,8 @@ module TagChosenHelper
|
|||
# depended_issues_id = @depended_issues_id
|
||||
|
||||
end
|
||||
project_members = project.members_user_infos
|
||||
project_members_info = [] #指派给
|
||||
project_members.includes(user: :user_extension).each do |member|
|
||||
user = member&.user
|
||||
project.all_collaborators.includes(:user_extension).each do |user|
|
||||
if user
|
||||
real_name = user.try(:show_real_name)
|
||||
user_id = user.id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
class SendTransferProjectAppliedMessageJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(applied_transfer_project, applied_user, message_status)
|
||||
project = applied_transfer_project.project
|
||||
owner = project.owner
|
||||
return unless project.present?
|
||||
return unless owner.present?
|
||||
if owner.is_a?(Organization)
|
||||
receivers = project.managers + owner.team_users.joins(:team).where(teams: {authorize: %w(owner admin)})
|
||||
else
|
||||
receivers = project.managers
|
||||
end
|
||||
receivers.each do |rec|
|
||||
next if applied_user.id == rec.user_id # 自己不要给自己发通知
|
||||
AppliedMessage.create!(user_id: rec.user_id,
|
||||
applied: applied_transfer_project,
|
||||
status: message_status,
|
||||
name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status, applied_user&.real_name),
|
||||
applied_user_id: applied_user.id,
|
||||
project_id: project.id)
|
||||
end
|
||||
if message_status == 'successed' # 如果转移成功,给转移发起者发通知已转移成功
|
||||
AppliedMessage.find_or_create_by!(user_id: applied_transfer_project.user_id,
|
||||
applied: applied_transfer_project,
|
||||
status: message_status,
|
||||
name: build_name(project.name, applied_transfer_project&.owner&.real_name, message_status),
|
||||
applied_user_id: applied_user.id,
|
||||
project_id: project.id)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def build_name(repo_name, owner_name, message_status, applied_name="")
|
||||
case message_status
|
||||
when 'canceled'
|
||||
return "取消转移【#{repo_name}】仓库"
|
||||
when 'common'
|
||||
return "正在将【#{repo_name}】仓库转移给【#{owner_name}】"
|
||||
when 'successed'
|
||||
return "【#{repo_name}】仓库成功转移给【#{owner_name}】"
|
||||
when 'failure'
|
||||
return "拒绝转移【#{repo_name}】仓库"
|
||||
end
|
||||
""
|
||||
end
|
||||
end
|
||||
|
|
@ -85,4 +85,24 @@ class Ci::Drone::API < Ci::Drone::Request
|
|||
post(endpoint, "/api/users", {login: options[:login], email: options[:email], avatar_url:options[:avatar_url],active:true, drone_token: options[:token]})
|
||||
end
|
||||
|
||||
# Creates a secret.
|
||||
def create_secret
|
||||
post(endpoint, "/api/repos/#{owner}/#{repo}/secrets", {name: options[:name], data: options[:data], pull_request:true, drone_token: drone_token})
|
||||
end
|
||||
|
||||
# Update a secret.
|
||||
def update_secret
|
||||
patch(endpoint, "/api/repos/#{owner}/#{repo}/secrets/#{options[:name]}", { data: options[:data], pull_request:true, drone_token: drone_token})
|
||||
end
|
||||
|
||||
# list of secrets.
|
||||
def secrets
|
||||
get(endpoint, "/api/repos/#{owner}/#{repo}/secrets", drone_token: drone_token)
|
||||
end
|
||||
|
||||
# delete secret.
|
||||
def delete_secret
|
||||
delete(endpoint, "/api/repos/#{owner}/#{repo}/secrets/#{options[:name]}", drone_token: drone_token)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,5 +19,10 @@
|
|||
class AppliedMessage < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :applied, polymorphic: true
|
||||
belongs_to :project
|
||||
belongs_to :applied_user, class_name: 'User'
|
||||
|
||||
enum viewed: {waiting: 0, viewed: 1}
|
||||
enum status: {canceled: -1, common: 0, successed: 1, failure: 2} # -1 已取消 0 正在操作 1 操作成功 2 操作失败
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: applied_transfer_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# owner_id :integer
|
||||
# user_id :integer
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_applied_transfer_projects_on_owner_id (owner_id)
|
||||
# index_applied_transfer_projects_on_project_id (project_id)
|
||||
# index_applied_transfer_projects_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class AppliedTransferProject < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :user # 操作者
|
||||
belongs_to :owner # 接收个人或组织
|
||||
|
||||
has_many :applied_messages, as: :applied, dependent: :destroy
|
||||
|
||||
enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝
|
||||
end
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
# disk_directory :string(255)
|
||||
# attachtype :integer default("1")
|
||||
# is_public :integer default("1")
|
||||
# copy_from :integer
|
||||
# copy_from :string(255)
|
||||
# quotes :integer default("0")
|
||||
# is_publish :integer default("1")
|
||||
# publish_time :datetime
|
||||
|
|
@ -26,15 +26,15 @@
|
|||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
# link :string(255)
|
||||
# clone_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_attachments_on_author_id (author_id)
|
||||
# index_attachments_on_clone_id (clone_id)
|
||||
# index_attachments_on_container_id_and_container_type (container_id,container_type)
|
||||
# index_attachments_on_course_second_category_id (course_second_category_id)
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
#
|
||||
|
||||
class Attachment < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: chart_rules
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# rule_type :string(255)
|
||||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# competition_id :integer
|
||||
# competition_stage_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_chart_rules_on_competition_id (competition_id)
|
||||
# index_chart_rules_on_competition_stage_id (competition_stage_id)
|
||||
#
|
||||
|
||||
class ChartRule < ApplicationRecord
|
||||
|
||||
validates :content, length: { maximum: 1000, too_long: "不能超过1000个字符" }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: stages
|
||||
#
|
||||
# id :integer not null
|
||||
# subject_id :integer
|
||||
# name :string(255)
|
||||
# description :text(65535)
|
||||
# user_id :integer
|
||||
# position :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# shixuns_count :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_stages_on_subject_id (subject_id)
|
||||
#
|
||||
|
||||
class Ci::Stage < Ci::RemoteBase
|
||||
self.primary_key = 'stage_id'
|
||||
|
||||
|
|
|
|||
|
|
@ -39,13 +39,14 @@
|
|||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# admin_visitable :boolean default("0")
|
||||
# collaborator :boolean default("0")
|
||||
# gitea_uid :integer
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
# gitea_token :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -53,8 +54,9 @@
|
|||
# index_users_on_homepage_engineer (homepage_engineer)
|
||||
# index_users_on_homepage_teacher (homepage_teacher)
|
||||
# index_users_on_laboratory_id (laboratory_id)
|
||||
# index_users_on_login (login)
|
||||
# index_users_on_mail (mail)
|
||||
# index_users_on_login (login) UNIQUE
|
||||
# index_users_on_mail (mail) UNIQUE
|
||||
# index_users_on_phone (phone) UNIQUE
|
||||
# index_users_on_type (type)
|
||||
#
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,14 @@ module ProjectOperable
|
|||
has_many :team_projects, dependent: :destroy
|
||||
end
|
||||
|
||||
def set_owner_permission(creator)
|
||||
return unless owner.is_a?(Organization)
|
||||
owner.build_permit_team_projects!(id)
|
||||
# 避免自己创建的项目,却无法拥有访问权,因为该用户所在团队暂未获得项目访问权
|
||||
return if creator.nil? || owner.is_owner?(creator.id)
|
||||
add_member!(creator.id, "Manager")
|
||||
end
|
||||
|
||||
def add_member!(user_id, role_name='Developer')
|
||||
member = members.create!(user_id: user_id)
|
||||
set_developer_role(member, role_name)
|
||||
|
|
@ -78,15 +86,40 @@ module ProjectOperable
|
|||
if owner.is_a?(User)
|
||||
reporters.exists?(user_id: user.id)
|
||||
elsif owner.is_a?(Organization)
|
||||
reporters.exists?(user_id: user.id) || owner.is_read?(user.id)
|
||||
reporters.exists?(user_id: user.id) || owner.is_only_read?(user.id)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def operator?(user)
|
||||
user.admin? || !reporter?(user)
|
||||
end
|
||||
|
||||
def set_developer_role(member, role_name)
|
||||
role = Role.find_by(name: role_name)
|
||||
member.member_roles.create!(role: role)
|
||||
end
|
||||
|
||||
def has_menu_permission(unit_type)
|
||||
self.project_units.where(unit_type: unit_type).exists?
|
||||
end
|
||||
|
||||
def all_collaborators
|
||||
member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer Reporter)}).to_sql
|
||||
team_user_sql = User.joins(teams: :team_projects).where(team_projects: {project_id: self.id}).to_sql
|
||||
return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct
|
||||
end
|
||||
|
||||
def all_developers
|
||||
member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer)}).to_sql
|
||||
team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin write)}, team_projects: {project_id: self.id}).to_sql
|
||||
return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct
|
||||
end
|
||||
|
||||
def all_managers
|
||||
member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager)}).to_sql
|
||||
team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin)},team_projects: {project_id: self.id}).to_sql
|
||||
return User.from("( #{ member_sql} UNION #{ team_user_sql } ) AS users").distinct
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ module Watchable
|
|||
has_many :watcher_users, through: :watchers, source: :user, validate: false
|
||||
|
||||
scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) }
|
||||
scope :following, -> (user_id) { watched_by(user_id) }
|
||||
end
|
||||
|
||||
def watched?(watchable)
|
||||
|
|
@ -21,6 +22,24 @@ module Watchable
|
|||
obj.destroy! if obj.present?
|
||||
end
|
||||
|
||||
# 我正在关注的、我追随的
|
||||
def following
|
||||
User.following(self.id)
|
||||
end
|
||||
|
||||
def following_count
|
||||
following.size
|
||||
end
|
||||
|
||||
# 关注我的、我的粉丝、我的追随者
|
||||
def followers
|
||||
watcher_users
|
||||
end
|
||||
|
||||
def followers_count
|
||||
followers.size
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,38 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: discusses
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# dis_type :string(255)
|
||||
# dis_id :integer
|
||||
# content :text(65535)
|
||||
# parent_id :integer
|
||||
# root_id :integer
|
||||
# praise_count :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# challenge_id :integer
|
||||
# reward :integer
|
||||
# hidden :boolean default("0")
|
||||
# last_reply_id :integer
|
||||
# position :integer
|
||||
# praises_count :integer default("0")
|
||||
# sticky :boolean default("0")
|
||||
# course_sticky :boolean default("0")
|
||||
# course_hidden :boolean default("0")
|
||||
# copy_message_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_discusses_on_challenge_id (challenge_id)
|
||||
# index_discusses_on_copy_message_id (copy_message_id)
|
||||
# index_discusses_on_course_hidden (course_hidden)
|
||||
# index_discusses_on_course_sticky (course_sticky)
|
||||
# index_discusses_on_dis_id_and_dis_type (dis_id,dis_type)
|
||||
# index_discusses_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Discuss < ApplicationRecord
|
||||
default_scope { order(created_at: :desc) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,24 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: forge_activities
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# project_id :integer
|
||||
# forge_act_id :integer
|
||||
# forge_act_type :string(255)
|
||||
# org_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# forge_act_index (project_id,forge_act_id,created_at,forge_act_type)
|
||||
# index_forge_activities_on_forge_act_id (forge_act_id)
|
||||
#
|
||||
|
||||
class ForgeActivity < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :forge_act, polymorphic: true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: helps
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# about_us :text(65535)
|
||||
# agreement :text(65535)
|
||||
# status :text(65535)
|
||||
# help_center :text(65535)
|
||||
# join_us :text(65535)
|
||||
#
|
||||
|
||||
class Help < ApplicationRecord
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
# sync_course :boolean default("0")
|
||||
# sync_subject :boolean default("0")
|
||||
# sync_shixun :boolean default("0")
|
||||
# is_local :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
# content :text(65535)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# is_secret :boolean default("0")
|
||||
#
|
||||
|
||||
class License < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -1,3 +1,27 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: live_links
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# course_id :integer
|
||||
# user_id :integer
|
||||
# url :string(255)
|
||||
# description :text(65535)
|
||||
# on_status :boolean default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# course_name :string(255)
|
||||
# platform :string(255)
|
||||
# live_time :datetime
|
||||
# duration :integer
|
||||
# position :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_live_links_on_course_id (course_id)
|
||||
# index_live_links_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class LiveLink < ApplicationRecord
|
||||
# belongs_to :course
|
||||
belongs_to :user
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
# course_group_id :integer default("0")
|
||||
# is_collect :integer default("1")
|
||||
# graduation_group_id :integer default("0")
|
||||
# is_apply_signature :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: message_details
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# content :text(4294967295)
|
||||
# message_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_message_details_on_message_id (message_id)
|
||||
#
|
||||
|
||||
class MessageDetail < ApplicationRecord
|
||||
# belongs_to :message, :touch => true
|
||||
validates :content, length: { maximum: 10000, too_long: "内容不能超过10000个字符" }
|
||||
|
|
|
|||
|
|
@ -39,13 +39,14 @@
|
|||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# admin_visitable :boolean default("0")
|
||||
# collaborator :boolean default("0")
|
||||
# gitea_uid :integer
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
# gitea_token :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -53,8 +54,9 @@
|
|||
# index_users_on_homepage_engineer (homepage_engineer)
|
||||
# index_users_on_homepage_teacher (homepage_teacher)
|
||||
# index_users_on_laboratory_id (laboratory_id)
|
||||
# index_users_on_login (login)
|
||||
# index_users_on_mail (mail)
|
||||
# index_users_on_login (login) UNIQUE
|
||||
# index_users_on_mail (mail) UNIQUE
|
||||
# index_users_on_phone (phone) UNIQUE
|
||||
# index_users_on_type (type)
|
||||
#
|
||||
|
||||
|
|
@ -78,8 +80,8 @@ class Organization < Owner
|
|||
|
||||
scope :with_visibility, ->(visibility) { joins(:organization_extension).where(organization_extensions: {visibility: visibility}) if visibility.present? }
|
||||
|
||||
def self.build(name, gitea_token=nil)
|
||||
self.create!(login: name, gitea_token: gitea_token)
|
||||
def self.build(name, nickname, gitea_token=nil)
|
||||
self.create!(login: name, nickname: nickname, gitea_token: gitea_token)
|
||||
end
|
||||
|
||||
def can_create_project?(user_id)
|
||||
|
|
@ -106,14 +108,27 @@ class Organization < Owner
|
|||
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read write admin owner)}).present?
|
||||
end
|
||||
|
||||
def is_only_read?(user_id)
|
||||
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read)}).present?
|
||||
end
|
||||
|
||||
# 是不是所有者团队的最后一个成员
|
||||
def is_owner_team_last_one?(user_id)
|
||||
owner_team_users = team_users.joins(:team).where(teams: {authorize: %w(owner)})
|
||||
owner_team_users.pluck(:user_id).include?(user_id) && owner_team_users.size == 1
|
||||
end
|
||||
|
||||
# 为包含组织所有项目的团队创建项目访问权限
|
||||
def build_permit_team_projects!(project_id)
|
||||
teams.where(includes_all_project: true).each do |team|
|
||||
TeamProject.build(id, team.id, project_id)
|
||||
end
|
||||
end
|
||||
|
||||
def real_name
|
||||
login
|
||||
name = lastname + firstname
|
||||
name = name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
end
|
||||
|
||||
def show_real_name
|
||||
|
|
|
|||
|
|
@ -66,4 +66,6 @@ class Owner < ApplicationRecord
|
|||
|
||||
has_many :projects, foreign_key: :user_id, dependent: :destroy
|
||||
has_many :repositories, foreign_key: :user_id, dependent: :destroy
|
||||
has_many :applied_transfer_projects, dependent: :destroy
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,73 +1,76 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# homepage :string(255) default("")
|
||||
# is_public :boolean default("1"), not null
|
||||
# parent_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# identifier :string(255)
|
||||
# status :integer default("1"), not null
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# inherit_members :boolean default("0"), not null
|
||||
# project_type :integer default("0")
|
||||
# hidden_repo :boolean default("0"), not null
|
||||
# attachmenttype :integer default("1")
|
||||
# user_id :integer
|
||||
# dts_test :integer default("0")
|
||||
# enterprise_name :string(255)
|
||||
# organization_id :integer
|
||||
# project_new_type :integer
|
||||
# gpid :integer
|
||||
# forked_from_project_id :integer
|
||||
# forked_count :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# hot :integer default("0")
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# script :text(65535)
|
||||
# training_status :integer default("0")
|
||||
# rep_identifier :string(255)
|
||||
# project_category_id :integer
|
||||
# project_language_id :integer
|
||||
# license_id :integer
|
||||
# ignore_id :integer
|
||||
# praises_count :integer default("0")
|
||||
# watchers_count :integer default("0")
|
||||
# issues_count :integer default("0")
|
||||
# pull_requests_count :integer default("0")
|
||||
# language :string(255)
|
||||
# versions_count :integer default("0")
|
||||
# issue_tags_count :integer default("0")
|
||||
# closed_issues_count :integer default("0")
|
||||
# open_devops :boolean default("0")
|
||||
# gitea_webhook_id :integer
|
||||
# open_devops_count :integer default("0")
|
||||
# recommend :boolean default("0")
|
||||
# platform :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
||||
# index_projects_on_identifier (identifier)
|
||||
# index_projects_on_is_public (is_public)
|
||||
# index_projects_on_lft (lft)
|
||||
# index_projects_on_name (name)
|
||||
# index_projects_on_platform (platform)
|
||||
# index_projects_on_project_type (project_type)
|
||||
# index_projects_on_recommend (recommend)
|
||||
# index_projects_on_rgt (rgt)
|
||||
# index_projects_on_status (status)
|
||||
# index_projects_on_updated_on (updated_on)
|
||||
#
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) default(""), not null
|
||||
# description :text(4294967295)
|
||||
# homepage :string(255) default("")
|
||||
# is_public :boolean default("1"), not null
|
||||
# parent_id :integer
|
||||
# created_on :datetime
|
||||
# updated_on :datetime
|
||||
# identifier :string(255)
|
||||
# status :integer default("1"), not null
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# inherit_members :boolean default("0"), not null
|
||||
# project_type :integer default("0")
|
||||
# hidden_repo :boolean default("0"), not null
|
||||
# attachmenttype :integer default("1")
|
||||
# user_id :integer
|
||||
# dts_test :integer default("0")
|
||||
# enterprise_name :string(255)
|
||||
# organization_id :integer
|
||||
# project_new_type :integer
|
||||
# gpid :integer
|
||||
# forked_from_project_id :integer
|
||||
# forked_count :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# hot :integer default("0")
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# script :text(65535)
|
||||
# training_status :integer default("0")
|
||||
# rep_identifier :string(255)
|
||||
# project_category_id :integer
|
||||
# project_language_id :integer
|
||||
# praises_count :integer default("0")
|
||||
# watchers_count :integer default("0")
|
||||
# issues_count :integer default("0")
|
||||
# pull_requests_count :integer default("0")
|
||||
# language :string(255)
|
||||
# versions_count :integer default("0")
|
||||
# issue_tags_count :integer default("0")
|
||||
# closed_issues_count :integer default("0")
|
||||
# open_devops :boolean default("0")
|
||||
# gitea_webhook_id :integer
|
||||
# open_devops_count :integer default("0")
|
||||
# recommend :boolean default("0")
|
||||
# platform :integer default("0")
|
||||
# license_id :integer
|
||||
# ignore_id :integer
|
||||
# default_branch :string(255) default("master")
|
||||
# website :string(255)
|
||||
# lesson_url :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_projects_on_forked_from_project_id (forked_from_project_id)
|
||||
# index_projects_on_identifier (identifier)
|
||||
# index_projects_on_is_public (is_public)
|
||||
# index_projects_on_lft (lft)
|
||||
# index_projects_on_name (name)
|
||||
# index_projects_on_platform (platform)
|
||||
# index_projects_on_project_type (project_type)
|
||||
# index_projects_on_recommend (recommend)
|
||||
# index_projects_on_rgt (rgt)
|
||||
# index_projects_on_status (status)
|
||||
# index_projects_on_updated_on (updated_on)
|
||||
#
|
||||
|
||||
|
||||
class Project < ApplicationRecord
|
||||
include Matchable
|
||||
|
|
@ -109,12 +112,16 @@ class Project < ApplicationRecord
|
|||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||
has_one :project_detail, dependent: :destroy
|
||||
has_many :team_projects, dependent: :destroy
|
||||
has_many :project_units, dependent: :destroy
|
||||
has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy
|
||||
|
||||
after_save :check_project_members
|
||||
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
|
||||
scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)}
|
||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||
|
||||
delegate :content, to: :project_detail, allow_nil: true
|
||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||
|
||||
|
||||
def self.search_project(search)
|
||||
|
|
@ -153,6 +160,7 @@ class Project < ApplicationRecord
|
|||
|
||||
#创建项目管理员
|
||||
def check_project_members
|
||||
return if owner.is_a?(Organization)
|
||||
unless members.present? && members.exists?(user_id: self.user_id)
|
||||
member_params = {
|
||||
user_id: self.user_id,
|
||||
|
|
@ -234,10 +242,12 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def get_premission user
|
||||
permission = "Reporter"
|
||||
member = members.find_by(user: user)
|
||||
return "Owner" if owner?(user)
|
||||
return "Manager" if manager?(user)
|
||||
return "Developer" if develper?(user)
|
||||
return "Reporter" if reporter?(user)
|
||||
|
||||
member&.roles&.last&.name || permission
|
||||
return ""
|
||||
end
|
||||
|
||||
def fork_project
|
||||
|
|
@ -287,4 +297,7 @@ class Project < ApplicationRecord
|
|||
update_column(:updated_on, time)
|
||||
end
|
||||
|
||||
def is_transfering
|
||||
applied_transfer_project&.common? ? true : false
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,11 +8,6 @@
|
|||
# projects_count :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# ancestry :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_categories_on_ancestry (ancestry)
|
||||
#
|
||||
|
||||
class ProjectCategory < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: project_units
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# unit_type :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_units_on_project_id (project_id)
|
||||
#
|
||||
|
||||
class ProjectUnit < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, devops: 4, versions: 5, resources: 6}
|
||||
|
||||
validates :unit_type, uniqueness: { scope: :project_id}
|
||||
|
||||
def self.init_types(project_id, project_type='common')
|
||||
unit_types = project_type == 'sync_mirror' ? ProjectUnit::unit_types.except("pulls") : ProjectUnit::unit_types
|
||||
unit_types.each do |_, v|
|
||||
self.create!(project_id: project_id, unit_type: v)
|
||||
end
|
||||
end
|
||||
|
||||
def self.update_by_unit_types!(project, types)
|
||||
# 同步镜像项目不能有合并请求模块
|
||||
types.delete("pulls") if project.sync_mirror?
|
||||
# 默认code类型自动创建
|
||||
types << "code"
|
||||
project.project_units.where.not(unit_type: types).each(&:destroy!)
|
||||
types.each do |type|
|
||||
project.project_units.find_or_create_by!(unit_type: type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -22,10 +22,11 @@
|
|||
# version_releases_count :integer default("0")
|
||||
# fork_url :string(255)
|
||||
# is_mirror :boolean default("0")
|
||||
# accelerator_url :string(255) default("")
|
||||
# source_clone_url :string(255) default("")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_repositories_on_identifier (identifier)
|
||||
# index_repositories_on_project_id (project_id)
|
||||
# index_repositories_on_user_id (user_id)
|
||||
#
|
||||
|
|
@ -41,6 +42,8 @@ class Repository < ApplicationRecord
|
|||
|
||||
validates :identifier, presence: true
|
||||
|
||||
delegate :default_branch, to: :project, allow_nil: true
|
||||
|
||||
def to_param
|
||||
self.identifier.parameterize
|
||||
end
|
||||
|
|
@ -75,4 +78,9 @@ class Repository < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def remote_mirror_url
|
||||
source_clone_url.blank? ? mirror_url : source_clone_url
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,39 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: schools
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# province :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# logo_link :string(255)
|
||||
# pinyin :string(255)
|
||||
# school_type :integer default("0")
|
||||
# city :string(255)
|
||||
# address :string(255)
|
||||
# auto_users_trial :boolean default("0")
|
||||
# shool_code :string(255)
|
||||
# authorization_time :datetime
|
||||
# ec_auth :integer default("0")
|
||||
# identifier :string(255)
|
||||
# is_online :boolean default("0")
|
||||
# video_name :string(255)
|
||||
# video_desc :string(255)
|
||||
# course_link :string(255)
|
||||
# course_name :string(255)
|
||||
# partner_id :integer
|
||||
# customer_id :integer
|
||||
# school_property_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_schools_on_customer_id (customer_id)
|
||||
# index_schools_on_identifier (identifier)
|
||||
# index_schools_on_partner_id (partner_id)
|
||||
# index_schools_on_school_property_id (school_property_id)
|
||||
#
|
||||
|
||||
class School < ApplicationRecord
|
||||
has_many :departments, dependent: :destroy
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: sites
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# url :string(255)
|
||||
# key :string(255)
|
||||
# site_type :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class Site < ApplicationRecord
|
||||
# add: 添加类链接
|
||||
# personal: 个人名下类链接,
|
||||
# common: 普通链接
|
||||
enum site_type: { add: 0, personal: 1, common: 2 }
|
||||
|
||||
def self.set_default_menu
|
||||
set_add_menu!
|
||||
set_personal_menu!
|
||||
set_common_menu!
|
||||
end
|
||||
|
||||
private
|
||||
def self.set_add_menu!
|
||||
adds= [
|
||||
{name: '新建镜像项目', key: 'add_mirror_project', url: '/projects/mirror/new'},
|
||||
{name: '新建托管项目', key: 'add_common', url: '/projects/deposit/new'},
|
||||
{name: '新建组织', key: 'add_r', url: '/organize/new'}]
|
||||
|
||||
adds.each { |ele|
|
||||
Site.find_or_create_by(key: ele[:key]) do |site|
|
||||
site.name = ele[:name]
|
||||
site.url = ele[:url]
|
||||
site.site_type = Site.site_types[:add]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.set_personal_menu!
|
||||
personals = [
|
||||
{name: '个人中心', key: 'my_page', url: '/users/current_user'},
|
||||
{name: '我的组织', key: 'my_organizes', url: '/users/current_user/organizes'}
|
||||
]
|
||||
|
||||
personals.each { |ele|
|
||||
Site.find_or_create_by(key: ele[:key]) do |site|
|
||||
site.name = ele[:name]
|
||||
site.url = ele[:url]
|
||||
site.site_type = Site.site_types[:personal]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.set_common_menu!
|
||||
commons = [
|
||||
{name: '通知', key: 'notice', url: '/users/current_user/user_messages'},
|
||||
{name: '找回密码', key: 'lost_password', url: '/account/lost_password'},
|
||||
{name: '注册', key: 'register', url: '/login?login=false'}
|
||||
]
|
||||
|
||||
commons.each { |ele|
|
||||
Site.find_or_create_by(key: ele[:key]) do |site|
|
||||
site.name = ele[:name]
|
||||
site.url = ele[:url]
|
||||
site.site_type = Site.site_types[:common]
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
# gtid :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# nickname :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -32,9 +33,10 @@ class Team < ApplicationRecord
|
|||
|
||||
enum authorize: {common: 0, read: 1, write: 2, admin: 3, owner: 4}
|
||||
|
||||
def self.build(organization_id, name, description, authorize, includes_all_project, can_create_org_project)
|
||||
def self.build(organization_id, name, nickname, description, authorize, includes_all_project, can_create_org_project)
|
||||
self.create!(organization_id: organization_id,
|
||||
name: name,
|
||||
nickname: nickname,
|
||||
description: description,
|
||||
authorize: authorize,
|
||||
includes_all_project: includes_all_project,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,87 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: courses
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# tea_id :integer
|
||||
# name :string(255)
|
||||
# state :integer
|
||||
# code :string(255)
|
||||
# time :integer
|
||||
# extra :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# location :string(255)
|
||||
# term :string(255)
|
||||
# string :string(255)
|
||||
# password :string(255)
|
||||
# setup_time :string(255)
|
||||
# endup_time :string(255)
|
||||
# class_period :integer default("0")
|
||||
# school_id :integer
|
||||
# description :text(65535)
|
||||
# status :integer default("1")
|
||||
# attachmenttype :integer default("2")
|
||||
# lft :integer
|
||||
# rgt :integer
|
||||
# is_public :integer default("1")
|
||||
# inherit_members :integer default("1")
|
||||
# open_student :integer default("0")
|
||||
# outline :integer default("0")
|
||||
# publish_resource :integer default("0")
|
||||
# is_delete :integer default("0")
|
||||
# end_time :integer
|
||||
# end_term :string(255)
|
||||
# is_excellent :integer default("0")
|
||||
# excellent_option :integer default("0")
|
||||
# is_copy :integer default("0")
|
||||
# visits :integer default("0")
|
||||
# syllabus_id :integer
|
||||
# invite_code :string(255)
|
||||
# qrcode :string(255)
|
||||
# qrcode_expiretime :integer default("0")
|
||||
# invite_code_halt :integer default("0")
|
||||
# os_allow :integer default("0")
|
||||
# credit :float(24)
|
||||
# is_end :boolean default("0")
|
||||
# end_date :date
|
||||
# choose_group_allow :boolean default("0")
|
||||
# homepage_show :boolean default("0")
|
||||
# course_list_id :integer
|
||||
# members_count :integer default("0")
|
||||
# homework_commons_count :integer default("0")
|
||||
# show_unit :boolean default("0")
|
||||
# teacher_list :string(255) default("老师")
|
||||
# student_list :string(255) default("学生")
|
||||
# is_hidden :boolean default("0")
|
||||
# course_members_count :integer default("0")
|
||||
# course_groups_count :integer default("0")
|
||||
# authentication :boolean default("0")
|
||||
# professional_certification :boolean default("0")
|
||||
# graduation_topics_count :integer default("0")
|
||||
# graduation_tasks_count :integer default("0")
|
||||
# polls_count :integer default("0")
|
||||
# exercises_count :integer default("0")
|
||||
# start_date :date
|
||||
# subject_id :integer default("0")
|
||||
# excellent :boolean default("0")
|
||||
# email_notify :boolean default("0")
|
||||
# sticky :boolean default("0")
|
||||
# sticky_time :datetime
|
||||
# laboratory_id :integer
|
||||
# mooc_course_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_courses_on_invite_code (invite_code) UNIQUE
|
||||
# index_courses_on_laboratory_id (laboratory_id)
|
||||
# index_courses_on_mooc_course_id (mooc_course_id)
|
||||
# index_courses_on_school_id_and_is_delete (school_id,is_delete)
|
||||
# index_courses_on_subject_id (subject_id)
|
||||
# index_courses_on_tea_id (tea_id)
|
||||
#
|
||||
|
||||
class Trustie::Course < Trustie::Database
|
||||
has_many :course_groups, class_name: "Trustie::CourseGroup"
|
||||
has_many :homework_commons, class_name: "Trustie::HomeworkCommon"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,25 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: course_groups
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# course_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# members_count :integer
|
||||
# invite_code :string(255)
|
||||
# position :integer default("0")
|
||||
# course_members_count :integer default("0")
|
||||
# invite_code_halt :boolean default("0")
|
||||
# invite_code_set :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_course_groups_on_course_id (course_id)
|
||||
# index_course_groups_on_invite_code (invite_code) UNIQUE
|
||||
#
|
||||
|
||||
class Trustie::CourseGroup < Trustie::Database
|
||||
belongs_to :course, class_name: "Trustie::Course"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,54 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: homework_commons
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# user_id :integer
|
||||
# description :text(65535)
|
||||
# publish_time :datetime
|
||||
# end_time :datetime
|
||||
# homework_type :integer default("1")
|
||||
# late_penalty :string(255) default("0")
|
||||
# course_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# teacher_priority :integer default("1")
|
||||
# anonymous_comment :boolean default("0")
|
||||
# quotes :integer default("0")
|
||||
# is_open :integer default("0")
|
||||
# simi_time :datetime
|
||||
# score_open :boolean default("0")
|
||||
# anonymous_appeal :boolean default("0")
|
||||
# homework_bank_id :integer
|
||||
# is_update :boolean default("0")
|
||||
# is_public :boolean default("0")
|
||||
# reference_answer :text(65535)
|
||||
# answer_public :boolean default("0")
|
||||
# archive_time :datetime
|
||||
# allow_late :boolean default("0")
|
||||
# late_time :datetime
|
||||
# work_public :boolean default("0")
|
||||
# explanation :text(65535)
|
||||
# unified_setting :boolean default("1")
|
||||
# comment_public :boolean default("1")
|
||||
# course_homework_category_id :integer
|
||||
# work_efficiency :boolean default("0")
|
||||
# eff_score :float(24) default("0")
|
||||
# max_efficiency :float(24) default("0")
|
||||
# course_second_category_id :integer default("0")
|
||||
# calculation_time :datetime
|
||||
# position :integer default("0")
|
||||
# total_score :float(24) default("100")
|
||||
# category_position :integer default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_homework_commons_on_course_id_and_id (course_id,id)
|
||||
# index_homework_commons_on_course_second_category_id (course_second_category_id)
|
||||
# index_homework_commons_on_homework_bank_id (homework_bank_id)
|
||||
#
|
||||
|
||||
class Trustie::HomeworkCommon < Trustie::Database
|
||||
belongs_to :course, class_name: "Trustie::Course"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,13 +39,14 @@
|
|||
# business :boolean default("0")
|
||||
# profile_completed :boolean default("0")
|
||||
# laboratory_id :integer
|
||||
# platform :string(255) default("0")
|
||||
# gitea_token :string(255)
|
||||
# gitea_uid :integer
|
||||
# is_shixun_marker :boolean default("0")
|
||||
# admin_visitable :boolean default("0")
|
||||
# collaborator :boolean default("0")
|
||||
# gitea_uid :integer
|
||||
# is_sync_pwd :boolean default("1")
|
||||
# watchers_count :integer default("0")
|
||||
# devops_step :integer default("0")
|
||||
# gitea_token :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
@ -53,8 +54,9 @@
|
|||
# index_users_on_homepage_engineer (homepage_engineer)
|
||||
# index_users_on_homepage_teacher (homepage_teacher)
|
||||
# index_users_on_laboratory_id (laboratory_id)
|
||||
# index_users_on_login (login)
|
||||
# index_users_on_mail (mail)
|
||||
# index_users_on_login (login) UNIQUE
|
||||
# index_users_on_mail (mail) UNIQUE
|
||||
# index_users_on_phone (phone) UNIQUE
|
||||
# index_users_on_type (type)
|
||||
#
|
||||
|
||||
|
|
@ -66,6 +68,7 @@ class User < Owner
|
|||
include Likeable
|
||||
include BaseModel
|
||||
include Droneable
|
||||
include User::Avatar
|
||||
# include Searchable::Dependents::User
|
||||
|
||||
# devops step
|
||||
|
|
@ -134,10 +137,6 @@ class User < Owner
|
|||
|
||||
has_many :attachments,foreign_key: :author_id, :dependent => :destroy
|
||||
|
||||
# 关注
|
||||
# has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注
|
||||
# has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户
|
||||
|
||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy
|
||||
|
||||
# 认证
|
||||
|
|
@ -148,9 +147,14 @@ class User < Owner
|
|||
has_many :trail_auth_apply_actions, -> { where(container_type: 'TrialAuthorization') }, class_name: 'ApplyAction'
|
||||
|
||||
# has_many :attendances
|
||||
|
||||
has_many :applied_messages, dependent: :destroy
|
||||
has_many :operate_applied_messages, class_name: 'AppliedMessage', dependent: :destroy
|
||||
# 项目
|
||||
has_many :applied_projects, dependent: :destroy
|
||||
has_many :operate_applied_transfer_projects, class_name: 'AppliedTransferProject', dependent: :destroy
|
||||
has_many :members, dependent: :destroy
|
||||
has_many :team_users, dependent: :destroy
|
||||
has_many :teams, through: :team_users
|
||||
|
||||
# 教学案例
|
||||
# has_many :libraries, dependent: :destroy
|
||||
|
|
@ -189,6 +193,10 @@ class User < Owner
|
|||
validate :validate_sensitive_string
|
||||
validate :validate_password_length
|
||||
|
||||
def name
|
||||
login
|
||||
end
|
||||
|
||||
# 删除自动登录的token,一旦退出下次会提示需要登录
|
||||
def delete_autologin_token(value)
|
||||
Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all
|
||||
|
|
@ -203,7 +211,7 @@ class User < Owner
|
|||
end
|
||||
|
||||
def project_manager?(project)
|
||||
project.managers.exists?(user: self) || self.admin?
|
||||
project.manager?(self) || self.admin?
|
||||
end
|
||||
|
||||
# 学号
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
require 'letter_avatar/has_avatar'
|
||||
require 'chinese_pinyin'
|
||||
|
||||
class User
|
||||
module Avatar
|
||||
extend ActiveSupport::Concern
|
||||
include LetterAvatar::HasAvatar
|
||||
|
||||
def username
|
||||
self.lastname.blank? ? self.login : Pinyin.t(self.lastname)
|
||||
end
|
||||
|
||||
def get_letter_avatar_url(size = :lg)
|
||||
avatar_path(self.username, size).split('public/')&.last
|
||||
end
|
||||
|
||||
def self.get_letter_avatar_url(name)
|
||||
return "" if name.blank?
|
||||
avatar = LetterAvatar.generate Pinyin.t(name), 120
|
||||
avatar.split('public/')&.last
|
||||
end
|
||||
|
||||
def avatar_path(username, size)
|
||||
LetterAvatar.generate username, avatar_size(size)
|
||||
end
|
||||
|
||||
# 返回头像尺寸
|
||||
# xs: 22px
|
||||
# sm: 32px
|
||||
# md: 48px
|
||||
# lg: 120px
|
||||
def avatar_size(size)
|
||||
case size
|
||||
when :xs then 22
|
||||
when :sm then 32
|
||||
when :md then 48
|
||||
when :lg then 120
|
||||
else size
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -12,7 +12,9 @@
|
|||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_user_actions_on_ip (ip)
|
||||
# index_user_actions_on_ip (ip)
|
||||
# index_user_actions_on_user_id (user_id)
|
||||
# index_user_actions_on_user_id_and_action_type (user_id,action_type)
|
||||
#
|
||||
|
||||
class UserAction < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@
|
|||
# updated_at :datetime not null
|
||||
# register_status :integer default("0")
|
||||
# action_status :integer default("0")
|
||||
# is_delete :boolean default("0")
|
||||
# user_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_user_agents_on_ip (ip) UNIQUE
|
||||
# index_user_agents_on_ip (ip)
|
||||
# index_user_agents_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class UserAgent < ApplicationRecord
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
# school_id :integer
|
||||
# description :string(255) default("")
|
||||
# department_id :integer
|
||||
# honor :text(65535)
|
||||
# edu_background :integer
|
||||
# edu_entry_year :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Ci::Builds::ListQuery < ApplicationQuery
|
|||
scope
|
||||
end
|
||||
|
||||
builds = scope.by_branch(params[:branch]) if params[:branch]
|
||||
builds = builds.by_branch(params[:branch]) if params[:branch]
|
||||
|
||||
custom_sort(builds, params[:sort_by], params[:sort_direction])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ class Projects::ListMyQuery < ApplicationQuery
|
|||
end
|
||||
|
||||
if params[:category].blank?
|
||||
projects = projects.members_projects(user.id)
|
||||
normal_projects = projects.members_projects(user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
elsif params[:category].to_s == "join"
|
||||
normal_projects = projects.where.not(user_id: user.id).members_projects(user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: user.id}).to_sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
class Gitea::Accelerator::MigrateService < ApplicationService
|
||||
attr_reader :params
|
||||
|
||||
# params description:
|
||||
# {
|
||||
# auth_username string
|
||||
# clone_addr* string #clone地址
|
||||
# description string
|
||||
# issues boolean
|
||||
# labels boolean
|
||||
# milestones boolean
|
||||
# mirror boolean
|
||||
# private boolean
|
||||
# pull_requests boolean
|
||||
# releases boolean
|
||||
# repo_name* string #仓库名称
|
||||
# uid* integer($int64) #gitea用户id或组织id
|
||||
# wiki boolean
|
||||
# }
|
||||
# EX:
|
||||
# params = {
|
||||
# clone_addr: 'xxx.com',
|
||||
# repo_name: 'repo_name',
|
||||
# uid: 2,
|
||||
# private: false
|
||||
# }
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
return error('[gitea:] accelerator config missing') if check_accelerator!
|
||||
response = post(url, request_params)
|
||||
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request_params
|
||||
{
|
||||
uid: access_uid,
|
||||
clone_addr: params[:clone_addr],
|
||||
repo_name: params[:repository_name],
|
||||
auth_username: params[:auth_username],
|
||||
auth_password: params[:auth_password],
|
||||
mirror: ActiveModel::Type::Boolean.new.cast(params[:is_mirror])
|
||||
}
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/migrate".freeze
|
||||
end
|
||||
|
||||
def post(url, params)
|
||||
puts "[gitea] request params: #{params}"
|
||||
puts "[gitea] access_username: #{access_username}"
|
||||
puts "[gitea] access_password: #{access_password}"
|
||||
conn.post do |req|
|
||||
req.url full_url(url)
|
||||
req.body = params.to_json
|
||||
end
|
||||
end
|
||||
|
||||
def conn
|
||||
@client ||= begin
|
||||
Faraday.new(url: domain) do |req|
|
||||
req.request :url_encoded
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.response :logger # 显示日志
|
||||
req.adapter Faraday.default_adapter
|
||||
req.basic_auth(access_username, access_password)
|
||||
end
|
||||
end
|
||||
@client
|
||||
end
|
||||
|
||||
def base_url
|
||||
accelerator["base_url"]
|
||||
end
|
||||
|
||||
def domain
|
||||
accelerator["domain"]
|
||||
end
|
||||
|
||||
def api_url
|
||||
[domain, base_url].join('')
|
||||
end
|
||||
|
||||
def full_url(api_rest, action='post')
|
||||
url = [api_url, api_rest].join('').freeze
|
||||
url = action === 'get' ? url : URI.escape(url)
|
||||
puts "[gitea] request url: #{url}"
|
||||
url
|
||||
end
|
||||
|
||||
def access_username
|
||||
accelerator["access_key_id"]
|
||||
end
|
||||
|
||||
def access_password
|
||||
accelerator["access_key_secret"]
|
||||
end
|
||||
|
||||
def access_uid
|
||||
accelerator["access_admin_uid"]
|
||||
end
|
||||
|
||||
def accelerator
|
||||
Gitea.gitea_config[:accelerator]
|
||||
end
|
||||
|
||||
def render_status(response)
|
||||
puts "[gitea] response status: #{response.status}"
|
||||
puts "[gitea] response body: #{response.body}"
|
||||
case response.status
|
||||
when 201
|
||||
success
|
||||
when 403
|
||||
error('APIForbiddenError')
|
||||
when 422
|
||||
error('APIValidationError')
|
||||
else
|
||||
error("MigrateError")
|
||||
end
|
||||
end
|
||||
|
||||
def error(message)
|
||||
{
|
||||
status: :error,
|
||||
message: message,
|
||||
data: nil
|
||||
}
|
||||
end
|
||||
|
||||
def success(data=nil)
|
||||
{
|
||||
status: :success,
|
||||
message: nil,
|
||||
data: data
|
||||
}
|
||||
end
|
||||
|
||||
def check_accelerator!
|
||||
accelerator.blank? || access_username.blank? || access_password.blank? || domain.blank?
|
||||
end
|
||||
end
|
||||
|
|
@ -176,6 +176,25 @@ class Gitea::ClientService < ApplicationService
|
|||
[status, message, body]
|
||||
end
|
||||
|
||||
def render_gitea_response(response)
|
||||
status = response.status
|
||||
body = response&.body
|
||||
|
||||
log_error(status, body)
|
||||
message = nil
|
||||
begin
|
||||
translate = YAML.load(File.read('config/gitea_response.yml'))
|
||||
|
||||
self.class.to_s.underscore.split("/").map{|i| translate=translate[i]}
|
||||
message = body.nil? ? translate[status]['default'] : JSON.parse(body)['message']
|
||||
message = translate[status][message].nil? ? message : translate[status][message]
|
||||
|
||||
return [status, message]
|
||||
rescue
|
||||
return [status, message]
|
||||
end
|
||||
end
|
||||
|
||||
def get_body_by_status(status, body)
|
||||
body, message =
|
||||
case status
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class Gitea::PullRequest::MergeService < Gitea::ClientService
|
|||
def call
|
||||
response = post(url, request_params)
|
||||
|
||||
render_200_no_body(response)
|
||||
render_gitea_response(response)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
class Gitea::Repository::Contributors::GetService < Gitea::ClientService
|
||||
attr_reader :owner, :repo_name
|
||||
|
||||
def initialize(owner, repo_name)
|
||||
@owner = owner
|
||||
@repo_name = repo_name
|
||||
end
|
||||
|
||||
def call
|
||||
response = get(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: owner.gitea_token)
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/#{owner.login}/#{repo_name}/contributors"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
class Gitea::Repository::Files::GetService < Gitea::ClientService
|
||||
attr_reader :owner, :repo_name, :ref, :q, :token
|
||||
|
||||
def initialize(owner, repo_name, ref, q=nil, token=nil)
|
||||
@owner = owner
|
||||
@repo_name = repo_name
|
||||
@ref = ref
|
||||
@q = q
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
response = get(url, params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: token, ref: ref, q: q)
|
||||
end
|
||||
|
||||
def url
|
||||
"/repos/#{owner.login}/#{repo_name}/find"
|
||||
end
|
||||
end
|
||||
|
|
@ -18,7 +18,8 @@ class Gitea::Versions::CreateService < Gitea::ClientService
|
|||
end
|
||||
|
||||
def call
|
||||
post(url, request_params)
|
||||
response = post(url, request_params)
|
||||
render_status(response)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
# Get a list of all commits from a repository
|
||||
class Gitea::Versions::ListService < Gitea::ClientService
|
||||
attr_reader :token, :user_name, :repo
|
||||
attr_reader :token, :user_name, :repo, :args
|
||||
|
||||
# sha: SHA or branch to start listing commits from (usually 'master')
|
||||
def initialize(token, user_name, repo)
|
||||
def initialize(token, user_name, repo, args={})
|
||||
@token = token
|
||||
@user_name = user_name
|
||||
@repo = repo
|
||||
@args = args
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
@ -16,7 +17,7 @@ class Gitea::Versions::ListService < Gitea::ClientService
|
|||
|
||||
private
|
||||
def params
|
||||
Hash.new.merge(token: token)
|
||||
args.merge(token: token)
|
||||
end
|
||||
|
||||
def url
|
||||
|
|
|
|||
|
|
@ -47,14 +47,14 @@ class Organizations::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def create_org_and_extension
|
||||
@organization = Organization.build(params[:name], user.gitea_token)
|
||||
@organization = Organization.build(params[:name], params[:nickname], user.gitea_token)
|
||||
org_extension = OrganizationExtension.build(organization.id, description, website,
|
||||
location, repo_admin_change_team_access,
|
||||
visibility, max_repo_creation)
|
||||
end
|
||||
|
||||
def create_owner_info
|
||||
@owner_team = Team.build(organization.id, "Owners", "", 4, true, true)
|
||||
@owner_team = Team.build(organization.id, "Owners", "Owner团队", "", 4, true, true)
|
||||
TeamUnit.unit_types.keys.each do |u_type|
|
||||
TeamUnit.build(organization.id, owner_team.id, u_type)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ class Organizations::Teams::CreateService < ApplicationService
|
|||
params[:name]
|
||||
end
|
||||
|
||||
def nickname
|
||||
params[:nickname]
|
||||
end
|
||||
|
||||
def description
|
||||
params[:description]
|
||||
end
|
||||
|
|
@ -45,7 +49,7 @@ class Organizations::Teams::CreateService < ApplicationService
|
|||
end
|
||||
|
||||
def create_team
|
||||
@team = Team.build(org.id, name, description, authorize,
|
||||
@team = Team.build(org.id, name, nickname, description, authorize,
|
||||
includes_all_project, can_create_org_project)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class Organizations::Teams::UpdateService < ApplicationService
|
|||
if team.authorize == "owner"
|
||||
update_params = params.slice(:description)
|
||||
else
|
||||
update_params = params.slice(:name, :description, :authorize, :includes_all_project, :can_create_org_project)
|
||||
update_params = params.slice(:name, :nickname, :description, :authorize, :includes_all_project, :can_create_org_project)
|
||||
end
|
||||
update_params
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
class Projects::AcceptTransferService < ApplicationService
|
||||
attr_accessor :applied_transfer_project, :owner
|
||||
attr_reader :user, :project
|
||||
|
||||
def initialize(user, project)
|
||||
@user = user
|
||||
@project = project
|
||||
@applied_transfer_project = project.applied_transfer_project
|
||||
@owner = @applied_transfer_project.owner
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("###### Project accept_transfer_service begin ######")
|
||||
ActiveRecord::Base.transaction do
|
||||
validate!
|
||||
update_apply
|
||||
operate_project
|
||||
send_apply_message
|
||||
end
|
||||
|
||||
Rails.logger.info("##### Project accept_transfer_service end ######")
|
||||
|
||||
|
||||
return @applied_transfer_project
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering
|
||||
raise Error, '未拥有接受转移权限' unless is_permit_operator
|
||||
end
|
||||
|
||||
def is_permit_operator
|
||||
return true if @user == @owner
|
||||
return @owner.is_a?(Organization) && @owner.is_admin?(@user)
|
||||
end
|
||||
|
||||
def update_apply
|
||||
@applied_transfer_project.update!(status: 'accepted')
|
||||
end
|
||||
|
||||
def operate_project
|
||||
@project = Projects::TransferService.call(@project, @owner)
|
||||
end
|
||||
|
||||
def send_apply_message
|
||||
SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'successed')
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
class Projects::ApplyTransferService < ApplicationService
|
||||
attr_accessor :owner, :applied_transfer_project
|
||||
attr_reader :user, :project, :params
|
||||
|
||||
def initialize(user, project, params)
|
||||
@user = user
|
||||
@project = project
|
||||
@params = params
|
||||
@owner = Owner.find_by(login: params[:owner_name])
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("###### Project apply_transfer_service begin ######")
|
||||
validate!
|
||||
create_apply
|
||||
send_apply_message
|
||||
Rails.logger.info("###### Project apply_transfer_service end ######")
|
||||
|
||||
return @applied_transfer_project
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, '仓库标识不正确' if @project.identifier != params[:identifier]
|
||||
raise Error, '该仓库正在迁移' if @project.is_transfering
|
||||
raise Error, '新拥有者不存在' unless @owner.present?
|
||||
raise Error, '新拥有者已经存在同名仓库!' if Project.where(user_id: @owner.id, identifier: params[:identifier]).present?
|
||||
raise Error, '未拥有转移权限' unless is_permit_owner
|
||||
end
|
||||
|
||||
def is_permit_owner
|
||||
return true unless @owner.is_a?(Organization)
|
||||
return @owner.is_owner?(@user)
|
||||
end
|
||||
|
||||
def create_apply
|
||||
@applied_transfer_project = AppliedTransferProject.create!(user_id: user.id, project_id: project.id, owner_id: @owner.id)
|
||||
end
|
||||
|
||||
def send_apply_message
|
||||
SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'common')
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
class Projects::CancelTransferService < ApplicationService
|
||||
attr_accessor :applied_transfer_project
|
||||
attr_reader :user, :project
|
||||
|
||||
def initialize(user, project)
|
||||
@user = user
|
||||
@project = project
|
||||
@applied_transfer_project = project.applied_transfer_project
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("###### Project cancel_transfer_service begin ######")
|
||||
validate!
|
||||
update_apply
|
||||
send_apply_message
|
||||
Rails.logger.info("###### Project cancel_transfer_service end ######")
|
||||
|
||||
return @applied_transfer_project
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering
|
||||
end
|
||||
|
||||
def update_apply
|
||||
@applied_transfer_project.update!(status: 'canceled')
|
||||
end
|
||||
|
||||
def send_apply_message
|
||||
SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'canceled')
|
||||
end
|
||||
end
|
||||
|
|
@ -13,6 +13,7 @@ class Projects::CreateService < ApplicationService
|
|||
ActiveRecord::Base.transaction do
|
||||
if @project.save!
|
||||
Project.update_common_projects_count!
|
||||
ProjectUnit.init_types(@project.id)
|
||||
Repositories::CreateService.new(user, @project, repository_params).call
|
||||
else
|
||||
Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}")
|
||||
|
|
@ -36,6 +37,7 @@ class Projects::CreateService < ApplicationService
|
|||
is_public: repo_is_public,
|
||||
ignore_id: params[:ignore_id],
|
||||
license_id: params[:license_id],
|
||||
website: params[:website],
|
||||
identifier: params[:repository_name] #新增,hs
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ class Projects::ForkService < ApplicationService
|
|||
new_repository.identifier = @project.identifier
|
||||
new_repository.save!
|
||||
|
||||
ProjectUnit.init_types(clone_project.id)
|
||||
|
||||
result = Gitea::Repository::ForkService.new(@project.owner, @target_owner, @project.identifier, @organization).call
|
||||
|
||||
@project.update_column('forked_count', @project&.forked_count.to_i + 1)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
class Projects::MigrateService < ApplicationService
|
||||
attr_reader :user, :params
|
||||
attr_accessor :project
|
||||
|
||||
def initialize(user, params)
|
||||
@user = user
|
||||
|
|
@ -9,7 +10,9 @@ class Projects::MigrateService < ApplicationService
|
|||
def call
|
||||
@project = Project.new(project_params)
|
||||
if @project.save!
|
||||
ProjectUnit.init_types(@project.id, project.project_type)
|
||||
Project.update_mirror_projects_count!
|
||||
@project.set_owner_permission(user)
|
||||
Repositories::MigrateService.new(user, @project, repository_params).call
|
||||
else
|
||||
#
|
||||
|
|
@ -47,7 +50,8 @@ class Projects::MigrateService < ApplicationService
|
|||
user_id: params[:user_id],
|
||||
login: params[:auth_username],
|
||||
password: params[:auth_password],
|
||||
is_mirror: params[:is_mirror]
|
||||
is_mirror: params[:is_mirror],
|
||||
source_clone_url: params[:source_clone_url]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
class Projects::RefuseTransferService < ApplicationService
|
||||
attr_accessor :applied_transfer_project, :owner
|
||||
attr_reader :user, :project
|
||||
|
||||
def initialize(user, project)
|
||||
@user = user
|
||||
@project = project
|
||||
@applied_transfer_project = project.applied_transfer_project
|
||||
@owner = @applied_transfer_project.owner
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("###### Project refuse_transfer_service begin ######")
|
||||
validate!
|
||||
update_apply
|
||||
send_apply_message
|
||||
Rails.logger.info("###### Project refuse_transfer_service end ######")
|
||||
|
||||
return @applied_transfer_project
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, '该仓库未在迁移' unless @applied_transfer_project.present? && @project.is_transfering
|
||||
raise Error, '未拥有拒绝转移权限' unless is_permit_operator
|
||||
end
|
||||
|
||||
def is_permit_operator
|
||||
return true if @user == @owner
|
||||
return @owner.is_a?(Organization) && @owner.is_admin?(@user)
|
||||
end
|
||||
|
||||
def update_apply
|
||||
@applied_transfer_project.update!(status: 'refused')
|
||||
end
|
||||
|
||||
def send_apply_message
|
||||
SendTransferProjectAppliedMessageJob.perform_now(@applied_transfer_project, @user, 'failure')
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue