From 921d2afc6989dfa8220032984f657210c07e8792 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Thu, 18 Jan 2018 09:31:00 +0000 Subject: [PATCH] Adds option to push over HTTP to create a new project --- .../projects/git_http_controller.rb | 21 +++++++++++++- lib/gitlab/git_access.rb | 29 +++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index 71ae60cb8cd..45a1a5cf0de 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -11,6 +11,12 @@ class Projects::GitHttpController < Projects::GitHttpClientController def info_refs log_user_activity if upload_pack? + if project.blank? && params[:service] == 'git-receive-pack' + @project = ::Projects::CreateService.new(access_actor, project_params).execute + + return render_ok if @project.saved? + end + render_ok end @@ -26,6 +32,15 @@ class Projects::GitHttpController < Projects::GitHttpClientController private + def project_params + { + description: "", + path: params[:project_id].gsub("\.git", ''), + namespace_id: namespace.id.to_s, + visibility_level: Gitlab::VisibilityLevel::PRIVATE.to_s + } + end + def download_request? upload_pack? end @@ -56,7 +71,11 @@ class Projects::GitHttpController < Projects::GitHttpClientController end def access - @access ||= access_klass.new(access_actor, project, 'http', authentication_abilities: authentication_abilities, redirected_path: redirected_path) + @access ||= access_klass.new(access_actor, project, 'http', authentication_abilities: authentication_abilities, redirected_path: redirected_path, target_namespace: namespace) + end + + def namespace + @namespace = Namespace.find_by_path_or_name(params[:namespace_id]) end def access_actor diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 56f6febe86d..9427a5e4baa 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -18,21 +18,23 @@ module Gitlab upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.', receive_pack_disabled_over_http: 'Pushing over HTTP is not allowed.', read_only: 'The repository is temporarily read-only. Please try again later.', - cannot_push_to_read_only: "You can't push code to a read-only GitLab instance." + cannot_push_to_read_only: "You can't push code to a read-only GitLab instance.", + create: "Creating a repository to that namespace is not allowed." }.freeze DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze PUSH_COMMANDS = %w{ git-receive-pack }.freeze ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS - attr_reader :actor, :project, :protocol, :authentication_abilities, :redirected_path + attr_reader :actor, :project, :protocol, :authentication_abilities, :redirected_path, :target_namespace - def initialize(actor, project, protocol, authentication_abilities:, redirected_path: nil) + def initialize(actor, project, protocol, authentication_abilities:, redirected_path: nil, target_namespace: nil) @actor = actor @project = project @protocol = protocol @redirected_path = redirected_path @authentication_abilities = authentication_abilities + @target_namespace = target_namespace end def check(cmd, changes) @@ -44,6 +46,7 @@ module Gitlab check_command_disabled!(cmd) check_command_existence!(cmd) check_repository_existence! + check_repository_creation! case cmd when *DOWNLOAD_COMMANDS @@ -96,7 +99,7 @@ module Gitlab end def check_project_accessibility! - if project.blank? || !can_read_project? + if (project.blank? || !can_read_project?) && !can_create_project_in_namespace? raise NotFoundError, ERROR_MESSAGES[:project_not_found] end end @@ -140,11 +143,19 @@ module Gitlab end def check_repository_existence! - unless project.repository.exists? + if (project.blank? || !project.repository.exists?) && !can_create_project_in_namespace? raise UnauthorizedError, ERROR_MESSAGES[:no_repo] end end + def check_repository_creation! + return unless target_namespace + + unless can_create_project_in_namespace? + raise UnauthorizedError, ERROR_MESSAGES[:create] + end + end + def check_download_access! return if deploy_key? @@ -158,6 +169,8 @@ module Gitlab end def check_push_access!(changes) + return if can_create_project_in_namespace? + if project.repository_read_only? raise UnauthorizedError, ERROR_MESSAGES[:read_only] end @@ -234,6 +247,12 @@ module Gitlab end || Guest.can?(:read_project, project) end + def can_create_project_in_namespace? + return unless target_namespace + + actor.can?(:create_projects, target_namespace) + end + def http? protocol == 'http' end