diff --git a/Gemfile b/Gemfile
index 713eb860..3da6f273 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,130 +1,138 @@
-source 'https://gems.ruby-china.com'
-git_source(:github) { |repo| "https://github.com/#{repo}.git" }
-
-gem 'rails', '~> 5.2.0'
-gem 'mysql2', '>= 0.4.4', '< 0.6.0'
-gem 'puma', '~> 3.11'
-gem 'sass-rails', '~> 5.0'
-gem 'uglifier', '>= 1.3.0'
-
-# gem 'coffee-rails', '~> 4.2'
-gem 'turbolinks', '~> 5'
-gem 'jbuilder', '~> 2.5'
-gem 'groupdate', '~> 4.1.0'
-gem 'chartkick'
-gem 'grape-entity', '~> 0.7.1'
-gem 'kaminari', '~> 1.1', '>= 1.1.1'
-
-gem 'bootsnap', '>= 1.1.0', require: false
-
-gem 'chinese_pinyin'
-
-gem 'rack-cors'
-gem 'redis-rails'
-gem 'roo-xls'
-gem 'simple_xlsx_reader'
-
-gem 'rubyzip'
-
-gem 'spreadsheet'
-gem 'ruby-ole'
-# 导出为xlsx
-gem 'axlsx', '~> 3.0.0.pre'
-gem 'axlsx_rails', '~> 0.5.2'
-
-gem 'oauth2'
-#导出为pdf
-gem 'pdfkit'
-gem 'wkhtmltopdf-binary'
-# gem 'request_store'
-#gem 'iconv'
-# markdown 转html
-gem 'redcarpet', '~> 3.4'
-
-gem 'rqrcode', '~> 0.10.1'
-gem 'rqrcode_png'
-
-gem 'acts-as-taggable-on', '~> 6.0'
-
-# a tree structure
-gem 'ancestry'
-gem 'acts_as_list'
-gem 'omniauth-cas'
-
-# profiler Middleware
-gem 'rack-mini-profiler'
-
-# object-based searching
-gem 'ransack'
-
-group :development, :test do
- gem 'rspec-rails', '~> 3.8'
-end
-
-group :development do
- gem 'prettier'
- gem 'rubocop', '~> 0.52.0'
- gem 'solargraph', '~> 0.38.0'
- gem 'awesome_print'
- gem 'web-console', '>= 3.3.0'
- gem 'listen', '>= 3.0.5', '< 3.2'
- gem 'spring'
- gem 'spring-watcher-listen', '~> 2.0.0'
- gem "annotate", "~> 2.6.0"
-end
-
-group :test do
- gem 'capybara', '>= 2.15', '< 4.0'
- gem 'selenium-webdriver'
- gem 'chromedriver-helper'
-end
-
-gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
-
-#编码检测
-gem 'rchardet', '~> 1.8'
-
-# http client
-gem 'faraday', '~> 0.15.4'
-
-# view
-gem 'active_decorator'
-gem 'bootstrap', '~> 4.3.1'
-gem 'jquery-rails'
-gem 'simple_form'
-gem 'font-awesome-sass', '4.7.0'
-
-# i18n
-gem 'rails-i18n', '~> 5.1'
-
-# job
-gem 'sidekiq'
-gem 'sinatra'
-gem "sidekiq-cron", "~> 1.1"
-
-# batch insert
-gem 'bulk_insert'
-
-# elasticsearch
-gem 'searchkick'
-
-gem 'aasm'
-gem 'enumerize'
-
-gem 'diffy'
-
-gem 'deep_cloneable', '~> 3.0.0'
-
-# oauth2
-gem 'omniauth', '~> 1.9.0'
-gem 'omniauth-oauth2', '~> 1.6.0'
-
-# global var
-gem 'request_store'
-
-# 敏感词汇
-gem 'harmonious_dictionary', '~> 0.0.1'
-
-gem 'parallel', '~> 1.19', '>= 1.19.1'
-
-gem 'letter_avatar'
+source 'https://gems.ruby-china.com'
+git_source(:github) { |repo| "https://github.com/#{repo}.git" }
+
+gem 'rails', '~> 5.2.0'
+gem 'mysql2', '>= 0.4.4', '< 0.6.0'
+gem 'puma', '~> 3.11'
+gem 'sass-rails', '~> 5.0'
+gem 'uglifier', '>= 1.3.0'
+
+# gem 'coffee-rails', '~> 4.2'
+gem 'turbolinks', '~> 5'
+gem 'jbuilder', '~> 2.5'
+gem 'groupdate', '~> 4.1.0'
+gem 'chartkick'
+gem 'grape-entity', '~> 0.7.1'
+gem 'kaminari', '~> 1.1', '>= 1.1.1'
+
+gem 'bootsnap', '>= 1.1.0', require: false
+
+gem 'chinese_pinyin'
+
+gem 'rack-cors'
+gem 'redis-rails'
+gem 'roo-xls'
+gem 'simple_xlsx_reader'
+
+gem 'rubyzip'
+
+gem 'spreadsheet'
+gem 'ruby-ole'
+# 导出为xlsx
+gem 'axlsx', '~> 3.0.0.pre'
+gem 'axlsx_rails', '~> 0.5.2'
+
+gem 'oauth2'
+#导出为pdf
+gem 'pdfkit'
+gem 'wkhtmltopdf-binary'
+# gem 'request_store'
+#gem 'iconv'
+# markdown 转html
+gem 'redcarpet', '~> 3.4'
+
+gem 'rqrcode', '~> 0.10.1'
+gem 'rqrcode_png'
+
+gem 'acts-as-taggable-on', '~> 6.0'
+
+# a tree structure
+gem 'ancestry'
+gem 'acts_as_list'
+gem 'omniauth-cas'
+
+# profiler Middleware
+gem 'rack-mini-profiler'
+
+# object-based searching
+gem 'ransack'
+
+group :development, :test do
+ gem 'rspec-rails', '~> 3.8'
+end
+
+group :development do
+ gem 'prettier'
+ gem 'rubocop', '~> 0.52.0'
+ gem 'solargraph', '~> 0.38.0'
+ gem 'awesome_print'
+ gem 'web-console', '>= 3.3.0'
+ gem 'listen', '>= 3.0.5', '< 3.2'
+ gem 'spring'
+ gem 'spring-watcher-listen', '~> 2.0.0'
+ gem "annotate", "~> 2.6.0"
+end
+
+group :test do
+ gem 'capybara', '>= 2.15', '< 4.0'
+ gem 'selenium-webdriver'
+ gem 'chromedriver-helper'
+end
+
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+#编码检测
+gem 'rchardet', '~> 1.8'
+
+# http client
+gem 'faraday', '~> 0.15.4'
+
+# view
+gem 'active_decorator'
+gem 'bootstrap', '~> 4.3.1'
+gem 'jquery-rails'
+gem 'simple_form'
+gem 'font-awesome-sass', '4.7.0'
+
+# i18n
+gem 'rails-i18n', '~> 5.1'
+
+# job
+gem 'sidekiq'
+gem 'sinatra'
+gem "sidekiq-cron", "~> 1.1"
+
+# batch insert
+gem 'bulk_insert'
+
+# elasticsearch
+gem 'searchkick'
+
+gem 'aasm'
+gem 'enumerize'
+
+gem 'diffy'
+
+gem 'deep_cloneable', '~> 3.0.0'
+
+# oauth2
+gem 'omniauth', '~> 1.9.0'
+gem 'omniauth-oauth2', '~> 1.6.0'
+
+# global var
+gem 'request_store'
+
+# 敏感词汇
+gem 'harmonious_dictionary', '~> 0.0.1'
+
+gem 'parallel', '~> 1.19', '>= 1.19.1'
+
+gem 'letter_avatar'
+
+gem 'jwt'
+
+gem 'doorkeeper'
+
+gem 'doorkeeper-jwt'
+
+gem 'gitea-client', '~> 0.10.2'
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index b1dc2cca..e27c504a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -106,6 +106,10 @@ GEM
activerecord (>= 3.1.0, < 7)
diff-lcs (1.3)
diffy (3.3.0)
+ doorkeeper (5.5.1)
+ railties (>= 5)
+ doorkeeper-jwt (0.4.1)
+ jwt (>= 2.1)
e2mmap (0.1.0)
elasticsearch (7.5.0)
elasticsearch-api (= 7.5.0)
@@ -450,6 +454,8 @@ DEPENDENCIES
chromedriver-helper
deep_cloneable (~> 3.0.0)
diffy
+ doorkeeper
+ doorkeeper-jwt
enumerize
faraday (~> 0.15.4)
font-awesome-sass (= 4.7.0)
@@ -458,6 +464,7 @@ DEPENDENCIES
harmonious_dictionary (~> 0.0.1)
jbuilder (~> 2.5)
jquery-rails
+ jwt
kaminari (~> 1.1, >= 1.1.1)
letter_avatar
listen (>= 3.0.5, < 3.2)
diff --git a/app/controllers/admins/dashboards_controller.rb b/app/controllers/admins/dashboards_controller.rb
index 3971971f..dccff054 100644
--- a/app/controllers/admins/dashboards_controller.rb
+++ b/app/controllers/admins/dashboards_controller.rb
@@ -1,10 +1,33 @@
class Admins::DashboardsController < Admins::BaseController
def index
- @active_user_count = User.where(last_login_on: today).count
- @weekly_active_user_count = User.where(last_login_on: current_week).count
- @month_active_user_count = User.where(last_login_on: current_month).count
+ # 用户活跃数
+ day_user_ids = CommitLog.where(created_at: today).pluck(:project_id).uniq
+ weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:project_id).uniq
+ month_user_ids = CommitLog.where(created_at: current_month).pluck(:project_id).uniq
+ @active_user_count = User.where(last_login_on: today).or(User.where(id: day_user_ids)).count
+ @weekly_active_user_count = User.where(last_login_on: current_week).or(User.where(id: weekly_user_ids)).count
+ @month_active_user_count = User.where(last_login_on: current_month).or(User.where(id: month_user_ids)).count
+ user_ids = User.where(created_on: pre_week).pluck(:id).uniq
+ weekly_keep_user_count = User.where(id: user_ids).where(last_login_on: current_week).count
+ @weekly_keep_rate = format("%.2f", user_ids.size > 0 ? weekly_keep_user_count.to_f / user_ids.size : 0)
- @new_user_count = User.where(created_on: current_month).count
+ # 新用户注册数
+ @day_new_user_count = User.where(created_on: today).count
+ @weekly_new_user_count = User.where(created_on: current_week).count
+ @month_new_user_count = User.where(created_on: current_month).count
+
+ # 活跃项目数
+ day_project_ids = (CommitLog.where(created_at: today).pluck(:project_id).uniq + Issue.where(created_on: today).pluck(:project_id).uniq).uniq
+ weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq
+ month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq
+ @day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count
+ @weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
+ @month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
+
+ # 新增项目数
+ @day_new_project_count = Project.where(created_on: today).count
+ @weekly_new_project_count = Project.where(created_on: current_week).count
+ @month_new_project_count = Project.where(created_on: current_month).count
end
def month_active_user
@@ -16,7 +39,6 @@ class Admins::DashboardsController < Admins::BaseController
{ value: count['professional'].to_i, name: '专业人士' },
{ value: count[nil].to_i, name: '未选职业' },
]
-
render_ok(data: data)
end
@@ -42,10 +64,14 @@ class Admins::DashboardsController < Admins::BaseController
end
def current_week
- 7.days.ago.beginning_of_day..Time.now.end_of_day
+ 7.days.ago.end_of_day..Time.now.end_of_day
end
def current_month
- 30.days.ago.beginning_of_day..Time.now.end_of_day
+ 30.days.ago.end_of_day..Time.now.end_of_day
+ end
+
+ def pre_week
+ 14.days.ago.end_of_day..7.days.ago.end_of_day
end
end
\ No newline at end of file
diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb
new file mode 100644
index 00000000..a66bfc52
--- /dev/null
+++ b/app/controllers/api/v1/base_controller.rb
@@ -0,0 +1,47 @@
+class Api::V1::BaseController < ApplicationController
+
+ include Api::ProjectHelper
+ include Api::UserHelper
+
+ # before_action :doorkeeper_authorize!
+ # skip_before_action :user_setup
+
+ protected
+ # def current_user
+ # #client方法对接,需要一直带着用户标识uid
+ # Rails.logger.info doorkeeper_token
+ # if doorkeeper_token && doorkeeper_token.resource_owner_id.blank?
+ # # return User.anonymous if params[:uid].nil?
+ # # tip_exception("2222")
+ # # return render_error('缺少用户标识!') if params[:uid].nil?
+ # User.current = User.find(params[:uid])
+ # else
+ # User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
+ # end
+ # end
+
+ def limit
+ params.fetch(:limit, 15)
+ end
+ def page
+ params.fetch(:page, 1)
+ end
+
+ # 具有对仓库的管理权限
+ def require_manager_above
+ @project = load_project
+ return render_forbidden unless current_user.admin? && @project.manager?(current_user)
+ end
+
+ # 具有对仓库的操作权限
+ def require_operate_above
+ @project = load_project
+ return render_forbidden unless current_user.admin? && @project.operator?(current_user)
+ end
+
+ # 具有对仓库的访问权限
+ def require_public_and_member_above
+ @project = load_project
+ return render_forbidden unless @project.is_public || (current_user.admin? && @project.member?(current_user))
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/branches_controller.rb b/app/controllers/api/v1/projects/branches_controller.rb
new file mode 100644
index 00000000..bc491961
--- /dev/null
+++ b/app/controllers/api/v1/projects/branches_controller.rb
@@ -0,0 +1,18 @@
+class Api::V1::Projects::BranchesController < Api::V1::BaseController
+ before_action :require_public_and_member_above, only: [:all]
+
+ def all
+ @result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
+ end
+
+ before_action :require_operate_above, only: [:create]
+
+ def create
+ @result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
+ end
+
+ private
+ def branch_params
+ params.require(:branch).permit(:new_branch_name, :old_branch_name)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/commits_controller.rb b/app/controllers/api/v1/projects/commits_controller.rb
new file mode 100644
index 00000000..a1545ae6
--- /dev/null
+++ b/app/controllers/api/v1/projects/commits_controller.rb
@@ -0,0 +1,12 @@
+class Api::V1::Projects::CommitsController < Api::V1::BaseController
+ before_action :require_public_and_member_above, only: [:index, :diff]
+
+ def index
+ @result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
+ puts @result_object
+ end
+
+ def diff
+ @result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/contents_controller.rb b/app/controllers/api/v1/projects/contents_controller.rb
new file mode 100644
index 00000000..a4e65051
--- /dev/null
+++ b/app/controllers/api/v1/projects/contents_controller.rb
@@ -0,0 +1,13 @@
+class Api::V1::Projects::ContentsController < Api::V1::BaseController
+ before_action :require_operate_above, only: [:batch]
+
+ def batch
+ @result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, batch_content_params, current_user&.gitea_token)
+ puts @result_object
+ end
+
+ private
+ def batch_content_params
+ params.require(:content).permit(:author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch, files: [ :action_type, :content, :encoding, :file_path])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/git_controller.rb b/app/controllers/api/v1/projects/git_controller.rb
new file mode 100644
index 00000000..f30dce1a
--- /dev/null
+++ b/app/controllers/api/v1/projects/git_controller.rb
@@ -0,0 +1,12 @@
+class Api::V1::Projects::GitController < Api::V1::BaseController
+ before_action :require_public_and_member_above, only: [:trees, :blobs]
+
+ def trees
+ @result_object = Api::V1::Projects::Git::TreesService.call(@project, params[:sha], {recursive: params[:recursive], page: page, limit: limit}, current_user&.gitea_token)
+ end
+
+ def blobs
+ @result_object = Api::V1::Projects::Git::BlobsService.call(@project, params[:sha], current_user&.gitea_token)
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects/webhooks_controller.rb b/app/controllers/api/v1/projects/webhooks_controller.rb
new file mode 100644
index 00000000..bb2c2172
--- /dev/null
+++ b/app/controllers/api/v1/projects/webhooks_controller.rb
@@ -0,0 +1,55 @@
+class Api::V1::Projects::WebhooksController < Api::V1::BaseController
+ before_action :require_manager_above
+ before_action :find_webhook, only: [:show, :update, :destroy, :tests, :hooktasks]
+
+ def index
+ # @result_object = Api::V1::Projects::Webhooks::ListService.call(@project, current_user&.gitea_token)
+ @webhooks = @project.webhooks
+ @webhooks = kaminari_paginate(@webhooks)
+ end
+
+ def create
+ @result_object = Api::V1::Projects::Webhooks::CreateService.call(@project, webhook_params, current_user&.gitea_token)
+ end
+
+ def show
+ @result_object = Api::V1::Projects::Webhooks::GetService.call(@project, params[:id], current_user&.gitea_token)
+ end
+
+ def update
+ @result_object = Api::V1::Projects::Webhooks::UpdateService.call(@project, params[:id], webhook_params, current_user&.gitea_token)
+ end
+
+ def destroy
+ @result_object = Api::V1::Projects::Webhooks::DeleteService.call(@project, params[:id], current_user&.gitea_token)
+ if @result_object
+ return render_ok
+ else
+ return render_error('删除失败!')
+ end
+ end
+
+ def tests
+ @result_object = Api::V1::Projects::Webhooks::TestsService.call(@project, params[:id], current_user&.gitea_token)
+ if @result_object
+ return render_ok
+ else
+ return render_error('推送失败!')
+ end
+ end
+
+ def hooktasks
+ @hooktasks = @webhook.tasks.where(is_delivered: true).order("delivered desc")
+ @hooktasks = kaminari_paginate(@hooktasks)
+ end
+
+ private
+ def webhook_params
+ params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, events: [])
+ end
+
+ def find_webhook
+ @webhook = Gitea::Webhook.find_by_id(params[:id])
+ return render_not_found unless @webhook.present?
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/projects_controller.rb b/app/controllers/api/v1/projects_controller.rb
new file mode 100644
index 00000000..bc51362a
--- /dev/null
+++ b/app/controllers/api/v1/projects_controller.rb
@@ -0,0 +1,20 @@
+class Api::V1::ProjectsController < Api::V1::BaseController
+ before_action :require_public_and_member_above, only: [:show, :compare, :blame]
+
+ def index
+ render_ok
+ end
+
+ def show
+ @result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token)
+ end
+
+ def compare
+ @result_object = Api::V1::Projects::CompareService.call(@project, params[:from], params[:to], current_user&.gitea_token)
+ end
+
+ def blame
+ @result_object = Api::V1::Projects::BlameService.call(@project, params[:sha], params[:filepath], current_user&.gitea_token)
+ puts @result_object
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/users/projects_controller.rb b/app/controllers/api/v1/users/projects_controller.rb
new file mode 100644
index 00000000..ac4b4832
--- /dev/null
+++ b/app/controllers/api/v1/users/projects_controller.rb
@@ -0,0 +1,13 @@
+class Api::V1::Users::ProjectsController < Api::V1::BaseController
+ before_action :load_observe_user
+
+ def index
+ @object_results = Api::V1::Users::Projects::ListService.call(@observe_user, query_params, current_user)
+ @projects = kaminari_paginate(@object_results)
+ end
+
+ private
+ def query_params
+ params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb
new file mode 100644
index 00000000..55f5cfb2
--- /dev/null
+++ b/app/controllers/api/v1/users_controller.rb
@@ -0,0 +1,6 @@
+class Api::V1::UsersController < Api::V1::BaseController
+
+ def index
+ render_ok
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 4dcf59d1..82aa9587 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -170,7 +170,6 @@ class ApplicationController < ActionController::Base
# 未授权的捕捉407,弹试用申请弹框
def require_login
#6.13 -hs
-
tip_exception(401, "请登录后再操作") unless User.current.logged?
end
@@ -249,39 +248,55 @@ class ApplicationController < ActionController::Base
#return if params[:controller] == "main"
# Find the current user
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
- User.current = find_current_user
- uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
-
- # 开放课程通过链接访问的用户
- if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
- content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
-
- if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
- user = open_class_user
- if user
- start_user_session(user)
- set_autologin_cookie(user)
+ if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
+ tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
+ if @doorkeeper_token.present?
+ # client方法对接,需要一直带着用户标识uid
+ if @doorkeeper_token.resource_owner_id.blank?
+ tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
+ User.current = User.find(params[:uid])
+ else
+ User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
end
- User.current = user
end
- end
- # if !User.current.logged? && Rails.env.development?
- # User.current = User.find 1
- # end
+ else
+ User.current = find_current_user
+ uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
+
+ # 开放课程通过链接访问的用户
+ if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
+ content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
+
+ if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
+ user = open_class_user
+ if user
+ start_user_session(user)
+ set_autologin_cookie(user)
+ end
+ User.current = user
+ end
+ end
+
+ # if !User.current.logged? && Rails.env.development?
+ # user = User.find 1
+ # User.current = user
+ # start_user_session(user)
+ # end
- # 测试版前端需求
- logger.info("subdomain:#{request.subdomain}")
- if request.subdomain != "www"
- if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
- User.current = User.find 81403
- elsif params[:debug] == 'student'
- User.current = User.find 8686
- elsif params[:debug] == 'admin'
- logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
- user = User.find 36480
- User.current = user
- cookies.signed[:user_id] = user.id
+ # 测试版前端需求
+ logger.info("subdomain:#{request.subdomain}")
+ if request.subdomain != "www"
+ if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
+ User.current = User.find 81403
+ elsif params[:debug] == 'student'
+ User.current = User.find 8686
+ elsif params[:debug] == 'admin'
+ logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
+ user = User.find 36480
+ User.current = user
+ cookies.signed[:user_id] = user.id
+ end
end
end
# User.current = User.find 81403
@@ -681,7 +696,7 @@ class ApplicationController < ActionController::Base
@project, @owner = Project.find_with_namespace(namespace, id)
- if @project and current_user.can_read_project?(@project)
+ if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
logger.info "###########: has project and can read project"
@project
# elsif @project && current_user.is_a?(AnonymousUser)
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 3aa98257..79047b51 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -33,8 +33,8 @@ class AttachmentsController < ApplicationController
normal_status(-1, "参数缺失") if params[:download_url].blank?
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
if url.starts_with?(base_url)
- domain = Gitea.gitea_config[:domain]
- api_url = Gitea.gitea_config[:base_url]
+ domain = GiteaService.gitea_config[:domain]
+ api_url = GiteaService.gitea_config[:base_url]
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
response = Faraday.get(request_url)
diff --git a/app/controllers/commit_logs_controller.rb b/app/controllers/commit_logs_controller.rb
new file mode 100644
index 00000000..c62c1300
--- /dev/null
+++ b/app/controllers/commit_logs_controller.rb
@@ -0,0 +1,27 @@
+class CommitLogsController < ApplicationController
+
+ def create
+ tip_exception "未认证" unless params[:token].to_s == "7917908927b6f1b792f2027a08a8b24a2de42c1692c2fd45da0dee5cf90a5af5"
+ ref = params[:ref]
+ user_name = params[:pusher][:login]
+ user_mail = params[:pusher][:email]
+ user = User.find_by(mail: user_mail)
+ user = User.find_by(login: user_name) if user.blank?
+
+ repository_id = params[:repository][:id]
+ repository_name = params[:repository][:name]
+ repository_full_name = params[:repository][:full_name]
+ owner_name = repository_full_name.split("/")[0]
+ owner = User.find_by(login: owner_name)
+ project = Project.where(identifier: repository_name).where(user_id: owner&.id)&.first
+ project = Project.where(identifier: repository_name).where(gpid: repository_id)&.first if project.blank?
+ params[:commits].each do |commit|
+ commit_id = commit[:id]
+ message = commit[:message]
+ CommitLog.create(user: user, project: project, repository_id: repository_id,
+ name: repository_name, full_name: repository_full_name,
+ ref: ref, commit_id: commit_id, message: message)
+ end
+
+ end
+end
diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb
index 1aab7adb..afdceac9 100644
--- a/app/controllers/compare_controller.rb
+++ b/app/controllers/compare_controller.rb
@@ -6,9 +6,14 @@ class CompareController < ApplicationController
end
def show
- load_compare_params
- compare
- @merge_status, @merge_message = get_merge_message
+ if params[:type] == "sha"
+ load_compare_params
+ @compare_result ||= gitea_compare(@base, @head)
+ else
+ load_compare_params
+ compare
+ @merge_status, @merge_message = get_merge_message
+ end
@page_size = page_size <= 0 ? 1 : page_size
@page_limit = page_limit <=0 ? 15 : page_limit
@page_offset = (@page_size -1) * @page_limit
diff --git a/app/controllers/concerns/acceleratorable.rb b/app/controllers/concerns/acceleratorable.rb
index 5243ac53..88ec4dd6 100644
--- a/app/controllers/concerns/acceleratorable.rb
+++ b/app/controllers/concerns/acceleratorable.rb
@@ -18,15 +18,15 @@ module Acceleratorable
end
def accelerator_domain
- Gitea.gitea_config[:accelerator]["domain"]
+ GiteaService.gitea_config[:accelerator]["domain"]
end
def accelerator_username
- Gitea.gitea_config[:accelerator]["access_key_id"]
+ GiteaService.gitea_config[:accelerator]["access_key_id"]
end
def config_accelerator?
- Gitea.gitea_config[:accelerator].present?
+ GiteaService.gitea_config[:accelerator].present?
end
def is_foreign_url?(clone_addr)
diff --git a/app/controllers/concerns/api/project_helper.rb b/app/controllers/concerns/api/project_helper.rb
new file mode 100644
index 00000000..52967e78
--- /dev/null
+++ b/app/controllers/concerns/api/project_helper.rb
@@ -0,0 +1,20 @@
+module Api::ProjectHelper
+ extend ActiveSupport::Concern
+
+ def load_project
+ namespace = params[:owner]
+ repo = params[:repo]
+
+ @project, @owner = Project.find_with_namespace(namespace, repo)
+
+ if @project
+ logger.info "###########:project founded"
+ @project
+ else
+ logger.info "###########:project not found"
+ @project = nil
+ render_not_found and return
+ end
+ @project
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/concerns/api/user_helper.rb b/app/controllers/concerns/api/user_helper.rb
new file mode 100644
index 00000000..e6156ea5
--- /dev/null
+++ b/app/controllers/concerns/api/user_helper.rb
@@ -0,0 +1,19 @@
+module Api::UserHelper
+ extend ActiveSupport::Concern
+
+ def load_observe_user
+ username = params[:owner]
+
+ @observe_user = User.find_by(login: username)
+
+ if @observe_user
+ logger.info "###########observe_user not founded"
+ @observe_user
+ else
+ logger.info "###########observe_user not found"
+ @observe_user = nil
+ render_not_found and return
+ end
+ @observe_user
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/concerns/login_helper.rb b/app/controllers/concerns/login_helper.rb
index e608b783..86ab175e 100644
--- a/app/controllers/concerns/login_helper.rb
+++ b/app/controllers/concerns/login_helper.rb
@@ -116,6 +116,7 @@ module LoginHelper
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
if interactor.success?
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
+ user.update_column(:is_sync_pwd, true)
true
else
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
diff --git a/app/controllers/concerns/repository/languages_percentagable.rb b/app/controllers/concerns/repository/languages_percentagable.rb
index dc6abcb9..53876327 100644
--- a/app/controllers/concerns/repository/languages_percentagable.rb
+++ b/app/controllers/concerns/repository/languages_percentagable.rb
@@ -5,7 +5,16 @@ module Repository::LanguagesPercentagable
result = Gitea::Repository::Languages::ListService.call(@owner.login,
@repository.identifier, current_user&.gitea_token)
- result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
+ @transform_language = result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
+ update_project_language(@transform_language) unless @transform_language.nil?
+ @transform_language
+ end
+
+ def update_project_language(language)
+ db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
+ @project.update_column(:project_language_id, db_language.id)
+ rescue
+ return
end
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}
diff --git a/app/controllers/oauth2_controller.rb b/app/controllers/oauth2_controller.rb
new file mode 100644
index 00000000..f1ac19a2
--- /dev/null
+++ b/app/controllers/oauth2_controller.rb
@@ -0,0 +1,39 @@
+class Oauth2Controller < ActionController::Base
+ layout 'doorkeeper/application'
+ include LoginHelper
+
+ def show
+ client_id = params[:call_url].split("client_id=")[1].split("&redirect_uri")[0]
+ @call_url = request.fullpath.split('call_url=').last
+ @app = Doorkeeper::Application.find_by(uid: client_id)
+ end
+
+ def create
+ if params[:login].blank?
+ @error = {msg: '邮箱地址或用户名不能为空', id: 'login'}
+ elsif params[:password].blank?
+ @error = {msg: '请输入密码', id: 'password'}
+ else
+ @user = User.try_to_login(params[:login], params[:password])
+
+ return @error = {msg: '账号或密码错误', id: 'login'} if @user.blank?
+ return @error = {msg: '违反平台使用规范,账号已被锁定', id: 'login'} if @user.locked?
+
+ login_control = LimitForbidControl::UserLogin.new(@user)
+ return @error = {msg: "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码", id: 'account'} if login_control.forbid?
+
+ password_ok = @user.check_password?(params[:password].to_s)
+ unless password_ok
+ if login_control.remain_times-1 == 0
+ @error = {msg: "登录密码出错已达上限,账号已被锁定, 请#{login_control.forbid_expires/60}分钟后重新登录或找回密码", id: 'account'}
+ else
+ @error = {msg: "你已经输错密码#{login_control.error_times+1}次,还剩余#{login_control.remain_times-1}次机会", id: 'account'}
+ end
+ login_control.increment!
+ return
+ end
+ login_control.clear
+ redirect_to params[:call_url] + "&auth=" + @user.login
+ end
+ end
+end
diff --git a/app/controllers/projects/project_invite_links_controller.rb b/app/controllers/projects/project_invite_links_controller.rb
new file mode 100644
index 00000000..ddf88e6b
--- /dev/null
+++ b/app/controllers/projects/project_invite_links_controller.rb
@@ -0,0 +1,42 @@
+class Projects::ProjectInviteLinksController < Projects::BaseController
+ before_action :require_manager!, except: [:show_link, :redirect_link]
+ before_action :require_login
+
+ def current_link
+ role = params[:role]
+ is_apply = params[:is_apply]
+ return render_error('请输入正确的参数!') unless role.present? && is_apply.present?
+ @project_invite_link = ProjectInviteLink.find_by(user_id: current_user.id, project_id: @project.id, role: role, is_apply: is_apply)
+ @project_invite_link = ProjectInviteLink.build!(@project, current_user, role, is_apply) unless @project_invite_link.present?
+ end
+
+ def generate_link
+ ActiveRecord::Base.transaction do
+ params_data = link_params.merge({user_id: current_user.id, project_id: @project.id})
+ Projects::ProjectInviteLinks::CreateForm.new(params_data).validate!
+ @project_invite_link = ProjectInviteLink.build!(project, user, params_data[:role], params_data[:is_apply])
+ end
+ rescue Exception => e
+ uid_logger_error(e.message)
+ tip_exception(e.message)
+ end
+
+ def show_link
+ @project_invite_link = ProjectInviteLink.find_by(sign: params[:invite_sign])
+ return render_not_found unless @project_invite_link.present?
+ end
+
+ def redirect_link
+ Projects::LinkJoinService.call(current_user, @project, params[:invite_sign])
+ render_ok
+ rescue Exception => e
+ uid_logger_error(e.message)
+ normal_status(-1, e.message)
+ end
+
+
+ private
+ def link_params
+ params.require(:project_invite_link).permit(:role, :is_apply)
+ end
+end
diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb
index f45d1f35..97fafe17 100644
--- a/app/controllers/pull_requests_controller.rb
+++ b/app/controllers/pull_requests_controller.rb
@@ -56,7 +56,12 @@ class PullRequestsController < ApplicationController
end
def create
- # return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
+ if params[:fork_project_id].present?
+ fork_project= Project.find_by(id: params[:fork_project_id])
+ return normal_status(-1, "您不是源项目开发者,没有权限,请联系源项目管理员.") unless fork_project && fork_project.operator?(current_user)
+ else
+ return normal_status(-1, "您不是项目开发者,没有权限,请联系项目管理员.") unless @project.operator?(current_user)
+ end
ActiveRecord::Base.transaction do
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
@@ -176,6 +181,7 @@ class PullRequestsController < ApplicationController
@issue_assign_to = @issue.get_assign_user
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
+ @last_review = @pull_request.issue.reviews.take
end
def pr_merge
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index 86cef7f3..6b2898b6 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -9,7 +9,7 @@ class RepositoriesController < ApplicationController
before_action :load_repository
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
- before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
+ before_action :get_ref, only: %i[entries sub_entries top_counts files archive]
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
before_action :get_statistics, only: %i[top_counts]
@@ -54,7 +54,7 @@ class RepositoriesController < ApplicationController
else
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
- @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
+ @path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
end
end
@@ -99,7 +99,7 @@ class RepositoriesController < ApplicationController
end
end
else
- @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
+ @path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
if interactor.success?
result = interactor.result
@@ -222,7 +222,7 @@ class RepositoriesController < ApplicationController
else
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
end
- @path = Gitea.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
+ @path = GiteaService.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
@readme = result[:status] === :success ? result[:body] : nil
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
@@ -240,8 +240,8 @@ class RepositoriesController < ApplicationController
end
def archive
- domain = Gitea.gitea_config[:domain]
- api_url = Gitea.gitea_config[:base_url]
+ domain = GiteaService.gitea_config[:domain]
+ api_url = GiteaService.gitea_config[:base_url]
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
file_path = [domain, api_url, archive_url].join
@@ -253,8 +253,8 @@ class RepositoriesController < ApplicationController
end
def raw
- domain = Gitea.gitea_config[:domain]
- api_url = Gitea.gitea_config[:base_url]
+ domain = GiteaService.gitea_config[:domain]
+ api_url = GiteaService.gitea_config[:base_url]
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{Addressable::URI.escape(params[:filepath])}?ref=#{Addressable::URI.escape(params[:ref])}"
file_path = [domain, api_url, url].join
diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb
new file mode 100644
index 00000000..eec57113
--- /dev/null
+++ b/app/controllers/reviews_controller.rb
@@ -0,0 +1,20 @@
+class ReviewsController < ApplicationController
+ before_action :require_login
+ before_action :load_project
+ before_action :load_pull_request
+
+ def create
+ return render_forbidden('您不是审查人员,无法进行审查!') if current_user&.id != @pull_request.issue.assigned_to_id
+ @journal, @review = Api::V1::Projects::PullRequests::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
+ end
+
+ private
+ def review_params
+ params.require(:review).permit(:content, :commit_id, :status)
+ end
+
+ def load_pull_request
+ @pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/traces/projects_controller.rb b/app/controllers/traces/projects_controller.rb
index 62573a1d..e39d77a9 100644
--- a/app/controllers/traces/projects_controller.rb
+++ b/app/controllers/traces/projects_controller.rb
@@ -69,12 +69,18 @@ class Traces::ProjectsController < Traces::BaseController
def task_pdf
- return render_error("task_id错误") if params[:task_id].blank?
- result = Trace::PdfReportService.call(current_user.trace_token, params[:task_id])
- if result.is_a?(Hash) && result[:code] == 200
- redirect_to result[:download_url]
+ task_id = params[:task_id]
+ return render_error("task_id错误") if task_id.blank?
+ file_save_path = "public/trace_task_results/#{task_id}/report.pdf"
+ if File.exists?(file_save_path)
+ redirect_to "/trace_task_results/#{task_id}/report.pdf"
else
- render_error("下载报告失败!")
+ result = Trace::PdfReportService.call(current_user.trace_token, task_id)
+ if result.is_a?(Hash) && result[:code] == 200
+ redirect_to result[:download_url]
+ else
+ render_error("下载报告失败!")
+ end
end
rescue Exception => exception
puts exception.message
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 056909f6..e7cf0e14 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -100,7 +100,7 @@ class UsersController < ApplicationController
def get_image
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
- return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
+ # return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
end
diff --git a/app/docs/slate/source/api.html.md b/app/docs/slate/source/api.html.md
index 0031a99f..95c32805 100644
--- a/app/docs/slate/source/api.html.md
+++ b/app/docs/slate/source/api.html.md
@@ -1,13 +1,13 @@
---
-title: Trustie API Reference
+title: GitLink API Reference
language_tabs: # must be one of https://git.io/vQNgJ
- shell: Shell
- javascript: JavaScript
toc_footers:
- - Sign Up for a User
- - Powered by Trustie
+ - Sign In for a User
+ - Powered by GitLink
includes:
- licenses
@@ -31,8 +31,8 @@ code_clipboard: true
# Introduction
-Welcome to the Trustie API! You can use our API to access Trustie API endpoints, which can get information on projects, repository, and users in our platform.
+Welcome to the GitLink API! You can use our API to access GitLink API endpoints, which can get information on projects, repository, and users in our platform.
We have language bindings in Shell,avaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
-This example API documentation page was created with [Trustie](https://www.trustie.net). Feel free to edit it and use it as a base for your own API's documentation.
+This example API documentation page was created with [GitLink](https://www.gitlink.org.cn). Feel free to edit it and use it as a base for your own API's documentation.
diff --git a/app/docs/slate/source/includes/_projects.md b/app/docs/slate/source/includes/_projects.md
index d29d200b..27295e76 100644
--- a/app/docs/slate/source/includes/_projects.md
+++ b/app/docs/slate/source/includes/_projects.md
@@ -1,4 +1,278 @@
# Projects
+## 获取项目邀请链接(项目管理员)
+当前登录(管理员)用户获取项目邀请链接的接口(第一次请求会默认生成role类型为developer和is_apply为true的链接)
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/current_link.json
+```
+
+```javascript
+await octokit.request('GET /api/yystopf/kellect/project_invite_links/current_link.json')
+```
+
+### HTTP 请求
+`GET /api/:owner/:repo/project_invite_links/current_link.json`
+
+### 请求参数
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
+|is_apply |是| |boolean |是否需要审核 |
+
+### 返回字段说明
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|id |int |链接id |
+|role |string |邀请角色|
+|is_apply |boolean |是否需要审核 |
+|sign |string |邀请标识(放在链接后面即可)|
+|expired_at |string |链接过期时间|
+|user.id |int |链接创建者的id |
+|user.type |string |链接创建者的类型 |
+|user.name |string |链接创建者的名称 |
+|user.login |string |链接创建者的标识 |
+|user.image_url |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 |链接关联项目拥有者头像 |
+
+> 返回的JSON示例:
+
+```json
+{
+ "id": 7,
+ "role": "developer",
+ "is_apply": false,
+ "sign": "6b6b454843c291d4e52e60853cb8ad9f",
+ "expired_at": "2022-06-23 10:08",
+ "user": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "project": {
+ "id": 474,
+ "identifier": "kellect",
+ "name": "kellect",
+ "description": null,
+ "is_public": true,
+ "owner": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ }
+ }
+}
+```
+## 生成项目邀请链接(项目管理员)
+当前登录(管理员)用户生成的项目邀请链接,可选role和is_apply参数
+
+> 示例:
+
+```shell
+curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/generate_link.json
+```
+
+```javascript
+await octokit.request('POST /api/yystopf/kellect/project_invite_links/generate_link.json')
+```
+
+### HTTP 请求
+`POST /api/:owner/:repo/project_invite_links/generate_link.json`
+
+### 请求参数
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
+|is_apply |是| |boolean |是否需要审核 |
+
+
+> 请求的JSON示例
+
+```json
+{
+ "role": "developer",
+ "is_apply": false
+}
+```
+
+### 返回字段说明
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|id |int |链接id |
+|role |string |邀请角色|
+|is_apply |boolean |是否需要审核 |
+|sign |string |邀请标识(放在链接后面即可)|
+|expired_at |string |链接过期时间|
+|user.id |int |链接创建者的id |
+|user.type |string |链接创建者的类型 |
+|user.name |string |链接创建者的名称 |
+|user.login |string |链接创建者的标识 |
+|user.image_url |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 |链接关联项目拥有者头像 |
+
+> 返回的JSON示例:
+
+```json
+{
+ "id": 7,
+ "role": "developer",
+ "is_apply": false,
+ "sign": "6b6b454843c291d4e52e60853cb8ad9f",
+ "expired_at": "2022-06-23 10:08",
+ "user": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "project": {
+ "id": 474,
+ "identifier": "kellect",
+ "name": "kellect",
+ "description": null,
+ "is_public": true,
+ "owner": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ }
+ }
+}
+```
+
+## 获取邀请链接信息(被邀请用户)
+用户请求邀请链接时,通过该接口来获取链接的信息
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
+```
+
+```javascript
+await octokit.request('POST /api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
+```
+
+### HTTP 请求
+`POST /api/:owner/:repo/project_invite_links/show_link.json?invite_sign=xxx`
+
+### 请求参数
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|invite_sign |是| |string |项目邀请链接的标识 |
+
+### 返回字段说明
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|id |int |链接id |
+|role |string |邀请角色|
+|is_apply |boolean |是否需要审核 |
+|sign |string |邀请标识(放在链接后面即可)|
+|expired_at |string |链接过期时间|
+|user.id |int |链接创建者的id |
+|user.type |string |链接创建者的类型 |
+|user.name |string |链接创建者的名称 |
+|user.login |string |链接创建者的标识 |
+|user.image_url |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 |链接关联项目拥有者头像 |
+
+> 返回的JSON示例:
+
+```json
+{
+ "id": 7,
+ "role": "developer",
+ "is_apply": false,
+ "sign": "6b6b454843c291d4e52e60853cb8ad9f",
+ "expired_at": "2022-06-23 10:08",
+ "user": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "project": {
+ "id": 474,
+ "identifier": "kellect",
+ "name": "kellect",
+ "description": null,
+ "is_public": true,
+ "owner": {
+ "id": 2,
+ "type": "User",
+ "name": "heh",
+ "login": "yystopf",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ }
+ }
+}
+```
+
+## 接受项目邀请链接(被邀请用户)
+当前登录(非项目)用户加入项目的接口,如果项目链接不需要审核,请求成功后即加入项目,如果需要审核,那么会提交一个申请,需要项目管理员审核
+
+> 示例:
+
+```shell
+curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
+```
+
+```javascript
+await octokit.request('POST /api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
+```
+
+### HTTP 请求
+`POST /api/:owner/:repo/project_invite_links/redirect_link.json?invite_sign=xxx`
+
+### 请求参数
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|invite_sign |是| |string |项目邀请链接的标识 |
+
+> 返回的JSON示例:
+
+```json
+{
+ "status": 0,
+ "message": "success"
+}
+```
## 申请加入项目
申请加入项目
diff --git a/app/docs/slate/source/includes/_repositories.md b/app/docs/slate/source/includes/_repositories.md
index a44d2b35..ae74dac7 100644
--- a/app/docs/slate/source/includes/_repositories.md
+++ b/app/docs/slate/source/includes/_repositories.md
@@ -26,25 +26,84 @@ await octokit.request('GET /api/jasder/jasder_test.json')
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
-|id |int |id |
-|name |string|项目名称|
-|identifier |string|项目标识|
-|is_public |boolean|项目是否公开, true:公开,false:私有|
-|description |string|项目简介|
-|repo_id |int|仓库id|
-|repo_identifier|string|仓库标识|
+|identifier |string|项目标识|
+|name |string|项目名称|
+|project_id |int |项目ID |
+|repo_id |int |仓库ID|
+|issues_count |int |疑修数量|
+|pull_requests_count |int |合并请求数量|
+|project_identifier |string|项目标识|
+|praises_count |int |项目点赞数|
+|forked_count |int |项目复刻数|
+|watchers_count |int |项目关注数|
+|versions_count |int |项目里程碑数量|
+|version_releases_count |int |项目版本数|
+|version_releasesed_count |int |项目已发行项目版本数|
+|contributor_users_count |int |项目贡献者数|
+|permission |string|用户权限 Admin: 平台管理员, Manager: 项目管理员, Developer: 项目开发者, Reporter: 项目报告者|
+|mirror_url |string|项目镜像地址|
+|mirror |bool |是否为镜像项目|
+|type |int |项目类型 0: 托管项目,1: 镜像项目,2: 同步镜像项目|
+|forked_from_project_id |int |项目复刻来源项目ID|
+|fork_info.fork_form_name |string|项目复刻来源项目的名称|
+|fork_info.fork_project_user_login|string|项目复刻来源项目拥有者标识|
+|fork_info.fork_project_identifier|string|项目复刻来源项目标识|
+|fork_info.fork_project_user_name |string|项目复刻来源项目拥有者名称|
+|size |string|项目大小|
+|ssh_url |string|项目ssh clone地址|
+|clone_url |string|项目http clone地址|
+|default_branch |string|项目默认分支|
+|empty |bool |项目是否为空|
+|full_name |string|项目路径|
+|private |bool |项目是否为私有项目|
+|author.id |int |项目拥有者ID|
+|author.login |string|项目拥有者标识|
+|author.type |string|项目拥有者类型|
+|author.name |string|项目拥有者名称|
+|author.image_url |string|项目拥有者头像地址|
> 返回的JSON示例:
```json
{
- "name": "ni项目",
- "identifier": "mirror_demo",
- "is_public": true,
- "description": "my first project mirror_demo",
- "repo_id": 75073,
- "repo_identifier": "mirror_demo"
+ "identifier": "hahahah",
+ "name": "hahahah",
+ "project_id": 469,
+ "repo_id": 469,
+ "issues_count": 2,
+ "pull_requests_count": 3,
+ "project_identifier": "hahahah",
+ "praises_count": 0,
+ "forked_count": 1,
+ "watchers_count": 0,
+ "versions_count": 0,
+ "version_releases_count": 0,
+ "version_releasesed_count": 0,
+ "contributor_users_count": 1,
+ "permission": "Admin",
+ "mirror_url": null,
+ "mirror": false,
+ "type": 0,
+ "open_devops": false,
+ "watched": false,
+ "praised": false,
+ "status": 1,
+ "forked_from_project_id": null,
+ "size": "2.1 MB",
+ "ssh_url": "virus@127.0.0.1:10081:yystopf/hahahah.git",
+ "clone_url": "http://127.0.0.1:10081/yystopf/hahahah.git",
+ "default_branch": "master",
+ "empty": false,
+ "full_name": "yystopf/hahahah",
+ "private": false,
+ "author": {
+ "id": 2,
+ "login": "yystopf",
+ "type": "User",
+ "name": "heh",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ }
}
```
@@ -75,25 +134,36 @@ await octokit.request('GET /api/jasder/jasder_test/simple.json')
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
-|id |int |id |
-|name |string|项目名称|
-|identifier |string|项目标识|
-|is_public |boolean|项目是否公开, true:公开,false:私有|
-|description |string|项目简介|
-|repo_id |int|仓库id|
-|repo_identifier|string|仓库标识|
+|id |int |id |
+|name |string|项目名称|
+|platform |string|项目平台|
+|identifier |string|项目标识|
+|repo_id |int |仓库id|
+|open_devops |bool |是否开启工作流|
+|type |int |项目类型 0: 托管项目,1: 镜像项目,2: 同步镜像项目|
+|author.login |string|项目拥有者标识|
+|author.type |string|项目拥有者类型|
+|author.name |string|项目拥有者名称|
+|author.image_url|string|项目拥有者头像地址|
> 返回的JSON示例:
```json
{
- "name": "ni项目",
- "identifier": "mirror_demo",
- "is_public": true,
- "description": "my first project mirror_demo",
- "repo_id": 75073,
- "repo_identifier": "mirror_demo"
+ "identifier": "hahahah",
+ "name": "hahahah",
+ "platform": "forge",
+ "id": 469,
+ "repo_id": 469,
+ "open_devops": false,
+ "type": 0,
+ "author": {
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ }
}
```
@@ -125,9 +195,13 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json')
--------- | ----------- | -----------
|content |string |仓库简介 |
|website |string |仓库网址 |
-|readme |string |readme文件|
+|lesson_url |string |课程地址 |
|identifier |string |项目标识 |
+|invite_code |string |项目邀请码 |
|name |string |项目名称 |
+|description |string |项目描述 |
+|project_id |int |项目ID |
+|repo_id |int |仓库ID|
|issues_count |int |项目issue数量|
|pull_requests_count |int |项目合并请求数量|
|project_identifier |int |项目标识|
@@ -137,7 +211,7 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json')
|versions_count |int |项目里程碑数量|
|version_releases_count |int |项目发行版数量|
|version_releasesed_count |int |项目发行版已发行数量|
-|permission |string |项目权限|
+|permission |string |项目权限, Admin: 平台管理员,Manager: 项目管理员, Developer: 项目开发者, Reporter: 项目报告者|
|mirror_url |string |镜像地址|
|mirror |bool |是否为镜像项目|
|type |int |项目类型 0 普通项目 1 普通镜像项目 2 同步镜像项目|
@@ -145,59 +219,49 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json')
|watched |bool |是否关注|
|praised |bool |是否点赞|
|status |int |项目状态|
-|forked_from_project_id |int |fork项目id|
-|fork_info |object |fork项目信息|
+|forked_from_project_id |int |项目复刻来源项目id|
+|fork_info.fork_form_name |string |项目复刻来源项目的名称|
+|fork_info.fork_project_user_login|string |项目复刻来源项目拥有者标识|
+|fork_info.fork_project_identifier|string |项目复刻来源项目标识|
+|fork_info.fork_project_user_name |string |项目复刻来源项目拥有者名称|
|size |string |仓库大小|
-|ssh_url |string |项目ssh地址|
-|clone_url |string |项目克隆地址|
+|ssh_url |string |项目ssh克隆地址|
+|clone_url |string |项目http克隆地址|
|default_branch |string |仓库默认分支|
|empty |bool |仓库是否为空|
|full_name |string |仓库全称|
|private |bool |仓库是否为私有项目|
|license_name |string |许可证名称|
-|release_versions.list.name |string |项目issue数量|
-|release_versions.list.tag_name |string |发行版标签名称|
-|release_versions.list.created_at |string |发行版创建时间|
-|release_versions.total_count |int |发行版数量|
-|branches.list.name |string |分支名称|
-|branches.total_count |int |分支数量|
-|tags.list.name |string |标签名称|
-|tags.total_count |int |标签数量|
-|contributors.list.contributions|int |贡献数量|
-|contributors.list.login |string |贡献者登录名|
-|contributors.list.name |string |贡献者用户名称|
-|contributors.list.image_url |string |贡献者头像|
-|languages |object |项目语言占比|
+|author.id |int |项目拥有者ID|
+|author.login |string |项目拥有者标识|
+|author.type |string |项目拥有者类型|
+|author.name |string |项目拥有者名称|
+|author.image_url |string |项目拥有者头像地址|
+
> 返回的JSON示例:
```json
{
- "content": "仓库简介",
- "website": "仓库网址",
- "readme": {
- "type": "file",
- "encoding": "base64",
- "size": 9,
- "name": "README.md",
- "path": "README.md",
- "content": "# ceshi\n\n",
- "sha": ""
- },
- "identifier": "ceshi",
- "name": "测试项目",
- "project_id": 2,
- "repo_id": 2,
- "issues_count": 0,
- "pull_requests_count": 0,
- "project_identifier": "ceshi",
+ "content": null,
+ "website": null,
+ "lesson_url": null,
+ "identifier": "hahahah",
+ "invite_code": "8zfKtM",
+ "name": "hahahah",
+ "description": null,
+ "project_id": 469,
+ "repo_id": 469,
+ "issues_count": 2,
+ "pull_requests_count": 2,
+ "project_identifier": "hahahah",
"praises_count": 0,
- "forked_count": 0,
+ "forked_count": 1,
"watchers_count": 0,
"versions_count": 0,
"version_releases_count": 0,
"version_releasesed_count": 0,
- "permission": "Reporter",
+ "permission": "Admin",
"mirror_url": null,
"mirror": false,
"type": 0,
@@ -205,71 +269,23 @@ await octokit.request('GET /api/yystopf/ceshi/detail.json')
"watched": false,
"praised": false,
"status": 1,
- "forked_from_project_id": 1,
- "fork_info": {
- "fork_form_name": "测试项目",
- "fork_project_user_login": "ceshi_org",
- "fork_project_identifier": "ceshi",
- "fork_project_user_name": "ceshi_org"
- },
- "size": "25.0 KB",
- "ssh_url": "virus@localhost:yystopf/ceshi.git",
- "clone_url": "http://localhost:10080/yystopf/ceshi.git",
+ "forked_from_project_id": null,
+ "size": "2.1 MB",
+ "ssh_url": "virus@127.0.0.1:10081:yystopf/hahahah.git",
+ "clone_url": "http://127.0.0.1:10081/yystopf/hahahah.git",
"default_branch": "master",
"empty": false,
- "full_name": "yystopf/ceshi",
+ "full_name": "yystopf/hahahah",
"private": false,
- "license_name": "gnu-javamail-exception",
- "release_versions": {
- "list": [
- {
- "id": 2,
- "name": "vvvv",
- "tag_name": "v1.1",
- "created_at": "2019-07-18 10:16"
- }
- ],
- "total_count": 1
- },
- "branches": {
- "list": [
- {
- "name": "master"
- }
- ],
- "total_count": 1
- },
- "tags": {
- "list": [
- {
- "name": "v1.1"
- },
- {
- "name": "v1.0"
- }
- ],
- "total_count": 2
- },
- "contributors": {
- "list": [
- {
- "contributions": 1,
- "gid": 2,
- "login": "yystopf",
- "type": "User",
- "name": "yystopf",
- "image_url": "avatars/User/b"
- }
- ],
- "total_count": 1
- },
- "languages": {
- "HTML": "50.9%",
- "Ruby": "25.6%",
- "JavaScript": "21.4%",
- "CSS": "1.3%",
- "CoffeeScript": "0.7%",
- "Shell": "0.1%"
+ "license_name": null,
+ "branches_count": 1201,
+ "tags_count": 0,
+ "author": {
+ "id": 2,
+ "login": "yystopf",
+ "type": "User",
+ "name": "heh",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
}
}
```
@@ -392,6 +408,254 @@ await octokit.request('GET /api/yystopf/csfjkkj/tags.json')
]
```
+
+## 仓库所有分支列表
+仓库所有分支列表
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/branches/all.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/branches/all.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/branches/all.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| |string |用户登录名 |
+|repo |是| |string |项目标识identifier |
+
+
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|name |string|分支名称|
+|http_url |string|分支http地址|
+|zip_url |string|分支zip包下载地址|
+|tar_url |string|分支tar包下载地址|
+
+
+> 返回的JSON示例:
+
+```json
+[
+ {
+ "name": "master",
+ "http_url": "http://127.0.0.1:10081/yystopf/hahahah.git",
+ "zip_url": "http://localhost:3000/api/yystopf/hahahah/archive/master.zip",
+ "tar_url": "http://localhost:3000/api/yystopf/hahahah/archive/master.tar.gz"
+ },
+ {
+ "name": "touch-10",
+ "http_url": "http://127.0.0.1:10081/yystopf/hahahah.git",
+ "zip_url": "http://localhost:3000/api/yystopf/hahahah/archive/touch-10.zip",
+ "tar_url": "http://localhost:3000/api/yystopf/hahahah/archive/touch-10.tar.gz"
+ },
+ {
+ "name": "touch-100",
+ "http_url": "http://127.0.0.1:10081/yystopf/hahahah.git",
+ "zip_url": "http://localhost:3000/api/yystopf/hahahah/archive/touch-100.zip",
+ "tar_url": "http://localhost:3000/api/yystopf/hahahah/archive/touch-100.tar.gz"
+ }
+]
+```
+
+## 仓库创建分支
+为仓库创建一个新的分支
+
+> 示例:
+
+```shell
+curl -X POST \
+-d "new_branch_name=ceshi_branch_1" \
+-d "old_branch_name=master" \
+http://localhost:3000/api/v1/yystopf/csfjkkj/branches.json
+```
+
+```javascript
+await octokit.request('POST /api/v1/yystopf/csfjkkj/branches.json')
+```
+
+### HTTP 请求
+`POST /api/v1/:owner/:repo/branches.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| |string |用户登录名 |
+|repo |是| |string |项目标识identifier |
+|new_branch_name|是||string| 新分支名称|
+|old_branch_name|否||string| 来源分支名称|
+
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|name |string|分支名称|
+|commit.id |string|提交ID|
+|commit.message |string|提交信息|
+|commit.author.id |string|提交作者ID|
+|commit.author.login |string|提交作者标识|
+|commit.author.name |string|提交作者名称|
+|commit.author.type |string|提交作者类型|
+|commit.committer.id |string|提交者ID|
+|commit.committer.login |string|提交者标识|
+|commit.committer.name |string|提交者名称|
+|commit.committer.type |string|提交者类型|
+|commit.committer.image_url|string|提交者头像|
+|commit.time_ago |string|分支最新提交时间距现在时间差|
+|commit.timestamp |string|分支最新提交时间|
+|protected |bool |是否为保护分支|
+|user_can_push |bool |当前用户是否能提交|
+|user_can_merge |bool |当前用户是否能合并|
+|commit_id |string|提交ID|
+|commit_time_from_now |string|分支最新提交时间距现在时间差|
+|commit_time |string|分支最新提交时间|
+|http_url |string|分支http地址|
+|zip_url |string|分支zip包下载地址|
+|tar_url |string|分支tar包下载地址|
+
+> 返回的JSON示例:
+
+```json
+{
+ "name": "new_branch_8",
+ "commit": {
+ "id": "80dd40214a58622312393b2ae693756a4781fab2",
+ "message": "x拟增\n\nSigned-off-by: yystopf ",
+ "author": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "committer": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "time_ago": "1天前",
+ "timestamp": "2022-07-13T09:54:15Z"
+ },
+ "protected": false,
+ "user_can_push": true,
+ "user_can_merge": true,
+ "commit_id": "80dd40214a58622312393b2ae693756a4781fab2",
+ "commit_time_from_now": "1天前",
+ "commit_time": "2022-07-13T09:54:15Z",
+ "default_branch": "master",
+ "http_url": "http://127.0.0.1:10081/yystopf/ceshi_hook.git",
+ "zip_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.zip",
+ "tar_url": "http://localhost:3000/api/yystopf/ceshi_hook/archive/new_branch_8.tar.gz"
+}
+```
+
+## 仓库贡献者列表
+仓库贡献者列表
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/yystopf/csfjkkj/contributors.json
+```
+
+```javascript
+await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
+```
+
+### HTTP 请求
+`GET /api/:owner/:repo/contributors.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| |string |用户登录名 |
+|repo |是| |string |项目标识identifier |
+
+
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|list.contributions |int |贡献者commit数量|
+|list.login |string|贡献者标识|
+|list.type |string|贡献者类型|
+|list.name |string|贡献者昵称|
+|list.image_url |string|贡献者头像地址|
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "list": [
+ {
+ "contributions": 2411,
+ "login": "yystopf",
+ "type": "User",
+ "name": "heh",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ {
+ "contributions": 6,
+ "login": "testforge3",
+ "type": null,
+ "name": "testforge3",
+ "image_url": "system/lets/letter_avatars/2/T/132_143_60/120.png"
+ }
+ ],
+ "total_count": 2
+}
+```
+
+## 仓库开发语言
+仓库开发语言组成
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/yystopf/csfjkkj/languages.json
+```
+
+```javascript
+await octokit.request('GET /api/yystopf/csfjkkj/languages.json')
+```
+
+### HTTP 请求
+`GET /api/:owner/:repo/languages.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| |string |用户登录名 |
+|repo |是| |string |项目标识identifier |
+
+
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|key |string |语言类型|
+|value |string |语言占比|
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "Go": "99.0%",
+ "Shell": "0.4%",
+ "Smarty": "0.4%",
+ "Makefile": "0.2%"
+}
+```
+
## 编辑仓库信息
编辑仓库信息
@@ -829,6 +1093,138 @@ await octokit.request('GET /api/yystopf/ceshi/files.json')
]
```
+## 提交文件到仓库
+提交文件到仓库,支持批量
+
+> 示例:
+
+```shell
+curl -X POST \
+-d "files[][action_type]=create" \
+-d "files[][content]=jfksj" \
+-d "files[][encoding]=text" \
+-d "files[][file_path]=heihei8" \
+-d "author_email=yystopf@163.com" \
+-d "author_name=yystopf" \
+-d "author_timeunix=1658214400" \
+-d "committer_email=yystopf@163.com" \
+-d "committer_name=yystopf" \
+-d "committer_timeunix=1658214400" \
+-d "branch=develop" \
+-d "new_branch=develop_ceshi" \
+-d "message=测试提交" \
+http://localhost:3000/api/v1/yystopf/ceshi/contents/batch.json
+```
+
+```javascript
+await octokit.request('POST /api/v1/yystopf/ceshi/contents/batch.json')
+```
+
+### HTTP 请求
+`POST /api/v1/:owner/:repo/contents/batch`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| |string |用户登录名 |
+|repo |是| |string |项目标识identifier |
+|files.action_type |是| |string|操作类型 create: 创建 update: 更新 delete: 删除|
+|files.content |是| |string|文件内容|
+|files.encoding |是| |string|文件编码方式 text 文本 base64 加密|
+|files.file_path |是| |string|文件路径|
+|author_email |是| |string|作者邮箱|
+|author_name |是| |string|作者名称|
+|author_timeunix |是| |int|编码时间,精确到秒|
+|committer_email |是| |string|提交者邮箱|
+|committer_name |是| |string|提交者名称|
+|committer_timeunix|是| |int|提交时间戳,精确到秒|
+|branch |是| |string|提交分支|
+|new_branch |否| |string|如果需要创建新分支,这个需要填|
+|message |是| |string|提交信息|
+
+> 请求的JSON示例:
+
+```json
+{
+ "files": [
+ {
+ "action_type": "create",
+ "content": "jfksj",
+ "encoding": "text",
+ "file_path": "heihei7"
+ }
+ ],
+ "author_email": "yystopf@163.com",
+ "author_name": "yystopf",
+ "author_timeunix": 1658214400,
+ "committer_email": "yystopf@163.com",
+ "committer_name": "yystopf",
+ "committer_timeunix": 1658214400,
+ "branch": "hh_ceshi",
+ "message": "测试提交"
+}
+```
+
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|commit.sha |string |提交ID|
+|commit.author |object |作者|
+|commit.committer |object |提交者|
+|commit.commit_message|string |提交信息|
+|commit.parent_shas |array |父节点commit ID|
+|commit.authored_time|int |编码时间|
+|commit.commited_time|int |提交时间|
+|contents.name |string |文件名称|
+|contents.path |string |文件路径|
+|contents.sha |string |文件标识|
+|contents.type |string |文件类型|
+|contents.size |int |文件大小|
+|contents.url |string |文件地址|
+|contents.encoding |string |编码类型 text 文本 base64 加密 |
+|contents.content |string |文件内容|
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "commit": {
+ "sha": "7c1e25f9b974e4b7a3816bd7f5e49b441078e999",
+ "author": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "committer": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "commit_message": "测试提交\n",
+ "parent_shas": [
+ "9aec816d0f3600082ca77893290a14bd29d805fe"
+ ],
+ "authored_time": 1658214400,
+ "commited_time": 1658214400
+ },
+ "contents": [
+ {
+ "name": "heihei7",
+ "path": "heihei7",
+ "sha": "f0acac8efb3021b0f6a7b13b42d033d86e076a4b",
+ "type": "file",
+ "size": 5,
+ "encoding": "base64",
+ "content": "amZrc2o="
+ }
+ ]
+}
+```
## 获取仓库代码目录
获取仓库代码目录
@@ -1042,71 +1438,665 @@ await octokit.request('GET /api/yystopf/csfjkkj/readme.json')
Success Data.
-## 获取仓库贡献者
-获取仓库贡献者
+
+## 获取文件树列表
+根据分支、标签、commit ID获取仓库文件树列表
> 示例:
```shell
curl -X GET \
--d "ref=master" \
--d "filepath=lib" \
-http://localhost:3000/api/yystopf/csfjkkj/contributors.json
+-d "recursive=true" \
+-d "page=1" \
+-d "limit=1" \
+http://localhost:3000/api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json
```
```javascript
-await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
+await octokit.request('GET /api/v1/yystopf/csfjkkj/git/trees/80dd40214a58622312393b2ae693756a4781fab2.json')
```
### HTTP 请求
-`GET /api/:owner/:repo/contributors.json`
+`GET /api/v1/:owner/:repo/git/trees/:sha.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
--------- | ------- | ------- | -------- | ----------
-|owner |是| |string |用户登录名 |
-|repo |是| |string |项目标识identifier |
-|ref |否| | string |分支名称、tag名称或是提交记录id,默认为整个仓库 |
-|filepath |否| | string |子目录名称,默认为空 |
-
+|owner |是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|sha |是| | string |分支名称、tag名称或是提交记录id |
+|recursive|否| | bool |是否显示目录|
+|page |否|1 | int |页码|
+|limit |否|15| int |分页个数|
### 返回字段说明:
参数 | 类型 | 字段说明
--------- | ----------- | -----------
-|total_count |integer|贡献者数量|
-|contributions |integer|贡献数量|
-|login |string |用户登录名 |
-|type |string|用户类型 |
-|name |string|用户昵称|
-|image_url |string|用户头像|
+|total_count |int |文件树数量|
+|sha |string |查询分支、标签、commit_id最后一次提交的ID |
+|entries.name |string |文件树名称|
+|entries.mode |string |文件树权限|
+|entries.type |string |文件树类型, file:文件,dir: 文件夹|
+|entries.size |int |文件树大小|
+|entries.sha |string |文件树commit_ID|
> 返回的JSON示例:
```json
{
- "contributors": [
+ "total_count": 13,
+ "sha": "80dd40214a58622312393b2ae693756a4781fab2",
+ "entries": [
{
- "contributions": 5,
- "login": "testforge2",
- "type": "User",
- "name": "testforge2",
- "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png"
- },
- {
- "contributions": 79,
- "login": "yystopf",
- "type": "User",
- "name": "yystopf",
- "image_url": "system/lets/letter_avatars/2/Y/241_125_89/120.png"
+ "name": "README.md",
+ "mode": "100644",
+ "type": "file",
+ "size": 14,
+ "sha": "b2f7b457fd8ca55f2274032cbb2abcb7dd8cd57e"
}
- ],
- "total_count": 2
+ ]
}
```
+## 获取仓库blobs内容
+根据commit ID获取仓库blobs内容
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/git/blobs/80dd40214a58622312393b2ae693756a4781fab2.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/git/blobs/:sha.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner|是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|sha |是| | string |提交记录id |
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|sha |string |提交ID |
+|size |int |blobs大小|
+|encoding |string |内容编码模式|
+|content |string |blobs内容|
+
+> 返回的JSON示例:
+
+```json
+{
+ "sha": "80dd40214a58622312393b2ae693756a4781fab2",
+ "size": 247,
+ "encoding": "base64",
+ "content": "dHJlZSAyN2JjYjI2ZDQ5YmU1M2RmOGZmYTk5NDc3MjRkYmI3YzIzZWI4MjY4CnBhcmVudCA3ZTRkOGJiM2MyOGUyNGQ0Y2Q2YjIwNWYyZWVkMzI1MTNlOTM3NTI0CmF1dGhvciB5eXN0b3BmIDx5eXN0b3BmQDE2My5jb20+IDE2NTc3MDYwNTUgKzAwMDAKY29tbWl0dGVyIHl5c3RvcGYgPHl5c3RvcGZAMTYzLmNvbT4gMTY1NzcwNjA1NSArMDAwMAoKeOaLn+WingoKU2lnbmVkLW9mZi1ieTogeXlzdG9wZiA8eXlzdG9wZkAxNjMuY29tPg=="
+}
+```
+
+
+## 获取仓库提交列表
+根据分支名、标签、commit ID来获取提交列表
+
+> 示例:
+
+```shell
+curl -X GET \
+-d "sha=master" \
+-d "page=1" \
+-d "limit=1" \
+http://localhost:3000/api/v1/yystopf/csfjkkj/commits.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/commits.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/commits.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner|是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|sha |否| | string |分支名、标签名或Commit ID|
+|page |否| | int |页码|
+|limit|否| | int |每页数量|
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|total_count|int|提交总数|
+|commits.sha|string|提交ID|
+|commits.author|object|提交作者|
+|commits.committer|object|提交者|
+|commits.commit_message|string|提交信息|
+|commits.parent_shas|array|提交父节点ID|
+|commits.files|array|提交文件|
+|commits.commit_date|string|提交日期|
+|commits.commit_time|string|提交时间|
+|commits.branch|string|提交分支|
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "total_count": 12,
+ "commits": [
+ {
+ "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "parent_shas": [
+ "411e4d259785241f1bd14faf99ca24fd1b802f2a"
+ ],
+ "files": [
+ "hd.txt"
+ ],
+ "commit_date": "2022-07-05",
+ "commit_time": "2022-07-05 11:00:45",
+ "branch": "hh_ceshi"
+ }
+ ]
+}
+```
+
+
+## 获取单个提交的blame信息
+根据commit ID获取blame信息
+
+> 示例:
+
+```shell
+curl -X GET http://localhost:3000/api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/commits/80dd40214a58622312393b2ae693756a4781fab2/diff.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/commits/:sha/diff.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner|是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|sha |是| | string |提交记录id |
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|file_nums|int|文件数量|
+|total_addition|int|新增行数|
+|total_deletion|int|删除行数|
+|files.name|string|文件名称|
+|files.oldname|string|文件修改前名称|
+|files.addition|int|文件新增行数|
+|files.deletion|int|文件删除行数|
+|files.type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制|
+|files.is_created|bool|是否为新建文件|
+|files.is_deleted|bool|是否为删除文件|
+|files.is_bin|bool|是否为二进制文件|
+|files.is_lfs_file|bool||
+|files.is_renamed|bool|是否重命名|
+|files.is_ambiguous|bool||
+|files.is_submodule|bool|是否为子模块|
+|files.sections.file_name|string|文件名称|
+|files.sections.name|string||
+|files.sections.lines.left_index|int||
+|files.sections.lines.right_index|int||
+|files.sections.lines.match|int||
+|files.sections.lines.type|int||
+|files.sections.lines.content|string||
+|files.sections.lines.section_path|string||
+|files.sections.lines.section_last_left_index|int||
+|files.sections.lines.section_last_right_index|int||
+|files.sections.lines.section_left_index|int||
+|files.sections.lines.section_right_index|int||
+|files.sections.lines.section_left_hunk_size|int||
+|files.sections.lines.section_right_hunk_size|int||
+
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "file_nums": 1,
+ "total_addition": 1,
+ "total_deletion": 0,
+ "files": [
+ {
+ "name": "xinzeng3",
+ "oldname": "xinzeng3",
+ "addition": 1,
+ "deletion": 0,
+ "type": 1,
+ "is_created": true,
+ "is_deleted": false,
+ "is_bin": false,
+ "is_lfs_file": false,
+ "is_renamed": false,
+ "is_ambiguous": false,
+ "is_submodule": false,
+ "sections": [
+ {
+ "file_name": "xinzeng3",
+ "name": "",
+ "lines": [
+ {
+ "left_index": 0,
+ "right_index": 0,
+ "match": 0,
+ "type": 4,
+ "content": "@@ -0,0 +1 @@",
+ "section_path": "xinzeng3",
+ "section_last_left_index": 0,
+ "section_last_right_index": 0,
+ "section_left_index": 0,
+ "section_right_index": 1,
+ "section_left_hunk_size": 0,
+ "section_right_hunk_size": 0
+ },
+ {
+ "left_index": 0,
+ "right_index": 1,
+ "match": -1,
+ "type": 2,
+ "content": "+1111122222"
+ }
+ ]
+ }
+ ],
+ "is_incomplete": false,
+ "is_incomplete_line_too_long": false,
+ "is_protected": false
+ }
+ ]
+}
+```
+
+
+## 获取单个文件的blame信息
+根据分支、标签、commitID获取某个文件的blame信息
+
+> 示例:
+
+```shell
+curl -X GET \
+-d "sha=master" \
+-d "filepath=hd.txt" \
+http://localhost:3000/api/v1/yystopf/csfjkkj/blame.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/blame.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/blame.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner |是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|sha |是| | string |分支、标签或提交记录id |
+|filepath|是| | string |文件路径|
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|file_size|int|文件大小|
+|file_name|string|文件名称|
+|num_lines|int|文件总行数|
+|blame_parts.commit|object|提交|
+|blame_parts.current_number|int|当前行数|
+|blame_parts.effect_line|int|影响的行数|
+|blame_parts.lines|array|行内容|
+
+> 返回的JSON示例:
+
+```json
+{
+ "file_size": 32,
+ "file_name": "hd.txt",
+ "num_lines": 12,
+ "blame_parts": [
+ {
+ "commit": {
+ "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "authored_time": "2022-07-04 18:41:25",
+ "committed_time": "2022-07-04 18:41:25",
+ "created_time": "2022-07-04 18:41:25"
+ },
+ "current_number": 1,
+ "effect_line": 5,
+ "lines": [
+ "dkfj",
+ "s",
+ "324",
+ "234",
+ "2"
+ ]
+ },
+ {
+ "commit": {
+ "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "authored_time": "2022-07-05 11:00:45",
+ "committed_time": "2022-07-05 11:00:45",
+ "created_time": "2022-07-05 11:00:45"
+ },
+ "current_number": 6,
+ "effect_line": 1,
+ "lines": [
+ "dd"
+ ]
+ },
+ {
+ "commit": {
+ "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "authored_time": "2022-07-04 18:41:25",
+ "committed_time": "2022-07-04 18:41:25",
+ "created_time": "2022-07-04 18:41:25"
+ },
+ "current_number": 7,
+ "effect_line": 3,
+ "lines": [
+ "23",
+ "4",
+ "23"
+ ]
+ },
+ {
+ "commit": {
+ "sha": "86c62a1e91c07b58b8aa6c89b94856d89c0f7e55",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "authored_time": "2022-07-05 11:00:45",
+ "committed_time": "2022-07-05 11:00:45",
+ "created_time": "2022-07-05 11:00:45"
+ },
+ "current_number": 10,
+ "effect_line": 1,
+ "lines": [
+ "s1"
+ ]
+ },
+ {
+ "commit": {
+ "sha": "40f76e80bf5bc41fcc94c28ca8a6eab506c15215",
+ "author": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "committer": {
+ "id": null,
+ "login": "viletyy",
+ "name": "viletyy",
+ "type": null,
+ "image_url": "system/lets/letter_avatars/2/V/39_141_222/120.png"
+ },
+ "commit_message": "fix\n",
+ "authored_time": "2022-07-04 18:41:25",
+ "committed_time": "2022-07-04 18:41:25",
+ "created_time": "2022-07-04 18:41:25"
+ },
+ "current_number": 11,
+ "effect_line": 1,
+ "lines": [
+ ""
+ ]
+ }
+ ]
+}
+```
+
+## 获取比较提交blame
+根据分支名、标签、commit ID来获取代码对比blame
+
+> 示例:
+
+```shell
+curl -X GET \
+-d "from=hh_ceshi" \
+-d "to=master" \
+http://localhost:3000/api/v1/yystopf/csfjkkj/compare.json
+```
+
+```javascript
+await octokit.request('GET /api/v1/yystopf/csfjkkj/compare.json')
+```
+
+### HTTP 请求
+`GET /api/v1/:owner/:repo/compare.json`
+
+### 请求参数:
+参数 | 必选 | 默认 | 类型 | 字段说明
+--------- | ------- | ------- | -------- | ----------
+|owner|是| | string |用户登录名 |
+|repo |是| | string |项目标识identifier |
+|from |是| | string |源分支、标签、commitID |
+|to|是||string|目标分支、标签、commitID|
+### 返回字段说明:
+参数 | 类型 | 字段说明
+--------- | ----------- | -----------
+|commits_count|int|提交数量|
+|commits.branch|string|提交分支|
+|commits.author|object|提交作者|
+|commits.committer|object|提交者|
+|commits.commit_message|string|提交信息|
+|commits.sha|string|提交ID|
+|commits.parent_shas|array|提交父节点ID|
+|diff.file_nums|int|文件数量|
+|diff.total_addition|int|新增行数|
+|diff.total_deletion|int|删除行数|
+|diff.files.name|string|文件名称|
+|diff.files.oldname|string|文件修改前名称|
+|diff.files.addition|int|文件新增行数|
+|diff.files.deletion|int|文件删除行数|
+|diff.files.type|int|文件类型 1: 新增 2: 更改 3: 删除 4: 重命名 5: 复制|
+|diff.files.is_created|bool|是否为新建文件|
+|diff.files.is_deleted|bool|是否为删除文件|
+|diff.files.is_bin|bool|是否为二进制文件|
+|diff.files.is_lfs_file|bool||
+|diff.files.is_renamed|bool|是否重命名|
+|diff.files.is_ambiguous|bool||
+|diff.files.is_submodule|bool|是否为子模块|
+|diff.files.sections.file_name|string|文件名称|
+|diff.files.sections.name|string||
+|diff.files.sections.lines.left_index|int||
+|diff.files.sections.lines.right_index|int||
+|diff.files.sections.lines.match|int||
+|diff.files.sections.lines.type|int||
+|diff.files.sections.lines.content|string||
+|diff.files.sections.lines.section_path|string||
+|diff.files.sections.lines.section_last_left_index|int||
+|diff.files.sections.lines.section_last_right_index|int||
+|diff.files.sections.lines.section_left_index|int||
+|diff.files.sections.lines.section_right_index|int||
+|diff.files.sections.lines.section_left_hunk_size|int||
+|diff.files.sections.lines.section_right_hunk_size|int||
+
+
+
+> 返回的JSON示例:
+
+```json
+{
+ "commits_count": 1,
+ "last_commit_sha": "80dd40214a58622312393b2ae693756a4781fab2",
+ "commits": [
+ {
+ "author": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "committer": {
+ "id": "2",
+ "login": "yystopf",
+ "name": "heh",
+ "type": "User",
+ "image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
+ },
+ "branch": "",
+ "commit_message": "x拟增\n\nSigned-off-by: yystopf ",
+ "sha": "7e4d8bb3c28e24d4cd6b205f2eed32513e937524",
+ "parent_shas": null
+ }
+ ],
+ "diff": {
+ "file_nums": 1,
+ "total_addition": 1,
+ "total_deletion": 0,
+ "files": [
+ {
+ "name": "ceshi123",
+ "oldname": "ceshi123",
+ "addition": 1,
+ "deletion": 0,
+ "type": 1,
+ "is_created": true,
+ "is_deleted": false,
+ "is_bin": false,
+ "is_lfs_file": false,
+ "is_renamed": false,
+ "is_ambiguous": false,
+ "is_submodule": false,
+ "sections": [
+ {
+ "file_name": "ceshi123",
+ "name": "",
+ "lines": [
+ {
+ "left_index": 0,
+ "right_index": 0,
+ "match": 0,
+ "type": 4,
+ "content": "@@ -0,0 +1 @@",
+ "section_path": "ceshi123",
+ "section_last_left_index": 0,
+ "section_last_right_index": 0,
+ "section_left_index": 0,
+ "section_right_index": 1,
+ "section_left_hunk_size": 0,
+ "section_right_hunk_size": 0
+ },
+ {
+ "left_index": 0,
+ "right_index": 1,
+ "match": -1,
+ "type": 2,
+ "content": "+1111122222"
+ }
+ ]
+ }
+ ],
+ "is_incomplete": false,
+ "is_incomplete_line_too_long": false,
+ "is_protected": false
+ }
+ ]
+ }
+}
+```
+
## 获取仓库webhooks列表
获取仓库webhooks列表
@@ -1115,15 +2105,15 @@ await octokit.request('GET /api/yystopf/csfjkkj/contributors.json')
```shell
curl -X GET \
-http://localhost:3000/api/yystopf/ceshi/webhooks.json
+http://localhost:3000/api/v1/yystopf/ceshi/webhooks.json
```
```javascript
-await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
+await octokit.request('GET /api/v1/yystopf/ceshi/webhooks.json')
```
### HTTP 请求
-`GET /api/:owner/:repo/webhooks.json`
+`GET /api/v1/:owner/:repo/webhooks.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
@@ -1139,7 +2129,6 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
|url |string|地址|
|http_method |string|请求方式|
|is_active |bool |是否激活|
-|type |string|类型|
|last_status |string|最后一次推送的状态|
|create_time |string|创建时间|
@@ -1155,7 +2144,6 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
"url": "https://oapi.dingtalk.com/robot/send?access_token=7e1e19d0eddb6a5e33c5c2c4e66f4c88f9437184b9ed2c2653194c6374c7d513",
"http_method": "",
"is_active": true,
- "type": "dingtalk",
"last_status": "succeed",
"create_time": "2021-07-12 10:50:07"
},
@@ -1164,7 +2152,6 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
"url": "http://localhost:3000",
"http_method": "GET",
"is_active": true,
- "type": "gitea",
"last_status": "succeed",
"create_time": "2021-07-26 10:03:45"
},
@@ -1173,7 +2160,6 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
"url": "http://localhost:10081",
"http_method": "POST",
"is_active": true,
- "type": "gitea",
"last_status": "waiting",
"create_time": "2021-07-26 16:56:53"
},
@@ -1182,7 +2168,6 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
"url": "http://localhost:3001",
"http_method": "POST",
"is_active": true,
- "type": "gitea",
"last_status": "fail",
"create_time": "2021-07-26 16:58:23"
}
@@ -1200,15 +2185,15 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks.json')
```shell
curl -X GET \
-http://localhost:3000/api/yystopf/ceshi/webhooks/3/edit.json
+http://localhost:3000/api/v1/yystopf/ceshi/webhooks/3.json
```
```javascript
-await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
+await octokit.request('GET /api/v1/yystopf/ceshi/webhooks/3.json')
```
### HTTP 请求
-`GET /api/:owner/:repo/webhooks/:id/edit.json`
+`GET /api/v1/:owner/:repo/webhooks/:id.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
@@ -1226,36 +2211,21 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
|content_type |string|POST Content Type|
|http_method |string|请求方式|
|secret| |string|密钥|
-|is_active |bool |是否激活|
-|type |string|类型|
-|last_status |string|最后一次推送的状态, waiting 等待,fail 失败,succeed 成功|
+|active |bool |是否激活|
|branch_filter |string|分支过滤|
|events |string|触发条件|
-|create_time |string|创建时间|
+|create_at |string|创建时间|
参数| 含义|
--------- | ------- | ------- |
|create|创建分支或标签|
|delete|分支或标签删除|
-|fork|仓库被fork|
|push|git仓库推送|
-|issue|疑修已打开、已关闭、已重新打开或编辑|
-|issue_assign|疑修被指派|
-|issue_label|疑修标签被更新或删除|
-|issue_milestone|疑修被收入里程碑|
-|issue_comment|疑修评论|
|pull_request|合并请求|
|pull_request_assign|合并请求被指派|
-|pull_request_label|合并请求被贴上标签|
-|pull_request_milestone|合并请求被记录于里程碑中|
-|pull_request_comment|合并请求被评论|
|pull_request_review_approved|合并请求被批准|
|pull_request_review_rejected|合并请求被拒绝|
-|pull_request_review_comment|合并请求被提出审查意见|
-|pull_request_sync|合并请求被同步|
-|repository|创建或删除仓库|
-|release|版本发布|
> 返回的JSON示例:
@@ -1266,31 +2236,15 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
"http_method": "GET",
"content_type": "form",
"url": "http://localhost:3000",
- "secret": "123456",
- "last_status": "succeed",
- "is_active": true,
- "type": "gitea",
- "create_time": "2021-07-26 10:03:45",
+ "active": true,
+ "create_at": "2021-07-26 10:03",
"branch_filter": "*",
"events": [
"create",
"delete",
- "fork",
- "issues",
- "issue_assign",
- "issue_label",
- "issue_milestone",
- "issue_comment",
"push",
"pull_request",
"pull_request_assign",
- "pull_request_label",
- "pull_request_milestone",
- "pull_request_comment",
- "pull_request_review",
- "pull_request_sync",
- "repository",
- "release"
]
}
```
@@ -1305,15 +2259,15 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json')
```shell
curl -X POST \
-http://localhost:3000/api/yystopf/ceshi/webhooks.json
+http://localhost:3000/api/v1/yystopf/ceshi/webhooks.json
```
```javascript
-await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
+await octokit.request('POST /api/v1/yystopf/ceshi/webhooks.json')
```
### HTTP 请求
-`POST /api/:owner/:repo/webhooks.json`
+`POST /api/v1/:owner/:repo/webhooks.json`
### 请求参数:
参数 | 必选 | 默认 | 类型 | 字段说明
@@ -1321,7 +2275,6 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
|owner |是| | string |用户登录名 |
|repo |是| | string |项目标识identifier |
|webhook.url |是| | string |目标url |
-|webhook.type |否| | string |类型|
|webhook.http_method |是| | string | http方法, POST和GET |
|webhook.content_type |是| | string | POST Content Type |
|webhook.secret |否| | string |密钥文本|
@@ -1335,24 +2288,11 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
--------- | ------- | ------- |
|create|创建分支或标签|
|delete|分支或标签删除|
-|fork|仓库被fork|
|push|git仓库推送|
-|issue|疑修已打开、已关闭、已重新打开或编辑|
-|issue_assign|疑修被指派|
-|issue_label|疑修标签被更新或删除|
-|issue_milestone|疑修被收入里程碑|
-|issue_comment|疑修评论|
|pull_request|合并请求|
|pull_request_assign|合并请求被指派|
-|pull_request_label|合并请求被贴上标签|
-|pull_request_milestone|合并请求被记录于里程碑中|
-|pull_request_comment|合并请求被评论|
|pull_request_review_approved|合并请求被批准|
|pull_request_review_rejected|合并请求被拒绝|
-|pull_request_review_comment|合并请求被提出审查意见|
-|pull_request_sync|合并请求被同步|
-|repository|创建或删除仓库|
-|release|版本发布|
> 请求的JSON示例:
@@ -1385,15 +2325,22 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
```json
{
- "id": 18,
- "type": "gitea",
+ "id": 68,
"content_type": "json",
- "url": "http://localhost:10000",
+ "http_method": "GET",
+ "url": "http://127.0.0.1:3000",
"events": [
- "push"
+ "create",
+ "delete",
+ "push",
+ "pull_request",
+ "pull_request_assign",
+ "pull_request_review_approved",
+ "pull_request_review_rejected"
],
"active": true,
- "create_time": "2021-07-26 18:53:43"
+ "branch_filter": "*",
+ "created_at": "2022-06-23 15:52"
}
```