| @@ -74,6 +74,7 @@ vendor/bundle/ | |||
| /log | |||
| /public/admin | |||
| /mysql_data | |||
| /public/repo/ | |||
| .generators | |||
| @@ -85,3 +86,4 @@ redis_data/ | |||
| Dockerfile | |||
| dump.rdb | |||
| .tags* | |||
| ceshi_user.xlsx | |||
| @@ -775,7 +775,8 @@ class ApplicationController < ActionController::Base | |||
| end | |||
| def convert_image! | |||
| @image = params[:image] || user_params[:image] | |||
| @image = params[:image] | |||
| @image = @image.nil? && params[:user].present? ? params[:user][:image] : @image | |||
| return unless @image.present? | |||
| max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M | |||
| if @image.class == ActionDispatch::Http::UploadedFile | |||
| @@ -48,6 +48,6 @@ class CompareController < ApplicationController | |||
| end | |||
| def gitea_compare(base, head) | |||
| Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head) | |||
| Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token) | |||
| end | |||
| end | |||
| @@ -7,7 +7,7 @@ class IssueTagsController < ApplicationController | |||
| def index | |||
| issue_tags = @project.issue_tags.order("#{order_name} #{order_type}") | |||
| issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}") | |||
| @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) | |||
| @page = params[:page] || 1 | |||
| @limit = params[:limit] || 15 | |||
| @@ -219,7 +219,7 @@ class IssuesController < ApplicationController | |||
| change_type = change_token > 0 ? "add" : "minus" | |||
| post_to_chain(change_type, change_token.abs, current_user.try(:login)) | |||
| end | |||
| @issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) | |||
| @issue.create_journal_detail(change_files, issue_files, issue_file_ids, current_user&.id) if @issue.previous_changes.present? | |||
| normal_status(0, "更新成功") | |||
| else | |||
| normal_status(-1, "更新失败") | |||
| @@ -302,9 +302,11 @@ class IssuesController < ApplicationController | |||
| # update_hash = params[:issue] | |||
| issue_ids = params[:ids] | |||
| if issue_ids.present? | |||
| issues = Issue.where(id: issue_ids) | |||
| if update_hash.blank? | |||
| normal_status(-1, "请选择批量更新内容") | |||
| elsif Issue.where(id: issue_ids)&.update(update_hash) | |||
| elsif issues&.update(update_hash) | |||
| issues.map{|i| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?} | |||
| normal_status(0, "批量更新成功") | |||
| else | |||
| normal_status(-1, "批量更新失败") | |||
| @@ -56,7 +56,7 @@ class MembersController < ApplicationController | |||
| end | |||
| def member_exists? | |||
| @project.members.exists?(params[:user_id]) | |||
| @project.members.exists?(user_id: params[:user_id]) | |||
| end | |||
| def operate! | |||
| @@ -64,10 +64,10 @@ class MembersController < ApplicationController | |||
| end | |||
| def check_member_exists! | |||
| return render_result(1, "user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists? | |||
| return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists? | |||
| end | |||
| def check_member_not_exists! | |||
| return render_result(1, "user_id为#{params[:user_id]}的用户还不是项目成员") unless @project.member?(params[:user_id]) | |||
| return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists? | |||
| end | |||
| end | |||
| @@ -29,6 +29,11 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||
| ActiveRecord::Base.transaction do | |||
| @team_user.destroy! | |||
| Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login) | |||
| org_team_users = @organization.team_users.where(user_id: @operate_user.id) | |||
| unless org_team_users.present? | |||
| @organization.organization_users.find_by(user_id: @operate_user.id).destroy! | |||
| Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, @operate_user.login) | |||
| end | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| @@ -43,6 +48,11 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||
| ActiveRecord::Base.transaction do | |||
| @team_user.destroy! | |||
| Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, current_user.login) | |||
| org_team_users = @organization.team_users.where(user_id: current_user.id) | |||
| unless org_team_users.present? | |||
| @organization.organization_users.find_by(user_id: current_user.id).destroy! | |||
| Gitea::Organization::OrganizationUser::DeleteService.call(@organization.gitea_token, @organization.login, current_user.login) | |||
| end | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| @@ -4,4 +4,7 @@ class Projects::BaseController < ApplicationController | |||
| before_action :load_project | |||
| before_action :load_repository | |||
| def require_manager! | |||
| return render_forbidden('你没有权限操作') unless current_user.admin? || @project.manager?(current_user) | |||
| end | |||
| end | |||
| @@ -14,7 +14,7 @@ class Projects::TeamsController < Projects::BaseController | |||
| def create | |||
| ActiveRecord::Base.transaction do | |||
| @team_project = TeamProject.build(@owner.id, @operate_team.id, @project.id) | |||
| Gitea::Organization::TeamProject::CreateService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier) | |||
| Gitea::Organization::TeamProject::CreateService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier) | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| @@ -25,7 +25,7 @@ class Projects::TeamsController < Projects::BaseController | |||
| def destroy | |||
| ActiveRecord::Base.transaction do | |||
| @team_project.destroy! | |||
| Gitea::Organization::TeamProject::DeleteService.call(@owner.gitea_token, @operate_team.gtid, @owner.login, @project.identifier) | |||
| Gitea::Organization::TeamProject::DeleteService.call(current_user.gitea_token, @operate_team.gtid, @owner.login, @project.identifier) | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| @@ -0,0 +1,116 @@ | |||
| class Projects::WebhooksController < Projects::BaseController | |||
| before_action :require_manager! | |||
| before_action :find_webhook, only:[:edit, :update, :destroy, :tasks, :test] | |||
| def index | |||
| @webhooks = @project.webhooks | |||
| @webhooks = kaminari_paginate(@webhooks) | |||
| end | |||
| def create | |||
| ActiveRecord::Base.transaction do | |||
| return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 19 | |||
| return render_error("参数错误.") unless webhook_params.present? | |||
| form = Projects::Webhooks::CreateForm.new(webhook_params) | |||
| return render json: {status: -1, message: form.errors} unless form.validate! | |||
| response = Gitea::Repository::Webhooks::CreateService.new(operating_token, @project&.owner&.login, @project&.identifier, gitea_webhooks_params).call | |||
| if response[0] == 201 | |||
| @webhook = response[2] | |||
| else | |||
| render_error("创建失败.") | |||
| end | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def edit | |||
| end | |||
| def update | |||
| return render_error("参数错误.") unless webhook_params.present? | |||
| form = Projects::Webhooks::CreateForm.new(webhook_params) | |||
| return render json: {status: -1, message: form.errors} unless form.validate! | |||
| response = Gitea::Repository::Webhooks::UpdateService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id, gitea_webhooks_params) | |||
| if response[0] == 200 | |||
| @webhook = response[2] | |||
| render_ok | |||
| else | |||
| render_error("更新失败.") | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def destroy | |||
| response = Gitea::Repository::Webhooks::DeleteService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id) | |||
| if response[0] == 204 | |||
| @webhook = response[2] | |||
| render_ok | |||
| else | |||
| render_error("删除失败.") | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def tasks | |||
| @tasks = @webhook.tasks.where(is_delivered: true).order("delivered desc") | |||
| @tasks = kaminari_paginate(@tasks) | |||
| end | |||
| def test | |||
| ActiveRecord::Base.transaction do | |||
| response = Gitea::Repository::Webhooks::TestService.call(operating_token, @project&.owner&.login, @project&.identifier, @webhook.id) | |||
| if response[0] == 204 | |||
| render_ok | |||
| else | |||
| render_error("测试推送失败.") | |||
| end | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| private | |||
| def find_webhook | |||
| @webhook = @project.webhooks.find_by_id(params[:id]) | |||
| return render_not_found if @webhook.nil? | |||
| end | |||
| def webhook_params | |||
| params.require(:webhook).permit(:url, :type, :http_method, :content_type, :secret, :active, :branch_filter, events: []) | |||
| end | |||
| def webhook_type | |||
| webhook_params.fetch(:type, "gitea") | |||
| end | |||
| def webhook_branch_filter | |||
| webhook_params.fetch(:branch_filter, "*") | |||
| end | |||
| def gitea_webhooks_params | |||
| { | |||
| active: webhook_params[:active], | |||
| branch_filter: webhook_branch_filter, | |||
| config: { | |||
| content_type: webhook_params[:content_type], | |||
| url: webhook_params[:url], | |||
| http_method: webhook_params[:http_method], | |||
| secret: webhook_params[:secret] | |||
| }, | |||
| events: webhook_params[:events], | |||
| type: webhook_type, | |||
| } | |||
| end | |||
| def operating_token | |||
| @project.member?(current_user) ? current_user.gitea_token : @project&.owner&.gitea_token | |||
| end | |||
| end | |||
| @@ -16,6 +16,7 @@ class ProjectsController < ApplicationController | |||
| menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code") | |||
| menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues") | |||
| menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") | |||
| menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") | |||
| menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") | |||
| menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions") | |||
| menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") | |||
| @@ -117,8 +118,14 @@ class ProjectsController < ApplicationController | |||
| ActiveRecord::Base.transaction do | |||
| # TODO: | |||
| # 临时特殊处理修改website、lesson_url操作方法 | |||
| if project_params.has_key?("website") | |||
| if project_params.has_key?("website") | |||
| @project.update(project_params) | |||
| elsif project_params.has_key?("default_branch") | |||
| @project.update(project_params) | |||
| gitea_params = { | |||
| default_branch: @project.default_branch | |||
| } | |||
| Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) | |||
| else | |||
| validate_params = project_params.slice(:name, :description, | |||
| :project_category_id, :project_language_id, :private) | |||
| @@ -222,7 +229,7 @@ class ProjectsController < ApplicationController | |||
| private | |||
| def project_params | |||
| params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, | |||
| params.permit(:user_id, :name, :description, :repository_name, :website, :lesson_url, :default_branch, | |||
| :project_category_id, :project_language_id, :license_id, :ignore_id, :private) | |||
| end | |||
| @@ -0,0 +1,64 @@ | |||
| class PublicKeysController < ApplicationController | |||
| before_action :require_login | |||
| before_action :find_public_key, only: [:destroy] | |||
| def index | |||
| @public_keys = current_user.public_keys | |||
| @public_keys = kaminari_paginate(@public_keys) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def create | |||
| return render_error("参数错误") if public_key_params.blank? | |||
| return render_ok({status: 10002, message: "请输入密钥"}) if public_key_params[:key].blank? | |||
| return render_ok({status: 10001, message: "请输入标题"}) if public_key_params[:title].blank? | |||
| @gitea_response = Gitea::User::Keys::CreateService.call(current_user.gitea_token, public_key_params) | |||
| if @gitea_response[0] == 201 | |||
| @public_key = @gitea_response[2] | |||
| else | |||
| return render_error("创建ssh key失败") if @gitea_response[2].blank? | |||
| return render_ok({status: 10002, message: "密钥格式不正确"}) if @gitea_response[2]["message"].starts_with?("Invalid key content") | |||
| exist_public_key = Gitea::PublicKey.find_by(content: public_key_params[:key]) | |||
| return render_ok({status: 10002, message: "密钥已被占用"}) if @gitea_response[2]["message"].starts_with?("Key content has been used as non-deploy key") && exist_public_key.present? && exist_public_key&.owner_id != current_user.gitea_uid | |||
| return render_ok({status: 10002, message: "密钥已存在,请勿重复添加"}) if @gitea_response[2]["message"].starts_with?("Key content has been used as non-deploy key") | |||
| @public_key = nil | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def destroy | |||
| return render_not_found unless @public_key.present? | |||
| result = Gitea::User::Keys::DeleteService.call(current_user.gitea_token, @public_key.id) | |||
| if result[0] == 204 | |||
| render_ok | |||
| else | |||
| render_error | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| private | |||
| def page | |||
| params[:page].to_i.zero? ? 1 : params[:page].to_i | |||
| end | |||
| def limit | |||
| limit = params[:limit] || params[:per_page] | |||
| limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i | |||
| end | |||
| def public_key_params | |||
| params.require(:public_key).permit(:key, :title) | |||
| end | |||
| def find_public_key | |||
| @public_key = current_user.public_keys.find_by_id(params[:id]) | |||
| end | |||
| end | |||
| @@ -19,6 +19,7 @@ class PullRequestsController < ApplicationController | |||
| @close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED}) | |||
| @merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED}) | |||
| @user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user)) | |||
| @user_admin_or_developer = current_user.present? && (current_user.admin || @project.all_developers.include?(current_user)) | |||
| scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "PullRequest") | |||
| @issues_size = scopes.size | |||
| @@ -5,7 +5,7 @@ class Users::BaseController < ApplicationController | |||
| helper_method :observed_logged_user?, :observed_user | |||
| def observed_user | |||
| @_observed_user ||= (User.find_by_id(params[:user_id]) || User.find_by_login(params[:user_id])) | |||
| @_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id])) | |||
| end | |||
| def observed_logged_user? | |||
| @@ -12,6 +12,7 @@ toc_footers: | |||
| includes: | |||
| - licenses | |||
| - gitignores | |||
| - public_keys | |||
| - users | |||
| - projects | |||
| - repositories | |||
| @@ -0,0 +1,158 @@ | |||
| <!-- | |||
| * @Date: 2021-07-14 15:10:29 | |||
| * @LastEditors: viletyy | |||
| * @LastEditTime: 2021-07-14 15:37:23 | |||
| * @FilePath: /forgeplus/app/docs/slate/source/includes/_public_keys.md | |||
| --> | |||
| # PublicKeys | |||
| ## public_keys列表 | |||
| 获取public_keys列表,支持分页 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/public_keys.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/public_keys.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET api/public_keys.json` | |||
| ### 请求参数 | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| page |否| 1 | int | 页码 | | |||
| limit |否| 15 | int | 每页数量 | | |||
| ### 返回字段说明 | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| total_count |int |总数 | | |||
| public_keys.id |int |ID| | |||
| public_keys.name |string|密钥标题| | |||
| public_keys.content |string|密钥内容| | |||
| public_keys.fingerprint |string|密钥标识| | |||
| public_keys.created_time |string|密钥创建时间| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "total_count": 1, | |||
| "public_keys": [ | |||
| { | |||
| "id": 16, | |||
| "name": "xxx", | |||
| "content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com", | |||
| "fingerprint": "SHA256:cU8AK/+roqUUyiaYXIdS2Nj4+Rb2p6rqWSeRDc+aqKM", | |||
| "created_unix": 1626246596, | |||
| "created_time": "2021/07/14 15:09" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success — a happy kitten is an authenticated kitten! | |||
| </aside> | |||
| ## 创建public_key | |||
| 创建public_key | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST \ | |||
| http://localhost:3000/api/public_keys.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/public_keys.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST api/public_keys.json` | |||
| ### 请求参数 | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| key |是 | 否 | string | 密钥 | | |||
| title |是 | 否 | string | 密钥标题 | | |||
| > 请求的JSON示例: | |||
| ```json | |||
| { | |||
| "public_key": { | |||
| "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com", | |||
| "title": "xxx" | |||
| } | |||
| } | |||
| ``` | |||
| ### 返回字段说明 | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| total_count |int |总数 | | |||
| id |int |ID| | |||
| name |string|密钥标题| | |||
| content |string|密钥内容| | |||
| fingerprint |string|密钥标识| | |||
| created_time |string|密钥创建时间| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "id": 17, | |||
| "name": "xxx", | |||
| "content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe5ETOTB5PcmcYJkIhfF7+mxmJQDCLg7/LnMoKHpKoo/jYUnFU9OjfsxVo3FTNUvh2475WXMAur5KsFoNKjK9+JHxvoXyJKmyVPWgXU/NRxQyaWPnPLPK8qPRF5ksJE6feBOqtsdxsvBiHs2r1NX/U26Ecnpr6avudD0cmyrEfbYMWbupLrhsd39dswPT73f3W5jc7B9Y47Ioiv8UOju3ABt1+kpuAjaaVC6VtUQoEFiZb1y33yBnyePya7dvFyApyD4ILyyIG2rtZWK7l53YFnwZDuFsTWjEEEQD0U4FBSFdH5wtwx0WQLMSNyTtaFBSG0kJ+uiQQIrxlvikcm63df7zbC3/rWLPsKgW122Zt966dcpFqiCiJNDKZPPw3qpg8TBL6X+qIZ+FxVEk/16/zScpyEfoxQp0GvgxI7hPLErmfkC5tMsib8MAXYBNyvJXna0vg/wOaNNIaI4SAH9Ksh3f/TtalYVjp6WxIwVBfnbq51WnmlnEXePtX6XjAGL+GbF2VQ1nv/IzrY09tNbTV6wQsrSIP3VDzYQxdJ1rdsVNMoJB0H2Pu0NdcSz53Wx45N+myD0QnE05ss+zDp5StY90OYsx2aCo6qAA8Qn2jUjdta7MQWwkPfKrta4tTQ0XbWMjx4/E1+l3J5liwZkl2XOGOwhfXdRsBjaEziZ18kQ== yystopf@163.com", | |||
| "fingerprint": "SHA256:cU8AK/+roqUUyiaYXIdS2Nj4+Rb2p6rqWSeRDc+aqKM", | |||
| "created_time": "2021/07/14 15:26" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success — a happy kitten is an authenticated kitten! | |||
| </aside> | |||
| ## 删除public_key | |||
| 删除public_key | |||
| > 示例: | |||
| ```shell | |||
| curl -X DELETE \ | |||
| http://localhost:3000/api/public_keys/:id.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('DELETE /api/public_keys/:id.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `DELETE api/public_keys/:id.json` | |||
| ### 请求参数 | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| id |是 | 否 | int | 密钥ID | | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success — a happy kitten is an authenticated kitten! | |||
| </aside> | |||
| @@ -867,3 +867,674 @@ await octokit.request('GET /api/jasder/jasder_test/sub_entries.json') | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库webhooks列表 | |||
| 获取仓库webhooks列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/ceshi/webhooks.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/webhooks.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |id |int |id | | |||
| |url |string|地址| | |||
| |http_method |string|请求方式| | |||
| |is_active |bool |是否激活| | |||
| |type |string|类型| | |||
| |last_status |string|最后一次推送的状态| | |||
| |create_time |string|创建时间| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "total_count": 4, | |||
| "webhooks": [ | |||
| { | |||
| "id": 2, | |||
| "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" | |||
| }, | |||
| { | |||
| "id": 3, | |||
| "url": "http://localhost:3000", | |||
| "http_method": "GET", | |||
| "is_active": true, | |||
| "type": "gitea", | |||
| "last_status": "succeed", | |||
| "create_time": "2021-07-26 10:03:45" | |||
| }, | |||
| { | |||
| "id": 4, | |||
| "url": "http://localhost:10081", | |||
| "http_method": "POST", | |||
| "is_active": true, | |||
| "type": "gitea", | |||
| "last_status": "waiting", | |||
| "create_time": "2021-07-26 16:56:53" | |||
| }, | |||
| { | |||
| "id": 5, | |||
| "url": "http://localhost:3001", | |||
| "http_method": "POST", | |||
| "is_active": true, | |||
| "type": "gitea", | |||
| "last_status": "fail", | |||
| "create_time": "2021-07-26 16:58:23" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库单个webhook | |||
| 获取仓库单个webhook | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks/3/edit.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/ceshi/webhooks/3/edit.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/webhooks/:id/edit.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |id |是||integer|webhook ID| | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |id |int |id | | |||
| |url |string|地址| | |||
| |content_type |string|POST Content Type| | |||
| |http_method |string|请求方式| | |||
| |secret| |string|密钥| | |||
| |is_active |bool |是否激活| | |||
| |type |string|类型| | |||
| |last_status |string|最后一次推送的状态, waiting 等待,fail 失败,succeed 成功| | |||
| |branch_filter |string|分支过滤| | |||
| |events |string|触发条件| | |||
| |create_time |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示例: | |||
| ```json | |||
| { | |||
| "id": 3, | |||
| "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", | |||
| "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" | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 添加仓库webhook | |||
| 添加仓库webhook | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/yystopf/ceshi/webhooks.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST /api/:owner/:repo/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 |密钥文本| | |||
| |webhook.active |是| | bool | 是否激活| | |||
| |webhook.branch_filter|否| |string|分支过滤| | |||
| |webhook.events |否| |array|触发事件| | |||
| 触发事件字段说明 | |||
| 参数| 含义| | |||
| --------- | ------- | ------- | | |||
| |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示例: | |||
| ```json | |||
| { | |||
| "active": true, | |||
| "content_type": "json", | |||
| "http_method": "GET", | |||
| "secret": "123456", | |||
| "url": "http://localhost:10000", | |||
| "branch_filter": "*", | |||
| "events": ["push"] | |||
| } | |||
| ``` | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |id |int |id | | |||
| |url |string|地址| | |||
| |content_type |string|POST Content Type| | |||
| |is_active |bool |是否激活| | |||
| |type |string|类型| | |||
| |events | array|触发事件 | | |||
| |create_time |string|创建时间| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "id": 18, | |||
| "type": "gitea", | |||
| "content_type": "json", | |||
| "url": "http://localhost:10000", | |||
| "events": [ | |||
| "push" | |||
| ], | |||
| "active": true, | |||
| "create_time": "2021-07-26 18:53:43" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 更新仓库webhook | |||
| 更新仓库webhook | |||
| > 示例: | |||
| ```shell | |||
| curl -X PATCH \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks/7.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('PATCH /api/yystopf/ceshi/webhooks/7.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `PATCH /api/:owner/:repo/webhooks/:id.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| | string |用户登录名 | | |||
| |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 |密钥文本| | |||
| |webhook.active |是| | bool | 是否激活| | |||
| |webhook.branch_filter|否| |string|分支过滤| | |||
| |webhook.events |否| |array|触发事件| | |||
| 触发事件字段说明 | |||
| 参数| 含义| | |||
| --------- | ------- | ------- | | |||
| |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示例: | |||
| ```json | |||
| { | |||
| "active": true, | |||
| "content_type": "json", | |||
| "http_method": "GET", | |||
| "secret": "123456", | |||
| "url": "http://localhost:10000", | |||
| "branch_filter": "*", | |||
| "events": ["push"] | |||
| } | |||
| ``` | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 删除仓库webhook | |||
| 删除仓库webhook | |||
| > 示例: | |||
| ```shell | |||
| curl -X DELETE \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks/7.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('DELETE /api/yystopf/ceshi/webhooks/7.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `DELETE /api/:owner/:repo/webhooks/:id.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| | string |用户登录名 | | |||
| |repo |是| | string |项目标识identifier | | |||
| |id |是| | string |webhook id | | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 获取仓库webhook的历史推送列表 | |||
| 获取仓库webhook的历史推送列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks/3/tasks.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/yystopf/ceshi/webhooks/3/tasks.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET /api/:owner/:repo/webhooks/:id/tasks.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| |string |用户登录名 | | |||
| |repo |是| |string |项目标识identifier | | |||
| |id |是| |integer |webhook ID| | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |id |int |id | | |||
| |uuid |string|推送uuid| | |||
| |type |string|类型| | |||
| |is_succeed |bool|是否推送成功| | |||
| |is_delivered |bool|是否完成推送| | |||
| |payload_content |json|请求主体内容| | |||
| |request_content |json|请求内容,头部等等| | |||
| |reponse_content |json|响应内容,状态,头部,主体等等| | |||
| |delivered_time |string|推送时间| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "total_count": 6, | |||
| "tasks": [ | |||
| { | |||
| "id": 20, | |||
| "type": "gitea", | |||
| "uuid": "99aa2c23-6884-4c44-9020-5469320aa408", | |||
| "is_succeed": true, | |||
| "is_delivered": true, | |||
| "payload_content": { | |||
| "secret": "123456", | |||
| "ref": "refs/heads/master", | |||
| "before": "feb48e31362787a7620b53d4df3c4effddbb6f0b", | |||
| "after": "feb48e31362787a7620b53d4df3c4effddbb6f0b", | |||
| "compare_url": "", | |||
| "commits": [ | |||
| { | |||
| "id": "feb48e31362787a7620b53d4df3c4effddbb6f0b", | |||
| "message": "fix\n", | |||
| "url": "http://localhost:10081/yystopf/ceshi/commit/feb48e31362787a7620b53d4df3c4effddbb6f0b", | |||
| "author": { | |||
| "name": "viletyy", | |||
| "email": "yystopf@163.com", | |||
| "username": "root" | |||
| }, | |||
| "committer": { | |||
| "name": "viletyy", | |||
| "email": "yystopf@163.com", | |||
| "username": "root" | |||
| }, | |||
| "verification": { | |||
| "verified": false, | |||
| "reason": "gpg.error.not_signed_commit", | |||
| "signature": "", | |||
| "signer": null, | |||
| "payload": "" | |||
| }, | |||
| "timestamp": "2021-07-26T13:52:13+08:00", | |||
| "added": null, | |||
| "removed": null, | |||
| "modified": null | |||
| } | |||
| ], | |||
| "head_commit": null, | |||
| "repository": { | |||
| "id": 2, | |||
| "owner": { | |||
| "id": 3, | |||
| "login": "yystopf", | |||
| "full_name": "", | |||
| "email": "yystopf@forge.com", | |||
| "avatar_url": "http://localhost:10081/user/avatar/yystopf/-1", | |||
| "language": "zh-CN", | |||
| "is_admin": true, | |||
| "last_login": "2021-07-21T18:38:21+08:00", | |||
| "created": "2021-06-03T14:50:25+08:00", | |||
| "username": "yystopf" | |||
| }, | |||
| "name": "ceshi", | |||
| "full_name": "yystopf/ceshi", | |||
| "description": "", | |||
| "empty": false, | |||
| "private": false, | |||
| "fork": false, | |||
| "template": false, | |||
| "parent": null, | |||
| "mirror": false, | |||
| "size": 3846, | |||
| "html_url": "http://localhost:10081/yystopf/ceshi", | |||
| "ssh_url": "virus@localhost:10081:yystopf/ceshi.git", | |||
| "clone_url": "http://localhost:10081/yystopf/ceshi.git", | |||
| "original_url": "", | |||
| "website": "", | |||
| "stars_count": 0, | |||
| "forks_count": 1, | |||
| "watchers_count": 1, | |||
| "open_issues_count": 0, | |||
| "open_pr_counter": 0, | |||
| "release_counter": 0, | |||
| "default_branch": "master", | |||
| "archived": false, | |||
| "created_at": "2021-06-03T15:15:30+08:00", | |||
| "updated_at": "2021-07-26T13:52:16+08:00", | |||
| "permissions": { | |||
| "admin": false, | |||
| "push": false, | |||
| "pull": false | |||
| }, | |||
| "has_issues": true, | |||
| "internal_tracker": { | |||
| "enable_time_tracker": true, | |||
| "allow_only_contributors_to_track_time": true, | |||
| "enable_issue_dependencies": true | |||
| }, | |||
| "has_wiki": true, | |||
| "has_pull_requests": true, | |||
| "ignore_whitespace_conflicts": false, | |||
| "allow_merge_commits": true, | |||
| "allow_rebase": true, | |||
| "allow_rebase_explicit": true, | |||
| "allow_squash_merge": true, | |||
| "avatar_url": "", | |||
| "internal": false | |||
| }, | |||
| "pusher": { | |||
| "id": 0, | |||
| "login": "yystopf", | |||
| "full_name": "", | |||
| "email": "yystopf@forge.com", | |||
| "avatar_url": "http://localhost:10081/user/avatar/yystopf/-1", | |||
| "language": "", | |||
| "is_admin": false, | |||
| "last_login": "0001-01-01T00:00:00Z", | |||
| "created": "2021-06-03T14:50:25+08:00", | |||
| "username": "yystopf" | |||
| }, | |||
| "sender": { | |||
| "id": 0, | |||
| "login": "yystopf", | |||
| "full_name": "", | |||
| "email": "yystopf@forge.com", | |||
| "avatar_url": "http://localhost:10081/user/avatar/yystopf/-1", | |||
| "language": "", | |||
| "is_admin": false, | |||
| "last_login": "0001-01-01T00:00:00Z", | |||
| "created": "2021-06-03T14:50:25+08:00", | |||
| "username": "yystopf" | |||
| } | |||
| }, | |||
| "request_content": { | |||
| "headers": { | |||
| "X-GitHub-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408", | |||
| "X-GitHub-Event": "push", | |||
| "X-Gitea-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408", | |||
| "X-Gitea-Event": "push", | |||
| "X-Gitea-Signature": "34a01edcd952ff6410ff6ebc946471161bde74aff86171f21621d2c2c4130f66", | |||
| "X-Gogs-Delivery": "99aa2c23-6884-4c44-9020-5469320aa408", | |||
| "X-Gogs-Event": "push", | |||
| "X-Gogs-Signature": "34a01edcd952ff6410ff6ebc946471161bde74aff86171f21621d2c2c4130f66" | |||
| } | |||
| }, | |||
| "response_content": { | |||
| "status": 200, | |||
| "headers": { | |||
| "Cache-Control": "no-store, must-revalidate, private, max-age=0", | |||
| "Content-Length": "2556", | |||
| "Content-Type": "text/html; charset=utf-8", | |||
| "Referrer-Policy": "strict-origin-when-cross-origin", | |||
| "Set-Cookie": "__profilin=p%3Dt; path=/; HttpOnly", | |||
| "Vary": "Origin", | |||
| "X-Content-Type-Options": "nosniff", | |||
| "X-Download-Options": "noopen", | |||
| "X-Frame-Options": "SAMEORIGIN", | |||
| "X-Miniprofiler-Ids": "9ynvpncz5xm0rpgorb5y,hgggd9mv6lr4a9drcrlr,j7zqlx2vy5aji2vtgoba,f1ktsmh3jxvq0z2hf612,mih3dvgvlqhi3zy8lf2x,5k1qbkvbnru8mye9cest,tj6ern8w6awqf2zsimbr,9isaehvubivd52wo5p9v,1rzfhtq1nhuwbgy9p76g,z0xzidzyywna0y7a69m0,hzoklky92ycjqt42gi0s,y0ai7y0t28mcn8x0py2x,322il7nadinp51mw2r5m,m6dukftfsh6tjcxzp1gq,667wlqbytfwbrirnmma1,jcehj3dl8lkw8gk510cr", | |||
| "X-Miniprofiler-Original-Cache-Control": "max-age=0, private, must-revalidate", | |||
| "X-Permitted-Cross-Domain-Policies": "none", | |||
| "X-Request-Id": "08bff080-bbb5-4183-b845-81de3d47120a", | |||
| "X-Runtime": "0.394766", | |||
| "X-Xss-Protection": "1; mode=block" | |||
| }, | |||
| "body": "<!doctype html><html lang=\"zh-CN\" class=\"notranslate translated-ltr\" translate=\"no\"><head><meta charset=\"utf-8\"><meta name=\"”Keywords”\" content=\"”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″\"><meta name=\"”Keywords”\" content=\"”TrustieOpenSourceProject″\"><meta name=\"”Keywords”\" content=\"”issue,bug,tracker,软件工程,课程实践″\"><meta name=\"”Description”\" content=\"”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”\"><meta name=\"theme-color\" content=\"#000000\"><link rel=\"manifest\" href=\"/react/build//manifest.json\"><link rel=\"stylesheet\" href=\"/react/build/css/iconfont.css\"><link rel=\"stylesheet\" href=\"/react/build/css/edu-purge.css\"><link rel=\"stylesheet\" href=\"/react/build/css/editormd.min.css\"><link rel=\"stylesheet\" href=\"/react/build/css/merge.css\"><link href=\"/react/build/static/css/main.07f7e90c.chunk.css\" rel=\"stylesheet\"></head><body><div id=\"md_div\" style=\"display:none\"></div><div id=\"root\" class=\"page -layout-v -fit widthunit\"></div><div id=\"picture_display\" style=\"display:none\"></div><script src=\"/react/build/js/jquery-1.8.3.min.js\"></script><script src=\"/react/build/js/js_min_all.js\"></script><script src=\"/react/build/js/codemirror/codemirror.js\"></script><script src=\"/react/build/js/editormd/editormd.min.js\"></script><script src=\"/react/build/js/codemirror/merge/merge.js\"></script><script src=\"/react/build/./static/js/runtime~main.3d644966.js\"></script><script src=\"/react/build/./static/js/main.e46872e3.chunk.js\"></script><script async type=\"text/javascript\" id=\"mini-profiler\" src=\"/mini-profiler-resources/includes.js?v=67dd1c2571ced7fc74ae7f1813e47bdf\" data-version=\"67dd1c2571ced7fc74ae7f1813e47bdf\" data-path=\"/mini-profiler-resources/\" data-current-id=\"9ynvpncz5xm0rpgorb5y\" data-ids=\"9ynvpncz5xm0rpgorb5y,hgggd9mv6lr4a9drcrlr,j7zqlx2vy5aji2vtgoba,f1ktsmh3jxvq0z2hf612,mih3dvgvlqhi3zy8lf2x,5k1qbkvbnru8mye9cest,tj6ern8w6awqf2zsimbr,9isaehvubivd52wo5p9v,1rzfhtq1nhuwbgy9p76g,z0xzidzyywna0y7a69m0,hzoklky92ycjqt42gi0s,y0ai7y0t28mcn8x0py2x,322il7nadinp51mw2r5m,m6dukftfsh6tjcxzp1gq,667wlqbytfwbrirnmma1,jcehj3dl8lkw8gk510cr\" data-horizontal-position=\"left\" data-vertical-position=\"top\" data-trivial=\"false\" data-children=\"false\" data-max-traces=\"20\" data-controls=\"false\" data-total-sql-count=\"false\" data-authorized=\"true\" data-toggle-shortcut=\"alt+p\" data-start-hidden=\"false\" data-collapse-results=\"true\" data-html-container=\"body\"></script>\n</body></html>" | |||
| }, | |||
| "delivered_time": "2021-07-28 11:47:29" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 仓库webhook测试推送 | |||
| 仓库webhook测试推送 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST \ | |||
| http://localhost:3000/api/yystopf/ceshi/webhooks/3/test.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/yystopf/ceshi/webhooks/3/test.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST /api/:owner/:repo/webhooks/:id/test.json` | |||
| ### 请求参数: | |||
| 参数 | 必选 | 默认 | 类型 | 字段说明 | |||
| --------- | ------- | ------- | -------- | ---------- | |||
| |owner |是| | string |用户登录名 | | |||
| |repo |是| | string |项目标识identifier | | |||
| |id |是| | integer|webhook ID| | |||
| ### 返回字段说明: | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| @@ -0,0 +1,8 @@ | |||
| class Projects::Webhooks::CreateForm < BaseForm | |||
| attr_accessor :type, :url, :http_method, :content_type, :secret, :events, :active, :branch_filter | |||
| 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"} | |||
| end | |||
| @@ -34,11 +34,12 @@ module ProjectsHelper | |||
| end | |||
| def json_response(project, user) | |||
| repo = Repository.includes(:mirror).select(:id, :mirror_url, :source_clone_url).find_by(project: project) | |||
| repo = Repository.includes(:mirror).select(:id, :is_mirror, :mirror_url, :source_clone_url).find_by(project: project) | |||
| tmp_json = {} | |||
| unless project.common? | |||
| tmp_json = tmp_json.merge({ | |||
| is_mirror: repo.is_mirror ? true : false, | |||
| mirror_status: repo.mirror_status, | |||
| mirror_num: repo.mirror_num, | |||
| mirror_url: repo.remote_mirror_url, | |||
| @@ -54,7 +55,11 @@ module ProjectsHelper | |||
| repo_id: repo.id, | |||
| open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?, | |||
| type: project.numerical_for_project_type, | |||
| author: render_owner(project) | |||
| author: render_owner(project), | |||
| project_category_id: project.project_category_id, | |||
| project_language_id: project.project_language_id, | |||
| license_id: project.license_id, | |||
| ignore_id: project.ignore_id | |||
| }).compact | |||
| render json: tmp_json | |||
| @@ -10,7 +10,7 @@ module RepositoriesHelper | |||
| end | |||
| def download_type(str) | |||
| default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot) | |||
| default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx dot otf eot ttf woff woff2) | |||
| default_type.include?(str&.downcase) | |||
| end | |||
| @@ -81,8 +81,10 @@ module RepositoriesHelper | |||
| content = Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] | |||
| readme_render_decode64_content(content, path) | |||
| else | |||
| file_type = entry['name'].to_s.split(".").last | |||
| return entry['content'] if download_type(file_type) | |||
| file_type = File.extname(entry['name'].to_s)[1..-1] | |||
| if download_type(file_type) | |||
| return entry['content'].nil? ? Gitea::Repository::Entries::GetService.call(owner, repo.identifier, entry['path'], ref: ref)['content'] : entry['content'] | |||
| end | |||
| render_decode64_content(entry['content']) | |||
| end | |||
| end | |||
| @@ -94,15 +96,16 @@ module RepositoriesHelper | |||
| 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(dir_path) | |||
| dir_path = generate_dir_path(full_path.split("/"+file_name)[0]) | |||
| file_path = [dir_path, file_path].join('/') | |||
| 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.split('public')[1] | |||
| file_path = file_path[6..-1] | |||
| File.join(base_url, file_path) | |||
| end | |||
| @@ -20,10 +20,16 @@ module TagChosenHelper | |||
| "done_ratio": render_complete_percentage, | |||
| "issue_tag": render_issue_tags(project), | |||
| "issue_type": render_issue_species, | |||
| "all_issues": all_issues | |||
| "all_issues": all_issues, | |||
| "branches": render_branches(project) | |||
| } | |||
| end | |||
| def render_branches(project) | |||
| branches = Gitea::Repository::Branches::ListService.call(project&.owner, project.identifier) | |||
| branches.collect{|i| i["name"] if i.is_a?(Hash)} | |||
| end | |||
| def render_cache_trackers | |||
| cache_key = "all_trackers/#{Tracker.maximum('id')}" | |||
| @@ -176,7 +182,7 @@ module TagChosenHelper | |||
| real_name = user.try(:show_real_name) | |||
| user_id = user.id | |||
| is_chosen = ((user.id.to_s == issue_info[0].to_s) ? "1" : "0") | |||
| member_info = {id: user_id, name: real_name,avatar_url: url_to_avatar(user),is_chosen: is_chosen} | |||
| member_info = {id: user_id, name: real_name,avatar_url: url_to_avatar(user), permission: project.get_premission(user), is_chosen: is_chosen} | |||
| project_members_info.push(member_info) | |||
| end | |||
| end | |||
| @@ -8,10 +8,13 @@ class MigrateRemoteRepositoryJob < ApplicationJob | |||
| puts "############ MigrateRemoteRepositoryJob starting ... ############" | |||
| gitea_repository = Gitea::Repository::MigrateService.new(token, params).call | |||
| if gitea_repository | |||
| repo&.project&.update_columns(gpid: gitea_repository["id"]) | |||
| puts "#gitea_repository#{gitea_repository}" | |||
| if gitea_repository[0]==201 | |||
| repo&.project&.update_columns(gpid: gitea_repository[2]["id"]) | |||
| repo&.mirror&.succeeded! | |||
| puts "############ mirror status: #{repo.mirror.status} ############" | |||
| else | |||
| repo&.mirror&.failed! | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,9 @@ | |||
| class Gitea::PublicKey < Gitea::Base | |||
| self.inheritance_column = nil # FIX The single-table inheritance mechanism failed | |||
| # establish_connection :gitea_db | |||
| self.table_name = "public_key" | |||
| belongs_to :user, class_name: '::User', primary_key: :gitea_uid, foreign_key: :owner_id, optional: true | |||
| end | |||
| @@ -0,0 +1,13 @@ | |||
| class Gitea::Webhook < Gitea::Base | |||
| serialize :events, JSON | |||
| self.inheritance_column = nil | |||
| self.table_name = 'webhook' | |||
| has_many :tasks, class_name: "Gitea::WebhookTask", foreign_key: :hook_id | |||
| belongs_to :project, class_name: "::Project", primary_key: :gpid, foreign_key: :repo_id, optional: true | |||
| enum hook_task_type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9} | |||
| enum last_status: {waiting: 0, succeed: 1, fail: 2} | |||
| enum content_type: {json: 1, form: 2} | |||
| end | |||
| @@ -0,0 +1,13 @@ | |||
| class Gitea::WebhookTask < Gitea::Base | |||
| serialize :payload_content, JSON | |||
| serialize :request_content, JSON | |||
| serialize :response_content, JSON | |||
| self.inheritance_column = nil | |||
| self.table_name = 'hook_task' | |||
| belongs_to :webhook, class_name: "Gitea::Webhook", foreign_key: :hook_id | |||
| enum type: {gogs: 1, slack: 2, gitea: 3, discord: 4, dingtalk: 5, telegram: 6, msteams: 7, feishu: 8, matrix: 9} | |||
| end | |||
| @@ -123,6 +123,7 @@ class Project < ApplicationRecord | |||
| has_one :applied_transfer_project,-> { order created_at: :desc }, dependent: :destroy | |||
| has_many :pinned_projects, dependent: :destroy | |||
| has_many :has_pinned_users, through: :pinned_projects, source: :user | |||
| has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id | |||
| after_save :check_project_members, :reset_cache_data | |||
| before_save :set_invite_code | |||
| @@ -31,7 +31,7 @@ class Team < ApplicationRecord | |||
| validates :name, uniqueness: {scope: :organization_id} | |||
| enum authorize: {common: 0, read: 1, write: 2, admin: 3, owner: 4} | |||
| enum authorize: {read: 1, write: 2, admin: 3, owner: 4} | |||
| def self.build(organization_id, name, nickname, description, authorize, includes_all_project, can_create_org_project) | |||
| self.create!(organization_id: organization_id, | |||
| @@ -20,7 +20,7 @@ class TeamUnit < ApplicationRecord | |||
| belongs_to :organization | |||
| belongs_to :team | |||
| enum unit_type: {code: 1, issues: 2, pulls: 3, releases: 4} | |||
| enum unit_type: {code: 1, issues: 2, pulls: 3, wiki: 4, releases: 5} | |||
| validates :unit_type, uniqueness: { scope: [:organization_id, :team_id]} | |||
| @@ -169,6 +169,7 @@ class User < Owner | |||
| accepts_nested_attributes_for :is_pinned_projects | |||
| has_many :issues, dependent: :destroy, foreign_key: :author_id | |||
| has_many :pull_requests, dependent: :destroy | |||
| has_many :public_keys, class_name: "Gitea::PublicKey",primary_key: :gitea_uid, foreign_key: :owner_id, dependent: :destroy | |||
| # Groups and active users | |||
| scope :active, lambda { where(status: STATUS_ACTIVE) } | |||
| @@ -44,7 +44,7 @@ class Gitea::Accelerator::MigrateService < Gitea::Accelerator::BaseService | |||
| clone_addr: params[:clone_addr], | |||
| repo_name: params[:repository_name], | |||
| auth_username: params[:auth_username], | |||
| auth_password: params[:auth_password], | |||
| auth_password: Base64.decode64(params[:auth_password]), | |||
| mirror: ActiveModel::Type::Boolean.new.cast(params[:is_mirror]) | |||
| } | |||
| end | |||
| @@ -108,6 +108,7 @@ class Gitea::ClientService < ApplicationService | |||
| def full_url(api_rest, action='post') | |||
| url = [api_url, api_rest].join('').freeze | |||
| url = action === 'get' ? url : URI.escape(url) | |||
| url = URI.escape(url) unless url.ascii_only? | |||
| puts "[gitea] request url: #{url}" | |||
| return url | |||
| end | |||
| @@ -33,7 +33,7 @@ class Gitea::Repository::MigrateService < Gitea::ClientService | |||
| def call | |||
| response = post(url, request_params) | |||
| render_201_response(response) | |||
| render_response(response) | |||
| end | |||
| private | |||
| @@ -0,0 +1,23 @@ | |||
| class Gitea::Repository::Webhooks::CreateService < Gitea::ClientService | |||
| attr_reader :token, :owner, :repo, :params | |||
| def initialize(token, owner, repo, params) | |||
| @token = token | |||
| @owner = owner | |||
| @repo = repo | |||
| @params = params | |||
| end | |||
| def call | |||
| response = post(url, request_params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def request_params | |||
| Hash.new.merge({token: token, data: params}) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/hooks".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,24 @@ | |||
| class Gitea::Repository::Webhooks::DeleteService < Gitea::ClientService | |||
| attr_reader :token, :owner, :repo, :id | |||
| def initialize(token, owner, repo, id) | |||
| @token = token | |||
| @owner = owner | |||
| @repo = repo | |||
| @id = id | |||
| end | |||
| def call | |||
| response = delete(url, params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge(token: token) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/hooks/#{id}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,27 @@ | |||
| class Gitea::Repository::Webhooks::TasksService < Gitea::ClientService | |||
| attr_reader :token, :owner, :repo, :webhook_id | |||
| # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) | |||
| # repo_name: the name of repository | |||
| def initialize(token, owner, repo, webhook_id) | |||
| @token = token | |||
| @owner = owner | |||
| @repo = repo | |||
| @webhook_id = webhook_id | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge(token: user.gitea_token) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/hooks/#{webhook_id}/hook_tasks".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,24 @@ | |||
| class Gitea::Repository::Webhooks::TestService < Gitea::ClientService | |||
| attr_reader :token, :owner, :repo, :webhook_id | |||
| def initialize(token, owner, repo, webhook_id) | |||
| @token = token | |||
| @owner = owner | |||
| @repo = repo | |||
| @webhook_id = webhook_id | |||
| end | |||
| def call | |||
| response = post(url, request_params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def request_params | |||
| Hash.new.merge({token: token}) | |||
| end | |||
| def url | |||
| "/repos/#{owner}/#{repo}/hooks/#{webhook_id}/tests".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,24 @@ | |||
| class Gitea::Repository::Webhooks::UpdateService < Gitea::ClientService | |||
| attr_reader :token, :owner, :repo, :id, :params | |||
| def initialize(token, owner, repo, id, params) | |||
| @token = token | |||
| @owner = owner | |||
| @repo = repo | |||
| @id = id | |||
| @params = params | |||
| end | |||
| def call | |||
| response = patch(url, data_params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def url | |||
| "/repos/#{owner}/#{repo}/hooks/#{id}" | |||
| end | |||
| def data_params | |||
| Hash.new.merge(token: token, data: params).compact | |||
| end | |||
| end | |||
| @@ -0,0 +1,21 @@ | |||
| class Gitea::User::Keys::CreateService < Gitea::ClientService | |||
| attr_reader :token, :params | |||
| def initialize(token, params) | |||
| @token = token | |||
| @params = params | |||
| end | |||
| def call | |||
| response = post(url, request_params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def request_params | |||
| Hash.new.merge({token: token, data: params}) | |||
| end | |||
| def url | |||
| '/user/keys'.freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,23 @@ | |||
| class Gitea::User::Keys::DeleteService < Gitea::ClientService | |||
| attr_reader :token, :key_id | |||
| def initialize(token, key_id) | |||
| @token = token | |||
| @key_id = key_id | |||
| end | |||
| def call | |||
| response = delete(url, params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge(token: token) | |||
| end | |||
| def url | |||
| "/user/keys/#{key_id}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,22 @@ | |||
| class Gitea::User::Keys::GetService < Gitea::ClientService | |||
| attr_reader :token, :key_id | |||
| def initialize(token, key_id) | |||
| @token = token | |||
| @key_id = key_id | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge({token: token}) | |||
| end | |||
| def url | |||
| "/user/keys/#{key_id}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,26 @@ | |||
| class Gitea::User::Keys::ListService < Gitea::ClientService | |||
| attr_reader :token, :page, :limit, :fingerprint | |||
| def initialize(token, page, limit, fingerprint="") | |||
| @token = token | |||
| @page = page | |||
| @limit = limit | |||
| @fingerprint = fingerprint | |||
| end | |||
| def call | |||
| response = get(url, params) | |||
| render_response(response) | |||
| end | |||
| private | |||
| def params | |||
| Hash.new.merge({token: token, fingerprint: fingerprint, page: page, limit: limit}) | |||
| end | |||
| def url | |||
| '/user/keys'.freeze | |||
| end | |||
| end | |||
| @@ -37,7 +37,7 @@ class Organizations::Teams::CreateService < ApplicationService | |||
| end | |||
| def authorize | |||
| params[:authorize].present? ? params[:authorize] : "common" | |||
| params[:authorize].present? ? params[:authorize] : "read" | |||
| end | |||
| def includes_all_project | |||
| @@ -54,7 +54,7 @@ class Organizations::Teams::CreateService < ApplicationService | |||
| end | |||
| def units_params | |||
| %w(admin owner).include?(authorize) ? %w(code issues pulls releases) : params[:unit_types] | |||
| %w(code issues pulls wiki releases) | |||
| end | |||
| def create_units | |||
| @@ -33,7 +33,7 @@ class Organizations::Teams::UpdateService < ApplicationService | |||
| end | |||
| def units_params | |||
| %w(admin owner).include?(team.authorize) ? %w(code issues pulls releases) : params[:unit_types] | |||
| %w(code issues pulls wiki releases) | |||
| end | |||
| def update_team(update_params) | |||
| @@ -30,7 +30,7 @@ class Projects::ApplyTransferService < ApplicationService | |||
| def is_permit_owner | |||
| return true unless @owner.is_a?(Organization) | |||
| return @owner.is_owner?(@user) | |||
| return @owner.is_admin?(@user) | |||
| end | |||
| def create_apply | |||
| @@ -15,8 +15,11 @@ class Projects::ForkService < ApplicationService | |||
| :rep_identifier, :project_category_id, :project_language_id, | |||
| :license_id, :ignore_id, {repository: [:identifier, :hidden]}] | |||
| result = Gitea::Repository::ForkService.new(@project.owner, @target_owner, @project.identifier, @organization).call | |||
| clone_project.owner = @target_owner | |||
| clone_project.forked_from_project_id = @project.id | |||
| clone_project.gpid = result['id'] | |||
| clone_project.save! | |||
| new_repository = clone_project.repository | |||
| @@ -26,8 +29,6 @@ class Projects::ForkService < ApplicationService | |||
| ProjectUnit.init_types(clone_project.id) | |||
| result = Gitea::Repository::ForkService.new(@project.owner, @target_owner, @project.identifier, @organization).call | |||
| @project.update_column('forked_count', @project&.forked_count.to_i + 1) | |||
| new_repository.update_column('url', result['clone_url']) if result | |||
| @@ -23,12 +23,12 @@ class Projects::TransferService < ApplicationService | |||
| private | |||
| def update_owner | |||
| project.members.find_by(user_id: owner.id).destroy! if owner.is_a?(User) | |||
| project.members.map{|m| m.destroy! if m.user_id == owner.id || (new_owner.is_a?(Organization) && new_owner.is_member?(m.user_id)) } | |||
| project.update!(user_id: new_owner.id) | |||
| end | |||
| def update_repo_url | |||
| project.repository.update!(url: @gitea_repo["clone_url"]) | |||
| project.repository.update!(user_id: new_owner.id, url: @gitea_repo["clone_url"]) | |||
| end | |||
| def update_visit_teams | |||
| @@ -32,7 +32,7 @@ class Repositories::MigrateService < ApplicationService | |||
| private: params[:hidden], | |||
| mirror: wrapper_mirror || false, | |||
| auth_username: params[:login], | |||
| auth_password: params[:password] | |||
| auth_password: Base64.decode64(params[:password]) | |||
| } | |||
| end | |||
| @@ -2,6 +2,7 @@ json.total_count @owners.size | |||
| json.owners @owners.each do |owner| | |||
| json.id owner.id | |||
| json.type owner.type | |||
| json.login owner.login | |||
| json.name owner&.show_real_name | |||
| json.avatar_url url_to_avatar(owner) | |||
| end | |||
| @@ -1,2 +1,2 @@ | |||
| json.extract! @project, :id, :name,:identifier | |||
| json.login @project&.owner&.login | |||
| json.login @project&.owner&.login | |||
| @@ -1 +1,2 @@ | |||
| json.extract! @project, :id, :name, :identifier | |||
| json.login @project&.owner&.login | |||
| @@ -1,5 +1,6 @@ | |||
| json.total_count @teams.total_count | |||
| json.can_add @owner.is_owner?(current_user.id) || @owner&.repo_admin_change_team_access | |||
| json.teams @teams.each do |team| | |||
| json.(team, :id, :name, :authorize) | |||
| json.can_remove !team.includes_all_project && team&.organization&.repo_admin_change_team_access | |||
| json.can_remove !team.includes_all_project && (@owner.is_owner?(current_user.id) || team&.organization&.repo_admin_change_team_access) | |||
| end | |||
| @@ -0,0 +1,4 @@ | |||
| json.(webhook, :id, :url, :http_method, :is_active) | |||
| json.type webhook.hook_task_type | |||
| json.last_status webhook.last_status | |||
| json.create_time Time.at(webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S") | |||
| @@ -0,0 +1,7 @@ | |||
| json.id @webhook["id"] | |||
| json.type @webhook["type"] | |||
| json.content_type @webhook["config"]["content_type"] | |||
| json.url @webhook["config"]["url"] | |||
| json.events @webhook["events"] | |||
| json.active @webhook["active"] | |||
| json.create_time @webhook["created_at"].to_time.strftime("%Y-%m-%d %H:%M:%S") | |||
| @@ -0,0 +1,11 @@ | |||
| json.id @webhook.id | |||
| json.(@webhook, :id, :http_method, :content_type, :url, :secret, :last_status, :is_active) | |||
| json.type @webhook.hook_task_type | |||
| json.create_time Time.at(@webhook.created_unix).strftime("%Y-%m-%d %H:%M:%S") | |||
| event = @webhook.events | |||
| json.branch_filter event["branch_filter"] | |||
| if event["send_everything"] | |||
| json.events event["events"].keys.collect{|i| i == "pull_request" ? i + "_only" : i} | |||
| else | |||
| json.events event["events"].select{|k, v| v}.keys.collect{|i| i == "pull_request" ? i + "_only" : i} | |||
| end | |||
| @@ -0,0 +1,4 @@ | |||
| json.total_count @webhooks.total_count | |||
| json.webhooks @webhooks.each do |webhook| | |||
| json.partial! 'detail', webhook: webhook | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| json.total_count @tasks.total_count | |||
| json.tasks @tasks.each do |task| | |||
| json.(task, :id, :type, :uuid, :is_succeed, :is_delivered, :payload_content, :request_content, :response_content) | |||
| json.delivered_time Time.at(task.delivered*10**-9).strftime("%Y-%m-%d %H:%M:%S") | |||
| end | |||
| @@ -0,0 +1,8 @@ | |||
| if @public_key.present? | |||
| json.status 0 | |||
| json.id @public_key["id"] | |||
| json.name @public_key["title"] | |||
| json.content @public_key["key"] | |||
| json.fingerprint @public_key["fingerprint"] | |||
| json.created_time @public_key["created_at"].to_time.strftime("%Y/%m/%d %H:%M") | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| json.total_count @public_keys.total_count | |||
| json.public_keys @public_keys do |public_key| | |||
| json.(public_key, :id, :name, :content, :fingerprint, :created_unix) | |||
| json.created_time Time.at(public_key.created_unix).strftime("%Y/%m/%d %H:%M") | |||
| end | |||
| @@ -5,6 +5,7 @@ json.merged_issues_size @merged_issues.size | |||
| json.search_count @issues_size | |||
| json.limit @limit | |||
| json.user_admin_or_member @user_admin_or_member | |||
| json.user_admin_or_developer @user_admin_or_developer | |||
| json.project_name @project.name | |||
| json.project_author_name @project.owner.try(:login) | |||
| @@ -1,6 +1,6 @@ | |||
| if @project.forge? | |||
| file_name = entry['name'] | |||
| file_type = file_name.to_s.split(".").last | |||
| file_type = File.extname(file_name.to_s)[1..-1] | |||
| direct_download = download_type(file_type) | |||
| image_type = image_type?(file_type) | |||
| json.name file_name | |||
| @@ -8,7 +8,7 @@ json.user_login @version.version_user.try(:login) | |||
| json.created_at format_time(@version.created_on) | |||
| json.updated_at format_time(@version.updated_on) | |||
| json.search_count @version_issues_size | |||
| json.percent @version.percent*100 | |||
| json.percent @version_close_issues_size.to_f/@version_issues_size*100#@version.percent*100 | |||
| json.extract! @version, :id,:name,:project_id,:description, :effective_date, :status, :sharing,:wiki_page_title | |||
| json.issues do | |||
| @@ -71,6 +71,8 @@ Rails.application.routes.draw do | |||
| # end | |||
| end | |||
| resources :public_keys, only: [:index, :create, :destroy] | |||
| resources :statistic, only: [:index] do | |||
| collection do | |||
| get :platform_profile | |||
| @@ -348,6 +350,7 @@ Rails.application.routes.draw do | |||
| get '/auth/qq/callback', to: 'oauth/qq#create' | |||
| get '/auth/wechat/callback', to: 'oauth/wechat#create' | |||
| get '/auth/educoder/callback', to: 'oauth/educoder#create' | |||
| resource :bind_user, only: [:create] | |||
| resources :hot_keywords, only: [:index] | |||
| @@ -571,6 +574,12 @@ Rails.application.routes.draw do | |||
| post :cancel | |||
| end | |||
| end | |||
| resources :webhooks, except: [:show, :new] do | |||
| member do | |||
| get :tasks | |||
| post :test | |||
| end | |||
| end | |||
| scope do | |||
| get( | |||
| '/blob/*id/diff', | |||
| @@ -0,0 +1,61 @@ | |||
| desc "Fix Some Unstep Data" | |||
| namespace :fix_some_error_data do | |||
| task org_member_and_project_member: :environment do | |||
| puts "======Begin: fix organization memberr======" | |||
| fix_org_count = 0 | |||
| OrganizationUser.find_each do |org_user| | |||
| org = org_user.organization | |||
| if org.team_users.where(user_id: org_user.user_id).blank? | |||
| Gitea::Organization::OrganizationUser::DeleteService.call(org_user.organization.gitea_token, org_user.organization.login, org_user&.user&.login) | |||
| org_user.destroy | |||
| fix_org_count += 1 | |||
| end | |||
| end | |||
| puts "======Count: #{fix_org_count}======" | |||
| puts "======End: fix organization member and project member======" | |||
| puts "======Begin: fix project member======" | |||
| fix_pro_count = 0 | |||
| Member.joins(project: :owner).where(users: {type: 'Organization'}).find_each do |member| | |||
| if member.project.owner.team_users.where(user_id: member.user_id).blank? | |||
| next | |||
| else | |||
| member.destroy | |||
| fix_pro_count += 1 | |||
| end | |||
| end | |||
| puts "======Count: #{fix_pro_count}======" | |||
| puts "======End: fix project member======" | |||
| end | |||
| task open_full_gitea_team_authorize: :environment do | |||
| puts "======Begin: fix open full team authorize======" | |||
| team_count = 0 | |||
| Team.find_each do |team| | |||
| team.team_units.destroy_all | |||
| %w(code issues pulls wiki releases).each do |unit| | |||
| TeamUnit.build(team.organization_id, team.id, unit) | |||
| end | |||
| Gitea::Organization::Team::UpdateService.call(team&.organization&.gitea_token, team) | |||
| team_count += 1 | |||
| end | |||
| puts "======Count: #{team_count}======" | |||
| puts "======End: fix open full team authorize======" | |||
| end | |||
| task transfer_repository_user_id: :environment do | |||
| puts "======Begin: fix open full team authorize======" | |||
| repo_count = 0 | |||
| AppliedTransferProject.find_each do |transfer| | |||
| next unless transfer.project.present? | |||
| next unless transfer.project.repository.present? | |||
| if transfer.project.user_id != transfer.project.repository.user_id | |||
| transfer.project.repository.update(user_id: transfer.project.user_id) | |||
| repo_count += 1 | |||
| end | |||
| end | |||
| puts "======Count: #{repo_count}======" | |||
| puts "======End: fix open full team authorize======" | |||
| end | |||
| end | |||
| @@ -0,0 +1,61 @@ | |||
| namespace :produce_and_export_ceshi_user do | |||
| desc "Produce ceshi user and Export to excel" | |||
| task call: :environment do | |||
| puts "=======Begin=======" | |||
| DCODES = %W(1 2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) | |||
| username = DCODES.sample(8).join | |||
| email = username + '@forge.com' | |||
| password = SecureRandom.base64[8..-1] | |||
| p = Axlsx::Package.new | |||
| p.workbook.add_worksheet(:name => '测试用户') do |sheet| | |||
| sheet.add_row ["用户名", "邮箱", "密码", "GiteaToken", "测试仓库", "测试仓库克隆地址"] | |||
| (1..100).to_a.each do |i| | |||
| while (User.find_by(login: username).present? || User.find_by(mail: email).present?) do | |||
| username = DCODES.sample(8).join | |||
| email = username + '@forge.com' | |||
| password = SecureRandom.base64[8..-1] | |||
| end | |||
| puts "=======Generate:[#{i}] Username: #{username}, Password: #{password}, Email: #{email}=======" | |||
| puts "=======Create User Begin====== " | |||
| user = User.new(admin: false, login: username, mail: email, type: "User") | |||
| user.password = password | |||
| user.platform = 'forge' | |||
| user.activate | |||
| next unless user.valid? | |||
| interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) | |||
| if interactor.success? | |||
| gitea_user = interactor.result | |||
| result = Gitea::User::GenerateTokenService.call(username, password) | |||
| user.gitea_token = result['sha1'] | |||
| user.gitea_uid = gitea_user[:body]['id'] | |||
| if user.save! | |||
| UserExtension.create!(user_id: user.id) | |||
| end | |||
| end | |||
| puts "=======Create User End====== " | |||
| code = DCODES.sample(8).join | |||
| project_params = { | |||
| user_id: user.id, | |||
| name: code, | |||
| repository_name: code, | |||
| project_category_id: ProjectCategory.pluck(:id).sample, | |||
| project_language_id: ProjectLanguage.pluck(:id).sample, | |||
| license_id: License.pluck(:id).sample, | |||
| ignore_id: Ignore.pluck(:id).sample, | |||
| private: true | |||
| } | |||
| project = Projects::CreateService.new(user, project_params).call | |||
| puts project.as_json | |||
| sheet.add_row [username, email, password, user.gitea_token, "#{username}/#{code}", project&.repository.url] | |||
| end | |||
| end | |||
| p.use_shared_strings = true | |||
| p.serialize('ceshi_user.xlsx') | |||
| puts "=======END=======" | |||
| end | |||
| end | |||