mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-20 11:45:57 +08:00
Merge remote-tracking branch 'origin/standalone_develop' into standalone_develop
This commit is contained in:
18
app/controllers/api/v1/base_controller.rb
Normal file
18
app/controllers/api/v1/base_controller.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
class Api::V1::BaseController < ApplicationController
|
||||
|
||||
include Api::ProjectHelper
|
||||
include Api::UserHelper
|
||||
|
||||
before_action :doorkeeper_authorize!
|
||||
skip_before_action :user_setup
|
||||
|
||||
protected
|
||||
def current_user
|
||||
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
|
||||
end
|
||||
|
||||
def require_manager_above
|
||||
@project = load_project
|
||||
return render_forbidden unless current_user.admin? && @project.manager?(current_user)
|
||||
end
|
||||
end
|
||||
55
app/controllers/api/v1/projects/webhooks_controller.rb
Normal file
55
app/controllers/api/v1/projects/webhooks_controller.rb
Normal file
@@ -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
|
||||
11
app/controllers/api/v1/projects_controller.rb
Normal file
11
app/controllers/api/v1/projects_controller.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class Api::V1::ProjectsController < Api::V1::BaseController
|
||||
before_action :load_project, only: [:show]
|
||||
|
||||
def index
|
||||
render_ok
|
||||
end
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token)
|
||||
end
|
||||
end
|
||||
13
app/controllers/api/v1/users/projects_controller.rb
Normal file
13
app/controllers/api/v1/users/projects_controller.rb
Normal file
@@ -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
|
||||
6
app/controllers/api/v1/users_controller.rb
Normal file
6
app/controllers/api/v1/users_controller.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
class Api::V1::UsersController < Api::V1::BaseController
|
||||
|
||||
def index
|
||||
render_ok
|
||||
end
|
||||
end
|
||||
@@ -170,7 +170,10 @@ class ApplicationController < ActionController::Base
|
||||
# 未授权的捕捉407,弹试用申请弹框
|
||||
def require_login
|
||||
#6.13 -hs
|
||||
|
||||
if request.headers["Authorization"].present?
|
||||
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
|
||||
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id) if @doorkeeper_token.present?
|
||||
end
|
||||
tip_exception(401, "请登录后再操作") unless User.current.logged?
|
||||
end
|
||||
|
||||
@@ -265,8 +268,11 @@ class ApplicationController < ActionController::Base
|
||||
User.current = user
|
||||
end
|
||||
end
|
||||
|
||||
# if !User.current.logged? && Rails.env.development?
|
||||
# User.current = User.find 1
|
||||
# user = User.find 1
|
||||
# User.current = user
|
||||
# start_user_session(user)
|
||||
# end
|
||||
|
||||
|
||||
@@ -681,7 +687,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
20
app/controllers/concerns/api/project_helper.rb
Normal file
20
app/controllers/concerns/api/project_helper.rb
Normal file
@@ -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 not founded"
|
||||
@project
|
||||
else
|
||||
logger.info "###########:project not found"
|
||||
@project = nil
|
||||
render_not_found and return
|
||||
end
|
||||
@project
|
||||
end
|
||||
end
|
||||
19
app/controllers/concerns/api/user_helper.rb
Normal file
19
app/controllers/concerns/api/user_helper.rb
Normal file
@@ -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
|
||||
@@ -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}"
|
||||
|
||||
@@ -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}
|
||||
|
||||
39
app/controllers/oauth2_controller.rb
Normal file
39
app/controllers/oauth2_controller.rb
Normal file
@@ -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
|
||||
42
app/controllers/projects/project_invite_links_controller.rb
Normal file
42
app/controllers/projects/project_invite_links_controller.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
20
app/controllers/reviews_controller.rb
Normal file
20
app/controllers/reviews_controller.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
- <a href='https://www.trustie.net/login?login=false'>Sign Up for a User</a>
|
||||
- <a href='https://www.trustie.net'>Powered by Trustie</a>
|
||||
- <a href='https://www.gitlink.org.cn/login'>Sign In for a User</a>
|
||||
- <a href='https://www.gitlink.org.cn'>Powered by GitLink</a>
|
||||
|
||||
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.
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
## 申请加入项目
|
||||
申请加入项目
|
||||
|
||||
@@ -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,162 @@ await octokit.request('GET /api/yystopf/csfjkkj/tags.json')
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## 仓库分支列表
|
||||
仓库分支列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/csfjkkj/branches.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/csfjkkj/branches.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/branches.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 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%"
|
||||
}
|
||||
```
|
||||
|
||||
## 编辑仓库信息
|
||||
编辑仓库信息
|
||||
|
||||
@@ -1115,15 +1287,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 +1311,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 +1326,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 +1334,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 +1342,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 +1350,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 +1367,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 +1393,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 +1418,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 +1441,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 +1457,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 +1470,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 +1507,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"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
@@ -1407,15 +1536,15 @@ await octokit.request('POST /api/yystopf/ceshi/webhooks.json')
|
||||
|
||||
```shell
|
||||
curl -X PATCH \
|
||||
http://localhost:3000/api/yystopf/ceshi/webhooks/7.json
|
||||
http://localhost:3000/api/v1/yystopf/ceshi/webhooks/7.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|
||||
await octokit.request('PATCH /api/v1/yystopf/ceshi/webhooks/7.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`PATCH /api/:owner/:repo/webhooks/:id.json`
|
||||
`PATCH /api/v1/:owner/:repo/webhooks/68.json`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
@@ -1424,7 +1553,6 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|
||||
|repo |是| | string |项目标识identifier |
|
||||
|id |是| | string |webhook id |
|
||||
|webhook.url |是| | string |目标url |
|
||||
|webhook.type |否| | string |类型|
|
||||
|webhook.http_method |是| | string | http方法, POST和GET |
|
||||
|webhook.content_type |是| | string | POST Content Type |
|
||||
|webhook.secret |否| | string |密钥文本|
|
||||
@@ -1438,24 +1566,11 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.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示例:
|
||||
@@ -1478,8 +1593,22 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
"id": 68,
|
||||
"content_type": "json",
|
||||
"http_method": "GET",
|
||||
"url": "http://127.0.0.1:3000",
|
||||
"events": [
|
||||
"create",
|
||||
"delete",
|
||||
"push",
|
||||
"pull_request",
|
||||
"pull_request_assign",
|
||||
"pull_request_review_approved",
|
||||
"pull_request_review_rejected"
|
||||
],
|
||||
"active": true,
|
||||
"branch_filter": "*",
|
||||
"created_at": "2022-06-23 15:52"
|
||||
}
|
||||
```
|
||||
<aside class="success">
|
||||
@@ -1494,15 +1623,15 @@ await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json')
|
||||
|
||||
```shell
|
||||
curl -X DELETE \
|
||||
http://localhost:3000/api/yystopf/ceshi/webhooks/7.json
|
||||
http://localhost:3000/api/v1/yystopf/ceshi/webhooks/7.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('DELETE /api/yystopf/ceshi/webhooks/7.json')
|
||||
await octokit.request('DELETE /api/v1/yystopf/ceshi/webhooks/7.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`DELETE /api/:owner/:repo/webhooks/:id.json`
|
||||
`DELETE /api/v1/:owner/:repo/webhooks/:id.json`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
@@ -1532,15 +1661,15 @@ await octokit.request('DELETE /api/yystopf/ceshi/webhooks/7.json')
|
||||
|
||||
```shell
|
||||
curl -X GET \
|
||||
http://localhost:3000/api/yystopf/ceshi/webhooks/3/tasks.json
|
||||
http://localhost:3000/api/v1/yystopf/ceshi/webhooks/3/hooktasks.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/ceshi/webhooks/3/tasks.json')
|
||||
await octokit.request('GET /api/v1/yystopf/ceshi/webhooks/3/hooktasks.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/webhooks/:id/tasks.json`
|
||||
`GET /api/v1/:owner/:repo/webhooks/:id/hooktasks.json`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
@@ -1568,7 +1697,7 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/tasks.json')
|
||||
```json
|
||||
{
|
||||
"total_count": 6,
|
||||
"tasks": [
|
||||
"hooktasks": [
|
||||
{
|
||||
"id": 20,
|
||||
"type": "gitea",
|
||||
@@ -1744,15 +1873,15 @@ await octokit.request('GET /api/yystopf/ceshi/webhooks/3/tasks.json')
|
||||
|
||||
```shell
|
||||
curl -X POST \
|
||||
http://localhost:3000/api/yystopf/ceshi/webhooks/3/test.json
|
||||
http://localhost:3000/api/v1/yystopf/ceshi/webhooks/3/tests.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/ceshi/webhooks/3/test.json')
|
||||
await octokit.request('POST /api/v1/yystopf/ceshi/webhooks/3/tests.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/webhooks/:id/test.json`
|
||||
`POST /api/v1/:owner/:repo/webhooks/:id/tests.json`
|
||||
|
||||
### 请求参数:
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
|
||||
@@ -47,6 +47,105 @@ await octokit.request('GET /api/users/me.json')
|
||||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 用户项目列表
|
||||
获取用户项目列表
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/v1/:login/projects.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/v1/:login/projects.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET api/v1/yystopf/projects.json`
|
||||
|
||||
### 请求字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|login | string | 用户的用户名|
|
||||
|category | string | 归属项目,默认为全部项目, join: 参与项目, created: 创建项目, manage: 管理项目, watched: 关注项目, forked: 复刻项目 |
|
||||
|is_public | boolean | 公/私有项目,true为公开项目,false为私有项目|
|
||||
|project_type | string | 项目类型,common为托管项目, mirror为镜像项目, sync_mirror为同步镜像项目|
|
||||
|sort_by | string | 项目的排序字段,比如 created_on, updated_on等|
|
||||
|sort_direction | string | 排序的类型,desc 倒序,asc 正序|
|
||||
|limit | integer | 每页个数 |
|
||||
|page | integer | 页码 |
|
||||
|
||||
### 返回字段说明:
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|total_count | integer | 项目总数 |
|
||||
|projects.owner.id | integer | 项目拥有者id |
|
||||
|projects.owner.type | string | 项目拥有者类型,User 用户,Organization 组织 |
|
||||
|projects.owner.name | string | 项目拥有者名称|
|
||||
|projects.owner.login | string | 项目拥有者用户名 |
|
||||
|projects.owner.image_url | string | 项目拥有者头像地址 |
|
||||
|type | string | 项目类型,common 托管项目,mirror 镜像项目, sync 同步镜像项目 |
|
||||
|description | string | 项目描述 |
|
||||
|forked_count | integer | 项目复刻数量 |
|
||||
|forked_from_project_id | integer | 项目复刻来源项目 |
|
||||
|identifier | string | 项目标识 |
|
||||
|issues_count | integer | 项目issues数量|
|
||||
|pull_requests_count | integer | 项目合并请求数量 |
|
||||
|invite_code | string | 项目邀请码|
|
||||
|website | string | 项目网址|
|
||||
|platform | string | 项目平台 |
|
||||
|name | string | 项目名称|
|
||||
|open_devops | boolean | 项目是否开启工作流 |
|
||||
|praises_count | integer | 项目点赞数量|
|
||||
|is_public | boolean | 项目是否公开|
|
||||
|status | integer | 项目状态|
|
||||
|watchers_count | integer | 项目关注数量|
|
||||
|ignore_id | integer | 项目ignoreID|
|
||||
|license_id | integer | 项目许可证ID|
|
||||
|project_category_id | integer | 项目分类ID|
|
||||
|project_language_id | integer | 项目语言ID|
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
"total_count": 1,
|
||||
"projects": [
|
||||
{
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"type": "common",
|
||||
"description": null,
|
||||
"forked_count": 1,
|
||||
"forked_from_project_id": null,
|
||||
"identifier": "hahahah",
|
||||
"issues_count": 5,
|
||||
"pull_requests_count": 3,
|
||||
"invite_code": "8zfKtM",
|
||||
"website": null,
|
||||
"platform": "forge",
|
||||
"name": "hahahah",
|
||||
"open_devops": false,
|
||||
"praises_count": 0,
|
||||
"is_public": true,
|
||||
"status": 1,
|
||||
"watchers_count": 0,
|
||||
"ignore_id": null,
|
||||
"license_id": null,
|
||||
"project_category_id": null,
|
||||
"project_language_id": null
|
||||
}
|
||||
]
|
||||
```
|
||||
<aside class="success">
|
||||
Success Data.
|
||||
</aside>
|
||||
|
||||
## 用户消息列表
|
||||
获取用户消息列表
|
||||
|
||||
|
||||
8
app/forms/projects/project_invite_links/create_form.rb
Normal file
8
app/forms/projects/project_invite_links/create_form.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Projects::ProjectInviteLinks::CreateForm < BaseForm
|
||||
attr_accessor :user_id, :project_id, :role, :is_apply
|
||||
|
||||
validates :user_id, :project_id, :role, presence: true
|
||||
validates :role, inclusion: { in: %w(manager developer reporter), message: "请输入正确的权限." }
|
||||
validates :is_apply, inclusion: {in: [true, false], message: "请输入是否需要管理员审核."}
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ module ProjectsHelper
|
||||
end
|
||||
|
||||
def gitea_domain
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def find_user_by_login_or_mail(identifier)
|
||||
|
||||
@@ -1,218 +1,217 @@
|
||||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
def render_decode64_content(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
||||
end
|
||||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
||||
if author_json["id"].present?
|
||||
return find_user_by_gitea_uid author_json['id']
|
||||
end
|
||||
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
||||
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
if author_json["Name"].present? && author_json["Email"].present?
|
||||
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
||||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
|
||||
if image_type?(ext) || download_type(ext)
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub(s[0], "/#{s_content}")
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
def render_format_time_with_unix(unix_time)
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
# date for example: 2020-11-01T19:57:27+08:00
|
||||
def render_format_time_with_date(date)
|
||||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
||||
end
|
||||
if download_type(file_type)
|
||||
return entry['content']
|
||||
end
|
||||
render_decode64_content(entry['content'])
|
||||
end
|
||||
end
|
||||
|
||||
def base64_to_image(path, content)
|
||||
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
||||
content = Base64.decode64(content)
|
||||
File.open(path, 'wb') { |f| f.write(content) }
|
||||
end
|
||||
|
||||
def render_download_image_url(dir_path, file_path, content)
|
||||
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
||||
file_name = full_path.split("/")[-1]
|
||||
# 用户名/项目标识/文件路径
|
||||
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
||||
|
||||
file_path = [dir_path, file_name].join('/')
|
||||
|
||||
puts "##### render_download_image_url file_path: #{file_path}"
|
||||
base64_to_image(file_path, content)
|
||||
file_path = file_path[6..-1]
|
||||
File.join(base_url, file_path)
|
||||
end
|
||||
|
||||
def generate_dir_path(dir_path)
|
||||
# tmp_dir_path
|
||||
# eg: jasder/forgeplus/raw/branch/ref
|
||||
dir_path = ["public", tmp_dir, dir_path].join('/')
|
||||
puts "#### dir_path: #{dir_path}"
|
||||
unless Dir.exists?(dir_path)
|
||||
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
||||
end
|
||||
dir_path
|
||||
end
|
||||
|
||||
def tmp_dir
|
||||
"repo"
|
||||
end
|
||||
|
||||
end
|
||||
module RepositoriesHelper
|
||||
def render_permission(user, project)
|
||||
return "Admin" if user&.admin?
|
||||
project.get_premission(user)
|
||||
end
|
||||
|
||||
def render_decode64_content(str)
|
||||
return nil if str.blank?
|
||||
Base64.decode64(str).force_encoding("UTF-8").encode("UTF-8", invalid: :replace)
|
||||
end
|
||||
|
||||
def download_type(str)
|
||||
default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2 mp4 mov wmv flv mpeg avi avchd webm mkv)
|
||||
default_type.include?(str&.downcase) || str.blank?
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def is_readme?(type, str)
|
||||
return false if type != 'file' || str.blank?
|
||||
readme_types = ["readme.md", "readme", "readme_en.md", "readme_zh.md", "readme_en", "readme_zh"]
|
||||
readme_types.include?(str.to_s.downcase) || str =~ CustomRegexp::MD_REGEX
|
||||
end
|
||||
|
||||
def render_commit_author(author_json)
|
||||
return nil if author_json.blank? || (author_json["id"].blank? && author_json['name'].blank?)
|
||||
if author_json["id"].present?
|
||||
return find_user_by_gitea_uid author_json['id']
|
||||
end
|
||||
if author_json["id"].nil? && (author_json["name"].present? && author_json["email"].present?)
|
||||
return find_user_by_login_and_mail(author_json['name'], author_json["email"])
|
||||
end
|
||||
end
|
||||
|
||||
def render_cache_commit_author(author_json)
|
||||
if author_json["name"].present? && author_json["email"].present?
|
||||
return find_user_in_redis_cache(author_json['name'], author_json['email'])
|
||||
end
|
||||
if author_json["Name"].present? && author_json["Email"].present?
|
||||
return find_user_in_redis_cache(author_json['Name'], author_json['Email'])
|
||||
end
|
||||
end
|
||||
|
||||
def readme_render_decode64_content(str, owner, repo, ref, path)
|
||||
return nil if str.blank?
|
||||
begin
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
|
||||
c_regex = /\!\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
src2_regex = /src='(.*?)'/
|
||||
ss = content.to_s.scan(c_regex)
|
||||
ss_src = content.scan(src_regex)
|
||||
ss_src2 = content.scan(src2_regex)
|
||||
total_images = ss + ss_src + ss_src2
|
||||
if total_images.length > 0
|
||||
total_images.each do |s|
|
||||
begin
|
||||
image_title = /\"(.*?)\"/
|
||||
r_content = s[0]
|
||||
remove_title = r_content.to_s.scan(image_title)
|
||||
# if remove_title.length > 0
|
||||
# r_content = r_content.gsub(/#{remove_title[0]}/, "").strip
|
||||
# end
|
||||
path_last = r_content
|
||||
path_current = ""
|
||||
# 相对路径处理
|
||||
if r_content.start_with?("../")
|
||||
relative_path_length = r_content.split("../").size - 1
|
||||
path_pre = path.split("/").size - 1 - relative_path_length
|
||||
path_pre = 0 if path_pre < 0
|
||||
path_current = path_pre == 0 ? "" : path.split("/")[0..path_pre].join("/")
|
||||
path_last = r_content.split("../").last
|
||||
elsif r_content.start_with?("/") # 根路径处理
|
||||
path_last = r_content[1..r_content.size]
|
||||
else
|
||||
path_current = path
|
||||
end
|
||||
# if r_content.include?("?")
|
||||
# new_r_content = r_content + "&raw=true"
|
||||
# else
|
||||
# new_r_content = r_content + "?raw=true"
|
||||
# end
|
||||
new_r_content = r_content
|
||||
|
||||
unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:")
|
||||
# new_r_content = "#{path}" + new_r_content
|
||||
new_r_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{path_current}/#{path_last}&ref=#{ref}"].join
|
||||
end
|
||||
content = content.gsub(/src=\"#{r_content}\"/, "src=\"#{new_r_content}\"").gsub(/src='#{r_content}'/, "src=\"#{new_r_content}\"")
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
# author hui.he
|
||||
def new_readme_render_decode64_content(str, owner, repo, ref, readme_path, readme_name)
|
||||
file_path = readme_path.include?('/') ? readme_path.gsub("/#{readme_name}", '') : readme_path.gsub("#{readme_name}", '')
|
||||
return nil if str.blank?
|
||||
content = Base64.decode64(str).force_encoding('UTF-8')
|
||||
s_regex = /\[.*?\]\((.*?)\)/
|
||||
src_regex = /src=\"(.*?)\"/
|
||||
ss = content.to_s.scan(s_regex)
|
||||
ss_src = content.to_s.scan(src_regex)
|
||||
total_sources = ss + ss_src
|
||||
total_sources.uniq!
|
||||
total_sources.each do |s|
|
||||
begin
|
||||
s_content = s[0]
|
||||
# 链接直接跳过不做替换
|
||||
next if s_content.starts_with?('http://') || s_content.starts_with?('https://') || s_content.starts_with?('mailto:') || s_content.blank?
|
||||
ext = File.extname(s_content)[1..-1]
|
||||
if (image_type?(ext) || download_type(ext)) && !ext.blank?
|
||||
s_content = File.expand_path(s_content, file_path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
# content = content.gsub(s[0], "/#{s_content}")
|
||||
s_content = [base_url, "/api/#{owner&.login}/#{repo.identifier}/raw?filepath=#{s_content}&ref=#{ref}"].join
|
||||
content = content.gsub(s[0], s_content)
|
||||
else
|
||||
path = [owner&.login, repo&.identifier, 'tree', ref, file_path].join("/")
|
||||
s_content = File.expand_path(s_content, path)
|
||||
s_content = s_content.split("#{Rails.root}/")[1]
|
||||
content = content.gsub('('+s[0]+')', '('+"/#{s_content}"+')')
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
return content
|
||||
rescue
|
||||
return str
|
||||
end
|
||||
|
||||
# unix_time values for example: 1604382982
|
||||
def render_format_time_with_unix(unix_time)
|
||||
Time.at(unix_time).strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
# date for example: 2020-11-01T19:57:27+08:00
|
||||
def render_format_time_with_date(date)
|
||||
date.to_time.strftime("%Y-%m-%d %H:%M")
|
||||
end
|
||||
|
||||
def readme_decode64_content(entry, owner, repo, ref, path=nil)
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
new_readme_render_decode64_content(content, owner, repo, ref, entry['path'], entry['name'])
|
||||
end
|
||||
|
||||
def decode64_content(entry, owner, repo, ref, path=nil)
|
||||
if is_readme?(entry['type'], entry['name'])
|
||||
Rails.logger.info("entry===#{entry["type"]} #{entry["name"]}")
|
||||
content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content']
|
||||
# Rails.logger.info("content===#{content}")
|
||||
# readme_render_decode64_content(content, owner, repo, ref)
|
||||
return Base64.decode64(content).force_encoding('UTF-8')
|
||||
else
|
||||
file_type = File.extname(entry['name'].to_s)[1..-1]
|
||||
if image_type?(file_type)
|
||||
return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, URI.escape(entry['path']), ref: ref)['content'] : entry['content']
|
||||
end
|
||||
if download_type(file_type)
|
||||
return entry['content']
|
||||
end
|
||||
render_decode64_content(entry['content'])
|
||||
end
|
||||
end
|
||||
|
||||
def base64_to_image(path, content)
|
||||
# generate to https://git.trusite.net/pawm36ozq/-/raw/branch/master/entrn.png"
|
||||
content = Base64.decode64(content)
|
||||
File.open(path, 'wb') { |f| f.write(content) }
|
||||
end
|
||||
|
||||
def render_download_image_url(dir_path, file_path, content)
|
||||
full_path = file_path.starts_with?("/") ? [dir_path, file_path].join("") : [dir_path, file_path].join("/")
|
||||
file_name = full_path.split("/")[-1]
|
||||
# 用户名/项目标识/文件路径
|
||||
dir_path = generate_dir_path(full_path.split("/"+file_name)[0])
|
||||
|
||||
file_path = [dir_path, file_name].join('/')
|
||||
|
||||
puts "##### render_download_image_url file_path: #{file_path}"
|
||||
base64_to_image(file_path, content)
|
||||
file_path = file_path[6..-1]
|
||||
File.join(base_url, file_path)
|
||||
end
|
||||
|
||||
def generate_dir_path(dir_path)
|
||||
# tmp_dir_path
|
||||
# eg: jasder/forgeplus/raw/branch/ref
|
||||
dir_path = ["public", tmp_dir, dir_path].join('/')
|
||||
puts "#### dir_path: #{dir_path}"
|
||||
unless Dir.exists?(dir_path)
|
||||
FileUtils.mkdir_p(dir_path) ##不成功这里会抛异常
|
||||
end
|
||||
dir_path
|
||||
end
|
||||
|
||||
def tmp_dir
|
||||
"repo"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -44,8 +44,8 @@ module Gitea
|
||||
|
||||
def token
|
||||
{
|
||||
username: Gitea.gitea_config[:access_key_id],
|
||||
password: Gitea.gitea_config[:access_key_secret]
|
||||
username: GiteaService.gitea_config[:access_key_id],
|
||||
password: GiteaService.gitea_config[:access_key_secret]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +37,7 @@ class Ci::Drone::Server
|
||||
|
||||
private
|
||||
def gitea_url
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def database_username
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module Gitea
|
||||
module GiteaService
|
||||
class << self
|
||||
def gitea_config
|
||||
gitea_config = {}
|
||||
@@ -2,24 +2,27 @@
|
||||
#
|
||||
# Table name: forge_applied_projects
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("0")
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_invite_link_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
# index_forge_applied_projects_on_project_id (project_id)
|
||||
# index_forge_applied_projects_on_project_invite_link_id (project_invite_link_id)
|
||||
# index_forge_applied_projects_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class AppliedProject < ApplicationRecord
|
||||
self.table_name = "forge_applied_projects"
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
belongs_to :project_invite_link, optional: true
|
||||
|
||||
has_many :applied_messages, as: :applied, dependent: :destroy
|
||||
# has_many :forge_activities, as: :forge_act, dependent: :destroy
|
||||
|
||||
@@ -69,6 +69,7 @@ class Issue < ApplicationRecord
|
||||
has_many :issue_tags, through: :issue_tags_relates
|
||||
has_many :issue_times, dependent: :destroy
|
||||
has_many :issue_depends, dependent: :destroy
|
||||
has_many :reviews, dependent: :destroy
|
||||
scope :issue_includes, ->{includes(:user)}
|
||||
scope :issue_many_includes, ->{includes(journals: :user)}
|
||||
scope :issue_issue, ->{where(issue_classify: [nil,"issue"])}
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
# parent_id :integer
|
||||
# comments_count :integer default("0")
|
||||
# reply_id :integer
|
||||
# review_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_journals_on_created_on (created_on)
|
||||
# index_journals_on_journalized_id (journalized_id)
|
||||
# index_journals_on_review_id (review_id)
|
||||
# index_journals_on_user_id (user_id)
|
||||
# journals_journalized_id (journalized_id,journalized_type)
|
||||
#
|
||||
|
||||
@@ -61,6 +61,7 @@ class MessageTemplate::CustomTip < MessageTemplate
|
||||
end
|
||||
title.gsub!('{platform}', PLATFORM)
|
||||
content.gsub!('{platform}', PLATFORM)
|
||||
content.gsub!('{baseurl}', base_url)
|
||||
|
||||
return title, content
|
||||
rescue => e
|
||||
|
||||
@@ -125,6 +125,7 @@ class Project < ApplicationRecord
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :user
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
has_many :project_invite_links, dependent: :destroy
|
||||
after_create :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :check_project_members
|
||||
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
|
||||
@@ -138,7 +139,7 @@ class Project < ApplicationRecord
|
||||
delegate :content, to: :project_detail, allow_nil: true
|
||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||
|
||||
validate :validate_sensitive_string
|
||||
validate :validate_sensitive_string, on: [:create, :update]
|
||||
|
||||
def self.all_visible(user_id=nil)
|
||||
user_projects_sql = Project.joins(:owner).where(users: {type: 'User'}).to_sql
|
||||
@@ -184,7 +185,7 @@ class Project < ApplicationRecord
|
||||
forked_project = self.forked_from_project
|
||||
if forked_project.present?
|
||||
forked_project.decrement(:forked_count, 1)
|
||||
forked_project.save
|
||||
forked_project.update_column(:forked_count, forked_project.forked_count)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
59
app/models/project_invite_link.rb
Normal file
59
app/models/project_invite_link.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: project_invite_links
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# role :integer default("4")
|
||||
# is_apply :boolean default("1")
|
||||
# sign :string(255)
|
||||
# expired_at :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_invite_links_on_project_id (project_id)
|
||||
# index_project_invite_links_on_sign (sign)
|
||||
# index_project_invite_links_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class ProjectInviteLink < ApplicationRecord
|
||||
|
||||
default_scope { where("expired_at > ?", Time.now).or(where(expired_at: nil)) }
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
has_many :applied_projects
|
||||
|
||||
scope :with_project_id, -> (project_id) {where(project_id: project_id)}
|
||||
scope :with_user_id, -> (user_id) {where(user_id: user_id)}
|
||||
|
||||
enum role: {manager: 3, developer: 4, reporter: 5}
|
||||
|
||||
before_create :set_old_data_expired_at
|
||||
|
||||
def self.random_hex_sign
|
||||
hex = (SecureRandom.hex(32))
|
||||
return hex unless ProjectInviteLink.where(sign: hex).exists?
|
||||
end
|
||||
|
||||
def self.build!(project, user, role="developer", is_apply=true)
|
||||
self.create!(
|
||||
project_id: project&.id,
|
||||
user_id: user&.id,
|
||||
role: role,
|
||||
is_apply: is_apply,
|
||||
sign: random_hex_sign,
|
||||
expired_at: Time.now + 3.days
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def set_old_data_expired_at
|
||||
ProjectInviteLink.where(user_id: self.user_id, project_id: self.project, role: self.role, is_apply: self.is_apply).update_all(expired_at: Time.now)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -14,6 +14,7 @@
|
||||
#
|
||||
|
||||
class ProjectUnit < ApplicationRecord
|
||||
|
||||
belongs_to :project
|
||||
|
||||
enum unit_type: {code: 1, issues: 2, pulls: 3, wiki:4, devops: 5, versions: 6, resources: 7, services: 8}
|
||||
|
||||
27
app/models/review.rb
Normal file
27
app/models/review.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: reviews
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# issue_id :integer
|
||||
# reviewer_id :integer
|
||||
# content :text(65535)
|
||||
# commit_id :string(255)
|
||||
# status :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_reviews_on_issue_id (issue_id)
|
||||
# index_reviews_on_reviewer_id (reviewer_id)
|
||||
#
|
||||
|
||||
class Review < ApplicationRecord
|
||||
|
||||
belongs_to :issue
|
||||
belongs_to :reviewer, class_name: 'User', foreign_key: :reviewer_id
|
||||
has_one :journal, dependent: :destroy
|
||||
|
||||
enum status: {common: 0, approved: 1, rejected: 2}
|
||||
end
|
||||
@@ -181,7 +181,7 @@ class User < Owner
|
||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||
scope :like, lambda { |keywords|
|
||||
sql = "CONCAT(lastname, firstname) LIKE :search OR nickname LIKE :search OR login LIKE :search OR mail LIKE :search OR nickname LIKE :search"
|
||||
where(sql, :search => "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
|
||||
where(sql, :search => "%#{keywords.strip}%") unless keywords.blank?
|
||||
}
|
||||
|
||||
scope :simple_select, -> {select(:id, :login, :lastname,:firstname, :nickname, :gitea_uid, :type)}
|
||||
@@ -567,7 +567,8 @@ class User < Owner
|
||||
return '游客' unless logged?
|
||||
name = lastname + firstname
|
||||
name = name.blank? ? (nickname.blank? ? login : nickname) : name
|
||||
name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
# name.gsub(/\s+/, '').strip #6.11 -hs
|
||||
name.strip
|
||||
end
|
||||
|
||||
def only_real_name
|
||||
@@ -684,6 +685,21 @@ class User < Owner
|
||||
raise text
|
||||
end
|
||||
|
||||
def self.authenticate!(login, password)
|
||||
user = self.where("login = ? or mail = ? or phone = ? ", login.to_s.gsub(" ",''),login.to_s.gsub(" ",''),login.downcase.to_s.gsub(" ",'')).limit(1).first
|
||||
return (user.check_password?(password) ? user : nil) unless user.nil?
|
||||
nil
|
||||
end
|
||||
|
||||
# Generate public/private keys
|
||||
def generate_keys
|
||||
key_size = (Rails.env == 'test' ? 512 : 2048)
|
||||
|
||||
serialized_private_key = OpenSSL::PKey::RSA::generate(key_size).to_s
|
||||
serialized_public_key = OpenSSL::PKey::RSA.new(serialized_private_key)
|
||||
[serialized_private_key, serialized_public_key]
|
||||
end
|
||||
|
||||
def show_real_name
|
||||
name = lastname + firstname
|
||||
if name.blank?
|
||||
|
||||
48
app/services/api/v1/projects/get_service.rb
Normal file
48
app/services/api/v1/projects/get_service.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
class Api::V1::Projects::GetService < ApplicationService
|
||||
|
||||
attr_reader :project, :token, :owner, :repo
|
||||
attr_accessor :gitea_data, :gitea_branch_tag_count
|
||||
|
||||
def initialize(project, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
load_gitea_branch_tag_count
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
result_object
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def result_object
|
||||
{
|
||||
full_name: "#{owner}/#{repo}",
|
||||
owner: project&.owner,
|
||||
ssh_url: gitea_data["ssh_url"],
|
||||
clone_url: gitea_data["clone_url"],
|
||||
size: gitea_data["size"],
|
||||
default_branch: gitea_data["default_branch"],
|
||||
empty: gitea_data["empty"],
|
||||
branch_count: gitea_branch_tag_count["branch_count"],
|
||||
tag_count: gitea_branch_tag_count["tag_count"],
|
||||
}
|
||||
end
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_by_owner_repo(owner, repo)
|
||||
end
|
||||
|
||||
def load_gitea_branch_tag_count
|
||||
@gitea_branch_tag_count = $gitea_client.get_repos_branch_tag_count_by_owner_repo(owner, repo)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
class Api::V1::Projects::PullRequests::Reviews::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :pull_request, :issue, :status, :commit_id, :content, :current_user
|
||||
attr_accessor :review, :journal
|
||||
|
||||
validates :status, inclusion: { in: %w(common approved rejected), message: '请输入正确的Type'}
|
||||
|
||||
def initialize(project, pull_request, params, current_user)
|
||||
@project = project
|
||||
@pull_request = pull_request
|
||||
@issue = pull_request&.issue
|
||||
@status = params[:status]
|
||||
@commit_id = params[:commit_id]
|
||||
@content = params[:content]
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
ActiveRecord::Base.transaction do
|
||||
create_review
|
||||
create_journal
|
||||
end
|
||||
|
||||
return @journal, @review
|
||||
rescue
|
||||
raise Error, '服务器错误,请联系系统管理员!'
|
||||
end
|
||||
|
||||
private
|
||||
def create_review
|
||||
@review = issue.reviews.create!(status: status, content: content, commit_id: commit_id, reviewer_id: @current_user.id)
|
||||
end
|
||||
|
||||
def create_journal
|
||||
@journal = issue.journals.create!(notes: content, user_id: @current_user.id, review_id: @review.id)
|
||||
end
|
||||
|
||||
end
|
||||
60
app/services/api/v1/projects/webhooks/create_service.rb
Normal file
60
app/services/api/v1/projects/webhooks/create_service.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
class Api::V1::Projects::Webhooks::CreateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :token, :owner, :repo, :active, :branch_filter, :content_type, :url, :http_method, :secret, :events
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :url, format: { with: URI::regexp(%w[http https]), message: "请输入正确的地址" }
|
||||
validates :active, inclusion: {in: [true, false]}
|
||||
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
|
||||
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
|
||||
|
||||
def initialize(project, params, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@active = params[:active]
|
||||
@branch_filter = params[:branch_filter]
|
||||
@content_type = params[:content_type]
|
||||
@url = params[:url]
|
||||
@http_method = params[:http_method]
|
||||
@secret = params[:secret]
|
||||
@events = params[:events]
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
begin
|
||||
$gitea_client.token = token unless token.blank?
|
||||
|
||||
excute_data_to_gitea
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def request_body
|
||||
{
|
||||
active: active,
|
||||
branch_filter: branch_filter,
|
||||
config: {
|
||||
content_type: content_type,
|
||||
url: url,
|
||||
http_method: http_method,
|
||||
secret: secret
|
||||
},
|
||||
events: events || [],
|
||||
type: 'gitea',
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_hooks_by_owner_repo(owner, repo, {body: request_body.to_json})
|
||||
end
|
||||
end
|
||||
30
app/services/api/v1/projects/webhooks/delete_service.rb
Normal file
30
app/services/api/v1/projects/webhooks/delete_service.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Api::V1::Projects::Webhooks::DeleteService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
excute_data_to_gitea
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.delete_repos_hooks_by_owner_repo_id(owner, repo, id)
|
||||
end
|
||||
end
|
||||
30
app/services/api/v1/projects/webhooks/get_service.rb
Normal file
30
app/services/api/v1/projects/webhooks/get_service.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Api::V1::Projects::Webhooks::GetService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_by_owner_repo_id(owner, repo, id)
|
||||
end
|
||||
end
|
||||
30
app/services/api/v1/projects/webhooks/hooktasks_service.rb
Normal file
30
app/services/api/v1/projects/webhooks/hooktasks_service.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Api::V1::Projects::Webhooks::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_hooktasks_by_owner_repo(owner, repo, id)
|
||||
end
|
||||
end
|
||||
29
app/services/api/v1/projects/webhooks/list_service.rb
Normal file
29
app/services/api/v1/projects/webhooks/list_service.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
class Api::V1::Projects::Webhooks::ListService < ApplicationService
|
||||
|
||||
attr_reader :project, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, token=nil)
|
||||
@project = project
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
load_gitea_data
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_gitea_data
|
||||
@gitea_data = $gitea_client.get_repos_hooks_by_owner_repo(owner, repo)
|
||||
end
|
||||
end
|
||||
30
app/services/api/v1/projects/webhooks/tests_service.rb
Normal file
30
app/services/api/v1/projects/webhooks/tests_service.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Api::V1::Projects::Webhooks::TestsService < ApplicationService
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo
|
||||
attr_accessor :gitea_data
|
||||
|
||||
def initialize(project, id, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
$gitea_client.token = token unless token.blank?
|
||||
excute_data_to_gitea
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.post_repos_hooks_tests_by_owner_repo_id(owner, repo, id)
|
||||
end
|
||||
end
|
||||
61
app/services/api/v1/projects/webhooks/update_service.rb
Normal file
61
app/services/api/v1/projects/webhooks/update_service.rb
Normal file
@@ -0,0 +1,61 @@
|
||||
class Api::V1::Projects::Webhooks::UpdateService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :project, :id, :token, :owner, :repo, :active, :branch_filter, :content_type, :url, :http_method, :secret, :events
|
||||
attr_accessor :gitea_data
|
||||
|
||||
validates :url, format: { with: URI::regexp(%w[http https]), message: "请输入正确的地址" }
|
||||
validates :active, inclusion: {in: [true, false]}
|
||||
validates :http_method, inclusion: { in: %w(POST GET), message: "请输入正确的请求方式"}
|
||||
validates :content_type, inclusion: { in: %w(json form), message: "请输入正确的Content Type"}
|
||||
|
||||
def initialize(project, id, params, token=nil)
|
||||
@project = project
|
||||
@id = id
|
||||
@owner = project&.owner.login
|
||||
@repo = project&.identifier
|
||||
@active = params[:active]
|
||||
@branch_filter = params[:branch_filter]
|
||||
@content_type = params[:content_type]
|
||||
@url = params[:url]
|
||||
@http_method = params[:http_method]
|
||||
@secret = params[:secret]
|
||||
@events = params[:events]
|
||||
@token = token
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(",") unless valid?
|
||||
begin
|
||||
$gitea_client.token = token unless token.blank?
|
||||
|
||||
excute_data_to_gitea
|
||||
|
||||
$gitea_client.token = nil unless token.blank?
|
||||
|
||||
gitea_data
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def request_body
|
||||
{
|
||||
active: active,
|
||||
branch_filter: branch_filter,
|
||||
config: {
|
||||
content_type: content_type,
|
||||
url: url,
|
||||
http_method: http_method,
|
||||
secret: secret
|
||||
},
|
||||
events: events || [],
|
||||
type: 'gitea',
|
||||
}
|
||||
end
|
||||
|
||||
def excute_data_to_gitea
|
||||
@gitea_data = $gitea_client.patch_repos_hooks_by_owner_repo_id(owner, repo, id, {body: request_body.to_json})
|
||||
end
|
||||
end
|
||||
86
app/services/api/v1/users/projects/list_service.rb
Normal file
86
app/services/api/v1/users/projects/list_service.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
class Api::V1::Users::Projects::ListService < ApplicationService
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :observe_user, :category, :is_public, :project_type, :sort_by, :sort_direction, :search, :current_user
|
||||
attr_accessor :queried_projects
|
||||
|
||||
validates :category, inclusion: {in: %w(all join created manage watched forked), message: "请输入正确的Category"}
|
||||
validates :is_public, inclusion: {in: [true, false], message: '请输入正确的IsPublic'}, allow_nil: true
|
||||
validates :project_type, inclusion: {in: %w(common mirror sync_mirror), message: '请输入正确的ProjectType'}, allow_nil: true
|
||||
validates :sort_by, inclusion: {in: Project.column_names, message: '请输入正确的SortBy'}
|
||||
validates :sort_direction, inclusion: {in: %w(asc desc), message: '请输入正确的SortDirection'}
|
||||
|
||||
def initialize(observe_user, params, current_user=nil)
|
||||
@observe_user = observe_user
|
||||
@category = params[:category] || 'all'
|
||||
@is_public = params[:is_public]
|
||||
@project_type = params[:project_type]
|
||||
@sort_by = params[:sort_by] || 'updated_on'
|
||||
@sort_direction = params[:sort_direction] || 'desc'
|
||||
@search = params[:search]
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def call
|
||||
raise Error, errors.full_messages.join(", ") unless valid?
|
||||
begin
|
||||
project_query_data
|
||||
|
||||
queried_projects
|
||||
rescue
|
||||
raise Error, "服务器错误,请联系系统管理员!"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def project_query_data
|
||||
if current_user.admin?
|
||||
projects = Project
|
||||
else
|
||||
projects = Project.visible
|
||||
end
|
||||
|
||||
case category
|
||||
when 'join'
|
||||
normal_projects = projects.where.not(user_id: observe_user.id).members_projects(observe_user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}).to_sql
|
||||
projects = Project.from("( #{normal_projects} UNION #{org_projects} ) AS projects").distinct
|
||||
when 'created'
|
||||
projects = projects.where(user_id: observe_user.id)
|
||||
when 'manage'
|
||||
normal_projects = projects.joins(members: :roles).where(members: {user_id: observe_user.id}, roles: {name: 'Manager'}).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}, teams: {authorize: %w(owner admin)}).to_sql
|
||||
projects = Project.from("( #{normal_projects} UNION #{org_projects} ) AS projects").distinct
|
||||
when 'watched'
|
||||
projects = projects.where.not(user_id: observe_user.id).joins(:watchers).where(watchers: {watchable_type: "Project", user_id: observe_user.id})
|
||||
when 'forked'
|
||||
fork_ids = observe_user.fork_users.select(:id, :fork_project_id).pluck(:fork_project_id)
|
||||
projects = projects.where(id: fork_ids)
|
||||
else
|
||||
normal_projects = projects.members_projects(observe_user.id).to_sql
|
||||
org_projects = projects.joins(team_projects: [team: :team_users]).where(team_users: {user_id: observe_user.id}).to_sql
|
||||
projects = Project.from("( #{ normal_projects} UNION #{ org_projects } ) AS projects").distinct
|
||||
end
|
||||
|
||||
unless is_public.nil?
|
||||
if is_public
|
||||
projects = projects.visible
|
||||
else
|
||||
projects = projects.is_private
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
projects = projects.with_project_type(project_type)
|
||||
|
||||
q = projects.ransack(name_or_identifier_cont: search)
|
||||
|
||||
scope = q.result.includes(:project_category, :project_language,:owner, :repository, :has_pinned_users)
|
||||
|
||||
|
||||
scope = scope.order("projects.#{sort_by} #{sort_direction}")
|
||||
|
||||
@queried_projects = scope
|
||||
end
|
||||
|
||||
end
|
||||
@@ -81,7 +81,7 @@ class Educoder::ClientService < ApplicationService
|
||||
end
|
||||
|
||||
def access_key_secret
|
||||
Gitea.gitea_config[:access_key_secret]
|
||||
GiteaService.gitea_config[:access_key_secret]
|
||||
end
|
||||
|
||||
def api_url(url)
|
||||
|
||||
@@ -56,7 +56,7 @@ class Gitea::Accelerator::BaseService < ApplicationService
|
||||
end
|
||||
|
||||
def accelerator
|
||||
Gitea.gitea_config[:accelerator]
|
||||
GiteaService.gitea_config[:accelerator]
|
||||
end
|
||||
|
||||
def render_status(response)
|
||||
|
||||
@@ -96,11 +96,11 @@ class Gitea::ClientService < ApplicationService
|
||||
end
|
||||
|
||||
def base_url
|
||||
Gitea.gitea_config[:base_url]
|
||||
GiteaService.gitea_config[:base_url]
|
||||
end
|
||||
|
||||
def domain
|
||||
Gitea.gitea_config[:domain]
|
||||
GiteaService.gitea_config[:domain]
|
||||
end
|
||||
|
||||
def api_url
|
||||
|
||||
@@ -14,8 +14,8 @@ class Gitea::User::DeleteService < Gitea::ClientService
|
||||
private
|
||||
def token
|
||||
{
|
||||
username: Gitea.gitea_config[:access_key_id],
|
||||
password: Gitea.gitea_config[:access_key_secret]
|
||||
username: GiteaService.gitea_config[:access_key_id],
|
||||
password: GiteaService.gitea_config[:access_key_secret]
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Gitea::User::UpdateService < Gitea::ClientService
|
||||
# source_id integer($int64)
|
||||
# website string
|
||||
|
||||
def initialize(edit_username, params={}, token={username: Gitea.gitea_config[:access_key_id], password: Gitea.gitea_config[:access_key_secret]})
|
||||
def initialize(edit_username, params={}, token={username: GiteaService.gitea_config[:access_key_id], password: GiteaService.gitea_config[:access_key_secret]})
|
||||
@token = token
|
||||
@params = params
|
||||
@edit_username = edit_username
|
||||
|
||||
86
app/services/projects/link_join_service.rb
Normal file
86
app/services/projects/link_join_service.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
class Projects::LinkJoinService < ApplicationService
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
attr_reader :user, :project, :invite_sign, :params
|
||||
|
||||
def initialize(user, project, invite_sign, params={})
|
||||
@user = user
|
||||
@project = project
|
||||
@invite_sign = invite_sign
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
ActiveRecord::Base.transaction do
|
||||
validate!
|
||||
if invite_link.is_apply
|
||||
# 如果需要申请才能加入,创建一条申请记录
|
||||
create_applied_project!
|
||||
else
|
||||
# 如果不需要申请,直接为项目添加该成员
|
||||
create_member!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def validate!
|
||||
raise Error, 'invite_sign必须存在!' if invite_sign.blank?
|
||||
raise Error, '邀请链接不存在!' unless invite_link.present?
|
||||
raise Error, '邀请链接已失效!' unless invite_user_in_project
|
||||
raise Error, '您已是仓库成员' if project.member?(user.id)
|
||||
raise Error, '您的申请管理员正在审核中,请勿重复申请!' if user.applied_projects.exists?(applied_project_params)
|
||||
end
|
||||
|
||||
def applied_project_params
|
||||
{
|
||||
status: 'common',
|
||||
project: project,
|
||||
role: role_value,
|
||||
project_invite_link_id: invite_link&.id
|
||||
}
|
||||
end
|
||||
|
||||
def create_applied_project!
|
||||
user.applied_projects.find_or_create_by!(status: 'common', project: project, role: role_value, project_invite_link_id: invite_link&.id)
|
||||
end
|
||||
|
||||
def create_member!
|
||||
Projects::AddMemberInteractor.call(project.owner, project, user, permission)
|
||||
end
|
||||
|
||||
def invite_link
|
||||
ProjectInviteLink.find_by(project_id: project.id, sign: invite_sign)
|
||||
end
|
||||
|
||||
def invite_user_in_project
|
||||
in_project = project.member?(invite_link.user)
|
||||
invite_link.update_column(:expired_at, Time.now) unless in_project
|
||||
in_project
|
||||
end
|
||||
|
||||
def role_value
|
||||
@_role ||=
|
||||
case invite_link&.role
|
||||
when 'manager' then 3
|
||||
when 'developer' then 4
|
||||
when 'reporter' then 5
|
||||
else
|
||||
5
|
||||
end
|
||||
end
|
||||
|
||||
def permission
|
||||
case invite_link&.role
|
||||
when 'manager'
|
||||
'admin'
|
||||
when 'developer'
|
||||
'write'
|
||||
when 'reporter'
|
||||
'read'
|
||||
else
|
||||
'read'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -63,7 +63,7 @@ class Repositories::CreateService < ApplicationService
|
||||
end
|
||||
|
||||
def remote_repository_url
|
||||
[Gitea.gitea_config[:domain], '/', user.login, '/', params[:identifier], ".git"].join("")
|
||||
[GiteaService.gitea_config[:domain], '/', user.login, '/', params[:identifier], ".git"].join("")
|
||||
end
|
||||
|
||||
def repository_params
|
||||
|
||||
10
app/views/api/v1/projects/_simple_detail.json.jbuilder
Normal file
10
app/views/api/v1/projects/_simple_detail.json.jbuilder
Normal file
@@ -0,0 +1,10 @@
|
||||
if project.present?
|
||||
json.type project.project_type
|
||||
json.(project,
|
||||
:description, :forked_count, :forked_from_project_id, :identifier,
|
||||
:issues_count, :pull_requests_count, :invite_code, :website, :platform,
|
||||
:name, :open_devops, :praises_count, :is_public, :status, :watchers_count,
|
||||
:ignore_id, :license_id, :project_category_id, :project_language_id)
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
5
app/views/api/v1/projects/show.json.jbuilder
Normal file
5
app/views/api/v1/projects/show.json.jbuilder
Normal file
@@ -0,0 +1,5 @@
|
||||
json.owner do
|
||||
json.partial! "api/v1/users/simple_user", user: @result_object[:owner]
|
||||
end
|
||||
json.(@result_object, :full_name, :ssh_url, :clone_url, :default_branch, :empty, :branch_count, :tag_count)
|
||||
json.partial! "api/v1/projects/simple_detail", project: @project
|
||||
@@ -0,0 +1,3 @@
|
||||
json.(webhook, :id, :url, :http_method, :is_active)
|
||||
json.last_status webhook.last_status
|
||||
json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S")
|
||||
@@ -0,0 +1,8 @@
|
||||
json.id webhook["id"]
|
||||
json.content_type webhook['config']['content_type']
|
||||
json.http_method webhook['config']['http_method']
|
||||
json.url webhook['config']['url']
|
||||
json.events webhook['events']
|
||||
json.active webhook['active']
|
||||
json.branch_filter webhook['branch_filter']
|
||||
json.created_at format_time(webhook['created_at'].to_time)
|
||||
1
app/views/api/v1/projects/webhooks/create.json.jbuilder
Normal file
1
app/views/api/v1/projects/webhooks/create.json.jbuilder
Normal file
@@ -0,0 +1 @@
|
||||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
||||
@@ -0,0 +1,6 @@
|
||||
json.total_count @hooktasks.total_count
|
||||
json.hooktasks @hooktasks.each do |task|
|
||||
json.(task, :id, :event_type, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content)
|
||||
json.response_content task.response_content_json
|
||||
json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S")
|
||||
end
|
||||
4
app/views/api/v1/projects/webhooks/index.json.jbuilder
Normal file
4
app/views/api/v1/projects/webhooks/index.json.jbuilder
Normal file
@@ -0,0 +1,4 @@
|
||||
json.total_count @webhooks.total_count
|
||||
json.webhooks @webhooks do |webhook|
|
||||
json.partial! "api/v1/projects/webhooks/simple_detail", webhook: webhook
|
||||
end
|
||||
1
app/views/api/v1/projects/webhooks/show.json.jbuilder
Normal file
1
app/views/api/v1/projects/webhooks/show.json.jbuilder
Normal file
@@ -0,0 +1 @@
|
||||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
||||
1
app/views/api/v1/projects/webhooks/update.json.jbuilder
Normal file
1
app/views/api/v1/projects/webhooks/update.json.jbuilder
Normal file
@@ -0,0 +1 @@
|
||||
json.partial! "api/v1/projects/webhooks/simple_gitea_detail", webhook: @result_object
|
||||
9
app/views/api/v1/users/_simple_user.json.jbuilder
Normal file
9
app/views/api/v1/users/_simple_user.json.jbuilder
Normal file
@@ -0,0 +1,9 @@
|
||||
if user.present?
|
||||
json.id user.id
|
||||
json.type user.type
|
||||
json.name user.real_name
|
||||
json.login user.login
|
||||
json.image_url url_to_avatar(user)
|
||||
else
|
||||
json.nil!
|
||||
end
|
||||
8
app/views/api/v1/users/projects/index.json.jbuilder
Normal file
8
app/views/api/v1/users/projects/index.json.jbuilder
Normal file
@@ -0,0 +1,8 @@
|
||||
json.total_count @projects.total_count
|
||||
|
||||
json.projects @projects do |project|
|
||||
json.owner do
|
||||
json.partial! "api/v1/users/simple_user", user: project.owner
|
||||
end
|
||||
json.partial! "api/v1/projects/simple_detail", project: project
|
||||
end
|
||||
141
app/views/layouts/doorkeeper/application.html.erb
Normal file
141
app/views/layouts/doorkeeper/application.html.erb
Normal file
@@ -0,0 +1,141 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>GitLink oauth2 认证</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<%= javascript_include_tag :application, 'data-turbolinks-track': 'reload' %>
|
||||
<%= stylesheet_link_tag "doorkeeper/application" %>
|
||||
<%= csrf_meta_tags %>
|
||||
<%= yield(:css) if content_for?(:css) %>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
background-color: #fff;
|
||||
-webkit-font-feature-settings: "tnum";
|
||||
font-feature-settings: "tnum";
|
||||
background: url(https://ali-cdn.educoder.net/react/build/static/media/beijintulogontwo.41076faf.png) center center / 100% 100% no-repeat fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
min-height: 100%;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
#container {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.mt-20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ee4a1f;
|
||||
text-align: left;
|
||||
margin-bottom: 0px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
color: #459be6;
|
||||
}
|
||||
|
||||
.logo-wraper {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.auth-desc {
|
||||
margin: 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.w {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 350px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #fff !important;
|
||||
display: block;
|
||||
background: #459be6;
|
||||
border-radius: 4px;
|
||||
letter-spacing: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
font-family: "Monospaced Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 4px 11px;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
height: 45px;
|
||||
padding: 5px;
|
||||
background-image: none;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
-webkit-transition: all .3s;
|
||||
-o-transition: all .3s;
|
||||
transition: all .3s;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.reg {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.reg-link {
|
||||
font-size: 18px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="page-header" role="banner">
|
||||
<div class="logo-wraper">
|
||||
<img src="https://www.gitlink.org.cn/images/avatars/LaboratorySetting/1nav?t=1638344455" style="cursor: pointer;width: 80px;">
|
||||
</div>
|
||||
</header>
|
||||
<div id="container">
|
||||
<%- if flash[:notice].present? %>
|
||||
<div class="alert alert-info">
|
||||
<%= flash[:notice] %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<%= yield %>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
25
app/views/oauth2/show.html.erb
Normal file
25
app/views/oauth2/show.html.erb
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
<main role="main">
|
||||
<p class="auth-desc">
|
||||
申请使用<strong class="app-name"> GitLink </strong>账号登录
|
||||
<strong class="app-name"><%= @app&.name %></strong>
|
||||
</p>
|
||||
|
||||
<div class="actions">
|
||||
<div class="w">
|
||||
<%= form_tag oauth2_path, method: :post, authenticity_token: true, remote: true, class: 'login-form' do %>
|
||||
<%= hidden_field_tag :client_id, @app.uid %>
|
||||
<%= hidden_field_tag :call_url, @call_url %>
|
||||
<p id="account_error" class='error'></p>
|
||||
<%= text_field_tag :login, '', placeholder: '请输入邮箱地址/用户名' %>
|
||||
<p id="login_error" class='error'></p>
|
||||
<%= password_field_tag :password, '', placeholder: '请输入密码'%>
|
||||
<p id="password_error" class='error'></p>
|
||||
<%= submit_tag '授权登录', class: "btn btn-login btn-lg btn-block mt-20" %>
|
||||
<% end %>
|
||||
<div class="reg">
|
||||
<%= link_to "注 册", '/register', class: 'reg-link' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
8
app/views/projects/_detail.json.jbuilder
Normal file
8
app/views/projects/_detail.json.jbuilder
Normal file
@@ -0,0 +1,8 @@
|
||||
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
|
||||
@@ -0,0 +1,12 @@
|
||||
json.(project_invite_link, :id, :role, :is_apply, :sign)
|
||||
json.expired_at format_time(project_invite_link&.expired_at)
|
||||
json.user do
|
||||
json.partial! "/users/user_simple", locals: {user: project_invite_link.user}
|
||||
end
|
||||
if project_invite_link&.project.present?
|
||||
json.project do
|
||||
json.partial! "/projects/detail", locals: {project: project_invite_link.project}
|
||||
end
|
||||
else
|
||||
json.project nil
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
json.partial! 'detail', locals: { project_invite_link: @project_invite_link }
|
||||
@@ -0,0 +1 @@
|
||||
json.partial! 'detail', locals: { project_invite_link: @project_invite_link }
|
||||
@@ -0,0 +1 @@
|
||||
json.partial! 'detail', locals: { project_invite_link: @project_invite_link }
|
||||
@@ -7,6 +7,20 @@ json.commits_count @gitea_pull["commit_num"]
|
||||
json.files_count @gitea_pull["changed_files"]
|
||||
json.comments_count @issue.journals.parent_journals.size
|
||||
json.comments_total_count @issue.get_journals_size
|
||||
json.assign_user do
|
||||
json.partial! 'users/user_simple', user: @issue_assign_to
|
||||
end
|
||||
|
||||
json.author do
|
||||
json.partial! 'users/user_simple', user: @issue_user
|
||||
end
|
||||
|
||||
if @last_review.present?
|
||||
json.last_review do
|
||||
json.(@last_review, :id, :commit_id, :content, :status)
|
||||
json.created_at format_time(@last_review.created_at)
|
||||
end
|
||||
end
|
||||
|
||||
json.pull_request do
|
||||
json.extract! @pull_request, :id,:base, :head, :status,:fork_project_id, :is_original
|
||||
|
||||
10
app/views/reviews/create.json.jbuilder
Normal file
10
app/views/reviews/create.json.jbuilder
Normal file
@@ -0,0 +1,10 @@
|
||||
json.issue do
|
||||
json.partial! 'pull_requests/detail', issue: @pull_request.issue
|
||||
end
|
||||
json.journal_id @journal.id
|
||||
json.journal_notes @journal.notes
|
||||
json.review_id @review.id
|
||||
json.commit_id @review.commit_id
|
||||
json.content @review.content
|
||||
json.status @review.status
|
||||
json.created_at format_time(@review.created_at)
|
||||
Reference in New Issue
Block a user