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 @@
获取当前登陆用户信息
@@ -622,183 +649,182 @@ Success — a happy kitten is an authenticated kitten! -获取项目列表,也可以更加相关条件过滤搜素
+待办事项-用户通知信息
-示例:
curl -X GET \
--d "page=1" \
--d "limit=5" \
-http://localhost:3000/api/projects | jq
-await octokit.request('GET /api/projects')
-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')
+GET /api/users/:login/applied_messages.json
| 参数 | -必选 | -默认 | 类型 | 字段说明 | ||
|---|---|---|---|---|---|---|
| page | -false | -1 | +login | string | -页数,第几页 | +用户标识 | +
| 参数 | +类型 | +字段说明 | |||||
|---|---|---|---|---|---|---|---|
| limit | -false | -15 | -string | -每页多少条数据,默认15条 | +applied | +object | +通知主体 |
| sort_by | -false | -- | string | -排序类型, 取值:updated_on、created_on、forked_count、praises_count; updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | +applied.id | +int | +通知主体的迁移id |
| sort_direction | -false | -+ | applied.status | string | -排序方式,取值为: desc、asc; desc: 降序排序, asc: 升序排序, 默认为:desc | +通知主体的迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝 | |
| search | -false | -+ | applied.time_ago | string | -按照项目名称搜索 | +通知主体的迁移创建的时间 | |
| category_id | -false | -+ | applied.project.id | int | -项目类别id | +通知主体的迁移项目的id | |
| language_id | -false | -- | int | -项目语言id | +applied.project.identifier | +string | +通知主体的迁移项目的标识 |
| project_type | -false | -+ | applied.project.name | string | -项目类型, 取值为:common、mirror; common:开源托管项目, mirror:开源镜像项目 | +通知主体的迁移项目的名称 |
| 参数 | -类型 | -字段说明 | +applied.project.description | +string | +通知主体的迁移项目的描述 |
|---|---|---|---|---|---|
| total_count | -int | -项目总条数 | +applied.project.is_public | +bool | +通知主体的迁移项目是否公开 |
| id | +applied.project.owner.id | +bool | +通知主体的迁移项目拥有者id | +||
| applied.project.owner.type | string | -项目id | +通知主体的迁移项目拥有者类型 | ||
| name | +applied.project.owner.name | string | -项目名称 | +通知主体的迁移项目拥有者昵称 | |
| description | +applied.project.owner.login | string | -项目简介 | +通知主体的迁移项目拥有者标识 | |
| visits | -int | -流量数 | +applied.project.owner.image_url | +string | +通知主体的迁移项目拥有者头像 |
| forked_count | +applied.user.id | int | -被fork的数量 | +通知主体的迁移创建者的id | |
| praises_count | -int | -star数量 | +applied.user.type | +string | +通知主体的迁移创建者的类型 |
| is_public | -boolean | -是否公开, true:公开,false:未公开 | +applied.user.name | +string | +通知主体的迁移创建者的名称 |
| mirror_url | +applied.user.login | string | -镜像url | +通知主体的迁移创建者的标识 | |
| last_update_time | +applied.user.image_url | +string | +通知主体的迁移创建者头像 | +||
| applied.owner.id | int | -最后更新时间,为UNIX格式的时间戳 | +通知主体的迁移接受者的id | ||
| author | -object | -项目创建者 | +applied.owner.type | +string | +通知主体的迁移接受者的类型 |
| -- name | +applied.owner.name | string | -用户名,也是用户标识 | +通知主体的迁移接受者的名称 | |
| category | -object | -项目类别 | +applied.owner.login | +string | +通知主体的迁移接受者的标识 |
| -- id | -int | -项目类型id | +applied.owner.image_url | +string | +通知主体的迁移接受者头像 |
| -- name | +applied_type | string | -项目类型名称 | +通知类型 | |
| language | -object | -项目语言 | +name | +string | +通知内容 |
| -- id | -int | -项目语言id | +viewed | +string | +是否已读,waiting:未读,viewed:已读 |
| -- name | +status | string | -项目语言名称 | +通知状态, canceled:已取消,common: 正常,successed:成功,failure:失败 | +|
| time_ago | +string | +通知时间 |
返回的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')
-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')
+GET /api/users/:login/applied_transfer_projects.json
| 参数 | @@ -865,134 +905,1298 @@ http://localhost:3000/api/projects/recommend | jq|||||
|---|---|---|---|---|---|
| total_count | -int | -项目总条数 | +login | +string | +用户标识 |
| id | -string | -项目id | +参数 | +类型 | +字段说明 |
|---|---|---|---|---|---|
| name | -string | -项目名称 | +id | +int | +迁移id |
| description | +status | string | -项目简介 | +迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝 | |
| visits | -int | -流量数 | +time_ago | +string | +迁移创建的时间 |
| forked_count | +project.id | int | -被fork的数量 | +迁移项目的id | |
| praises_count | -int | -star数量 | +project.identifier | +string | +迁移项目的标识 |
| is_public | -boolean | -是否公开, true:公开,false:未公开 | +project.name | +string | +迁移项目的名称 |
| mirror_url | +project.description | string | -镜像url | +迁移项目的描述 | |
| last_update_time | -int | -最后更新时间,为UNIX格式的时间戳 | +project.is_public | +bool | +迁移项目是否公开 |
| author | -object | -项目创建者 | +project.owner.id | +bool | +迁移项目拥有者id |
| -- name | +project.owner.type | string | -用户名,也是用户标识 | +迁移项目拥有者类型 | |
| category | -object | -项目类别 | +project.owner.name | +string | +迁移项目拥有者昵称 |
| -- id | -int | -项目类型id | +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示例:
+
{
+ "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')
+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示例:
+
{
+ "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')
+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示例:
+
{
+ "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 GET \
+-d "page=1" \
+-d "limit=5" \
+http://localhost:3000/api/projects | jq
+await octokit.request('GET /api/projects')
+GET api/projects
| 参数 | +必选 | +默认 | +类型 | +字段说明 | +
|---|---|---|---|---|
| page | +false | +1 | +string | +页数,第几页 | +
| limit | +false | +15 | +string | +每页多少条数据,默认15条 | +
| sort_by | +false | ++ | string | +排序类型, 取值:updated_on、created_on、forked_count、praises_count; updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | +
| sort_direction | +false | ++ | string | +排序方式,取值为: desc、asc; desc: 降序排序, asc: 升序排序, 默认为:desc | +
| search | +false | ++ | string | +按照项目名称搜索 | +
| category_id | +false | ++ | int | +项目类别id | +
| language_id | +false | ++ | int | +项目语言id | +
| project_type | +false | ++ | string | +项目类型, 取值为:common、mirror; common:开源托管项目, mirror:开源镜像项目 | +
| 参数 | +类型 | +字段说明 | +
|---|---|---|
| total_count | +int | +项目总条数 | +
| id | +string | +项目id | +
| name | +string | +项目名称 | +
| description | +string | +项目简介 | +
| visits | +int | +流量数 | +
| forked_count | +int | +被fork的数量 | +
| praises_count | +int | +star数量 | +
| is_public | +boolean | +是否公开, true:公开,false:未公开 | +
| mirror_url | +string | +镜像url | +
| last_update_time | +int | +最后更新时间,为UNIX格式的时间戳 | +
| author | +object | +项目创建者 | +
| -- name | +string | +用户名,也是用户标识 | +
| category | +object | +项目类别 | +
| -- id | +int | +项目类型id | +
| -- name | +string | +项目类型名称 | +
| language | +object | +项目语言 | +
| -- id | +int | +项目语言id | +
| -- name | +string | +项目语言名称 | +
++返回的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')
+GET api/projects/recommend
| 参数 | +类型 | +字段说明 | +|
|---|---|---|---|
| total_count | +int | +项目总条数 | +|
| id | +string | +项目id | +|
| name | +string | +项目名称 | +|
| description | +string | +项目简介 | +|
| visits | +int | +流量数 | +|
| forked_count | +int | +被fork的数量 | +|
| praises_count | +int | +star数量 | +|
| is_public | +boolean | +是否公开, true:公开,false:未公开 | +|
| mirror_url | +string | +镜像url | +|
| last_update_time | +int | +最后更新时间,为UNIX格式的时间戳 | +|
| author | +object | +项目创建者 | +|
| -- name | +string | +用户名,也是用户标识 | +|
| category | +object | +项目类别 | +|
| -- id | +int | +项目类型id | +|
| -- name | +string | +项目类型名称 | +|
| language | +object | +项目语言 | +|
| -- id | +int | +项目语言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')
+GET api/:owner/:repo/menu_list
| 参数 | +必选 | +默认 | +类型 | +字段说明 | +
|---|---|---|---|---|
| owner | +是 | ++ | string | +用户登录名 | +
| repo | +是 | ++ | string | +项目标识identifier | +
| 参数 | +类型 | +字段说明 | +
|---|---|---|
| menu_name | +string | +导航名称, 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')
+GET api/:owner/:repo/about
| 参数 | +必选 | +默认 | +类型 | +字段说明 | +
|---|---|---|---|---|
| owner | +是 | ++ | string | +用户登录名 | +
| repo | +是 | ++ | string | +项目标识identifier | +
| 参数 | +类型 | +字段说明 | +
|---|---|---|
| identifier | +string | +project's identifier | +
| content | +string | +主页内容 | +
| attachments | +array | +附件 | +
++返回的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')
+GET /api/yystopf/ceshi/project_units
| 参数 | +类型 | +字段说明 | +
|---|---|---|
| type | +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')
+POST /api/yystopf/ceshi/project_units
| 参数 | +必选 | +默认 | +类型 | +字段说明 | +
|---|---|---|---|---|
| unit_types | +是 | ++ | array | +项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 | +
| 参数 | +类型 | +字段说明 | +
|---|---|---|
| status | +int | +返回状态, 0: 表示操作成功 | +
| message | +string | +返回信息说明 |
++返回的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')
+POST api/projects
| language | -object | -项目语言 | +参数 | +必选 | +默认 | +类型 | +字段说明 |
|---|---|---|---|---|---|---|---|
| -- id | +user_id | +是 | ++ | int | +用户id或者组织id | +||
| name | +是 | ++ | string | +项目名称 | +|||
| description | +是 | ++ | string | +项目描述 | +|||
| repository_name | +是 | ++ | string | +仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|||
| project_category_id | +是 | ++ | int | +项目类别id | +|||
| project_language_id | +是 | +int | 项目语言id | ||||
| -- name | +ignore_id | +否 | ++ | int | +gitignore相关id | +||
| license_id | +否 | ++ | int | +开源许可证id | +|||
| private | +否 | ++ | boolean | +项目是否私有, true:为私有,false: 公开,默认为公开 | +
| 参数 | +类型 | +字段说明 | +|
|---|---|---|---|
| id | +int | +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": "其他"
- }
- }
-]
-获取项目导航信息
+{
+ "id": 3240,
+ "name": "好项目"
+}
+创建镜像项目
-示例:
curl -X GET \
-http://localhost:3000/api/yystopf/ceshi/menu_list | jq
-await octokit.request('GET /api/yystopf/ceshi/menu_list')
-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')
+POST api/projects/migrate.json
| 参数 | @@ -1003,21 +2207,84 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq||||||||
|---|---|---|---|---|---|---|---|---|
| owner | +user_id | +是 | ++ | int | +用户id或者组织id | +|||
| name | +是 | ++ | string | +项目名称 | +||||
| clone_addr | +是 | ++ | string | +镜像项目clone地址 | +||||
| description | +否 | ++ | string | +项目描述 | +||||
| repository_name | +是 | ++ | string | +仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +||||
| project_category_id | +是 | ++ | int | +项目类别id | +||||
| project_language_id | 是 | + | int | +项目语言id | +||||
| is_mirror | +否 | ++ | boolean | +是否设置为镜像, true:是, false:否,默认为否 | +||||
| auth_username | +否 | ++ | string | +镜像源仓库的登录用户名 | +||||
| auth_password | +否 | +string | -用户登录名 | +镜像源仓库的登录秘密 | ||||
| repo | -是 | +private | +否 | - | string | -项目标识identifier | +boolean | +项目是否私有, true:为私有,false: 非私有,默认为公开 |
| 参数 | @@ -1026,41 +2293,35 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq|||
|---|---|---|---|
| menu_name | +id | +int | +id | +
| 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')
-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')
+POST api/repositories/:id/sync_mirror.json
| 参数 | @@ -1071,21 +2332,14 @@ http://localhost:3000/api/jasder/forgeplus/about | jq|||||||
|---|---|---|---|---|---|---|---|
| owner | -是 | -- | string | -用户登录名 | -|||
| repo | +id | 是 | - | string | -项目标识identifier | +int | +仓库id |
| 参数 | @@ -1094,19 +2348,14 @@ http://localhost:3000/api/jasder/forgeplus/about | jq|||||
|---|---|---|---|---|---|
| identifier | -string | -project's identifier | +status | +int | +状态码, 0:标识请求成功 |
| content | +message | string | -主页内容 | -||
| attachments | -array | -附件 | +服务端返回的信息说明 |
返回的JSON示例:
{
- "content": "",
- "identifier": "forgeplus",
- attachments: []
+ "status": 0,
+ "message": "success"
}
-项目模块信息
+fork项目
-示例:
curl -X GET \
-http://localhost:3000/api/yystopf/ceshi/project_units.json
-await octokit.request('GET /api/yystopf/ceshi/project_units')
-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')
+POST api/:owner/:repo/forks.json
| 参数 | +必选 | +默认 | 类型 | 字段说明 | |
|---|---|---|---|---|---|
| type | +owner | +是 | +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')
-POST /api/yystopf/ceshi/project_units
| 参数 | -必选 | -默认 | -类型 | -字段说明 | +用户登录名 | ||
|---|---|---|---|---|---|---|---|
| unit_types | +repo | 是 | - | array | -项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 | +string | +项目标识identifier |
| 参数 | @@ -1203,14 +2410,14 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json||||
|---|---|---|---|---|
| status | +id | int | -返回状态, 0: 表示操作成功 | +项目id |
| message | +identifier | string | -返回信息说明 | +项目标识 |
返回的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')
-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')
+GET api/:owner/:repo/applied_transfer_projects/organizations
| 参数 | @@ -1251,86 +2450,47 @@ http://localhost:3000/api/projects.json||||||
|---|---|---|---|---|---|---|
| user_id | -是 | -- | int | -用户id或者组织id | -||
| name | -是 | -- | string | -项目名称 | -||
| description | +owner | 是 | string | -项目描述 | +用户登录名 | |
| repository_name | +repo | 是 | string | -仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | -||
| project_category_id | -是 | -- | int | -项目类别id | -||
| project_language_id | -是 | -- | int | -项目语言id | -||
| ignore_id | -否 | -- | int | -gitignore相关id | -||
| license_id | -否 | -- | int | -开源许可证id | -||
| private | -否 | -- | boolean | -项目是否私有, true:为私有,false: 公开,默认为公开 | +项目标识identifier |
| 参数 | 类型 | 字段说明 | |||
|---|---|---|---|---|---|
| name | +string | +组织标识 | +|||
| id | -int | -id | +nickname | +string | +组织名称 |
| name | +description | string | -项目名称 | +组织描述 | +|
| avatar_url | +string|组织头像 | +
返回的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')
-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')
+POST /api/:owner/:repo/applied_transfer_projects.json
| 参数 | @@ -1369,155 +2544,149 @@ http://localhost:3000/api/projects/migrate.json|||||||
|---|---|---|---|---|---|---|---|
| user_id | +owner | 是 | - | int | -用户id或者组织id | +string | +用户登录名 |
| name | +repo | 是 | string | -项目名称 | +项目标识identifier | ||
| clone_addr | +owner_name | 是 | string | -镜像项目clone地址 | +迁移对象标识 |
| description | -否 | -+ | 参数 | +类型 | +字段说明 | +||
|---|---|---|---|---|---|---|---|
| id | +int | +项目id | +|||||
| status | string | -项目描述 | +项目迁移状态,canceled:取消,common:正在迁移, accept:已接受,refuse:已拒绝 | ||||
| repository_name | -是 | -+ | time_ago | string | -仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +项目迁移创建的时间 | |
| project_category_id | -是 | -+ | project.id | int | -项目类别id | +迁移项目的id | |
| project_language_id | -是 | -- | int | -项目语言id | +project.identifier | +string | +迁移项目的标识 |
| is_mirror | -否 | -- | boolean | -是否设置为镜像, true:是, false:否,默认为否 | +project.name | +string | +迁移项目的名称 |
| auth_username | -否 | -+ | project.description | string | -镜像源仓库的登录用户名 | +迁移项目的描述 | |
| auth_password | -否 | -+ | project.is_public | +bool | +迁移项目是否公开 | +||
| project.owner.id | +bool | +迁移项目拥有者id | +|||||
| project.owner.type | string | -镜像源仓库的登录秘密 | +迁移项目拥有者类型 | ||||
| private | -否 | -- | boolean | -项目是否私有, true:为私有,false: 非私有,默认为公开 | +project.owner.name | +string | +迁移项目拥有者昵称 |
| 参数 | -类型 | -字段说明 | +project.owner.login | +string | +迁移项目拥有者标识 |
|---|---|---|---|---|---|
| id | +project.owner.image_url | +string | +迁移项目拥有者头像 | +||
| user.id | int | -id | +迁移创建者的id | ||
| name | +user.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')
-POST api/repositories/:id/sync_mirror.json
| 参数 | -必选 | -默认 | -类型 | -字段说明 | +user.name | +string | +迁移创建者的名称 |
|---|---|---|---|---|---|---|---|
| id | -是 | -- | int | -仓库id | +user.login | +string | +迁移创建者的标识 |
| 参数 | -类型 | -字段说明 | +user.image_url | +string | +迁移创建者头像 |
|---|---|---|---|---|---|
| status | +owner.id | int | -状态码, 0:标识请求成功 | +迁移接受者的id | |
| message | +owner.type | string | -服务端返回的信息说明 | +迁移接受者的类型 | +|
| owner.name | +string | +迁移接受者的名称 | +|||
| owner.login | +string | +迁移接受者的标识 | +|||
| owner.image_url | +string | +迁移接受者头像 |
返回的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项目
+迁移项目,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')
-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')
+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 | |
| identifier | +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示例:
{
- "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分钟前"
}
仓库详情