From 191a405896c11bec5177f4cb022cd348120fda9c Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 23 Dec 2019 10:39:15 +0800 Subject: [PATCH 1/3] FIX --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/README.md b/README.md index 8de564fec..ad9ba54f0 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,9 @@ curl -X POST \ -d "repository_name=gorails" \ -d "project_category_id=1" \ -d "project_language_id=2" \ +-d "ignore_id=2000" \ +-d "license_id=1" \ +-d "private=true" http://localhost:3000/api/projects/ | jq ``` *请求参数说明:* @@ -273,6 +276,54 @@ http://localhost:3000/api/projects/ | jq |name |string|项目名称| +返回值 +``` +{ + "id": 3240, + "name": "好项目" +} +``` +--- + +#### 新建镜像项目 +``` +POST api/projects/migrate +``` +*示例* +``` +curl -X POST \ +-d "user_id=36401" \ +-d "clone_addr=https://gitea.com/CasperVector/slew.git" +-d "name=好项目" \ +-d "description=my first project" \ +-d "repository_name=gorails" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +-d "private=true" +http://localhost:3000/api/projects/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +-|-|-|- +|user_id |是|int |用户id或者组织id | +|name |是|string |项目名称 | +|clone_addr |是|string |镜像项目clone地址 | +|description |否|string |项目描述 | +|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|project_category_id|是|int |项目类别id | +|project_language_id|是|int |项目语言id | +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|id |int |id | +|name |string|项目名称| + + 返回值 ``` { From a74d34a07143d4a50fb248df862752e3b2804d09 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 23 Dec 2019 17:40:43 +0800 Subject: [PATCH 2/3] ADD some migration --- .../20191220092618_add_user_ref_to_repository.rb | 10 ++++++++++ db/migrate/20191223031855_add_gitea_uid_to_users.rb | 5 +++++ .../20191223063139_add_mirror_url_to_repositories.rb | 5 +++++ 3 files changed, 20 insertions(+) create mode 100644 db/migrate/20191220092618_add_user_ref_to_repository.rb create mode 100644 db/migrate/20191223031855_add_gitea_uid_to_users.rb create mode 100644 db/migrate/20191223063139_add_mirror_url_to_repositories.rb diff --git a/db/migrate/20191220092618_add_user_ref_to_repository.rb b/db/migrate/20191220092618_add_user_ref_to_repository.rb new file mode 100644 index 000000000..cab95a144 --- /dev/null +++ b/db/migrate/20191220092618_add_user_ref_to_repository.rb @@ -0,0 +1,10 @@ +class AddUserRefToRepository < ActiveRecord::Migration[5.2] + def change + add_column :repositories, :user_id, :integer + add_index :repositories, :user_id + + Project.joins(:repository).find_each do |project| + project&.repository&.update_column(:user_id, project&.user_id) unless project&.repository.blank? + end + end +end diff --git a/db/migrate/20191223031855_add_gitea_uid_to_users.rb b/db/migrate/20191223031855_add_gitea_uid_to_users.rb new file mode 100644 index 000000000..1e32e59ed --- /dev/null +++ b/db/migrate/20191223031855_add_gitea_uid_to_users.rb @@ -0,0 +1,5 @@ +class AddGiteaUidToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :gitea_uid, :integer + end +end diff --git a/db/migrate/20191223063139_add_mirror_url_to_repositories.rb b/db/migrate/20191223063139_add_mirror_url_to_repositories.rb new file mode 100644 index 000000000..2f82c8964 --- /dev/null +++ b/db/migrate/20191223063139_add_mirror_url_to_repositories.rb @@ -0,0 +1,5 @@ +class AddMirrorUrlToRepositories < ActiveRecord::Migration[5.2] + def change + add_column :repositories, :mirror_url, :string + end +end From 7a144a668413214bdf8432c0e44d33d070557d62 Mon Sep 17 00:00:00 2001 From: Jasder <2053003901@@qq.com> Date: Mon, 23 Dec 2019 17:43:45 +0800 Subject: [PATCH 3/3] ADD create mirror project and repository --- app/controllers/projects_controller.rb | 15 ++++++ app/forms/base_form.rb | 16 ++++++ app/forms/projects/create_form.rb | 8 +-- app/forms/projects/migrate_form.rb | 17 +++++++ app/models/repository.rb | 1 + app/models/user.rb | 3 ++ .../gitea/repository/migrate_service.rb | 47 +++++++++++++++++ app/services/projects/migrate_service.rb | 49 ++++++++++++++++++ app/services/repositories/migrate_service.rb | 51 +++++++++++++++++++ app/views/projects/migrate.json.jbuilder | 1 + config/routes.rb | 6 ++- 11 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 app/forms/projects/migrate_form.rb create mode 100644 app/services/gitea/repository/migrate_service.rb create mode 100644 app/services/projects/migrate_service.rb create mode 100644 app/services/repositories/migrate_service.rb create mode 100644 app/views/projects/migrate.json.jbuilder diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 627decb9c..66cef715c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -14,9 +14,24 @@ class ProjectsController < ApplicationController tip_exception(e.message) end + def migrate + ActiveRecord::Base.transaction do + Projects::MigrateForm.new(mirror_params).validate! + @project = Projects::MigrateService.new(current_user, mirror_params).call + end + rescue Exception => e + uid_logger_error(e.message) + tip_exception(e.message) + end + private def project_params params.permit(:user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :license_id, :ignore_id) end + + def mirror_params + params.permit(:user_id, :name, :description, :repository_name, + :project_category_id, :project_language_id, :clone_addr, :private) + end end diff --git a/app/forms/base_form.rb b/app/forms/base_form.rb index 40c7c51e3..015332d82 100644 --- a/app/forms/base_form.rb +++ b/app/forms/base_form.rb @@ -1,3 +1,19 @@ class BaseForm include ActiveModel::Model + + def check_project_category(project_category_id) + raise "project_category_id参数值无效." if (ProjectCategory.find_by_id project_category_id).blank? + end + + def check_project_language(project_language_id) + raise "project_language_id参数值无效." if (ProjectLanguage.find_by_id project_language_id).blank? + end + + def check_repository_name(user_id, repository_name) + raise "仓库名称已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists? + end + + def check_project_name(user_id, project_name) + raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists? + end end diff --git a/app/forms/projects/create_form.rb b/app/forms/projects/create_form.rb index cd4f3941f..39c372309 100644 --- a/app/forms/projects/create_form.rb +++ b/app/forms/projects/create_form.rb @@ -5,11 +5,13 @@ class Projects::CreateForm < BaseForm validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true - # validates_format_of :repository_name, with: REPOSITORY_NAME_REGEX, multiline: true - validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, - message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } validate :check_ignore, :check_license + validate do + check_project_category(project_category_id) + check_project_language(project_language_id) + end def check_license raise "license_id值无效. " if license_id && License.find_by(id: license_id).blank? diff --git a/app/forms/projects/migrate_form.rb b/app/forms/projects/migrate_form.rb new file mode 100644 index 000000000..f3804beaa --- /dev/null +++ b/app/forms/projects/migrate_form.rb @@ -0,0 +1,17 @@ +class Projects::MigrateForm < BaseForm + REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 + URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i + + attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :clone_addr, :private + + validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true + validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } + validates :clone_addr, format: { with: URL_REGEX, multiline: true, message: "地址格式不正确" } + validate do + check_project_name(user_id, name) + check_repository_name(user_id, repository_name) + check_project_category(project_category_id) + check_project_language(project_language_id) + end + +end diff --git a/app/models/repository.rb b/app/models/repository.rb index aac23fd80..fdfbad582 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,6 +1,7 @@ class Repository < ApplicationRecord self.inheritance_column = nil # FIX The single-table inheritance mechanism failed belongs_to :project + belongs_to :user validates :identifier, presence: true, uniqueness: true end diff --git a/app/models/user.rb b/app/models/user.rb index f25ecc4b8..8ed7e3b6e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -146,6 +146,9 @@ class User < ApplicationRecord # 项目 has_many :applied_projects, dependent: :destroy + has_many :projects, dependent: :destroy + has_many :repositories, dependent: :destroy + # 教学案例 has_many :libraries, dependent: :destroy diff --git a/app/services/gitea/repository/migrate_service.rb b/app/services/gitea/repository/migrate_service.rb new file mode 100644 index 000000000..568e4d5c5 --- /dev/null +++ b/app/services/gitea/repository/migrate_service.rb @@ -0,0 +1,47 @@ +class Gitea::Repository::MigrateService < Gitea::ClientService + attr_reader :token, :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(token, params) + @token = token + @params = params + end + + def call + post(url, request_params) + end + + private + + def request_params + Hash.new.merge(token: token, data: params) + end + + def url + "/repos/migrate".freeze + end + +end diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb new file mode 100644 index 000000000..a3c6b131e --- /dev/null +++ b/app/services/projects/migrate_service.rb @@ -0,0 +1,49 @@ +class Projects::MigrateService < ApplicationService + attr_reader :user, :params + + def initialize(user, params) + @user = user + @params = params + end + + def call + @project = Project.new(project_params) + ActiveRecord::Base.transaction do + if @project.save! + Repositories::MigrateService.new(user, @project, repository_params).call + else + # + end + end + @project + rescue => e + puts "create mirror project service error: #{e.message}" + raise Error, e.message + end + + private + + def project_params + { + name: params[:name], + user_id: params[:user_id], + description: params[:description], + project_category_id: params[:project_category_id], + project_language_id: params[:project_language_id], + is_public: get_is_public + } + end + + def repository_params + { + hidden: get_is_public, + identifier: params[:repository_name], + mirror_url: params[:clone_addr], + user_id: user.id + } + end + + def get_is_public + params[:private] || false + end +end diff --git a/app/services/repositories/migrate_service.rb b/app/services/repositories/migrate_service.rb new file mode 100644 index 000000000..f80a16d69 --- /dev/null +++ b/app/services/repositories/migrate_service.rb @@ -0,0 +1,51 @@ +class Repositories::MigrateService < ApplicationService + attr_reader :user, :project, :params + + def initialize(user, project, params) + @project = project + @user = user + @params = params + end + + def call + @repository = Repository.new(repository_params) + ActiveRecord::Base.transaction do + if @repository.save! + gitea_repository = Gitea::Repository::MigrateService.new(user.gitea_token, gitea_repository_params).call + sync_project(gitea_repository) + sync_repository(@repository, gitea_repository) + end + @repository + end + rescue => e + puts "create mirror repository service error: #{e.message}" + raise Error, e.message + end + + private + + def sync_project(gitea_repository) + project.update_columns(gpid: gitea_repository["id"]) if gitea_repository + end + + def sync_repository(repository, gitea_repository) + repository.update_columns(url: remote_repository_url) if gitea_repository + end + + def remote_repository_url + [Gitea.gitea_config[:domain], '/', user.login, '/', params[:identifier], ".git"].join("") + end + + def repository_params + params.merge(project_id: project.id,) + end + + def gitea_repository_params + { + clone_addr: params[:mirror_url], + repo_name: params[:identifier], + uid: user.gitea_uid, + private: params[:hidden] + } + end +end diff --git a/app/views/projects/migrate.json.jbuilder b/app/views/projects/migrate.json.jbuilder new file mode 100644 index 000000000..818eb0180 --- /dev/null +++ b/app/views/projects/migrate.json.jbuilder @@ -0,0 +1 @@ +json.extract! @project, :id, :name diff --git a/config/routes.rb b/config/routes.rb index 34412ccae..47c4f5bd2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,7 +29,11 @@ Rails.application.routes.draw do resources :ignores, only: [:index, :show] resources :licenses, only: [:index, :show] - resources :projects, only: [:index, :create] + resources :projects, only: [:index, :create, :show] do + collection do + post :migrate + end + end # resources :memos do # member do