add: applied join project

This commit is contained in:
vilet.yy 2021-06-09 16:53:09 +08:00
parent d4b8b3e24f
commit 5489ea9fbc
32 changed files with 1497 additions and 132 deletions

View File

@ -0,0 +1,13 @@
class AppliedProjectsController < ApplicationController
before_action :require_login
def create
@applied_project = Projects::ApplyJoinService.call(current_user, applied_params)
rescue Projects::ApplyJoinService::Error => ex
render_error(ex.message)
end
private
def applied_params
params.require(:applied_project).permit(:code, :role)
end
end

View File

@ -9,7 +9,7 @@ class Users::AppliedMessagesController < Users::BaseController
private
def check_auth
return render_forbidden unless observed_logged_user?
return render_forbidden unless current_user.admin? || observed_logged_user?
end
def view_messages

View File

@ -0,0 +1,39 @@
class Users::AppliedProjectsController < Users::BaseController
before_action :check_auth
before_action :find_applied_project, except: [:index]
before_action :find_project, except: [:index]
def index
@applied_projects = AppliedProject.where(project_id: observed_user.full_admin_projects)
@applied_projects = paginate @applied_projects.order("created_at desc")
end
# 接受申请
def accept
@applied_project = Projects::AcceptJoinService.call(current_user, @applied_project)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
# 拒绝申请
def refuse
@applied_project = Projects::RefuseJoinService.call(current_user, @applied_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? || observed_logged_user?
end
def find_applied_project
@applied_project = AppliedProject.find_by_id params[:id]
end
def find_project
@project = @applied_project.project
end
end

View File

@ -28,7 +28,7 @@ class Users::AppliedTransferProjectsController < Users::BaseController
private
def check_auth
return render_forbidden unless observed_logged_user?
return render_forbidden unless current_user.admin? || observed_logged_user?
end
def find_applied_transfer_project

View File

@ -1,5 +1,91 @@
# Projects
## 申请加入项目
申请加入项目
> 示例:
```shell
curl -X POST http://localhost:3000/api/applied_projects.json
```
```javascript
await octokit.request('POST /api/appliedr_projects.json')
```
### HTTP 请求
`POST /api/applied_projects.json`
### 请求参数
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
|applied_project.code |是| |string |邀请码 |
|applied_project.role |否| |string |项目权限reporter: 报告者, developer: 开发者manager管理员 |
> 请求的JSON示例
```json
{
"applied_project": {
"code": "1una34",
"role": "developer"
}
}
```
### 返回字段说明
参数 | 类型 | 字段说明
--------- | ----------- | -----------
|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 |申请创建者头像 |
> 返回的JSON示例:
```json
{
"project": {
"id": 74,
"identifier": "hehuisssjssjjsjs",
"name": "hehuisssjssjjsjs",
"description": "wwww",
"is_public": false,
"owner": {
"id": 10,
"type": "User",
"name": "testforge1",
"login": "testforge1",
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
}
},
"user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"id": 7,
"status": "common",
"created_at": "2021-06-09 16:41",
"time_ago": "1分钟前"
}
```
## 获取项目列表
获取项目列表,也可以更加相关条件过滤搜素

View File

@ -1,7 +1,7 @@
<!--
* @Date: 2021-03-01 10:35:21
* @LastEditors: viletyy
* @LastEditTime: 2021-06-03 10:18:53
* @LastEditTime: 2021-06-09 16:51:18
* @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md
-->
# Users
@ -1002,11 +1002,11 @@ await octokit.request('GET /api/users/:login/applied_messages.json')
|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_user.id |int |通知发起者的id |
|applied_user.type |string |通知发起者的类型 |
|applied_user.name |string |通知发起者的名称 |
|applied_user.login |string |通知发起者的标识 |
|applied_user.image_url |string |通知发起者头像 |
|applied_type |string |通知类型 |
|name |string | 通知内容 |
|viewed |string|是否已读waiting:未读,viewed:已读|
@ -1020,6 +1020,48 @@ await octokit.request('GET /api/users/:login/applied_messages.json')
{
"total_count": 5,
"applied_messages": [
{
"applied": {
"project": {
"id": 74,
"identifier": "hehuisssjssjjsjs",
"name": "hehuisssjssjjsjs",
"description": "wwww",
"is_public": false,
"owner": {
"id": 10,
"type": "User",
"name": "testforge1",
"login": "testforge1",
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
}
},
"user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"id": 6,
"status": "accepted",
"created_at": "2021-06-09 16:34",
"time_ago": "1分钟前"
},
"applied_user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"applied_type": "AppliedProject",
"name": "已通过你加入【hehuisssjssjjsjs】仓库的申请。",
"viewed": "waiting",
"status": "successed",
"created_at": "2021-06-09 16:34",
"time_ago": "1分钟前"
},
{
"applied": {
"project": {
@ -1344,4 +1386,240 @@ await octokit.request('GET /api/users/:login/applied_transfer_projects/:id/refus
"created_at": "2021-04-25 18:06",
"time_ago": "16小时前"
}
```
## 待办事项-项目申请
待办事项-项目申请
> 示例:
```shell
curl -X GET http://localhost:3000/api/users/yystopf/applied_projects.json
```
```javascript
await octokit.request('GET /api/users/:login/applied_projects.json')
```
### HTTP 请求
`GET /api/users/:login/applied_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 |申请创建者头像 |
> 返回的JSON示例:
```json
{
"total_count": 4,
"applied_transfer_projects": [
{
"project": {
"id": 74,
"identifier": "hehuisssjssjjsjs",
"name": "hehuisssjssjjsjs",
"description": "wwww",
"is_public": false,
"owner": {
"id": 10,
"type": "User",
"name": "testforge1",
"login": "testforge1",
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
}
},
"user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"id": 7,
"status": "common",
"created_at": "2021-06-09 16:41",
"time_ago": "7分钟前"
},
...
]
}
```
## 用户接受迁移
用户接受迁移
> 示例:
```shell
curl -X POST http://localhost:3000/api/users/yystopf/applied_projects/2/accept.json
```
```javascript
await octokit.request('GET /api/users/:login/applied_projects/:id/accept.json')
```
### HTTP 请求
`GET /api/users/:login/applied_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 |申请创建者头像 |
> 返回的JSON示例:
```json
{
"project": {
"id": 74,
"identifier": "hehuisssjssjjsjs",
"name": "hehuisssjssjjsjs",
"description": "wwww",
"is_public": false,
"owner": {
"id": 10,
"type": "User",
"name": "testforge1",
"login": "testforge1",
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
}
},
"user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"id": 7,
"status": "accept",
"created_at": "2021-06-09 16:41",
"time_ago": "7分钟前"
}
```
## 用户拒绝迁移
用户拒绝迁移
> 示例:
```shell
curl -X POST http://localhost:3000/api/users/yystopf/applied_projects/2/refuse.json
```
```javascript
await octokit.request('GET /api/users/:login/applied_projects/:id/refuse.json')
```
### HTTP 请求
`GET /api/users/:login/applied_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 |申请创建者头像 |
> 返回的JSON示例:
```json
{
"project": {
"id": 74,
"identifier": "hehuisssjssjjsjs",
"name": "hehuisssjssjjsjs",
"description": "wwww",
"is_public": false,
"owner": {
"id": 10,
"type": "User",
"name": "testforge1",
"login": "testforge1",
"image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png"
}
},
"user": {
"id": 6,
"type": "User",
"name": "何慧",
"login": "yystopf",
"image_url": "images/avatars/User/6?t=1622513134"
},
"id": 7,
"status": "accept",
"created_at": "2021-06-09 16:41",
"time_ago": "7分钟前"
}
```

View File

@ -23,7 +23,7 @@ module Projects
ActiveRecord::Base.transaction do
gitea_result = Gitea::Repository::Members::AddService.new(owner, project.identifier, collaborator.login, permission).call
if gitea_result.status == 204
project.add_member!(collaborator.id)
project.add_member!(collaborator.id, role_name)
end
fail!(nil)
end
@ -38,5 +38,20 @@ module Projects
@error = error
end
def role_name
case permission
when 'read'
'Reporter'
when 'write'
'Developer'
when 'admin'
'Manager'
when 'owner'
'Manager'
else
'Reporter'
end
end
end
end

View File

@ -0,0 +1,27 @@
class SendJoinProjectAppliedMessageJob < ApplicationJob
queue_as :default
def perform(applied_project, applied_user, message_status)
project = applied_project.project
return unless project.present?
return unless applied_user.present?
return unless applied_project.user.present?
AppliedMessage.find_or_create_by!(user_id: applied_project.user_id,
applied: applied_project,
status: message_status,
name: build_name(project.name, message_status),
applied_user_id: applied_user.id,
project_id: project.id)
end
private
def build_name(repo_name, message_status, applied_name="")
case message_status
when 'successed'
return "已通过你加入【#{repo_name}】仓库的申请。"
when 'failure'
return "已拒绝你加入【#{repo_name}】仓库的申请。"
end
""
end
end

View File

@ -7,6 +7,8 @@
# user_id :integer not null
# role :integer default("0")
# status :integer default("0")
# created_at :datetime
# updated_at :datetime
#
class AppliedProject < ApplicationRecord
@ -16,6 +18,7 @@ class AppliedProject < ApplicationRecord
has_many :applied_messages, as: :applied, dependent: :destroy
# has_many :forge_activities, as: :forge_act, dependent: :destroy
enum role: {manager: 3, developer: 4, reporter: 5}
enum status: {canceled: -1, common: 0, accepted: 1, refused: 2} # -1 已取消 0 待操作 1 已接收 2 已拒绝
end

View File

@ -1,41 +1,42 @@
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#
# == Schema Information
#
# Table name: attachments
#
# id :integer not null, primary key
# container_id :integer
# container_type :string(30)
# filename :string(255) default(""), not null
# disk_filename :string(255) default(""), not null
# filesize :integer default("0"), not null
# content_type :string(255) default("")
# digest :string(60) default(""), not null
# downloads :integer default("0"), not null
# author_id :integer default("0"), not null
# created_on :datetime
# description :text(65535)
# disk_directory :string(255)
# attachtype :integer default("1")
# is_public :integer default("1")
# copy_from :integer
# quotes :integer default("0")
# is_publish :integer default("1")
# publish_time :datetime
# resource_bank_id :integer
# unified_setting :boolean default("1")
# cloud_url :string(255) default("")
# course_second_category_id :integer default("0")
# delay_publish :boolean default("0")
#
# Indexes
#
# index_attachments_on_author_id (author_id)
# index_attachments_on_container_id_and_container_type (container_id,container_type)
# index_attachments_on_course_second_category_id (course_second_category_id)
# index_attachments_on_created_on (created_on)
# index_attachments_on_is_public (is_public)
# index_attachments_on_quotes (quotes)
#
class Attachment < ApplicationRecord
include BaseModel

View File

@ -46,6 +46,10 @@
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#

View File

@ -65,7 +65,7 @@ module ProjectOperable
if owner.is_a?(User)
managers.exists?(user_id: user.id)
elsif owner.is_a?(Organization)
managers.exists?(user_id: user.id) || owner.is_admin?(user.id)
managers.exists?(user_id: user.id) || owner.is_only_admin?(user.id)
else
false
end
@ -76,7 +76,7 @@ module ProjectOperable
if owner.is_a?(User)
developers.exists?(user_id: user.id)
elsif owner.is_a?(Organization)
developers.exists?(user_id: user.id) || owner.is_write?(user.id)
developers.exists?(user_id: user.id) || owner.is_only_write?(user.id)
else
false
end

View File

@ -6,7 +6,7 @@
# tracker_id :integer not null
# project_id :integer not null
# subject :string(255) default(""), not null
# description :text(65535)
# description :text(4294967295)
# due_date :date
# category_id :integer
# status_id :integer not null
@ -14,7 +14,6 @@
# priority_id :integer not null
# fixed_version_id :integer
# author_id :integer not null
# lock_version :integer default("0"), not null
# created_on :datetime
# updated_on :datetime
# start_date :date
@ -28,7 +27,7 @@
# closed_on :datetime
# project_issues_index :integer
# issue_type :string(255)
# token :string(255)
# token :integer default("0")
# issue_tags_value :string(255)
# is_lock :boolean default("0")
# issue_classify :string(255)

View File

@ -7,6 +7,7 @@
# content :text(65535)
# created_at :datetime not null
# updated_at :datetime not null
# is_secret :boolean default("0")
#
class License < ApplicationRecord

View File

@ -11,6 +11,7 @@
# course_group_id :integer default("0")
# is_collect :integer default("1")
# graduation_group_id :integer default("0")
# is_apply_signature :boolean default("0")
#
# Indexes
#

View File

@ -46,6 +46,10 @@
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#
@ -106,6 +110,14 @@ class Organization < Owner
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read write admin owner)}).present?
end
def is_only_admin?(user_id)
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(admin)}).present?
end
def is_only_write?(user_id)
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(write)}).present?
end
def is_only_read?(user_id)
team_users.joins(:team).where(user_id: user_id, teams: {authorize: %w(read)}).present?
end

View File

@ -1,19 +1,20 @@
# == Schema Information
#
# Table name: praise_treads
#
# id :integer not null, primary key
# user_id :integer not null
# praise_tread_object_id :integer
# praise_tread_object_type :string(255)
# praise_or_tread :integer default("1")
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# praise_tread (praise_tread_object_id,praise_tread_object_type)
#
# == Schema Information
#
# Table name: praise_treads
#
# id :integer not null, primary key
# user_id :integer not null
# praise_tread_object_id :integer
# praise_tread_object_type :string(255)
# praise_or_tread :integer default("1")
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# praise_tread (praise_tread_object_id,praise_tread_object_type)
#
class PraiseTread < ApplicationRecord
belongs_to :user

View File

@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# name :string(255) default(""), not null
# description :text(65535)
# description :text(4294967295)
# homepage :string(255) default("")
# is_public :boolean default("1"), not null
# parent_id :integer
@ -43,6 +43,19 @@
# watchers_count :integer default("0")
# issues_count :integer default("0")
# pull_requests_count :integer default("0")
# language :string(255)
# versions_count :integer default("0")
# issue_tags_count :integer default("0")
# closed_issues_count :integer default("0")
# open_devops :boolean default("0")
# gitea_webhook_id :integer
# open_devops_count :integer default("0")
# recommend :boolean default("0")
# platform :integer default("0")
# default_branch :string(255) default("master")
# website :string(255)
# order_index :integer default("0")
# lesson_url :string(255)
#
# Indexes
#

View File

@ -16,6 +16,11 @@
# head :string(255)
# base :string(255)
# issue_id :integer
# fork_project_id :integer
# is_original :boolean default("0")
# comments_count :integer default("0")
# commits_count :integer default("0")
# files_count :integer default("0")
#
class PullRequest < ApplicationRecord

View File

@ -46,6 +46,10 @@
# is_sync_pwd :boolean default("1")
# watchers_count :integer default("0")
# devops_step :integer default("0")
# sponsor_certification :integer default("0")
# sponsor_num :integer default("0")
# sponsored_num :integer default("0")
# award_time :datetime
#
# Indexes
#
@ -206,6 +210,13 @@ class User < Owner
return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
end
# 用户管理的所有项目
def full_admin_projects
normal_projects = Project.joins(members: :roles).where(roles: {name: 'Manager'}, members: {user_id: self.id}).to_sql
org_projects = Project.joins(teams: :team_users).where(teams: {authorize: %w(admin owner)}, team_users: {user_id: self.id}).to_sql
return Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
end
def name
login
end

View File

@ -0,0 +1,61 @@
class Projects::AcceptJoinService < ApplicationService
attr_accessor :applied_project, :owner
attr_reader :user, :project
def initialize(user, applied_project)
@user = user
@project = applied_project.project
@applied_project = applied_project
end
def call
Rails.logger.info("###### Project accept_join_service begin ######")
ActiveRecord::Base.transaction do
validate!
update_apply
operate_project_member
send_apply_message
end
Rails.logger.info("##### Project accept_join_service end ######")
return @applied_project
end
private
def permission
case @applied_project.role
when 'manager'
'admin'
when 'developer'
'write'
when 'reporter'
'read'
else
'read'
end
end
def validate!
raise Error, '该申请已经被接受' if @applied_project.accepted?
raise Error, '该申请不存在' unless @applied_project.present?
raise Error, '未拥有接受申请权限' unless is_permit_operator
end
def is_permit_operator
return @user.admin? || @project.manager?(@user)
end
def update_apply
@applied_project.update!(status: 'accepted')
end
def operate_project_member
Projects::AddMemberInteractor.call(@project.owner, @project, @user, permission)
end
def send_apply_message
SendJoinProjectAppliedMessageJob.perform_now(@applied_project, @user, 'successed')
end
end

View File

@ -9,26 +9,25 @@ class Projects::ApplyJoinService < ApplicationService
end
def call
validate!
# 项目报告人员直接加入项目
if params[:role] == 'reporter'
# Projects::JoinService.call(project, user, role: 'reporter')
return project
end
# if params[:role] == 'reporter'
# # Projects::JoinService.call(project, user, role: 'reporter')
# return project
# end
ActiveRecord::Base.transaction do
validate!
apply = user.applied_projects.create!(project: project, role: role_value)
apply
# apply.forge_activities.find_or_create_by!(user: user, project: project)
apply.forge_activities.find_or_create_by!(user: user, project: project)
notify_project_manager!(apply)
# notify_project_manager!(apply)
end
# notify_project_owner
ApplyJoinProjectNotifyJob.perform_later(user.id, project.id, role_value)
# ApplyJoinProjectNotifyJob.perform_later(user.id, project.id, role_value)
project
end
private
@ -43,7 +42,8 @@ class Projects::ApplyJoinService < ApplicationService
when 'manager' then 3
when 'developer' then 4
when 'reporter' then 5
else raise Error, '角色无效'
else
5
end
end
@ -74,12 +74,18 @@ class Projects::ApplyJoinService < ApplicationService
def validate!
# params check
raise Error, '邀请码不能为空' if params[:code].blank?
raise Error, '角色不能为空' if params[:role].blank?
raise Error, '角色无效' unless %w(manager developer reporter).include?(params[:role])
raise Error, '请输入6位项目邀请码' unless valid_invite_code( params[:code])
# logical check
raise Error, '邀请码无效' if project.blank?
raise Error, '您已在该项目中' if project.member?(user)
raise Error, '您已经提交过申请' if user.applied_projects.pending.exists?(project: project)
raise Error, '您已是项目成员' if project.member?(user)
raise Error, '您已经提交过申请' if user.applied_projects.common.exists?(project: project)
end
def valid_invite_code(str)
if (str =~ /^[A-Za-z0-9]{6}+$/)
return true
end
return false
end
end

View File

@ -0,0 +1,39 @@
class Projects::RefuseJoinService < ApplicationService
attr_accessor :applied_project, :owner
attr_reader :user, :project
def initialize(user, applied_project)
@user = user
@project = applied_project.project
@applied_project = applied_project
end
def call
Rails.logger.info("###### Project refuse_join_service begin ######")
validate!
update_apply
send_apply_message
Rails.logger.info("###### Project refuse_join_service end ######")
return @applied_project
end
private
def validate!
raise Error, '该申请已被拒绝' if @applied_project.refused?
raise Error, '该申请不存在' unless @applied_project.present?
raise Error, '未拥有接受申请权限' unless is_permit_operator
end
def is_permit_operator
return @user.admin? || @project.manager?(@user)
end
def update_apply
@applied_project.update!(status: 'refused')
end
def send_apply_message
SendJoinProjectAppliedMessageJob.perform_now(@applied_project, @user, 'failure')
end
end

View File

@ -0,0 +1,18 @@
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.id object.id
json.status object.status
json.created_at format_time(object.created_at)
json.time_ago time_from_now(object.created_at)

View File

@ -0,0 +1 @@
json.partial! "detail", locals: {object: @applied_project}

View File

@ -13,7 +13,12 @@
# json.partial! "/users/user_simple", locals: {user: object.user}
# end
json.applied do
json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied}
case object.applied_type
when 'AppliedTransferProject'
json.partial! "/projects/applied_transfer_projects/detail", locals: {object: object.applied}
when 'AppliedProject'
json.partial! "/applied_projects/detail", locals: {object: object.applied}
end
end
json.applied_user do
json.partial! "/users/user_simple", locals: {user: object.applied_user}

View File

@ -0,0 +1 @@
json.partial! "/applied_projects/detail", locals: {object: @applied_project}

View File

@ -0,0 +1,4 @@
json.total_count @applied_projects.total_count
json.applied_projects @applied_projects do |apply|
json.partial! "/applied_projects/detail", locals: {object: apply}
end

View File

@ -0,0 +1 @@
json.partial! "/applied_projects/detail", locals: {object: @applied_project}

View File

@ -148,6 +148,8 @@ Rails.application.routes.draw do
resources :issue_depends, only: [:create, :destroy]
end
resources :applied_projects, only: [:create]
resources :project_categories, only: [:index, :show] do
get :group_list, on: :collection
end
@ -266,6 +268,12 @@ Rails.application.routes.draw do
post :refuse
end
end
resources :applied_projects, only: [:index] do
member do
post :accept
post :refuse
end
end
resources :headmaps, only: [:index]
resources :is_pinned_projects, only: [:index, :update] do
collection do

View File

@ -0,0 +1,5 @@
class AddTimestampToAppliedProjects < ActiveRecord::Migration[5.2]
def change
add_timestamps(:applied_projects, null: true)
end
end

View File

@ -373,11 +373,23 @@
<li>
<a href="#5e6ed41015" class="toc-h2 toc-link" data-title="用户拒绝迁移">用户拒绝迁移</a>
</li>
<li>
<a href="#ba97e431b8" class="toc-h2 toc-link" data-title="待办事项-项目申请">待办事项-项目申请</a>
</li>
<li>
<a href="#db5a40a55d-2" class="toc-h2 toc-link" data-title="用户接受迁移">用户接受迁移</a>
</li>
<li>
<a href="#5e6ed41015-2" class="toc-h2 toc-link" data-title="用户拒绝迁移">用户拒绝迁移</a>
</li>
</ul>
</li>
<li>
<a href="#projects" class="toc-h1 toc-link" data-title="Projects">Projects</a>
<ul class="toc-list-h2">
<li>
<a href="#ac55469b06" class="toc-h2 toc-link" data-title="申请加入项目">申请加入项目</a>
</li>
<li>
<a href="#bfdfb34952" class="toc-h2 toc-link" data-title="获取项目列表">获取项目列表</a>
</li>
@ -617,7 +629,7 @@ Success — a happy kitten is an authenticated kitten!
<!--
* @Date: 2021-03-01 10:35:21
* @LastEditors: viletyy
* @LastEditTime: 2021-06-03 10:18:53
* @LastEditTime: 2021-06-09 16:51:18
* @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md
-->
<h1 id='users'>Users</h1><h2 id='1ae74893b1'>获取当前登陆用户信息</h2>
@ -2016,29 +2028,29 @@ Success — a happy kitten is an authenticated kitten!
<td>通知主体的迁移创建者头像</td>
</tr>
<tr>
<td>applied.owner.id</td>
<td>applied_user.id</td>
<td>int</td>
<td>通知主体的迁移接受者的id</td>
<td>通知发起者的id</td>
</tr>
<tr>
<td>applied.owner.type</td>
<td>applied_user.type</td>
<td>string</td>
<td>通知主体的迁移接受者的类型</td>
<td>通知发起者的类型</td>
</tr>
<tr>
<td>applied.owner.name</td>
<td>applied_user.name</td>
<td>string</td>
<td>通知主体的迁移接受者的名称</td>
<td>通知发起者的名称</td>
</tr>
<tr>
<td>applied.owner.login</td>
<td>applied_user.login</td>
<td>string</td>
<td>通知主体的迁移接受者的标识</td>
<td>通知发起者的标识</td>
</tr>
<tr>
<td>applied.owner.image_url</td>
<td>applied_user.image_url</td>
<td>string</td>
<td>通知主体的迁移接受者头像</td>
<td>通知发起者头像</td>
</tr>
<tr>
<td>applied_type</td>
@ -2073,6 +2085,48 @@ Success — a happy kitten is an authenticated kitten!
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"total_count"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w">
</span><span class="nl">"applied_messages"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"applied"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">74</span><span class="p">,</span><span class="w">
</span><span class="nl">"identifier"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"wwww"</span><span class="p">,</span><span class="w">
</span><span class="nl">"is_public"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"accepted"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:34"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1分钟前"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"applied_user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"applied_type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"AppliedProject"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"已通过你加入【hehuisssjssjjsjs】仓库的申请。"</span><span class="p">,</span><span class="w">
</span><span class="nl">"viewed"</span><span class="p">:</span><span class="w"> </span><span class="s2">"waiting"</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"successed"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:34"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1分钟前"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"applied"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
@ -2699,7 +2753,660 @@ Success — a happy kitten is an authenticated kitten!
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-04-25 18:06"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"16小时前"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h1 id='projects'>Projects</h1><h2 id='bfdfb34952'>获取项目列表</h2>
</span></code></pre></div><h2 id='ba97e431b8'>待办事项-项目申请</h2>
<p>待办事项-项目申请</p>
<blockquote>
<p>示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/applied_projects.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-16'>HTTP 请求</h3>
<p><code>GET /api/users/:login/applied_projects.json</code></p>
<h3 id='aa883f5d52-13'>请求字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>login</td>
<td>string</td>
<td>用户标识</td>
</tr>
</tbody></table>
<h3 id='7447e4874e-13'>返回字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
<tr>
<td>status</td>
<td>string</td>
<td>申请状态canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝</td>
</tr>
<tr>
<td>time_ago</td>
<td>string</td>
<td>申请创建的时间</td>
</tr>
<tr>
<td>project.id</td>
<td>int</td>
<td>申请项目的id</td>
</tr>
<tr>
<td>project.identifier</td>
<td>string</td>
<td>申请项目的标识</td>
</tr>
<tr>
<td>project.name</td>
<td>string</td>
<td>申请项目的名称</td>
</tr>
<tr>
<td>project.description</td>
<td>string</td>
<td>申请项目的描述</td>
</tr>
<tr>
<td>project.is_public</td>
<td>bool</td>
<td>申请项目是否公开</td>
</tr>
<tr>
<td>project.owner.id</td>
<td>bool</td>
<td>申请项目拥有者id</td>
</tr>
<tr>
<td>project.owner.type</td>
<td>string</td>
<td>申请项目拥有者类型</td>
</tr>
<tr>
<td>project.owner.name</td>
<td>string</td>
<td>申请项目拥有者昵称</td>
</tr>
<tr>
<td>project.owner.login</td>
<td>string</td>
<td>申请项目拥有者标识</td>
</tr>
<tr>
<td>project.owner.image_url</td>
<td>string</td>
<td>申请项目拥有者头像</td>
</tr>
<tr>
<td>user.id</td>
<td>int</td>
<td>申请创建者的id</td>
</tr>
<tr>
<td>user.type</td>
<td>string</td>
<td>申请创建者的类型</td>
</tr>
<tr>
<td>user.name</td>
<td>string</td>
<td>申请创建者的名称</td>
</tr>
<tr>
<td>user.login</td>
<td>string</td>
<td>申请创建者的标识</td>
</tr>
<tr>
<td>user.image_url</td>
<td>string</td>
<td>申请创建者头像</td>
</tr>
</tbody></table>
<blockquote>
<p>返回的JSON示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"total_count"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w">
</span><span class="nl">"applied_transfer_projects"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">74</span><span class="p">,</span><span class="w">
</span><span class="nl">"identifier"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"wwww"</span><span class="p">,</span><span class="w">
</span><span class="nl">"is_public"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"common"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:41"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"7分钟前"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h2 id='db5a40a55d-2'>用户接受迁移</h2>
<p>用户接受迁移</p>
<blockquote>
<p>示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_projects/2/accept.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects/:id/accept.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-17'>HTTP 请求</h3>
<p><code>GET /api/users/:login/applied_projects/:id/accept.json</code></p>
<h3 id='aa883f5d52-14'>请求字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>login</td>
<td>string</td>
<td>用户标识</td>
</tr>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
</tbody></table>
<h3 id='7447e4874e-14'>返回字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
<tr>
<td>status</td>
<td>string</td>
<td>申请状态canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝</td>
</tr>
<tr>
<td>time_ago</td>
<td>string</td>
<td>申请创建的时间</td>
</tr>
<tr>
<td>project.id</td>
<td>int</td>
<td>申请项目的id</td>
</tr>
<tr>
<td>project.identifier</td>
<td>string</td>
<td>申请项目的标识</td>
</tr>
<tr>
<td>project.name</td>
<td>string</td>
<td>申请项目的名称</td>
</tr>
<tr>
<td>project.description</td>
<td>string</td>
<td>申请项目的描述</td>
</tr>
<tr>
<td>project.is_public</td>
<td>bool</td>
<td>申请项目是否公开</td>
</tr>
<tr>
<td>project.owner.id</td>
<td>bool</td>
<td>申请项目拥有者id</td>
</tr>
<tr>
<td>project.owner.type</td>
<td>string</td>
<td>申请项目拥有者类型</td>
</tr>
<tr>
<td>project.owner.name</td>
<td>string</td>
<td>申请项目拥有者昵称</td>
</tr>
<tr>
<td>project.owner.login</td>
<td>string</td>
<td>申请项目拥有者标识</td>
</tr>
<tr>
<td>project.owner.image_url</td>
<td>string</td>
<td>申请项目拥有者头像</td>
</tr>
<tr>
<td>user.id</td>
<td>int</td>
<td>申请创建者的id</td>
</tr>
<tr>
<td>user.type</td>
<td>string</td>
<td>申请创建者的类型</td>
</tr>
<tr>
<td>user.name</td>
<td>string</td>
<td>申请创建者的名称</td>
</tr>
<tr>
<td>user.login</td>
<td>string</td>
<td>申请创建者的标识</td>
</tr>
<tr>
<td>user.image_url</td>
<td>string</td>
<td>申请创建者头像</td>
</tr>
</tbody></table>
<blockquote>
<p>返回的JSON示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">74</span><span class="p">,</span><span class="w">
</span><span class="nl">"identifier"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"wwww"</span><span class="p">,</span><span class="w">
</span><span class="nl">"is_public"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"accept"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:41"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"7分钟前"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h2 id='5e6ed41015-2'>用户拒绝迁移</h2>
<p>用户拒绝迁移</p>
<blockquote>
<p>示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_projects/2/refuse.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects/:id/refuse.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-18'>HTTP 请求</h3>
<p><code>GET /api/users/:login/applied_projects/:id/refuse.json</code></p>
<h3 id='aa883f5d52-15'>请求字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>login</td>
<td>string</td>
<td>用户标识</td>
</tr>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
</tbody></table>
<h3 id='7447e4874e-15'>返回字段说明:</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
<tr>
<td>status</td>
<td>string</td>
<td>申请状态canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝</td>
</tr>
<tr>
<td>time_ago</td>
<td>string</td>
<td>申请创建的时间</td>
</tr>
<tr>
<td>project.id</td>
<td>int</td>
<td>申请项目的id</td>
</tr>
<tr>
<td>project.identifier</td>
<td>string</td>
<td>申请项目的标识</td>
</tr>
<tr>
<td>project.name</td>
<td>string</td>
<td>申请项目的名称</td>
</tr>
<tr>
<td>project.description</td>
<td>string</td>
<td>申请项目的描述</td>
</tr>
<tr>
<td>project.is_public</td>
<td>bool</td>
<td>申请项目是否公开</td>
</tr>
<tr>
<td>project.owner.id</td>
<td>bool</td>
<td>申请项目拥有者id</td>
</tr>
<tr>
<td>project.owner.type</td>
<td>string</td>
<td>申请项目拥有者类型</td>
</tr>
<tr>
<td>project.owner.name</td>
<td>string</td>
<td>申请项目拥有者昵称</td>
</tr>
<tr>
<td>project.owner.login</td>
<td>string</td>
<td>申请项目拥有者标识</td>
</tr>
<tr>
<td>project.owner.image_url</td>
<td>string</td>
<td>申请项目拥有者头像</td>
</tr>
<tr>
<td>user.id</td>
<td>int</td>
<td>申请创建者的id</td>
</tr>
<tr>
<td>user.type</td>
<td>string</td>
<td>申请创建者的类型</td>
</tr>
<tr>
<td>user.name</td>
<td>string</td>
<td>申请创建者的名称</td>
</tr>
<tr>
<td>user.login</td>
<td>string</td>
<td>申请创建者的标识</td>
</tr>
<tr>
<td>user.image_url</td>
<td>string</td>
<td>申请创建者头像</td>
</tr>
</tbody></table>
<blockquote>
<p>返回的JSON示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">74</span><span class="p">,</span><span class="w">
</span><span class="nl">"identifier"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"wwww"</span><span class="p">,</span><span class="w">
</span><span class="nl">"is_public"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"accept"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:41"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"7分钟前"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h1 id='projects'>Projects</h1><h2 id='ac55469b06'>申请加入项目</h2>
<p>申请加入项目</p>
<blockquote>
<p>示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/applied_projects.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/appliedr_projects.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http'>HTTP 请求</h3>
<p><code>POST /api/applied_projects.json</code></p>
<h3 id='1f9ac54b15'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
<th>必选</th>
<th>默认</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>applied_project.code</td>
<td></td>
<td></td>
<td>string</td>
<td>邀请码</td>
</tr>
<tr>
<td>applied_project.role</td>
<td></td>
<td></td>
<td>string</td>
<td>项目权限reporter: 报告者, developer: 开发者manager管理员</td>
</tr>
</tbody></table>
<blockquote>
<p>请求的JSON示例</p>
</blockquote>
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"applied_project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"code"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1una34"</span><span class="p">,</span><span class="w">
</span><span class="nl">"role"</span><span class="p">:</span><span class="w"> </span><span class="s2">"developer"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h3 id='b302a98fa6'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>字段说明</th>
</tr>
</thead><tbody>
<tr>
<td>id</td>
<td>int</td>
<td>申请id</td>
</tr>
<tr>
<td>status</td>
<td>string</td>
<td>申请状态canceled:取消,common:正在申请, accept:已接受,refuse:已拒绝</td>
</tr>
<tr>
<td>time_ago</td>
<td>string</td>
<td>项目申请创建的时间</td>
</tr>
<tr>
<td>project.id</td>
<td>int</td>
<td>申请项目的id</td>
</tr>
<tr>
<td>project.identifier</td>
<td>string</td>
<td>申请项目的标识</td>
</tr>
<tr>
<td>project.name</td>
<td>string</td>
<td>申请项目的名称</td>
</tr>
<tr>
<td>project.description</td>
<td>string</td>
<td>申请项目的描述</td>
</tr>
<tr>
<td>project.is_public</td>
<td>bool</td>
<td>申请项目是否公开</td>
</tr>
<tr>
<td>project.owner.id</td>
<td>bool</td>
<td>申请项目拥有者id</td>
</tr>
<tr>
<td>project.owner.type</td>
<td>string</td>
<td>申请项目拥有者类型</td>
</tr>
<tr>
<td>project.owner.name</td>
<td>string</td>
<td>申请项目拥有者昵称</td>
</tr>
<tr>
<td>project.owner.login</td>
<td>string</td>
<td>申请项目拥有者标识</td>
</tr>
<tr>
<td>project.owner.image_url</td>
<td>string</td>
<td>申请项目拥有者头像</td>
</tr>
<tr>
<td>user.id</td>
<td>int</td>
<td>申请创建者的id</td>
</tr>
<tr>
<td>user.type</td>
<td>string</td>
<td>申请创建者的类型</td>
</tr>
<tr>
<td>user.name</td>
<td>string</td>
<td>申请创建者的名称</td>
</tr>
<tr>
<td>user.login</td>
<td>string</td>
<td>申请创建者的标识</td>
</tr>
<tr>
<td>user.image_url</td>
<td>string</td>
<td>申请创建者头像</td>
</tr>
</tbody></table>
<blockquote>
<p>返回的JSON示例:</p>
</blockquote>
<div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w">
</span><span class="nl">"project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">74</span><span class="p">,</span><span class="w">
</span><span class="nl">"identifier"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"hehuisssjssjjsjs"</span><span class="p">,</span><span class="w">
</span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"wwww"</span><span class="p">,</span><span class="w">
</span><span class="nl">"is_public"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"何慧"</span><span class="p">,</span><span class="w">
</span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"images/avatars/User/6?t=1622513134"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
</span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"common"</span><span class="p">,</span><span class="w">
</span><span class="nl">"created_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2021-06-09 16:41"</span><span class="p">,</span><span class="w">
</span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1分钟前"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div><h2 id='bfdfb34952'>获取项目列表</h2>
<p>获取项目列表,也可以更加相关条件过滤搜素</p>
<blockquote>
@ -2710,9 +3417,9 @@ Success — a happy kitten is an authenticated kitten!
<span class="nt">-d</span> <span class="s2">"limit=5"</span> <span class="se">\</span>
http://localhost:3000/api/projects | jq
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/projects</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http'>HTTP 请求</h3>
</code></pre></div><h3 id='http-2'>HTTP 请求</h3>
<p><code>GET api/projects</code></p>
<h3 id='1f9ac54b15'>请求参数</h3>
<h3 id='1f9ac54b15-2'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -2779,7 +3486,7 @@ http://localhost:3000/api/projects | jq
<td>项目类型, 取值为common、mirror; common:开源托管项目, mirror:开源镜像项目</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6'>返回字段说明</h3>
<h3 id='b302a98fa6-2'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -2931,9 +3638,9 @@ Remember — a happy kitten is an authenticated kitten!
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
http://localhost:3000/api/projects/recommend | jq
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/projects/recommend.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-2'>HTTP 请求</h3>
</code></pre></div><h3 id='http-3'>HTTP 请求</h3>
<p><code>GET api/projects/recommend</code></p>
<h3 id='b302a98fa6-2'>返回字段说明</h3>
<h3 id='b302a98fa6-3'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3067,9 +3774,9 @@ Remember — a happy kitten is an authenticated kitten!
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
http://localhost:3000/api/yystopf/ceshi/menu_list | jq
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/yystopf/ceshi/menu_list</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-3'>HTTP 请求</h3>
</code></pre></div><h3 id='http-4'>HTTP 请求</h3>
<p><code>GET api/:owner/:repo/menu_list</code></p>
<h3 id='1f9ac54b15-2'>请求参数</h3>
<h3 id='1f9ac54b15-3'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3094,7 +3801,7 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq
<td>项目标识identifier</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-3'>返回字段说明</h3>
<h3 id='b302a98fa6-4'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3135,9 +3842,9 @@ http://localhost:3000/api/yystopf/ceshi/menu_list | jq
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
http://localhost:3000/api/jasder/forgeplus/about | jq
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/jasder/forgeplus/about</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-4'>HTTP 请求</h3>
</code></pre></div><h3 id='http-5'>HTTP 请求</h3>
<p><code>GET api/:owner/:repo/about</code></p>
<h3 id='1f9ac54b15-3'>请求参数</h3>
<h3 id='1f9ac54b15-4'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3162,7 +3869,7 @@ http://localhost:3000/api/jasder/forgeplus/about | jq
<td>项目标识identifier</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-4'>返回字段说明</h3>
<h3 id='b302a98fa6-5'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3208,7 +3915,7 @@ Remember — a happy kitten is an authenticated kitten!
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
http://localhost:3000/api/yystopf/ceshi/project_units.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/yystopf/ceshi/project_units</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-5'>HTTP 请求</h3>
</code></pre></div><h3 id='http-6'>HTTP 请求</h3>
<p><code>GET /api/yystopf/ceshi/project_units</code></p>
<h3 id='7447e4874e'>返回字段说明:</h3>
<table><thead>
@ -3251,9 +3958,9 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json
<span class="nt">-d</span> <span class="s2">"{ </span><span class="se">\"</span><span class="s2">unit_typs</span><span class="se">\"</span><span class="s2">: [</span><span class="se">\"</span><span class="s2">code</span><span class="se">\"</span><span class="s2">, </span><span class="se">\"</span><span class="s2">pulls</span><span class="se">\"</span><span class="s2">]}"</span> <span class="se">\</span>
http://localhost:3000/api/yystopf/ceshi/project_units.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/yystopf/ceshi/project_units</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-6'>HTTP 请求</h3>
</code></pre></div><h3 id='http-7'>HTTP 请求</h3>
<p><code>POST /api/yystopf/ceshi/project_units</code></p>
<h3 id='1f9ac54b15-4'>请求参数</h3>
<h3 id='1f9ac54b15-5'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3315,9 +4022,9 @@ http://localhost:3000/api/yystopf/ceshi/project_units.json
<span class="nt">-d</span> <span class="s2">"license_id=1"</span> <span class="se">\</span>
http://localhost:3000/api/projects.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/projects.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-7'>HTTP 请求</h3>
</code></pre></div><h3 id='http-8'>HTTP 请求</h3>
<p><code>POST api/projects</code></p>
<h3 id='1f9ac54b15-5'>请求参数</h3>
<h3 id='1f9ac54b15-6'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3391,7 +4098,7 @@ http://localhost:3000/api/projects.json
<td>项目是否私有, true为私有false: 公开,默认为公开</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-5'>返回字段说明</h3>
<h3 id='b302a98fa6-6'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3433,9 +4140,9 @@ http://localhost:3000/api/projects.json
<span class="nt">-d</span> <span class="s2">"project_language_id=2"</span> <span class="se">\</span>
http://localhost:3000/api/projects/migrate.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/projects/migrate.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-8'>HTTP 请求</h3>
</code></pre></div><h3 id='http-9'>HTTP 请求</h3>
<p><code>POST api/projects/migrate.json</code></p>
<h3 id='1f9ac54b15-6'>请求参数</h3>
<h3 id='1f9ac54b15-7'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3523,7 +4230,7 @@ http://localhost:3000/api/projects/migrate.json
<td>项目是否私有, true为私有false: 非私有,默认为公开</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-6'>返回字段说明</h3>
<h3 id='b302a98fa6-7'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3558,9 +4265,9 @@ http://localhost:3000/api/projects/migrate.json
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/repositories/1244/sync_mirror.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/repositories/1244/sync_mirror.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-9'>HTTP 请求</h3>
</code></pre></div><h3 id='http-10'>HTTP 请求</h3>
<p><code>POST api/repositories/:id/sync_mirror.json</code></p>
<h3 id='1f9ac54b15-7'>请求参数</h3>
<h3 id='1f9ac54b15-8'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3578,7 +4285,7 @@ http://localhost:3000/api/projects/migrate.json
<td>仓库id</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-7'>返回字段说明</h3>
<h3 id='b302a98fa6-8'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3613,9 +4320,9 @@ http://localhost:3000/api/projects/migrate.json
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/jasder/forgeplus/forks.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/jaser/jasder_test/forks.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-10'>HTTP 请求</h3>
</code></pre></div><h3 id='http-11'>HTTP 请求</h3>
<p><code>POST api/:owner/:repo/forks.json</code></p>
<h3 id='1f9ac54b15-8'>请求参数</h3>
<h3 id='1f9ac54b15-9'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3640,7 +4347,7 @@ http://localhost:3000/api/projects/migrate.json
<td>项目标识identifier</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-8'>返回字段说明</h3>
<h3 id='b302a98fa6-9'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3676,9 +4383,9 @@ http://localhost:3000/api/projects/migrate.json
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET <span class="se">\</span>
http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizations.json | jq
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/:owner/:repo/applied_transfer_projects/organizations</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-11'>HTTP 请求</h3>
</code></pre></div><h3 id='http-12'>HTTP 请求</h3>
<p><code>GET api/:owner/:repo/applied_transfer_projects/organizations</code></p>
<h3 id='1f9ac54b15-9'>请求参数</h3>
<h3 id='1f9ac54b15-10'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3703,7 +4410,7 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
<td>项目标识identifier</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-9'>返回字段说明</h3>
<h3 id='b302a98fa6-10'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3770,9 +4477,9 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/:owner/:repo/applied_transfer_projects.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-12'>HTTP 请求</h3>
</code></pre></div><h3 id='http-13'>HTTP 请求</h3>
<p><code>POST /api/:owner/:repo/applied_transfer_projects.json</code></p>
<h3 id='1f9ac54b15-10'>请求参数</h3>
<h3 id='1f9ac54b15-11'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3804,7 +4511,7 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
<td>迁移对象标识</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-10'>返回字段说明</h3>
<h3 id='b302a98fa6-11'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>
@ -3974,9 +4681,9 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
</blockquote>
<div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/cancel.json
</code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/:owner/:repo/applied_transfer_projects/cancel.json</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div><h3 id='http-13'>HTTP 请求</h3>
</code></pre></div><h3 id='http-14'>HTTP 请求</h3>
<p><code>POST /api/:owner/:repo/applied_transfer_projects/cancel.json</code></p>
<h3 id='1f9ac54b15-11'>请求参数</h3>
<h3 id='1f9ac54b15-12'>请求参数</h3>
<table><thead>
<tr>
<th>参数</th>
@ -4001,7 +4708,7 @@ http://localhost:3000/api/ceshi1/ceshi_repo1/applied_transfer_projects/organizat
<td>项目标识identifier</td>
</tr>
</tbody></table>
<h3 id='b302a98fa6-11'>返回字段说明</h3>
<h3 id='b302a98fa6-12'>返回字段说明</h3>
<table><thead>
<tr>
<th>参数</th>