| @@ -0,0 +1,28 @@ | |||
| module Acceleratorable | |||
| extend ActiveSupport::Concern | |||
| def enable_accelerator?(clone_addr) | |||
| clone_addr.include?(github_domain) || clone_addr.include?(gitlab_domain) | |||
| end | |||
| def accelerator_url(repo_name) | |||
| [accelerator_domain, accelerator_username, "#{repo_name}.git"].join('/') | |||
| end | |||
| def github_domain | |||
| 'github.com' | |||
| end | |||
| def gitlab_domain | |||
| 'gitlab.com' | |||
| end | |||
| def accelerator_domain | |||
| Gitea.gitea_config[:accelerator]["domain"] | |||
| end | |||
| def accelerator_username | |||
| Gitea.gitea_config[:accelerator]["access_key_id"] | |||
| end | |||
| end | |||
| @@ -2,6 +2,8 @@ class ProjectsController < ApplicationController | |||
| include ApplicationHelper | |||
| include OperateProjectAbilityAble | |||
| include ProjectsHelper | |||
| include Acceleratorable | |||
| before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about menu_list] | |||
| before_action :load_project, except: %i[index group_type_list migrate create recommend] | |||
| before_action :authorizate_user_can_edit_project!, only: %i[update] | |||
| @@ -53,7 +55,23 @@ class ProjectsController < ApplicationController | |||
| def migrate | |||
| Projects::MigrateForm.new(mirror_params).validate! | |||
| @project = Projects::MigrateService.new(current_user, mirror_params).call | |||
| @project = | |||
| if enable_accelerator?(mirror_params[:clone_addr]) | |||
| source_clone_url = mirror_params[:clone_addr] | |||
| uid_logger("########## 已动加速器 ##########") | |||
| result = Gitea::Accelerator::MigrateService.call(mirror_params) | |||
| if result[:status] == :success | |||
| Rails.logger.info "########## 加速镜像成功 ########## " | |||
| Projects::MigrateService.call(current_user, | |||
| mirror_params.merge(source_clone_url: source_clone_url, | |||
| clone_addr: accelerator_url(mirror_params[:repository_name]))) | |||
| else | |||
| Projects::MigrateService.call(current_user, mirror_params) | |||
| end | |||
| else | |||
| Projects::MigrateService.call(current_user, mirror_params) | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| @@ -140,7 +140,7 @@ class PullRequestsController < ApplicationController | |||
| end | |||
| def pr_merge | |||
| return render_forbidden("你没有权限操作.") unless @project.develper?(current_user) | |||
| return render_forbidden("你没有权限操作.") unless @project.operator?(current_user) | |||
| if params[:do].blank? | |||
| normal_status(-1, "请选择合并方式") | |||
| @@ -34,15 +34,14 @@ module ProjectsHelper | |||
| end | |||
| def json_response(project, user) | |||
| # repo = project.repository | |||
| repo = Repository.includes(:mirror).select(:id, :mirror_url).find_by(project: project) | |||
| repo = Repository.includes(:mirror).select(:id, :mirror_url, :source_clone_url).find_by(project: project) | |||
| tmp_json = {} | |||
| unless project.common? | |||
| tmp_json = tmp_json.merge({ | |||
| mirror_status: repo.mirror_status, | |||
| mirror_num: repo.mirror_num, | |||
| mirror_url: repo.mirror_url, | |||
| mirror_url: repo.source_clone_url || repo.mirror_url, | |||
| first_sync: repo.first_sync? | |||
| }) | |||
| end | |||
| @@ -84,6 +84,10 @@ module ProjectOperable | |||
| end | |||
| end | |||
| def operator?(user) | |||
| user.admin? || !reporter?(user) | |||
| end | |||
| def set_developer_role(member, role_name) | |||
| role = Role.find_by(name: role_name) | |||
| member.member_roles.create!(role: role) | |||
| @@ -1,75 +1,76 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: projects | |||
| # | |||
| # id :integer not null, primary key | |||
| # name :string(255) default(""), not null | |||
| # description :text(4294967295) | |||
| # homepage :string(255) default("") | |||
| # is_public :boolean default("1"), not null | |||
| # parent_id :integer | |||
| # created_on :datetime | |||
| # updated_on :datetime | |||
| # identifier :string(255) | |||
| # status :integer default("1"), not null | |||
| # lft :integer | |||
| # rgt :integer | |||
| # inherit_members :boolean default("0"), not null | |||
| # project_type :integer default("0") | |||
| # hidden_repo :boolean default("0"), not null | |||
| # attachmenttype :integer default("1") | |||
| # user_id :integer | |||
| # dts_test :integer default("0") | |||
| # enterprise_name :string(255) | |||
| # organization_id :integer | |||
| # project_new_type :integer | |||
| # gpid :integer | |||
| # forked_from_project_id :integer | |||
| # forked_count :integer default("0") | |||
| # publish_resource :integer default("0") | |||
| # visits :integer default("0") | |||
| # hot :integer default("0") | |||
| # invite_code :string(255) | |||
| # qrcode :string(255) | |||
| # qrcode_expiretime :integer default("0") | |||
| # script :text(65535) | |||
| # training_status :integer default("0") | |||
| # rep_identifier :string(255) | |||
| # project_category_id :integer | |||
| # project_language_id :integer | |||
| # praises_count :integer default("0") | |||
| # watchers_count :integer default("0") | |||
| # issues_count :integer default("0") | |||
| # pull_requests_count :integer default("0") | |||
| # language :string(255) | |||
| # versions_count :integer default("0") | |||
| # issue_tags_count :integer default("0") | |||
| # closed_issues_count :integer default("0") | |||
| # open_devops :boolean default("0") | |||
| # gitea_webhook_id :integer | |||
| # open_devops_count :integer default("0") | |||
| # recommend :boolean default("0") | |||
| # platform :integer default("0") | |||
| # license_id :integer | |||
| # ignore_id :integer | |||
| # default_branch :string(255) default("master") | |||
| # website :string(255) | |||
| # lesson_url :string(255) | |||
| # | |||
| # Indexes | |||
| # | |||
| # index_projects_on_forked_from_project_id (forked_from_project_id) | |||
| # index_projects_on_identifier (identifier) | |||
| # index_projects_on_is_public (is_public) | |||
| # index_projects_on_lft (lft) | |||
| # index_projects_on_name (name) | |||
| # index_projects_on_platform (platform) | |||
| # index_projects_on_project_type (project_type) | |||
| # index_projects_on_recommend (recommend) | |||
| # index_projects_on_rgt (rgt) | |||
| # index_projects_on_status (status) | |||
| # index_projects_on_updated_on (updated_on) | |||
| # | |||
| # == Schema Information | |||
| # | |||
| # Table name: projects | |||
| # | |||
| # id :integer not null, primary key | |||
| # name :string(255) default(""), not null | |||
| # description :text(4294967295) | |||
| # homepage :string(255) default("") | |||
| # is_public :boolean default("1"), not null | |||
| # parent_id :integer | |||
| # created_on :datetime | |||
| # updated_on :datetime | |||
| # identifier :string(255) | |||
| # status :integer default("1"), not null | |||
| # lft :integer | |||
| # rgt :integer | |||
| # inherit_members :boolean default("0"), not null | |||
| # project_type :integer default("0") | |||
| # hidden_repo :boolean default("0"), not null | |||
| # attachmenttype :integer default("1") | |||
| # user_id :integer | |||
| # dts_test :integer default("0") | |||
| # enterprise_name :string(255) | |||
| # organization_id :integer | |||
| # project_new_type :integer | |||
| # gpid :integer | |||
| # forked_from_project_id :integer | |||
| # forked_count :integer default("0") | |||
| # publish_resource :integer default("0") | |||
| # visits :integer default("0") | |||
| # hot :integer default("0") | |||
| # invite_code :string(255) | |||
| # qrcode :string(255) | |||
| # qrcode_expiretime :integer default("0") | |||
| # script :text(65535) | |||
| # training_status :integer default("0") | |||
| # rep_identifier :string(255) | |||
| # project_category_id :integer | |||
| # project_language_id :integer | |||
| # praises_count :integer default("0") | |||
| # watchers_count :integer default("0") | |||
| # issues_count :integer default("0") | |||
| # pull_requests_count :integer default("0") | |||
| # language :string(255) | |||
| # versions_count :integer default("0") | |||
| # issue_tags_count :integer default("0") | |||
| # closed_issues_count :integer default("0") | |||
| # open_devops :boolean default("0") | |||
| # gitea_webhook_id :integer | |||
| # open_devops_count :integer default("0") | |||
| # recommend :boolean default("0") | |||
| # platform :integer default("0") | |||
| # license_id :integer | |||
| # ignore_id :integer | |||
| # default_branch :string(255) default("master") | |||
| # website :string(255) | |||
| # lesson_url :string(255) | |||
| # | |||
| # Indexes | |||
| # | |||
| # index_projects_on_forked_from_project_id (forked_from_project_id) | |||
| # index_projects_on_identifier (identifier) | |||
| # index_projects_on_is_public (is_public) | |||
| # index_projects_on_lft (lft) | |||
| # index_projects_on_name (name) | |||
| # index_projects_on_platform (platform) | |||
| # index_projects_on_project_type (project_type) | |||
| # index_projects_on_recommend (recommend) | |||
| # index_projects_on_rgt (rgt) | |||
| # index_projects_on_status (status) | |||
| # index_projects_on_updated_on (updated_on) | |||
| # | |||
| class Project < ApplicationRecord | |||
| include Matchable | |||
| @@ -22,6 +22,8 @@ | |||
| # version_releases_count :integer default("0") | |||
| # fork_url :string(255) | |||
| # is_mirror :boolean default("0") | |||
| # accelerator_url :string(255) default("") | |||
| # source_clone_url :string(255) default("") | |||
| # | |||
| # Indexes | |||
| # | |||
| @@ -0,0 +1,148 @@ | |||
| class Gitea::Accelerator::MigrateService < ApplicationService | |||
| attr_reader :params | |||
| # params description: | |||
| # { | |||
| # auth_username string | |||
| # clone_addr* string #clone地址 | |||
| # description string | |||
| # issues boolean | |||
| # labels boolean | |||
| # milestones boolean | |||
| # mirror boolean | |||
| # private boolean | |||
| # pull_requests boolean | |||
| # releases boolean | |||
| # repo_name* string #仓库名称 | |||
| # uid* integer($int64) #gitea用户id或组织id | |||
| # wiki boolean | |||
| # } | |||
| # EX: | |||
| # params = { | |||
| # clone_addr: 'xxx.com', | |||
| # repo_name: 'repo_name', | |||
| # uid: 2, | |||
| # private: false | |||
| # } | |||
| def initialize(params) | |||
| @params = params | |||
| end | |||
| def call | |||
| return error('[gitea:] accelerator config missing') if check_accelerator! | |||
| response = post(url, request_params) | |||
| render_status(response) | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| uid: access_uid, | |||
| clone_addr: params[:clone_addr], | |||
| repo_name: params[:repository_name], | |||
| auth_username: params[:auth_username], | |||
| auth_password: params[:auth_password], | |||
| mirror: ActiveModel::Type::Boolean.new.cast(params[:is_mirror]) | |||
| } | |||
| end | |||
| def url | |||
| "/repos/migrate".freeze | |||
| end | |||
| def post(url, params) | |||
| puts "[gitea] request params: #{params}" | |||
| puts "[gitea] access_username: #{access_username}" | |||
| puts "[gitea] access_password: #{access_password}" | |||
| conn.post do |req| | |||
| req.url full_url(url) | |||
| req.body = params.to_json | |||
| end | |||
| end | |||
| def conn | |||
| @client ||= begin | |||
| Faraday.new(url: domain) do |req| | |||
| req.request :url_encoded | |||
| req.headers['Content-Type'] = 'application/json' | |||
| req.response :logger # 显示日志 | |||
| req.adapter Faraday.default_adapter | |||
| req.basic_auth(access_username, access_password) | |||
| end | |||
| end | |||
| @client | |||
| end | |||
| def base_url | |||
| accelerator["base_url"] | |||
| end | |||
| def domain | |||
| accelerator["domain"] | |||
| end | |||
| def api_url | |||
| [domain, base_url].join('') | |||
| end | |||
| def full_url(api_rest, action='post') | |||
| url = [api_url, api_rest].join('').freeze | |||
| url = action === 'get' ? url : URI.escape(url) | |||
| puts "[gitea] request url: #{url}" | |||
| url | |||
| end | |||
| def access_username | |||
| accelerator["access_key_id"] | |||
| end | |||
| def access_password | |||
| accelerator["access_key_secret"] | |||
| end | |||
| def access_uid | |||
| accelerator["access_admin_uid"] | |||
| end | |||
| def accelerator | |||
| Gitea.gitea_config[:accelerator] | |||
| end | |||
| def render_status(response) | |||
| puts "[gitea] response status: #{response.status}" | |||
| puts "[gitea] response body: #{response.body}" | |||
| case response.status | |||
| when 201 | |||
| success | |||
| when 403 | |||
| error('APIForbiddenError') | |||
| when 422 | |||
| error('APIValidationError') | |||
| else | |||
| error("MigrateError") | |||
| end | |||
| end | |||
| def error(message) | |||
| { | |||
| status: :error, | |||
| message: message, | |||
| data: nil | |||
| } | |||
| end | |||
| def success(data=nil) | |||
| { | |||
| status: :success, | |||
| message: nil, | |||
| data: data | |||
| } | |||
| end | |||
| def check_accelerator! | |||
| accelerator.blank? || access_username.blank? || access_password.blank? || domain.blank? | |||
| end | |||
| end | |||
| @@ -48,7 +48,8 @@ class Projects::MigrateService < ApplicationService | |||
| user_id: params[:user_id], | |||
| login: params[:auth_username], | |||
| password: params[:auth_password], | |||
| is_mirror: params[:is_mirror] | |||
| is_mirror: params[:is_mirror], | |||
| source_clone_url: params[:source_clone_url] | |||
| } | |||
| end | |||
| @@ -21,7 +21,9 @@ class Repositories::MigrateService < ApplicationService | |||
| private | |||
| def repository_params | |||
| params.merge(project_id: project.id, identifier: params[:identifier]) | |||
| params.merge(project_id: project.id, | |||
| identifier: params[:identifier], | |||
| source_clone_url: params[:source_clone_url]) | |||
| end | |||
| def gitea_repository_params | |||
| @@ -21,7 +21,7 @@ json.versions_count @project.versions_count #里程碑数量 | |||
| json.version_releases_count @project.releases_size(@user.try(:id), "all") | |||
| json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 | |||
| json.permission render_permission(@user, @project) | |||
| json.mirror_url @project&.repository.mirror_url | |||
| json.mirror_url @project&.repository.source_clone_url | |||
| json.mirror @project&.repository.mirror_url.present? | |||
| json.type @project.numerical_for_project_type | |||
| json.open_devops @project.open_devops? | |||
| @@ -50,10 +50,16 @@ default: &default | |||
| redirect_uri: 'https://testforgeplus.trustie.net/api/auth/educoder/callback' | |||
| gitea: | |||
| access_key_id: 'root' | |||
| access_key_secret: '_Trustie_10010' | |||
| domain: 'https://testgitea.trustie.net' | |||
| access_key_id: '' | |||
| access_key_secret: '' | |||
| domain: 'https://testgit.trustie.net' | |||
| base_url: '/api/v1' | |||
| accelerator: | |||
| access_key_id: '' | |||
| access_key_secret: '' | |||
| access_admin_uid: 1 | |||
| domain: 'https://testgit.trustie.net' | |||
| base_url: '/api/v1' | |||
| production: | |||
| @@ -0,0 +1,5 @@ | |||
| class AddAcceleratorUrlToRepositories < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :repositories, :accelerator_url, :string, default: "" | |||
| end | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| class AddSourceCloneUrlToRepositories < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :repositories, :source_clone_url, :string, default: "" | |||
| end | |||
| end | |||