diff --git a/app/controllers/projects/applied_transfer_projects_controller.rb b/app/controllers/projects/applied_transfer_projects_controller.rb new file mode 100644 index 000000000..e62033f21 --- /dev/null +++ b/app/controllers/projects/applied_transfer_projects_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users/applied_messages_controller.rb b/app/controllers/users/applied_messages_controller.rb new file mode 100644 index 000000000..e80cabf92 --- /dev/null +++ b/app/controllers/users/applied_messages_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users/applied_transfer_projects_controller.rb b/app/controllers/users/applied_transfer_projects_controller.rb new file mode 100644 index 000000000..b1777f526 --- /dev/null +++ b/app/controllers/users/applied_transfer_projects_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6bc2f2659..80439acd3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -27,11 +27,20 @@ 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_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 user_projects = User.current.logged? && (User.current.admin? || User.current.login == @user.login) ? @user.projects : @user.projects.visible @projects_common_count = user_projects.common.size @projects_mirrior_count = user_projects.mirror.size diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md index 0a46d8cc7..87a37c45b 100644 --- a/app/docs/slate/source/includes/_projects.md +++ b/app/docs/slate/source/includes/_projects.md @@ -526,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分钟前" +} +``` \ No newline at end of file diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md index 62a6391e1..1d1afc028 100644 --- a/app/docs/slate/source/includes/_users.md +++ b/app/docs/slate/source/includes/_users.md @@ -1,3 +1,9 @@ + # Users ## 获取当前登陆用户信息 @@ -40,3 +46,390 @@ await octokit.request('GET /api/users/me.json') + +## 待办事项-用户通知信息 +待办事项-用户通知信息 + +> 示例: + +```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小时前" +} +``` \ No newline at end of file diff --git a/app/jobs/send_transfer_project_applied_message_job.rb b/app/jobs/send_transfer_project_applied_message_job.rb new file mode 100644 index 000000000..92ea306d1 --- /dev/null +++ b/app/jobs/send_transfer_project_applied_message_job.rb @@ -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 \ No newline at end of file diff --git a/app/models/applied_message.rb b/app/models/applied_message.rb index 8098e6e07..b3ebad34e 100644 --- a/app/models/applied_message.rb +++ b/app/models/applied_message.rb @@ -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 diff --git a/app/models/applied_transfer_project.rb b/app/models/applied_transfer_project.rb new file mode 100644 index 000000000..d0e0e5c44 --- /dev/null +++ b/app/models/applied_transfer_project.rb @@ -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 diff --git a/app/models/owner.rb b/app/models/owner.rb index 1d537a1e0..b65ee0544 100644 --- a/app/models/owner.rb +++ b/app/models/owner.rb @@ -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 diff --git a/app/models/project.rb b/app/models/project.rb index da1a8615b..170bae06a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -112,6 +112,7 @@ class Project < ApplicationRecord 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)} @@ -295,4 +296,7 @@ class Project < ApplicationRecord update_column(:updated_on, time) end + def is_transfering + applied_transfer_project&.common? ? true : false + end end diff --git a/app/models/user.rb b/app/models/user.rb index 2317c402e..5b581e7cb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -148,9 +148,11 @@ 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 :libraries, dependent: :destroy diff --git a/app/services/projects/accept_transfer_service.rb b/app/services/projects/accept_transfer_service.rb new file mode 100644 index 000000000..c99885ca0 --- /dev/null +++ b/app/services/projects/accept_transfer_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/projects/apply_transfer_service.rb b/app/services/projects/apply_transfer_service.rb new file mode 100644 index 000000000..28097bed5 --- /dev/null +++ b/app/services/projects/apply_transfer_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/projects/cancel_transfer_service.rb b/app/services/projects/cancel_transfer_service.rb new file mode 100644 index 000000000..153b24ffb --- /dev/null +++ b/app/services/projects/cancel_transfer_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/projects/refuse_transfer_service.rb b/app/services/projects/refuse_transfer_service.rb new file mode 100644 index 000000000..1b81b5741 --- /dev/null +++ b/app/services/projects/refuse_transfer_service.rb @@ -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 \ No newline at end of file diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index b32b24817..4582a2103 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -23,6 +23,7 @@ class Projects::TransferService < ApplicationService private def update_owner + project.members.find_by(user_id: owner.id).destroy! if owner.is_a?(User) project.update!(user_id: new_owner.id) end diff --git a/app/views/organizations/organizations/_simple.json.jbuilder b/app/views/organizations/organizations/_simple.json.jbuilder new file mode 100644 index 000000000..12792b125 --- /dev/null +++ b/app/views/organizations/organizations/_simple.json.jbuilder @@ -0,0 +1,5 @@ +json.id organization.id +json.name organization.login +json.nickname organization.nickname.blank? ? organization.name : organization.nickname +json.description organization.description +json.avatar_url url_to_avatar(organization) diff --git a/app/views/projects/applied_transfer_projects/_detail.json.jbuilder b/app/views/projects/applied_transfer_projects/_detail.json.jbuilder new file mode 100644 index 000000000..e583ed1d1 --- /dev/null +++ b/app/views/projects/applied_transfer_projects/_detail.json.jbuilder @@ -0,0 +1,21 @@ +project = object.project +json.project do + json.id project.id + json.identifier project.identifier + json.name project.name + json.description project.description + json.is_public project.is_public + json.owner do + json.partial! "/users/user_simple", locals: {user: project.owner} + end +end +json.user do + json.partial! "/users/user_simple", locals: {user: object.user} +end +json.owner do + json.partial! "/users/user_simple", locals: {user: object.owner} +end +json.id object.id +json.status object.status +json.created_at format_time(object.created_at) +json.time_ago time_from_now(object.created_at) diff --git a/app/views/projects/applied_transfer_projects/cancel.json.jbuilder b/app/views/projects/applied_transfer_projects/cancel.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/projects/applied_transfer_projects/cancel.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/projects/applied_transfer_projects/create.json.jbuilder b/app/views/projects/applied_transfer_projects/create.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/projects/applied_transfer_projects/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/projects/applied_transfer_projects/organizations.json.jbuilder b/app/views/projects/applied_transfer_projects/organizations.json.jbuilder new file mode 100644 index 000000000..772910f0b --- /dev/null +++ b/app/views/projects/applied_transfer_projects/organizations.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @organizations.size +json.organizations @organizations do |org| + json.partial! "/organizations/organizations/simple", locals: {organization: org} +end diff --git a/app/views/repositories/edit.json.jbuilder b/app/views/repositories/edit.json.jbuilder index 076ac3aa8..7a11411f4 100644 --- a/app/views/repositories/edit.json.jbuilder +++ b/app/views/repositories/edit.json.jbuilder @@ -7,4 +7,9 @@ json.project_language_id @project.project_language_id json.private !@project.is_public json.website @project.website json.project_units @project.project_units.pluck(:unit_type) -json.lesson_url @project.lesson_url \ No newline at end of file +json.lesson_url @project.lesson_url +json.permission render_permission(current_user, @project) +json.is_transfering @project.is_transfering +json.transfer do + json.partial! "/users/user_simple", locals: {user: @project&.applied_transfer_project&.owner} +end \ No newline at end of file diff --git a/app/views/users/_user_simple.json.jbuilder b/app/views/users/_user_simple.json.jbuilder index 3f9feebbe..5da161509 100644 --- a/app/views/users/_user_simple.json.jbuilder +++ b/app/views/users/_user_simple.json.jbuilder @@ -1,4 +1,9 @@ -json.id user.id -json.name user.real_name -json.login user.login -json.image_url url_to_avatar(user) \ No newline at end of file +if user.present? + json.id user.id + json.type user.type + json.name user.real_name + json.login user.login + json.image_url url_to_avatar(user) +else + json.nil! +end \ No newline at end of file diff --git a/app/views/users/applied_messages/_detail.json.jbuilder b/app/views/users/applied_messages/_detail.json.jbuilder new file mode 100644 index 000000000..cca202c10 --- /dev/null +++ b/app/views/users/applied_messages/_detail.json.jbuilder @@ -0,0 +1,26 @@ +# project = object.project +# json.project do +# json.id project.id +# json.identifier project.identifier +# json.name project.name +# json.description project.description +# json.is_public project.is_public +# json.owner do +# json.partial! "/users/user_simple", locals: {user: project.owner} +# end +# end +# json.user do +# json.partial! "/users/user_simple", locals: {user: object.user} +# end +json.applied do + json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied} +end +json.applied_user do + json.partial! "/users/user_simple", locals: {user: object.applied_user} +end +json.applied_type object.applied_type +json.name object.name +json.viewed object.viewed +json.status object.status +json.created_at format_time(object.created_at) +json.time_ago time_from_now(object.created_at) diff --git a/app/views/users/applied_messages/index.json.jbuilder b/app/views/users/applied_messages/index.json.jbuilder new file mode 100644 index 000000000..75647566f --- /dev/null +++ b/app/views/users/applied_messages/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @applied_messages.total_count +json.applied_messages @applied_messages do |message| + json.partial! "/users/applied_messages/detail", locals: {object: message} +end diff --git a/app/views/users/applied_transfer_projects/accept.json.jbuilder b/app/views/users/applied_transfer_projects/accept.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/users/applied_transfer_projects/accept.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/users/applied_transfer_projects/index.json.jbuilder b/app/views/users/applied_transfer_projects/index.json.jbuilder new file mode 100644 index 000000000..caf9d1ade --- /dev/null +++ b/app/views/users/applied_transfer_projects/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @applied_transfer_projects.total_count +json.applied_transfer_projects @applied_transfer_projects do |apply| + json.partial! "/projects/applied_transfer_projects/detail", locals: {object: apply} +end diff --git a/app/views/users/applied_transfer_projects/refuse.json.jbuilder b/app/views/users/applied_transfer_projects/refuse.json.jbuilder new file mode 100644 index 000000000..59da42d4e --- /dev/null +++ b/app/views/users/applied_transfer_projects/refuse.json.jbuilder @@ -0,0 +1 @@ +json.partial! "/projects/applied_transfer_projects/detail", locals: {object: @applied_transfer_project} diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index 54f85c5c2..e80ac7494 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -10,6 +10,8 @@ json.user_identity @user.identity json.is_watch current_user&.watched?(@user) json.watched_count @user.fan_count #粉丝 json.watching_count @user.follow_count #关注数 +json.undo_messages @waiting_applied_messages.size +json.undo_transfer_projects @common_applied_transfer_projects.size json.undo_events @undo_events json.user_composes_count @user_composes_count json.user_org_count @user_org_count diff --git a/config/routes.rb b/config/routes.rb index a67b3b62f..de642e5db 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -257,6 +257,13 @@ Rails.application.routes.draw do end scope module: :users do + resources :applied_messages, only: [:index] + resources :applied_transfer_projects, only: [:index] do + member do + post :accept + post :refuse + end + end resources :organizations, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] @@ -533,6 +540,12 @@ Rails.application.routes.draw do scope module: :projects do resources :teams, only: [:index, :create, :destroy] resources :project_units, only: [:index, :create] + resources :applied_transfer_projects, only: [:create] do + collection do + get :organizations + post :cancel + end + end scope do get( '/blob/*id/diff', diff --git a/db/migrate/20210425032825_create_applied_transfer_projects.rb b/db/migrate/20210425032825_create_applied_transfer_projects.rb new file mode 100644 index 000000000..5c6774095 --- /dev/null +++ b/db/migrate/20210425032825_create_applied_transfer_projects.rb @@ -0,0 +1,12 @@ +class CreateAppliedTransferProjects < ActiveRecord::Migration[5.2] + def change + create_table :applied_transfer_projects do |t| + t.references :project + t.references :owner + t.references :user + t.integer :status, default: 0 + + t.timestamps + end + end +end diff --git a/public/docs/api.html b/public/docs/api.html index 1b75a97a2..f970ea84d 100644 --- a/public/docs/api.html +++ b/public/docs/api.html @@ -331,6 +331,18 @@
  • 获取当前登陆用户信息
  • +
  • + 待办事项-用户通知信息 +
  • +
  • + 待办事项-接受仓库 +
  • +
  • + 用户接受迁移 +
  • +
  • + 用户拒绝迁移 +
  • @@ -366,6 +378,15 @@
  • Fork项目
  • +
  • + 用户管理的组织列表 +
  • +
  • + 迁移项目 +
  • +
  • + 取消迁移项目 +
  • @@ -563,6 +584,12 @@ http://localhost:3000/api/ignores.json +

    Users

    获取当前登陆用户信息

    获取当前登陆用户信息

    @@ -622,183 +649,182 @@ Success — a happy kitten is an authenticated kitten! -

    Projects

    获取项目列表

    -

    获取项目列表,也可以更加相关条件过滤搜素

    +

    待办事项-用户通知信息

    +

    待办事项-用户通知信息

    示例:

    -
    curl -X GET \
    --d "page=1" \
    --d "limit=5" \
    -http://localhost:3000/api/projects  | jq
    -
    await octokit.request('GET /api/projects')
    -

    HTTP 请求

    -

    GET api/projects

    -

    请求参数

    +
    curl -X GET http://localhost:3000/api/users/yystopf/applied_messages.json
    +
    await octokit.request('GET /api/users/:login/applied_messages.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_messages.json

    +

    请求字段说明:

    - - - - - + - + + +
    参数必选默认 类型 字段说明
    pagefalse1login string页数,第几页用户标识
    +

    返回字段说明:

    + + + + + + - - - - - + + + - - - - - + + + - - - + - + - - - + - + - - - + - + - - - - - + + + - - - + - + -
    参数类型字段说明
    limitfalse15string每页多少条数据,默认15条appliedobject通知主体
    sort_byfalsestring排序类型, 取值:updated_on、created_on、forked_count、praises_count; updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序applied.idint通知主体的迁移id
    sort_directionfalseapplied.status string排序方式,取值为: desc、asc; desc: 降序排序, asc: 升序排序, 默认为:desc通知主体的迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    searchfalseapplied.time_ago string按照项目名称搜索通知主体的迁移创建的时间
    category_idfalseapplied.project.id int项目类别id通知主体的迁移项目的id
    language_idfalseint项目语言idapplied.project.identifierstring通知主体的迁移项目的标识
    project_typefalseapplied.project.name string项目类型, 取值为:common、mirror; common:开源托管项目, mirror:开源镜像项目通知主体的迁移项目的名称
    -

    返回字段说明

    - - - - + + + - - - - + + + - + + + + + + - + - + - + - + - + - - - + + + - + - + - - - + + + - - - + + + - + - + - + + + + + + - + - - - + + + - + - + - - - + + + - - - + + + - + - + - - - + + + - - - + + + - + - + + + + + +
    参数类型字段说明applied.project.descriptionstring通知主体的迁移项目的描述
    total_countint项目总条数applied.project.is_publicbool通知主体的迁移项目是否公开
    idapplied.project.owner.idbool通知主体的迁移项目拥有者id
    applied.project.owner.type string项目id通知主体的迁移项目拥有者类型
    nameapplied.project.owner.name string项目名称通知主体的迁移项目拥有者昵称
    descriptionapplied.project.owner.login string项目简介通知主体的迁移项目拥有者标识
    visitsint流量数applied.project.owner.image_urlstring通知主体的迁移项目拥有者头像
    forked_countapplied.user.id int被fork的数量通知主体的迁移创建者的id
    praises_countintstar数量applied.user.typestring通知主体的迁移创建者的类型
    is_publicboolean是否公开, true:公开,false:未公开applied.user.namestring通知主体的迁移创建者的名称
    mirror_urlapplied.user.login string镜像url通知主体的迁移创建者的标识
    last_update_timeapplied.user.image_urlstring通知主体的迁移创建者头像
    applied.owner.id int最后更新时间,为UNIX格式的时间戳通知主体的迁移接受者的id
    authorobject项目创建者applied.owner.typestring通知主体的迁移接受者的类型
    -- nameapplied.owner.name string用户名,也是用户标识通知主体的迁移接受者的名称
    categoryobject项目类别applied.owner.loginstring通知主体的迁移接受者的标识
    -- idint项目类型idapplied.owner.image_urlstring通知主体的迁移接受者头像
    -- nameapplied_type string项目类型名称通知类型
    languageobject项目语言namestring通知内容
    -- idint项目语言idviewedstring是否已读,waiting:未读,viewed:已读
    -- namestatus string项目语言名称通知状态, canceled:已取消,common: 正常,successed:成功,failure:失败
    time_agostring通知时间
    @@ -806,57 +832,71 @@ http://localhost:3000/api/projects | jq

    返回的JSON示例:

    {
    -  "total_count": 3096,
    -  "projects": [
    -    {
    -      "id": 1400794,
    -      "repo_id": 1402452,
    -      "identifier": "cscw_2021_sponsor",
    -      "name": "Sponsor机制下的开源贡献",
    -      "description": "CSCW 2021 sponsor机制研究",
    -      "visits": 5,
    -      "praises_count": 0,
    -      "forked_count": 0,
    -      "is_public": true,
    -      "mirror_url": null,
    -      "type": 0,
    -      "last_update_time": 1611971671,
    -      "time_ago": "2天前",
    -      "forked_from_project_id": null,
    -      "open_devops": false,
    -      "platform": "forge",
    -      "author": {
    -        "name": "张迅晖",
    -        "login": "Nigel",
    -        "image_url": "images/avatars/User/3675?t=1611832880"
    -      },
    -      "category": {
    -        "id": 13,
    -        "name": "云计算和大数据"
    -      },
    -      "language": {
    -        "id": 34,
    -        "name": "Python3.6"
    -      }
    -    }
    -  ]
    +    "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分钟前"
    +        },
    +        ...
    +    ]
     }
    -
    - -

    推荐项目

    -

    获取推荐项目列表

    +

    待办事项-接受仓库

    +

    待办事项-接受仓库

    示例:

    -
    curl -X GET \
    -http://localhost:3000/api/projects/recommend  | jq
    -
    await octokit.request('GET /api/projects/recommend.json')
    -

    HTTP 请求

    -

    GET api/projects/recommend

    -

    返回字段说明

    +
    curl -X GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects.json

    +

    请求字段说明:

    @@ -865,134 +905,1298 @@ http://localhost:3000/api/projects/recommend | jq - - - + + + +
    参数
    total_countint项目总条数loginstring用户标识
    +

    返回字段说明:

    + - - - + + + + - - - + + + - + - + - - - + + + - + - + - - - + + + - - - + + + - + - + - - - + + + - - - + + + - + - + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    idstring项目id参数类型字段说明
    namestring项目名称idint迁移id
    descriptionstatus string项目简介迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    visitsint流量数time_agostring迁移创建的时间
    forked_countproject.id int被fork的数量迁移项目的id
    praises_countintstar数量project.identifierstring迁移项目的标识
    is_publicboolean是否公开, true:公开,false:未公开project.namestring迁移项目的名称
    mirror_urlproject.description string镜像url迁移项目的描述
    last_update_timeint最后更新时间,为UNIX格式的时间戳project.is_publicbool迁移项目是否公开
    authorobject项目创建者project.owner.idbool迁移项目拥有者id
    -- nameproject.owner.type string用户名,也是用户标识迁移项目拥有者类型
    categoryobject项目类别project.owner.namestring迁移项目拥有者昵称
    -- idint项目类型idproject.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的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小时前"
    +        },
    +        ...
    +    ]
    +}
    +

    用户接受迁移

    +

    用户接受迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/accept.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects/:id/accept.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    idint迁移id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint迁移id
    statusstring迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的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小时前"
    +}
    +

    用户拒绝迁移

    +

    用户拒绝迁移

    + +
    +

    示例:

    +
    +
    curl -X POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json
    +
    await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refuse.json')
    +

    HTTP 请求

    +

    GET /api/users/:login/applied_transfer_projects/:id/refuse.json

    +

    请求字段说明:

    + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    loginstring用户标识
    idint迁移id
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    idint迁移id
    statusstring迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    + +
    +

    返回的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小时前"
    +}
    +

    Projects

    获取项目列表

    +

    获取项目列表,也可以更加相关条件过滤搜素

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +-d "page=1" \
    +-d "limit=5" \
    +http://localhost:3000/api/projects  | jq
    +
    await octokit.request('GET /api/projects')
    +

    HTTP 请求

    +

    GET api/projects

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    pagefalse1string页数,第几页
    limitfalse15string每页多少条数据,默认15条
    sort_byfalsestring排序类型, 取值:updated_on、created_on、forked_count、praises_count; updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序
    sort_directionfalsestring排序方式,取值为: desc、asc; desc: 降序排序, asc: 升序排序, 默认为:desc
    searchfalsestring按照项目名称搜索
    category_idfalseint项目类别id
    language_idfalseint项目语言id
    project_typefalsestring项目类型, 取值为:common、mirror; common:开源托管项目, mirror:开源镜像项目
    +

    返回字段说明

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    total_countint项目总条数
    idstring项目id
    namestring项目名称
    descriptionstring项目简介
    visitsint流量数
    forked_countint被fork的数量
    praises_countintstar数量
    is_publicboolean是否公开, true:公开,false:未公开
    mirror_urlstring镜像url
    last_update_timeint最后更新时间,为UNIX格式的时间戳
    authorobject项目创建者
    -- namestring用户名,也是用户标识
    categoryobject项目类别
    -- idint项目类型id
    -- namestring项目类型名称
    languageobject项目语言
    -- idint项目语言id
    -- namestring项目语言名称
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +  "total_count": 3096,
    +  "projects": [
    +    {
    +      "id": 1400794,
    +      "repo_id": 1402452,
    +      "identifier": "cscw_2021_sponsor",
    +      "name": "Sponsor机制下的开源贡献",
    +      "description": "CSCW 2021 sponsor机制研究",
    +      "visits": 5,
    +      "praises_count": 0,
    +      "forked_count": 0,
    +      "is_public": true,
    +      "mirror_url": null,
    +      "type": 0,
    +      "last_update_time": 1611971671,
    +      "time_ago": "2天前",
    +      "forked_from_project_id": null,
    +      "open_devops": false,
    +      "platform": "forge",
    +      "author": {
    +        "name": "张迅晖",
    +        "login": "Nigel",
    +        "image_url": "images/avatars/User/3675?t=1611832880"
    +      },
    +      "category": {
    +        "id": 13,
    +        "name": "云计算和大数据"
    +      },
    +      "language": {
    +        "id": 34,
    +        "name": "Python3.6"
    +      }
    +    }
    +  ]
    +}
    +
    + +

    推荐项目

    +

    获取推荐项目列表

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/projects/recommend  | jq
    +
    await octokit.request('GET /api/projects/recommend.json')
    +

    HTTP 请求

    +

    GET api/projects/recommend

    +

    返回字段说明

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + +
    参数类型字段说明
    total_countint项目总条数
    idstring项目id
    namestring项目名称
    descriptionstring项目简介
    visitsint流量数
    forked_countint被fork的数量
    praises_countintstar数量
    is_publicboolean是否公开, true:公开,false:未公开
    mirror_urlstring镜像url
    last_update_timeint最后更新时间,为UNIX格式的时间戳
    authorobject项目创建者
    -- namestring用户名,也是用户标识
    categoryobject项目类别
    -- idint项目类型id
    -- namestring项目类型名称
    languageobject项目语言
    -- idint项目语言id
    -- name string项目类型名称项目语言名称
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +  {
    +    "id": 20,
    +    "repo_id": 2,
    +    "identifier": "PNAekinmH",
    +    "name": "FNILL",
    +    "visits": 13567,
    +    "author": {
    +      "name": "王一达",
    +      "login": "wangyida",
    +      "image_url": "avatars/User/b"
    +    },
    +    "category": {
    +      "id": 8,
    +      "name": "其他"
    +    }
    +  }
    +]
    +
    + +

    项目导航

    +

    获取项目导航信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/yystopf/ceshi/menu_list  | jq
    +
    await octokit.request('GET /api/yystopf/ceshi/menu_list')
    +

    HTTP 请求

    +

    GET api/:owner/:repo/menu_list

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明

    + + + + + + + + + + + + +
    参数类型字段说明
    menu_namestring导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +    {
    +        "menu_name": "home"
    +    },
    +    {
    +        "menu_name": "code"
    +    },
    +    {
    +        "menu_name": "pulls"
    +    },
    +    {
    +        "menu_name": "activity"
    +    }
    +]
    +

    项目主页

    +

    获取项目主页信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/jasder/forgeplus/about  | jq
    +
    await octokit.request('GET /api/jasder/forgeplus/about')
    +

    HTTP 请求

    +

    GET api/:owner/:repo/about

    +

    请求参数

    + + + + + + + + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    ownerstring用户登录名
    repostring项目标识identifier
    +

    返回字段说明

    + + + + + + + + + + + + + + + + + + + + + + +
    参数类型字段说明
    identifierstringproject's identifier
    contentstring主页内容
    attachmentsarray附件
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +  "content": "",
    +  "identifier": "forgeplus",
    +  attachments: []
    +}
    +
    + +

    项目模块信息

    +

    项目模块信息

    + +
    +

    示例:

    +
    +
    curl -X GET \
    +http://localhost:3000/api/yystopf/ceshi/project_units.json
    +
    await octokit.request('GET /api/yystopf/ceshi/project_units')
    +

    HTTP 请求

    +

    GET /api/yystopf/ceshi/project_units

    +

    返回字段说明:

    + + + + + + + + + + + + +
    参数类型字段说明
    typestring模块名称
    + +
    +

    返回的JSON示例:

    +
    +
    [
    +    {
    +        "type": "code"
    +    },
    +    {
    +        "type": "pulls"
    +    },
    +    {
    +        "type": "issues"
    +    }
    +]
    +

    更改项目模块展示

    +

    更改项目模块展示

    + +
    +

    示例:

    +
    +
    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
    +
    await octokit.request('POST /api/yystopf/ceshi/project_units')
    +

    HTTP 请求

    +

    POST /api/yystopf/ceshi/project_units

    +

    请求参数

    + + + + + + + + + + + + + + + + +
    参数必选默认类型字段说明
    unit_typesarray项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑
    +

    返回字段说明:

    + + + + + + + + + + + + + + + + +
    参数类型字段说明
    statusint返回状态, 0: 表示操作成功
    messagestring返回信息说明
    + +
    +

    返回的JSON示例:

    +
    +
    {
    +    "status": 0,
    +    "message": "success"
    +}
    +

    创建项目

    +

    创建项目

    + +
    +

    示例:

    +
    +
    curl -X POST \
    +-d "user_id=36401" \
    +-d "name=hnfl_demo" \
    +-d "description=my first project" \
    +-d "repository_name=hnfl_demo" \
    +-d "project_category_id=1" \
    +-d "project_language_id=2" \
    +-d "ignore_id=2" \
    +-d "license_id=1" \
    +http://localhost:3000/api/projects.json
    +
    await octokit.request('GET /api/projects.json')
    +

    HTTP 请求

    +

    POST api/projects

    +

    请求参数

    + - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + +
    languageobject项目语言参数必选默认类型字段说明
    -- iduser_idint用户id或者组织id
    namestring项目名称
    descriptionstring项目描述
    repository_namestring仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一
    project_category_idint项目类别id
    project_language_id int 项目语言id
    -- nameignore_idintgitignore相关id
    license_idint开源许可证id
    privateboolean项目是否私有, true:为私有,false: 公开,默认为公开
    +

    返回字段说明

    + + + + + + + + + + + + + + - +
    参数类型字段说明
    idintid
    name string项目语言名称项目名称

    返回的JSON示例:

    -
    [
    -  {
    -    "id": 20,
    -    "repo_id": 2,
    -    "identifier": "PNAekinmH",
    -    "name": "FNILL",
    -    "visits": 13567,
    -    "author": {
    -      "name": "王一达",
    -      "login": "wangyida",
    -      "image_url": "avatars/User/b"
    -    },
    -    "category": {
    -      "id": 8,
    -      "name": "其他"
    -    }
    -  }
    -]
    -
    - -

    项目导航

    -

    获取项目导航信息

    +
    {
    +  "id": 3240,
    +  "name": "好项目"
    +}
    +

    创建镜像项目

    +

    创建镜像项目

    示例:

    -
    curl -X GET \
    -http://localhost:3000/api/yystopf/ceshi/menu_list  | jq
    -
    await octokit.request('GET /api/yystopf/ceshi/menu_list')
    -

    HTTP 请求

    -

    GET api/:owner/:repo/menu_list

    -

    请求参数

    +
    curl -X POST \
    +-d "user_id=36408" \
    +-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
    +-d "name=golden_mirror1" \
    +-d "description=golden_mirror" \
    +-d "project_category_id=1" \
    +-d "project_language_id=2" \
    +http://localhost:3000/api/projects/migrate.json
    +
    await octokit.request('GET /api/projects/migrate.json')
    +

    HTTP 请求

    +

    POST api/projects/migrate.json

    +

    请求参数

    @@ -1003,21 +2207,84 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + +
    参数
    owneruser_idint用户id或者组织id
    namestring项目名称
    clone_addrstring镜像项目clone地址
    descriptionstring项目描述
    repository_namestring仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一
    project_category_idint项目类别id
    project_language_id int项目语言id
    is_mirrorboolean是否设置为镜像, true:是, false:否,默认为否
    auth_usernamestring镜像源仓库的登录用户名
    auth_password string用户登录名镜像源仓库的登录秘密
    repoprivate string项目标识identifierboolean项目是否私有, true:为私有,false: 非私有,默认为公开
    -

    返回字段说明

    +

    返回字段说明

    @@ -1026,41 +2293,35 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq - + + + + + + - +
    参数
    menu_nameidintid
    name string导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置项目名称

    返回的JSON示例:

    -
    [
    -    {
    -        "menu_name": "home"
    -    },
    -    {
    -        "menu_name": "code"
    -    },
    -    {
    -        "menu_name": "pulls"
    -    },
    -    {
    -        "menu_name": "activity"
    -    }
    -]
    -

    项目主页

    -

    获取项目主页信息

    +
    {
    +  "id": 3241,
    +  "name": "这是一个镜像项目"
    +}
    +

    同步镜像

    +

    手动同步镜像

    示例:

    -
    curl -X GET \
    -http://localhost:3000/api/jasder/forgeplus/about  | jq
    -
    await octokit.request('GET /api/jasder/forgeplus/about')
    -

    HTTP 请求

    -

    GET api/:owner/:repo/about

    -

    请求参数

    +
    curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
    +
    await octokit.request('POST /api/repositories/1244/sync_mirror.json')
    +

    HTTP 请求

    +

    POST api/repositories/:id/sync_mirror.json

    +

    请求参数

    @@ -1071,21 +2332,14 @@ http://localhost:3000/api/jasder/forgeplus/about | jq - - - - - - - - + - - + +
    参数
    ownerstring用户登录名
    repoid string项目标识identifierint仓库id
    -

    返回字段说明

    +

    返回字段说明

    @@ -1094,19 +2348,14 @@ http://localhost:3000/api/jasder/forgeplus/about | jq - - - + + + - + - - - - - - +
    参数
    identifierstringproject's identifierstatusint状态码, 0:标识请求成功
    contentmessage string主页内容
    attachmentsarray附件服务端返回的信息说明
    @@ -1114,87 +2363,45 @@ http://localhost:3000/api/jasder/forgeplus/about | jq

    返回的JSON示例:

    {
    -  "content": "",
    -  "identifier": "forgeplus",
    -  attachments: []
    +  "status": 0,
    +  "message": "success"
     }
    -
    - -

    项目模块信息

    -

    项目模块信息

    +

    Fork项目

    +

    fork项目

    示例:

    -
    curl -X GET \
    -http://localhost:3000/api/yystopf/ceshi/project_units.json
    -
    await octokit.request('GET /api/yystopf/ceshi/project_units')
    -

    HTTP 请求

    -

    GET /api/yystopf/ceshi/project_units

    -

    返回字段说明:

    +
    curl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
    +
    await octokit.request('POST /api/jaser/jasder_test/forks.json')
    +

    HTTP 请求

    +

    POST api/:owner/:repo/forks.json

    +

    请求参数

    + + - + + + - - -
    参数必选默认 类型 字段说明
    typeowner string模块名称
    - -
    -

    返回的JSON示例:

    -
    -
    [
    -    {
    -        "type": "code"
    -    },
    -    {
    -        "type": "pulls"
    -    },
    -    {
    -        "type": "issues"
    -    }
    -]
    -

    更改项目模块展示

    -

    更改项目模块展示

    - -
    -

    示例:

    -
    -
    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
    -
    await octokit.request('POST /api/yystopf/ceshi/project_units')
    -

    HTTP 请求

    -

    POST /api/yystopf/ceshi/project_units

    -

    请求参数

    - - - - - - - + - - + - - + +
    参数必选默认类型字段说明用户登录名
    unit_typesrepo array项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑string项目标识identifier
    -

    返回字段说明:

    +

    返回字段说明

    @@ -1203,14 +2410,14 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json - + - + - + - +
    参数
    statusid int返回状态, 0: 表示操作成功项目id
    messageidentifier string返回信息说明项目标识
    @@ -1218,29 +2425,21 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json

    返回的JSON示例:

    {
    -    "status": 0,
    -    "message": "success"
    +  "id": 3290,
    +  "identifier": "newadm"
     }
    -

    创建项目

    -

    创建项目

    +

    用户管理的组织列表

    +

    用户管理的组织列表

    示例:

    -
    curl -X POST \
    --d "user_id=36401" \
    --d "name=hnfl_demo" \
    --d "description=my first project" \
    --d "repository_name=hnfl_demo" \
    --d "project_category_id=1" \
    --d "project_language_id=2" \
    --d "ignore_id=2" \
    --d "license_id=1" \
    -http://localhost:3000/api/projects.json
    -
    await octokit.request('GET /api/projects.json')
    -

    HTTP 请求

    -

    POST api/projects

    -

    请求参数

    +
    curl -X GET \
    +http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json  | jq
    +
    await octokit.request('GET /api/:owner/:repo/applied_transfer_projects/organizations')
    +

    HTTP 请求

    +

    GET api/:owner/:repo/applied_transfer_projects/organizations

    +

    请求参数

    @@ -1251,86 +2450,47 @@ http://localhost:3000/api/projects.json - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
    参数
    user_idint用户id或者组织id
    namestring项目名称
    descriptionowner string项目描述用户登录名
    repository_namerepo string仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一
    project_category_idint项目类别id
    project_language_idint项目语言id
    ignore_idintgitignore相关id
    license_idint开源许可证id
    privateboolean项目是否私有, true:为私有,false: 公开,默认为公开项目标识identifier
    -

    返回字段说明

    +

    返回字段说明

    - + + + + + + - - - + + + - + - + + + + + +
    参数 类型 字段说明
    namestring组织标识
    idintidnicknamestring组织名称
    namedescription string项目名称组织描述
    avatar_urlstring|组织头像
    @@ -1338,27 +2498,42 @@ http://localhost:3000/api/projects.json

    返回的JSON示例:

    {
    -  "id": 3240,
    -  "name": "好项目"
    +    "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表示正在迁移

    示例:

    -
    curl -X POST \
    --d "user_id=36408" \
    --d "clone_addr=https://gitea.com/mx8090alex/golden.git" \
    --d "name=golden_mirror1" \
    --d "description=golden_mirror" \
    --d "project_category_id=1" \
    --d "project_language_id=2" \
    -http://localhost:3000/api/projects/migrate.json
    -
    await octokit.request('GET /api/projects/migrate.json')
    -

    HTTP 请求

    -

    POST api/projects/migrate.json

    -

    请求参数

    +
    curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json
    +
    await octokit.request('POST /api/:owner/:repo/applied_transfer_projects.json')
    +

    HTTP 请求

    +

    POST /api/:owner/:repo/applied_transfer_projects.json

    +

    请求参数

    @@ -1369,155 +2544,149 @@ http://localhost:3000/api/projects/migrate.json - + - - + + - + - + - + - + +
    参数
    user_idowner int用户id或者组织idstring用户登录名
    namerepo string项目名称项目标识identifier
    clone_addrowner_name string镜像项目clone地址迁移对象标识
    +

    返回字段说明

    + - - - + + + + + + + + + + + + - + - - - + - + - - - + - + - - - - - + + + - - - - - + + + - - - + - + - - - + + + + + + + + + + + - + - - - - - + + + -
    description参数类型字段说明
    idint项目id
    status string项目描述项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    repository_nametime_ago string仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一项目迁移创建的时间
    project_category_idproject.id int项目类别id迁移项目的id
    project_language_idint项目语言idproject.identifierstring迁移项目的标识
    is_mirrorboolean是否设置为镜像, true:是, false:否,默认为否project.namestring迁移项目的名称
    auth_usernameproject.description string镜像源仓库的登录用户名迁移项目的描述
    auth_passwordproject.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.type string镜像源仓库的登录秘密迁移项目拥有者类型
    privateboolean项目是否私有, true:为私有,false: 非私有,默认为公开project.owner.namestring迁移项目拥有者昵称
    -

    返回字段说明

    - - - - + + + - - + + + + + + - + - + - + -
    参数类型字段说明project.owner.loginstring迁移项目拥有者标识
    idproject.owner.image_urlstring迁移项目拥有者头像
    user.id intid迁移创建者的id
    nameuser.type string项目名称迁移创建者的类型
    - -
    -

    返回的JSON示例:

    -
    -
    {
    -  "id": 3241,
    -  "name": "这是一个镜像项目"
    -}
    -

    同步镜像

    -

    手动同步镜像

    - -
    -

    示例:

    -
    -
    curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror.json
    -
    await octokit.request('POST /api/repositories/1244/sync_mirror.json')
    -

    HTTP 请求

    -

    POST api/repositories/:id/sync_mirror.json

    -

    请求参数

    - - - - - - + + + - - - - - - + + + -
    参数必选默认类型字段说明user.namestring迁移创建者的名称
    idint仓库iduser.loginstring迁移创建者的标识
    -

    返回字段说明

    - - - - + + + - - + - + - + - + + + + + + + + + + + + + + + +
    参数类型字段说明user.image_urlstring迁移创建者头像
    statusowner.id int状态码, 0:标识请求成功迁移接受者的id
    messageowner.type string服务端返回的信息说明迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    @@ -1525,20 +2694,50 @@ http://localhost:3000/api/projects/migrate.json

    返回的JSON示例:

    {
    -  "status": 0,
    -  "message": "success"
    +    "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分钟前"
     }
    -

    Fork项目

    -

    fork项目

    +

    取消迁移项目

    +

    迁移项目,edit接口is_transfering为true表示正在迁移

    示例:

    -
    curl -X POST http://localhost:3000/api/jasder/forgeplus/forks.json
    -
    await octokit.request('POST /api/jaser/jasder_test/forks.json')
    -

    HTTP 请求

    -

    POST api/:owner/:repo/forks.json

    -

    请求参数

    +
    curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json
    +
    await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.json')
    +

    HTTP 请求

    +

    POST /api/:owner/:repo/applied_transfer_projects/cancel.json

    +

    请求参数

    @@ -1563,7 +2762,7 @@ http://localhost:3000/api/projects/migrate.json
    参数项目标识identifier
    -

    返回字段说明

    +

    返回字段说明

    @@ -1574,12 +2773,117 @@ http://localhost:3000/api/projects/migrate.json - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数
    id int项目id迁移id
    identifierstatus string项目标识迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝
    time_agostring迁移创建的时间
    project.idint迁移项目的id
    project.identifierstring迁移项目的标识
    project.namestring迁移项目的名称
    project.descriptionstring迁移项目的描述
    project.is_publicbool迁移项目是否公开
    project.owner.idbool迁移项目拥有者id
    project.owner.typestring迁移项目拥有者类型
    project.owner.namestring迁移项目拥有者昵称
    project.owner.loginstring迁移项目拥有者标识
    project.owner.image_urlstring迁移项目拥有者头像
    user.idint迁移创建者的id
    user.typestring迁移创建者的类型
    user.namestring迁移创建者的名称
    user.loginstring迁移创建者的标识
    user.image_urlstring迁移创建者头像
    owner.idint迁移接受者的id
    owner.typestring迁移接受者的类型
    owner.namestring迁移接受者的名称
    owner.loginstring迁移接受者的标识
    owner.image_urlstring迁移接受者头像
    @@ -1587,8 +2891,38 @@ http://localhost:3000/api/projects/migrate.json

    返回的JSON示例:

    {
    -  "id": 3290,
    -  "identifier": "newadm"
    +    "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分钟前"
     }
     

    Repositories

    仓库详情

    仓库详情