| @@ -338,10 +338,10 @@ http://localhost:3000/api/projects/ | jq | |||||
| |-|-|-|-| | |-|-|-|-| | ||||
| |user_id |是|int |用户id或者组织id | | |user_id |是|int |用户id或者组织id | | ||||
| |name |是|string |项目名称 | | |name |是|string |项目名称 | | ||||
| |description |是|string |项目描述 | | |||||
| |description |否|string |项目描述 | | |||||
| |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | ||||
| |project_category_id|是|int |项目类别id | | |||||
| |project_language_id|是|int |项目语言id | | |||||
| |project_category_id|否|int |项目类别id | | |||||
| |project_language_id|否|int |项目语言id | | |||||
| |ignore_id |否|int |gitignore相关id | | |ignore_id |否|int |gitignore相关id | | ||||
| |license_id |否|int |开源许可证id | | |license_id |否|int |开源许可证id | | ||||
| |private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | | |private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | | ||||
| @@ -374,9 +374,7 @@ curl -X POST \ | |||||
| -d "user_id=36408" \ | -d "user_id=36408" \ | ||||
| -d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ | -d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ | ||||
| -d "name=golden_mirror1" \ | -d "name=golden_mirror1" \ | ||||
| -d "description=golden_mirror" \ | |||||
| -d "project_category_id=1" \ | |||||
| -d "project_language_id=2" \ | |||||
| -d "repository_name=golden_mirror1" \ | |||||
| http://localhost:3000/api/projects/migrate.json | jq | http://localhost:3000/api/projects/migrate.json | jq | ||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| @@ -388,8 +386,8 @@ http://localhost:3000/api/projects/migrate.json | jq | |||||
| |clone_addr |是|string |镜像项目clone地址 | | |clone_addr |是|string |镜像项目clone地址 | | ||||
| |description |否|string |项目描述 | | |description |否|string |项目描述 | | ||||
| |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | ||||
| |project_category_id|是|int |项目类别id | | |||||
| |project_language_id|是|int |项目语言id | | |||||
| |project_category_id|否|int |项目类别id | | |||||
| |project_language_id|否|int |项目语言id | | |||||
| |is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | | |is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | | ||||
| |auth_username |否|string|镜像源仓库的登录用户名 | | |auth_username |否|string|镜像源仓库的登录用户名 | | ||||
| |auth_password |否|string|镜像源仓库的登录秘密 | | |auth_password |否|string|镜像源仓库的登录秘密 | | ||||
| @@ -41,7 +41,7 @@ module LaboratoryHelper | |||||
| my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist", | my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist", | ||||
| my_projects: "/users/#{current_user.try(:login)}/projects", | my_projects: "/users/#{current_user.try(:login)}/projects", | ||||
| my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations", | my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations", | ||||
| default_url: "https://www.trustie.net/", | |||||
| default_url: Rails.application.config_for(:configuration)['platform_url'], | |||||
| tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages", | tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages", | ||||
| register_url: "https://www.trustie.net/login?login=false" | register_url: "https://www.trustie.net/login?login=false" | ||||
| } | } | ||||
| @@ -46,7 +46,6 @@ class ProjectsController < ApplicationController | |||||
| def create | def create | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| tip_exception("无法使用以下关键词:#{project_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(project_params[:repository_name]).present? | |||||
| Projects::CreateForm.new(project_params).validate! | Projects::CreateForm.new(project_params).validate! | ||||
| @project = Projects::CreateService.new(current_user, project_params).call | @project = Projects::CreateService.new(current_user, project_params).call | ||||
| @@ -57,7 +56,6 @@ class ProjectsController < ApplicationController | |||||
| end | end | ||||
| def migrate | def migrate | ||||
| tip_exception("无法使用以下关键词:#{mirror_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(mirror_params[:repository_name]).present? | |||||
| Projects::MigrateForm.new(mirror_params).validate! | Projects::MigrateForm.new(mirror_params).validate! | ||||
| @project = | @project = | ||||
| @@ -2,18 +2,24 @@ class BaseForm | |||||
| include ActiveModel::Model | include ActiveModel::Model | ||||
| def check_project_category(project_category_id) | def check_project_category(project_category_id) | ||||
| raise "project_category_id参数值无效." if (ProjectCategory.find_by_id project_category_id).blank? | |||||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||||
| end | end | ||||
| def check_project_language(project_language_id) | def check_project_language(project_language_id) | ||||
| raise "project_language_id参数值无效." if (ProjectLanguage.find_by_id project_language_id).blank? | |||||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||||
| end | end | ||||
| def check_repository_name(user_id, repository_name) | def check_repository_name(user_id, repository_name) | ||||
| raise "仓库名称已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists? | |||||
| check_reversed_keyword(repository_name) | |||||
| raise "项目标识已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists? | |||||
| end | end | ||||
| def check_project_name(user_id, project_name) | def check_project_name(user_id, project_name) | ||||
| raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists? | raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists? | ||||
| end | end | ||||
| def check_reversed_keyword(repository_name) | |||||
| raise "项目标识已被占用." if ReversedKeyword.is_reversed(repository_name).exists? | |||||
| end | |||||
| end | end | ||||
| @@ -1,11 +1,9 @@ | |||||
| class Projects::CreateForm < BaseForm | class Projects::CreateForm < BaseForm | ||||
| REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 | |||||
| attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, | attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, | ||||
| :project_language_id, :ignore_id, :license_id, :private, :owner | :project_language_id, :ignore_id, :license_id, :private, :owner | ||||
| 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 :user_id, :name, :repository_name, presence: true | |||||
| validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :name, length: { maximum: 50 } | validates :name, length: { maximum: 50 } | ||||
| validates :repository_name, length: { maximum: 100 } | validates :repository_name, length: { maximum: 100 } | ||||
| @@ -1,12 +1,13 @@ | |||||
| class Projects::MigrateForm < BaseForm | 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, :repository_name, :project_category_id, :description, | |||||
| :project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner | |||||
| attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner | |||||
| 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: "地址格式不正确" } | |||||
| validates :user_id, :name, :repository_name, :clone_addr, presence: true | |||||
| validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :clone_addr, format: { with: CustomRegexp::URL_REGEX, multiline: true, message: "地址格式不正确" } | |||||
| validates :name, length: { maximum: 50 } | |||||
| validates :repository_name, length: { maximum: 100 } | |||||
| validates :description, length: { maximum: 200 } | |||||
| validate do | validate do | ||||
| check_project_name(user_id, name) unless name.blank? | check_project_name(user_id, name) unless name.blank? | ||||
| check_repository_name(user_id, repository_name) unless repository_name.blank? | check_repository_name(user_id, repository_name) unless repository_name.blank? | ||||
| @@ -6,4 +6,8 @@ module CustomRegexp | |||||
| PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ | PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ | ||||
| URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/ | URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/ | ||||
| IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ | IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ | ||||
| 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 | |||||
| REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 | |||||
| end | end | ||||
| @@ -15,8 +15,8 @@ class Gitea::Organization::Repository::CreateService < Gitea::ClientService | |||||
| private | private | ||||
| def request_params | def request_params | ||||
| create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: create_params) | |||||
| # create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: params) | |||||
| end | end | ||||
| def url | def url | ||||
| @@ -25,8 +25,8 @@ class Gitea::Repository::CreateService < Gitea::ClientService | |||||
| private | private | ||||
| def request_params | def request_params | ||||
| create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: create_params) | |||||
| # create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: params) | |||||
| end | end | ||||
| def url | def url | ||||
| @@ -43,7 +43,7 @@ class Projects::CreateService < ApplicationService | |||||
| ignore_id: params[:ignore_id], | ignore_id: params[:ignore_id], | ||||
| license_id: params[:license_id], | license_id: params[:license_id], | ||||
| website: params[:website], | website: params[:website], | ||||
| identifier: params[:repository_name] #新增,hs | |||||
| identifier: params[:repository_name] | |||||
| } | } | ||||
| end | end | ||||
| @@ -32,7 +32,7 @@ class Repositories::MigrateService < ApplicationService | |||||
| private: params[:hidden], | private: params[:hidden], | ||||
| mirror: wrapper_mirror || false, | mirror: wrapper_mirror || false, | ||||
| auth_username: params[:login], | auth_username: params[:login], | ||||
| auth_password: Base64.decode64(params[:password]) | |||||
| auth_password: Base64.decode64(params[:password] || "") | |||||
| } | } | ||||
| end | end | ||||
| @@ -3,18 +3,18 @@ json.login @user.login | |||||
| json.name @user.full_name | json.name @user.full_name | ||||
| json.location @user.location | json.location @user.location | ||||
| json.image_url url_to_avatar(@user) | json.image_url url_to_avatar(@user) | ||||
| json.url "#{request.base_url }/users/#{@user.login}" | |||||
| json.url "#{request.base_url }/#{@user.login}" | |||||
| json.followers_count @user.followers_count | json.followers_count @user.followers_count | ||||
| json.followers_url "#{base_url}/users/#{@user.login}/fan_users" | |||||
| json.followers_url "#{base_url}/#{@user.login}/fan_users" | |||||
| json.following_count @user.following_count | json.following_count @user.following_count | ||||
| json.following_url "#{base_url}/users/#{@user.login}/watchers" | |||||
| json.following_url "#{base_url}/#{@user.login}/watchers" | |||||
| json.projects_count @user.projects_count | json.projects_count @user.projects_count | ||||
| json.projects_url "#{base_url}/users/#{@user.login}" | |||||
| json.projects_url "#{base_url}/#{@user.login}" | |||||
| json.projects_count @user.projects_count | json.projects_count @user.projects_count | ||||
| json.is_watch current_user&.watched?(@user) | json.is_watch current_user&.watched?(@user) | ||||
| json.organizations @user.organizations do |organization| | json.organizations @user.organizations do |organization| | ||||
| json.login organization.login | json.login organization.login | ||||
| json.name organization.real_name | json.name organization.real_name | ||||
| json.image_url url_to_avatar(organization) | json.image_url url_to_avatar(organization) | ||||
| json.url "#{base_url}/organize/#{organization.login}" | |||||
| json.url "#{base_url}/#{organization.login}" | |||||
| end | end | ||||
| @@ -1,51 +0,0 @@ | |||||
| # 新版Git测试说明 | |||||
| 统一: | |||||
| 参考实训:http://47.96.87.25:48080/shixuns/ca9fvobr/repository | |||||
| 请求方式:POST | |||||
| 参数{repo_path: "educoder/ca9fvobr.git"} | |||||
| 公共方法: | |||||
| ['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', | |||||
| 'file_content', 'commits'] | |||||
| 1、仓库目录接口 | |||||
| 测试方法:模拟1000个用户同时去访问接口,访问方式 | |||||
| http://121.199.19.206:9000/api/file_tree | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", path: ''} // 如:{path: 'step1'} | |||||
| 2、创建版本库 | |||||
| 访问地址:http://121.199.19.206:9000/api/add_repository | |||||
| 参数: | |||||
| {repo_path: 比如:"Hjqreturn/aaass1.git"} | |||||
| 3、fork版本库 | |||||
| http://121.199.19.206:9000/api/fork_repository | |||||
| 参数: | |||||
| {repo_path: 'Hjqreturn/aaass1.git', fork_repository_path: 'educoder/ca9fvobr.git'} | |||||
| 说明:fork_repository_path是新项目的repo_path, repo_path是源项目的 | |||||
| 4、更新文件 | |||||
| 测试方法: | |||||
| 1、更新同一个文件,并发量可以不用很大,可以用同一个用户并发10-100 | |||||
| 2、更新不同的文件:可以依据创建的版本库去更新 | |||||
| 访问地址:http://121.199.19.206:9000/api/update_file | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", | |||||
| file_path: 'step1/main.py', | |||||
| message: 'commit by test', | |||||
| content: 'afdjadsjfj1111', | |||||
| author_name: 'guange', | |||||
| author_email: '8863824@gmil.com'} | |||||
| 5、获取文件内容 | |||||
| 访问地址:http://121.199.19.206:9000/api/file_content | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", path: 'step1/main.py',} | |||||
| 6、获取提交记录 | |||||
| 访问地址:http://121.199.19.206:9000/api/commits | |||||
| 参数: | |||||
| {repo_path: 比如:"educoder/ca9fvobr.git"} | |||||
| @@ -1,72 +0,0 @@ | |||||
| mbtclufr | |||||
| 9op3hs4j | |||||
| 96ctv7yr | |||||
| rtmzxfke | |||||
| ofqxthrf | |||||
| czu9w4gj | |||||
| 9fpzj6et | |||||
| pwhc865b | |||||
| maozpx4l | |||||
| y5wh2ofx | |||||
| b5rzhpf3 | |||||
| bs243nrl | |||||
| 47fn2yfb | |||||
| kwotfxey | |||||
| w5468sbp | |||||
| fyekprio | |||||
| q6ze5fih | |||||
| b5hjq9zm | |||||
| ky8pbqux | |||||
| 53phc7nq | |||||
| b9j2yuix | |||||
| 9t3uphwk | |||||
| iokm8ah2 | |||||
| qlsy6xb4 | |||||
| 345bqhfi | |||||
| v728fqia | |||||
| 4euftvf2 | |||||
| f23sef5m | |||||
| nhqis8m9 | |||||
| qp72tb5x | |||||
| gt3anszw | |||||
| tng6heyf | |||||
| nb9keawo | |||||
| elgnbkp9 | |||||
| 4neslomg | |||||
| lh35s6ma | |||||
| xmc4rpay | |||||
| qrpaxi6b | |||||
| 9fla2zry | |||||
| efuibzrm | |||||
| fzp3iu4w | |||||
| pligsyn8 | |||||
| glbksr29 | |||||
| kfm7ghyc | |||||
| p6hk3svf | |||||
| p539gjhm | |||||
| am5o73er | |||||
| 4x3qwrbe | |||||
| fqosyl8g | |||||
| of5z3fci | |||||
| tb7hw62n | |||||
| ie6zxg7r | |||||
| 4q2bmy9h | |||||
| fpm3u5yb | |||||
| nikx3ojt | |||||
| vt82s9bq | |||||
| ma59fefo | |||||
| lxa39tfq | |||||
| 4gnockxf | |||||
| nxwg84ey | |||||
| fmie8nzb | |||||
| w5nsr24v | |||||
| 4hn3efwc | |||||
| h9ljfbq7 | |||||
| nuv54t8b | |||||
| 2te9fmfq | |||||
| vihnsayz | |||||
| qhlyn82s | |||||
| vw74kmfr | |||||
| vcta36bz | |||||
| henz425l | |||||
| g529v38z | |||||