summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Botelho <tiagonbotelho@hotmail.com>2018-01-19 13:04:14 +0000
committerTiago Botelho <tiagonbotelho@hotmail.com>2018-02-06 13:35:35 +0000
commit32b2ff26011a5274bdb8a3dd41ad360a67c3148a (patch)
tree56064e3de4e9ca505730bdf1af3597ba8ead499f
parent35882e681b681f68a818bda9a8d2624edfecc219 (diff)
downloadgitlab-ce-32b2ff26011a5274bdb8a3dd41ad360a67c3148a.tar.gz
Adds remote messsage when project is created in a push over SSH or HTTP
-rw-r--r--app/controllers/projects/git_http_controller.rb38
-rw-r--r--app/models/project.rb4
-rw-r--r--lib/api/helpers/internal_helpers.rb16
-rw-r--r--lib/api/internal.rb17
-rw-r--r--lib/gitlab/checks/new_project.rb60
-rw-r--r--lib/gitlab/git_access.rb35
-rw-r--r--lib/gitlab/git_access_wiki.rb4
-rw-r--r--spec/lib/gitlab/git_access_spec.rb20
8 files changed, 150 insertions, 44 deletions
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index 97c0f5b8c87..6010423c243 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -11,10 +11,14 @@ class Projects::GitHttpController < Projects::GitHttpClientController
def info_refs
log_user_activity if upload_pack?
- if project.blank? && params[:service] == 'git-receive-pack'
+ if user && project.blank? && receive_pack?
@project = ::Projects::CreateService.new(user, project_params).execute
- return render_ok if @project.saved?
+ if @project.saved?
+ Gitlab::Checks::NewProject.new(user, @project, 'http').add_new_project_message
+ else
+ raise Gitlab::GitAccess::NotFoundError, 'Could not create project'
+ end
end
render_ok
@@ -32,15 +36,6 @@ 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
@@ -49,6 +44,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController
git_command == 'git-upload-pack'
end
+ def receive_pack?
+ git_command == 'git-receive-pack'
+ end
+
def git_command
if action_name == 'info_refs'
params[:service]
@@ -74,10 +73,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
@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
return user if user
return :ci if ci?
@@ -93,6 +88,19 @@ class Projects::GitHttpController < Projects::GitHttpClientController
@access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
end
+ def project_params
+ {
+ description: "",
+ path: Project.parse_project_id(params[:project_id]),
+ namespace_id: namespace&.id,
+ visibility_level: Gitlab::VisibilityLevel::PRIVATE.to_s
+ }
+ end
+
+ def namespace
+ @namespace ||= Namespace.find_by_path_or_name(params[:namespace_id])
+ end
+
def log_user_activity
Users::ActivityService.new(user, 'pull').execute
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 12d5f28f5ea..a4d83b2a79a 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -468,6 +468,10 @@ class Project < ActiveRecord::Base
def group_ids
joins(:namespace).where(namespaces: { type: 'Group' }).select(:namespace_id)
end
+
+ def parse_project_id(project_id)
+ project_id.gsub("\.git", '')
+ end
end
# returns all ancestor-groups upto but excluding the given namespace
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index eb67de81a0d..c0fcae43638 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -29,6 +29,10 @@ module API
{}
end
+ def receive_pack?
+ params[:action] == 'git-receive-pack'
+ end
+
def fix_git_env_repository_paths(env, repository_path)
if obj_dir_relative = env['GIT_OBJECT_DIRECTORY_RELATIVE'].presence
env['GIT_OBJECT_DIRECTORY'] = File.join(repository_path, obj_dir_relative)
@@ -62,6 +66,18 @@ module API
private
+ def project_path_regex
+ @project_regex ||= /\A(?<namespace_id>#{Gitlab::PathRegex.full_namespace_route_regex})\/(?<project_id>#{Gitlab::PathRegex.project_git_route_regex})\z/.freeze
+ end
+
+ def project_match
+ @match ||= params[:project].match(project_path_regex).captures
+ end
+
+ def namespace
+ @namespace ||= Namespace.find_by_path_or_name(project_match[:namespace_id])
+ end
+
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def set_project
if params[:gl_repository]
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index a83f714a1f3..f641ef457a3 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -43,7 +43,7 @@ module API
access_checker_klass = wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
access_checker = access_checker_klass
- .new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities, redirected_path: redirected_path, target_namespace: user.namespace)
+ .new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities, redirected_path: redirected_path, target_namespace: namespace)
begin
access_checker.check(params[:action], params[:changes])
@@ -51,17 +51,21 @@ module API
return { status: false, message: e.message }
end
- if project.blank? && params[:action] == 'git-receive-pack'
+ if user && project.blank? && receive_pack?
project_params = {
description: "",
- path: params[:project].split('/').last.gsub("\.git", ''),
- namespace_id: user.namespace.id.to_s,
+ path: Project.parse_project_id(project_match[:project_name]),
+ namespace_id: namespace&.id,
visibility_level: Gitlab::VisibilityLevel::PRIVATE.to_s
}
@project = ::Projects::CreateService.new(user, project_params).execute
- return { status: false, message: "Could not create project" } unless @project.saved?
+ if @project.saved?
+ Gitlab::Checks::NewProject.new(user, @project, protocol).add_new_project_message
+ else
+ return { status: false, message: "Could not create project" }
+ end
end
log_user_activity(actor)
@@ -221,7 +225,10 @@ module API
# key could be used
if user
redirect_message = Gitlab::Checks::ProjectMoved.fetch_redirect_message(user.id, project.id)
+ new_project_message = Gitlab::Checks::NewProject.fetch_new_project_message(user.id, project.id)
+
output[:redirected_message] = redirect_message if redirect_message
+ output[:new_project_message] = new_project_message if new_project_message
end
output
diff --git a/lib/gitlab/checks/new_project.rb b/lib/gitlab/checks/new_project.rb
new file mode 100644
index 00000000000..40d0acefaba
--- /dev/null
+++ b/lib/gitlab/checks/new_project.rb
@@ -0,0 +1,60 @@
+module Gitlab
+ module Checks
+ class NewProject
+ NEW_PROJECT = "new_project".freeze
+
+ def initialize(user, project, protocol)
+ @user = user
+ @project = project
+ @protocol = protocol
+ end
+
+ def self.fetch_new_project_message(user_id, project_id)
+ new_project_key = new_project_message_key(user_id, project_id)
+
+ Gitlab::Redis::SharedState.with do |redis|
+ message = redis.get(new_project_key)
+ redis.del(new_project_key)
+ message
+ end
+ end
+
+ def add_new_project_message
+ Gitlab::Redis::SharedState.with do |redis|
+ key = self.class.new_project_message_key(user.id, project.id)
+ redis.setex(key, 5.minutes, new_project_message)
+ end
+ end
+
+ def new_project_message
+ <<~MESSAGE.strip_heredoc
+
+ The private project #{project.full_path} was created.
+
+ To configure the remote, run:
+ git remote add origin #{git_url}
+
+ To view the project, visit:
+ #{project_url}
+
+ MESSAGE
+ end
+
+ private
+
+ attr_reader :project, :user, :protocol
+
+ def self.new_project_message_key(user_id, project_id)
+ "#{NEW_PROJECT}:#{user_id}:#{project_id}"
+ end
+
+ def project_url
+ Gitlab::Routing.url_helpers.project_url(project)
+ end
+
+ def git_url
+ protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 7de8a99f9dc..598506aa418 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -13,6 +13,7 @@ module Gitlab
'This deploy key does not have write access to this project.',
no_repo: 'A repository for this project does not exist yet.',
project_not_found: 'The project you were looking for could not be found.',
+ namespace_not_found: 'The namespace you were looking for could not be found.',
account_blocked: 'Your account has been blocked.',
command_not_allowed: "The command you're trying to execute is not allowed.",
upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.',
@@ -41,18 +42,18 @@ module Gitlab
check_protocol!
check_valid_actor!
check_active_user!
- check_project_accessibility!
+ check_project_accessibility!(cmd)
check_project_moved!
check_command_disabled!(cmd)
check_command_existence!(cmd)
- check_repository_existence!
- check_repository_creation!
+ check_repository_existence!(cmd)
case cmd
when *DOWNLOAD_COMMANDS
check_download_access!
when *PUSH_COMMANDS
- check_push_access!(changes)
+ check_push_access!(cmd, changes)
+ check_repository_creation!(cmd)
end
true
@@ -98,8 +99,8 @@ module Gitlab
end
end
- def check_project_accessibility!
- if (project.blank? || !can_read_project?) && !can_create_project_in_namespace?
+ def check_project_accessibility!(cmd)
+ if (project.blank? || !can_read_project?) && !can_create_project_in_namespace?(cmd)
raise NotFoundError, ERROR_MESSAGES[:project_not_found]
end
end
@@ -142,16 +143,20 @@ module Gitlab
end
end
- def check_repository_existence!
- if (project.blank? || !project.repository.exists?) && !can_create_project_in_namespace?
+ def check_repository_existence!(cmd)
+ if (project.blank? || !project.repository.exists?) && !can_create_project_in_namespace?(cmd)
raise UnauthorizedError, ERROR_MESSAGES[:no_repo]
end
end
- def check_repository_creation!
- return unless target_namespace
+ def check_repository_creation!(cmd)
+ return unless project.blank?
- unless can_create_project_in_namespace?
+ unless target_namespace
+ raise NotFoundError, ERROR_MESSAGES[:namespace_not_found]
+ end
+
+ unless can_create_project_in_namespace?(cmd)
raise UnauthorizedError, ERROR_MESSAGES[:create]
end
end
@@ -168,8 +173,8 @@ module Gitlab
end
end
- def check_push_access!(changes)
- return if can_create_project_in_namespace?
+ def check_push_access!(cmd, changes)
+ return if project.blank? && can_create_project_in_namespace?(cmd)
if project.repository_read_only?
raise UnauthorizedError, ERROR_MESSAGES[:read_only]
@@ -247,8 +252,8 @@ module Gitlab
end || Guest.can?(:read_project, project)
end
- def can_create_project_in_namespace?
- return unless target_namespace
+ def can_create_project_in_namespace?(cmd)
+ return false unless PUSH_COMMANDS.include?(cmd) && target_namespace
user.can?(:create_projects, target_namespace)
end
diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb
index 1c9477e84b2..f679b5e8ed6 100644
--- a/lib/gitlab/git_access_wiki.rb
+++ b/lib/gitlab/git_access_wiki.rb
@@ -25,6 +25,10 @@ module Gitlab
true
end
+ def check_repository_creation!(cmd)
+ # Method not used in wiki
+ end
+
def push_to_read_only_message
ERROR_MESSAGES[:read_only]
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 2009a8ac48c..457e219c1a5 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -501,15 +501,17 @@ describe Gitlab::GitAccess do
end
aggregate_failures do
- matrix.each do |action, allowed|
- check = -> { access.send(:check_push_access!, changes[action]) }
-
- if allowed
- expect(&check).not_to raise_error,
- -> { "expected #{action} to be allowed" }
- else
- expect(&check).to raise_error(Gitlab::GitAccess::UnauthorizedError),
- -> { "expected #{action} to be disallowed" }
+ Gitlab::GitAccess::ALL_COMMANDS.each do |cmd|
+ matrix.each do |action, allowed|
+ check = -> { access.send(:check_push_access!, cmd, changes[action]) }
+
+ if allowed
+ expect(&check).not_to raise_error,
+ -> { "expected #{action} to be allowed" }
+ else
+ expect(&check).to raise_error(Gitlab::GitAccess::UnauthorizedError),
+ -> { "expected #{action} to be disallowed" }
+ end
end
end
end