Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
1e56b3f4
Commit
1e56b3f4
authored
Feb 02, 2018
by
Tiago Botelho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moves project creationg to git access check for git push
parent
839829a7
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
273 additions
and
234 deletions
+273
-234
GITLAB_SHELL_VERSION
GITLAB_SHELL_VERSION
+1
-1
app/controllers/projects/git_http_controller.rb
app/controllers/projects/git_http_controller.rb
+7
-12
app/services/projects/create_from_push_service.rb
app/services/projects/create_from_push_service.rb
+0
-37
doc/gitlab-basics/create-project.md
doc/gitlab-basics/create-project.md
+7
-10
lib/api/helpers/internal_helpers.rb
lib/api/helpers/internal_helpers.rb
+8
-12
lib/api/internal.rb
lib/api/internal.rb
+5
-10
lib/gitlab/checks/post_push_message.rb
lib/gitlab/checks/post_push_message.rb
+1
-1
lib/gitlab/checks/project_created.rb
lib/gitlab/checks/project_created.rb
+3
-3
lib/gitlab/checks/project_moved.rb
lib/gitlab/checks/project_moved.rb
+2
-2
lib/gitlab/git_access.rb
lib/gitlab/git_access.rb
+56
-36
lib/gitlab/path_regex.rb
lib/gitlab/path_regex.rb
+1
-1
lib/gitlab/user_access.rb
lib/gitlab/user_access.rb
+2
-1
spec/lib/gitlab/git_access_spec.rb
spec/lib/gitlab/git_access_spec.rb
+180
-48
spec/requests/api/internal_spec.rb
spec/requests/api/internal_spec.rb
+0
-26
spec/services/projects/create_from_push_service_spec.rb
spec/services/projects/create_from_push_service_spec.rb
+0
-34
No files found.
GITLAB_SHELL_VERSION
View file @
1e56b3f4
6.0.
2
6.0.
3
app/controllers/projects/git_http_controller.rb
View file @
1e56b3f4
...
@@ -11,7 +11,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
...
@@ -11,7 +11,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
# GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
# GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
def
info_refs
def
info_refs
log_user_activity
if
upload_pack?
log_user_activity
if
upload_pack?
create_new_project
if
receive_pack?
&&
project
.
blank?
render_ok
render_ok
end
end
...
@@ -36,10 +35,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
...
@@ -36,10 +35,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
git_command
==
'git-upload-pack'
git_command
==
'git-upload-pack'
end
end
def
receive_pack?
git_command
==
'git-receive-pack'
end
def
git_command
def
git_command
if
action_name
==
'info_refs'
if
action_name
==
'info_refs'
params
[
:service
]
params
[
:service
]
...
@@ -48,10 +43,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
...
@@ -48,10 +43,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
end
end
end
end
def
create_new_project
@project
=
::
Projects
::
CreateFromPushService
.
new
(
user
,
params
[
:project_id
],
namespace
,
'http'
).
execute
end
def
render_ok
def
render_ok
set_workhorse_internal_api_content_type
set_workhorse_internal_api_content_type
render
json:
Gitlab
::
Workhorse
.
git_http_ok
(
repository
,
wiki?
,
user
,
action_name
)
render
json:
Gitlab
::
Workhorse
.
git_http_ok
(
repository
,
wiki?
,
user
,
action_name
)
...
@@ -70,7 +61,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController
...
@@ -70,7 +61,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController
end
end
def
access
def
access
@access
||=
access_klass
.
new
(
access_actor
,
project
,
'http'
,
authentication_abilities:
authentication_abilities
,
redirected_path:
redirected_path
,
target_namespace:
namespace
)
@access
||=
access_klass
.
new
(
access_actor
,
project
,
'http'
,
authentication_abilities:
authentication_abilities
,
namespace_path:
params
[
:namespace_id
],
project_path:
project_path
,
redirected_path:
redirected_path
)
end
end
def
access_actor
def
access_actor
...
@@ -82,14 +76,15 @@ class Projects::GitHttpController < Projects::GitHttpClientController
...
@@ -82,14 +76,15 @@ class Projects::GitHttpController < Projects::GitHttpClientController
# Use the magic string '_any' to indicate we do not know what the
# Use the magic string '_any' to indicate we do not know what the
# changes are. This is also what gitlab-shell does.
# changes are. This is also what gitlab-shell does.
access
.
check
(
git_command
,
'_any'
)
access
.
check
(
git_command
,
'_any'
)
@project
||=
access
.
project
end
end
def
access_klass
def
access_klass
@access_klass
||=
wiki?
?
Gitlab
::
GitAccessWiki
:
Gitlab
::
GitAccess
@access_klass
||=
wiki?
?
Gitlab
::
GitAccessWiki
:
Gitlab
::
GitAccess
end
end
def
namespace
def
project_path
@
namespace
||=
Namespace
.
find_by_full_path
(
params
[
:namespace_id
]
)
@
project_path
||=
params
[
:project_id
].
sub
(
/\.git$/
,
''
)
end
end
def
log_user_activity
def
log_user_activity
...
...
app/services/projects/create_from_push_service.rb
deleted
100644 → 0
View file @
839829a7
module
Projects
class
CreateFromPushService
<
BaseService
attr_reader
:user
,
:project_path
,
:namespace
,
:protocol
def
initialize
(
user
,
project_path
,
namespace
,
protocol
)
@user
=
user
@project_path
=
project_path
@namespace
=
namespace
@protocol
=
protocol
end
def
execute
return
unless
user
project
=
Projects
::
CreateService
.
new
(
user
,
project_params
).
execute
if
project
.
saved?
Gitlab
::
Checks
::
ProjectCreated
.
new
(
project
,
user
,
protocol
).
add_message
else
raise
Gitlab
::
GitAccess
::
ProjectCreationError
,
"Could not create project:
#{
project
.
errors
.
full_messages
.
join
(
', '
)
}
"
end
project
end
private
def
project_params
{
description:
""
,
path:
project_path
.
gsub
(
/\.git$/
,
''
),
namespace_id:
namespace
&
.
id
,
visibility_level:
Gitlab
::
VisibilityLevel
::
PRIVATE
.
to_s
}
end
end
end
doc/gitlab-basics/create-project.md
View file @
1e56b3f4
...
@@ -39,18 +39,18 @@
...
@@ -39,18 +39,18 @@
When you create a new repo locally, instead of going to GitLab to manually
When you create a new repo locally, instead of going to GitLab to manually
create a new project and then push the repo, you can directly push it to
create a new project and then push the repo, you can directly push it to
GitLab to create the new project, all without leaving your terminal.
T
hat
GitLab to create the new project, all without leaving your terminal.
If you have access to t
hat
will automatically create a new project under a GitLab namespace that you have access to
namespace, we will automatically create a new project under that GitLab namespace with its
with its visibility set to private by default (you can later change it
).
visibility set to private by default (you can later change it in the UI
).
This can be done by using either SSH or HTTP:
This can be done by using either SSH or HTTP:
```
```
## Git push using SSH
## Git push using SSH
git push git@gitlab.
com:namespace/nonexistent-project.git branch_name
git push git@gitlab.
example.com:namespace/nonexistent-project.git
## Git push using HTTP
## Git push using HTTP
git push https://gitlab.
com/namespace/nonexistent-project.git branch_name
git push https://gitlab.
example.com/namespace/nonexistent-project.git
```
```
Once the push finishes successfully, a remote message will indicate
Once the push finishes successfully, a remote message will indicate
...
@@ -61,15 +61,12 @@ remote:
...
@@ -61,15 +61,12 @@ remote:
remote: The private project namespace/nonexistent-project was created.
remote: The private project namespace/nonexistent-project was created.
remote:
remote:
remote: To configure the remote, run:
remote: To configure the remote, run:
remote: git remote add origin https://gitlab.com/namespace/nonexistent-project.git
remote: git remote add origin https://gitlab.
example.
com/namespace/nonexistent-project.git
remote:
remote:
remote: To view the project, visit:
remote: To view the project, visit:
remote: https://gitlab.com/namespace/nonexistent-project
remote: https://gitlab.
example.
com/namespace/nonexistent-project
remote:
remote:
```
```
If the project name is already in use, your push will be rejected
to prevent accidental overwriting the existing project.
[
import it
]:
../workflow/importing/README.md
[
import it
]:
../workflow/importing/README.md
[
reserved
]:
../user/reserved_names.md
[
reserved
]:
../user/reserved_names.md
lib/api/helpers/internal_helpers.rb
View file @
1e56b3f4
module
API
module
API
module
Helpers
module
Helpers
module
InternalHelpers
module
InternalHelpers
include
Gitlab
::
Utils
::
StrongMemoize
attr_reader
:redirected_path
attr_reader
:redirected_path
def
wiki?
def
wiki?
...
@@ -49,10 +47,6 @@ module API
...
@@ -49,10 +47,6 @@ module API
::
Users
::
ActivityService
.
new
(
actor
,
'Git SSH'
).
execute
if
commands
.
include?
(
params
[
:action
])
::
Users
::
ActivityService
.
new
(
actor
,
'Git SSH'
).
execute
if
commands
.
include?
(
params
[
:action
])
end
end
def
receive_pack?
params
[
:action
]
==
'git-receive-pack'
end
def
merge_request_urls
def
merge_request_urls
::
MergeRequests
::
GetUrlsService
.
new
(
project
).
execute
(
params
[
:changes
])
::
MergeRequests
::
GetUrlsService
.
new
(
project
).
execute
(
params
[
:changes
])
end
end
...
@@ -66,16 +60,18 @@ module API
...
@@ -66,16 +60,18 @@ module API
false
false
end
end
def
project_namespace
def
project_path
strong_memoize
(
:project_namespace
)
do
project
&
.
path
||
project_path_match
[
:project_path
]
project
&
.
namespace
||
Namespace
.
find_by_full_path
(
project_match
[
:namespace_path
])
end
end
def
namespace_path
project
&
.
namespace
&
.
full_path
||
project_path_match
[
:namespace_path
]
end
end
private
private
def
project_match
def
project_
path_
match
@project_match
||=
params
[
:project
].
match
(
Gitlab
::
PathRegex
.
full_project_git_path_regex
)
||
{}
@project_
path_
match
||=
params
[
:project
].
match
(
Gitlab
::
PathRegex
.
full_project_git_path_regex
)
||
{}
end
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
...
...
lib/api/internal.rb
View file @
1e56b3f4
...
@@ -42,23 +42,18 @@ module API
...
@@ -42,23 +42,18 @@ module API
end
end
access_checker_klass
=
wiki?
?
Gitlab
::
GitAccessWiki
:
Gitlab
::
GitAccess
access_checker_klass
=
wiki?
?
Gitlab
::
GitAccessWiki
:
Gitlab
::
GitAccess
access_checker
=
access_checker_klass
access_checker
=
access_checker_klass
.
new
(
actor
,
project
,
.
new
(
actor
,
project
,
protocol
,
authentication_abilities:
ssh_authentication_abilities
,
redirected_path:
redirected_path
,
target_namespace:
project_namespace
)
protocol
,
authentication_abilities:
ssh_authentication_abilities
,
namespace_path:
namespace_path
,
project_path:
project_path
,
redirected_path:
redirected_path
)
begin
begin
access_checker
.
check
(
params
[
:action
],
params
[
:changes
])
access_checker
.
check
(
params
[
:action
],
params
[
:changes
])
@project
||=
access_checker
.
project
rescue
Gitlab
::
GitAccess
::
UnauthorizedError
,
Gitlab
::
GitAccess
::
NotFoundError
=>
e
rescue
Gitlab
::
GitAccess
::
UnauthorizedError
,
Gitlab
::
GitAccess
::
NotFoundError
=>
e
return
{
status:
false
,
message:
e
.
message
}
return
{
status:
false
,
message:
e
.
message
}
end
end
if
receive_pack?
&&
project
.
blank?
begin
@project
=
::
Projects
::
CreateFromPushService
.
new
(
user
,
project_match
[
:project_path
],
project_namespace
,
protocol
).
execute
rescue
Gitlab
::
GitAccess
::
ProjectCreationError
=>
e
return
{
status:
false
,
message:
e
.
message
}
end
end
log_user_activity
(
actor
)
log_user_activity
(
actor
)
{
{
...
...
lib/gitlab/checks/
base_project
.rb
→
lib/gitlab/checks/
post_push_message
.rb
View file @
1e56b3f4
module
Gitlab
module
Gitlab
module
Checks
module
Checks
class
BaseProject
class
PostPushMessage
def
initialize
(
project
,
user
,
protocol
)
def
initialize
(
project
,
user
,
protocol
)
@project
=
project
@project
=
project
@user
=
user
@user
=
user
...
...
lib/gitlab/checks/project_created.rb
View file @
1e56b3f4
module
Gitlab
module
Gitlab
module
Checks
module
Checks
class
ProjectCreated
<
BaseProject
class
ProjectCreated
<
PostPushMessage
PROJECT_CREATED
=
"project_created"
.
freeze
PROJECT_CREATED
=
"project_created"
.
freeze
def
message
def
message
<<~
MESSAGE
.
strip_heredoc
<<~
MESSAGE
The private project
#{
project
.
full_path
}
was created.
The private project
#{
project
.
full_path
}
was
successfully
created.
To configure the remote, run:
To configure the remote, run:
git remote add origin
#{
url_to_repo
}
git remote add origin
#{
url_to_repo
}
...
...
lib/gitlab/checks/project_moved.rb
View file @
1e56b3f4
module
Gitlab
module
Gitlab
module
Checks
module
Checks
class
ProjectMoved
<
BaseProject
class
ProjectMoved
<
PostPushMessage
REDIRECT_NAMESPACE
=
"redirect_namespace"
.
freeze
REDIRECT_NAMESPACE
=
"redirect_namespace"
.
freeze
def
initialize
(
project
,
user
,
protocol
,
redirected_path
)
def
initialize
(
project
,
user
,
protocol
,
redirected_path
)
...
@@ -10,7 +10,7 @@ module Gitlab
...
@@ -10,7 +10,7 @@ module Gitlab
end
end
def
message
(
rejected:
false
)
def
message
(
rejected:
false
)
<<~
MESSAGE
.
strip_heredoc
<<~
MESSAGE
Project '
#{
redirected_path
}
' was moved to '
#{
project
.
full_path
}
'.
Project '
#{
redirected_path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote:
Please update your Git remote:
...
...
lib/gitlab/git_access.rb
View file @
1e56b3f4
...
@@ -28,32 +28,37 @@ module Gitlab
...
@@ -28,32 +28,37 @@ module Gitlab
PUSH_COMMANDS
=
%w{ git-receive-pack }
.
freeze
PUSH_COMMANDS
=
%w{ git-receive-pack }
.
freeze
ALL_COMMANDS
=
DOWNLOAD_COMMANDS
+
PUSH_COMMANDS
ALL_COMMANDS
=
DOWNLOAD_COMMANDS
+
PUSH_COMMANDS
attr_reader
:actor
,
:project
,
:protocol
,
:authentication_abilities
,
:
redirected_path
,
:target_namespace
attr_reader
:actor
,
:project
,
:protocol
,
:authentication_abilities
,
:
namespace_path
,
:project_path
,
:redirected_path
def
initialize
(
actor
,
project
,
protocol
,
authentication_abilities
:,
redirected_path:
nil
,
target_namespace
:
nil
)
def
initialize
(
actor
,
project
,
protocol
,
authentication_abilities
:,
namespace_path:
nil
,
project_path:
nil
,
redirected_path
:
nil
)
@actor
=
actor
@actor
=
actor
@project
=
project
@project
=
project
@protocol
=
protocol
@protocol
=
protocol
@redirected_path
=
redirected_path
@authentication_abilities
=
authentication_abilities
@authentication_abilities
=
authentication_abilities
@target_namespace
=
target_namespace
@namespace_path
=
namespace_path
@project_path
=
project_path
@redirected_path
=
redirected_path
end
end
def
check
(
cmd
,
changes
)
def
check
(
cmd
,
changes
)
check_protocol!
check_protocol!
check_valid_actor!
check_valid_actor!
check_active_user!
check_active_user!
check_project_accessibility!
(
cmd
)
check_project_moved!
check_command_disabled!
(
cmd
)
check_command_disabled!
(
cmd
)
check_command_existence!
(
cmd
)
check_command_existence!
(
cmd
)
check_repository_existence!
(
cmd
)
check_db_accessibility!
(
cmd
)
ensure_project_on_push!
(
cmd
,
changes
)
check_project_accessibility!
check_project_moved!
check_repository_existence!
case
cmd
case
cmd
when
*
DOWNLOAD_COMMANDS
when
*
DOWNLOAD_COMMANDS
check_download_access!
check_download_access!
when
*
PUSH_COMMANDS
when
*
PUSH_COMMANDS
check_push_access!
(
c
md
,
c
hanges
)
check_push_access!
(
changes
)
end
end
true
true
...
@@ -99,8 +104,8 @@ module Gitlab
...
@@ -99,8 +104,8 @@ module Gitlab
end
end
end
end
def
check_project_accessibility!
(
cmd
)
def
check_project_accessibility!
unless
can_create_project_in_namespace?
(
cmd
)
||
can_read_project?
if
project
.
blank?
||
!
can_read_project?
raise
NotFoundError
,
ERROR_MESSAGES
[
:project_not_found
]
raise
NotFoundError
,
ERROR_MESSAGES
[
:project_not_found
]
end
end
end
end
...
@@ -143,16 +148,49 @@ module Gitlab
...
@@ -143,16 +148,49 @@ module Gitlab
end
end
end
end
def
check_repository_existence!
(
cmd
)
def
check_db_accessibility!
(
cmd
)
unless
can_create_project_in_namespace?
(
cmd
)
||
project
.
repository
.
exists?
return
unless
receive_pack?
(
cmd
)
if
Gitlab
::
Database
.
read_only?
raise
UnauthorizedError
,
push_to_read_only_message
end
end
def
ensure_project_on_push!
(
cmd
,
changes
)
return
if
project
||
deploy_key?
return
unless
receive_pack?
(
cmd
)
&&
changes
==
'_any'
&&
authentication_abilities
.
include?
(
:push_code
)
namespace
=
Namespace
.
find_by_full_path
(
namespace_path
)
return
unless
user
&
.
can?
(
:create_projects
,
namespace
)
project_params
=
{
path:
project_path
,
namespace_id:
namespace
.
id
,
visibility_level:
Gitlab
::
VisibilityLevel
::
PRIVATE
}
project
=
Projects
::
CreateService
.
new
(
user
,
project_params
).
execute
unless
project
.
saved?
raise
ProjectCreationError
,
"Could not create project:
#{
project
.
errors
.
full_messages
.
join
(
', '
)
}
"
end
@project
=
project
user_access
.
project
=
@project
Checks
::
ProjectCreated
.
new
(
project
,
user
,
protocol
).
add_message
end
def
check_repository_existence!
unless
project
.
repository
.
exists?
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:no_repo
]
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:no_repo
]
end
end
end
end
def
check_download_access!
def
check_download_access!
return
if
deploy_key?
passed
=
deploy_key?
||
user_can_download_code?
||
passed
=
user_can_download_code?
||
build_can_download_code?
||
build_can_download_code?
||
guest_can_download_code?
guest_can_download_code?
...
@@ -161,13 +199,7 @@ module Gitlab
...
@@ -161,13 +199,7 @@ module Gitlab
end
end
end
end
def
check_push_access!
(
cmd
,
changes
)
def
check_push_access!
(
changes
)
if
Gitlab
::
Database
.
read_only?
raise
UnauthorizedError
,
push_to_read_only_message
end
return
if
can_create_project_in_namespace?
(
cmd
)
if
project
.
repository_read_only?
if
project
.
repository_read_only?
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:read_only
]
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:read_only
]
end
end
...
@@ -180,8 +212,6 @@ module Gitlab
...
@@ -180,8 +212,6 @@ module Gitlab
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:upload
]
raise
UnauthorizedError
,
ERROR_MESSAGES
[
:upload
]
end
end
return
if
changes
.
blank?
# Allow access.
check_change_access!
(
changes
)
check_change_access!
(
changes
)
end
end
...
@@ -198,6 +228,8 @@ module Gitlab
...
@@ -198,6 +228,8 @@ module Gitlab
end
end
def
check_change_access!
(
changes
)
def
check_change_access!
(
changes
)
return
if
changes
.
blank?
# Allow access.
changes_list
=
Gitlab
::
ChangesList
.
new
(
changes
)
changes_list
=
Gitlab
::
ChangesList
.
new
(
changes
)
# Iterate over all changes to find if user allowed all of them to be applied
# Iterate over all changes to find if user allowed all of them to be applied
...
@@ -240,14 +272,6 @@ module Gitlab
...
@@ -240,14 +272,6 @@ module Gitlab
end
||
Guest
.
can?
(
:read_project
,
project
)
end
||
Guest
.
can?
(
:read_project
,
project
)
end
end
def
can_create_project_in_namespace?
(
cmd
)
strong_memoize
(
:can_create_project_in_namespace
)
do
return
false
unless
push?
(
cmd
)
&&
target_namespace
&&
project
.
blank?
user
.
can?
(
:create_projects
,
target_namespace
)
end
end
def
http?
def
http?
protocol
==
'http'
protocol
==
'http'
end
end
...
@@ -260,10 +284,6 @@ module Gitlab
...
@@ -260,10 +284,6 @@ module Gitlab
command
==
'git-receive-pack'
command
==
'git-receive-pack'
end
end
def
push?
(
cmd
)
PUSH_COMMANDS
.
include?
(
cmd
)
end
def
upload_pack_disabled_over_http?
def
upload_pack_disabled_over_http?
!
Gitlab
.
config
.
gitlab_shell
.
upload_pack
!
Gitlab
.
config
.
gitlab_shell
.
upload_pack
end
end
...
...
lib/gitlab/path_regex.rb
View file @
1e56b3f4
...
@@ -188,7 +188,7 @@ module Gitlab
...
@@ -188,7 +188,7 @@ module Gitlab
end
end
def
full_project_git_path_regex
def
full_project_git_path_regex
@full_project_git_path_regex
||=
/\A\/?(?<namespace_path>
#{
full_namespace_route_regex
}
)\/(?<project_path>
#{
project_git_route_regex
}
)\z/
.
freeze
@full_project_git_path_regex
||=
%r{
\A\/
?(?<namespace_path>
#{
full_namespace_route_regex
}
)
\/
(?<project_path>
#{
project_route_regex
}
)
\.
git
\z
}
end
end
def
full_namespace_format_regex
def
full_namespace_format_regex
...
...
lib/gitlab/user_access.rb
View file @
1e56b3f4
...
@@ -6,7 +6,8 @@ module Gitlab
...
@@ -6,7 +6,8 @@ module Gitlab
[
user
&
.
id
,
project
&
.
id
]
[
user
&
.
id
,
project
&
.
id
]
end
end
attr_reader
:user
,
:project
attr_reader
:user
attr_accessor
:project
def
initialize
(
user
,
project:
nil
)
def
initialize
(
user
,
project:
nil
)
@user
=
user
@user
=
user
...
...
spec/lib/gitlab/git_access_spec.rb
View file @
1e56b3f4
...
@@ -5,11 +5,19 @@ describe Gitlab::GitAccess do
...
@@ -5,11 +5,19 @@ describe Gitlab::GitAccess do
let
(
:actor
)
{
user
}
let
(
:actor
)
{
user
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:project_path
)
{
project
.
path
}
let
(
:namespace_path
)
{
project
&
.
namespace
&
.
path
}
let
(
:protocol
)
{
'ssh'
}
let
(
:protocol
)
{
'ssh'
}
let
(
:authentication_abilities
)
{
%i[read_project download_code push_code]
}
let
(
:authentication_abilities
)
{
%i[read_project download_code push_code]
}
let
(
:redirected_path
)
{
nil
}
let
(
:redirected_path
)
{
nil
}
let
(
:access
)
{
described_class
.
new
(
actor
,
project
,
protocol
,
authentication_abilities:
authentication_abilities
,
redirected_path:
redirected_path
)
}
let
(
:access
)
do
described_class
.
new
(
actor
,
project
,
protocol
,
authentication_abilities:
authentication_abilities
,
namespace_path:
namespace_path
,
project_path:
project_path
,
redirected_path:
redirected_path
)
end
let
(
:push_access_check
)
{
access
.
check
(
'git-receive-pack'
,
'_any'
)
}
let
(
:push_access_check
)
{
access
.
check
(
'git-receive-pack'
,
'_any'
)
}
let
(
:pull_access_check
)
{
access
.
check
(
'git-upload-pack'
,
'_any'
)
}
let
(
:pull_access_check
)
{
access
.
check
(
'git-upload-pack'
,
'_any'
)
}
...
@@ -145,6 +153,7 @@ describe Gitlab::GitAccess do
...
@@ -145,6 +153,7 @@ describe Gitlab::GitAccess do
context
'when the project is nil'
do
context
'when the project is nil'
do
let
(
:project
)
{
nil
}
let
(
:project
)
{
nil
}
let
(
:project_path
)
{
"new-project"
}
it
'blocks push and pull with "not found"'
do
it
'blocks push and pull with "not found"'
do
aggregate_failures
do
aggregate_failures
do
...
@@ -154,7 +163,13 @@ describe Gitlab::GitAccess do
...
@@ -154,7 +163,13 @@ describe Gitlab::GitAccess do
end
end
context
'when user is allowed to create project in namespace'
do
context
'when user is allowed to create project in namespace'
do
let
(
:access
)
{
described_class
.
new
(
actor
,
nil
,
protocol
,
authentication_abilities:
authentication_abilities
,
redirected_path:
redirected_path
,
target_namespace:
user
.
namespace
)
}
let
(
:namespace_path
)
{
user
.
namespace
.
path
}
let
(
:access
)
do
described_class
.
new
(
actor
,
nil
,
protocol
,
authentication_abilities:
authentication_abilities
,
project_path:
project_path
,
namespace_path:
namespace_path
,
redirected_path:
redirected_path
)
end
it
'blocks pull access with "not found"'
do
it
'blocks pull access with "not found"'
do
expect
{
pull_access_check
}.
to
raise_not_found
expect
{
pull_access_check
}.
to
raise_not_found
...
@@ -167,7 +182,13 @@ describe Gitlab::GitAccess do
...
@@ -167,7 +182,13 @@ describe Gitlab::GitAccess do
context
'when user is not allowed to create project in namespace'
do
context
'when user is not allowed to create project in namespace'
do
let
(
:user2
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
let
(
:access
)
{
described_class
.
new
(
actor
,
nil
,
protocol
,
authentication_abilities:
authentication_abilities
,
redirected_path:
redirected_path
,
target_namespace:
user2
.
namespace
)
}
let
(
:namespace_path
)
{
user2
.
namespace
.
path
}
let
(
:access
)
do
described_class
.
new
(
actor
,
nil
,
protocol
,
authentication_abilities:
authentication_abilities
,
project_path:
project_path
,
namespace_path:
namespace_path
,
redirected_path:
redirected_path
)
end
it
'blocks push and pull with "not found"'
do
it
'blocks push and pull with "not found"'
do
aggregate_failures
do
aggregate_failures
do
...
@@ -297,6 +318,52 @@ describe Gitlab::GitAccess do
...
@@ -297,6 +318,52 @@ describe Gitlab::GitAccess do
end
end
end
end
describe
'#check_authentication_abilities!'
do
before
do
project
.
add_master
(
user
)
end
context
'when download'
do
let
(
:authentication_abilities
)
{
[]
}
it
'raises unauthorized with download error'
do
expect
{
pull_access_check
}.
to
raise_unauthorized
(
described_class
::
ERROR_MESSAGES
[
:download
])
end
context
'when authentication abilities include download code'
do
let
(
:authentication_abilities
)
{
[
:download_code
]
}
it
'does not raise any errors'
do
expect
{
pull_access_check
}.
not_to
raise_error
end
end
context
'when authentication abilities include build download code'
do
let
(
:authentication_abilities
)
{
[
:build_download_code
]
}
it
'does not raise any errors'
do
expect
{
pull_access_check
}.
not_to
raise_error
end
end
end
context
'when upload'
do
let
(
:authentication_abilities
)
{
[]
}
it
'raises unauthorized with push error'
do
expect
{
push_access_check
}.
to
raise_unauthorized
(
described_class
::
ERROR_MESSAGES
[
:upload
])
end
context
'when authentication abilities include push code'
do
let
(
:authentication_abilities
)
{
[
:push_code
]
}
it
'does not raise any errors'
do
expect
{
push_access_check
}.
not_to
raise_error
end
end
end
end
describe
'#check_command_disabled!'
do
describe
'#check_command_disabled!'
do
before
do
before
do
project
.
add_master
(
user
)
project
.
add_master
(
user
)
...
@@ -335,34 +402,112 @@ describe Gitlab::GitAccess do
...
@@ -335,34 +402,112 @@ describe Gitlab::GitAccess do
end
end
end
end
describe
'#check_namespace_accessibility!'
do
describe
'#check_db_accessibility!'
do
context
'when project exists'
do
context
'when in a read-only GitLab instance'
do
context
'when user can pull or push'
do
before
do
before
do
create
(
:protected_branch
,
name:
'feature'
,
project:
project
)
project
.
add_master
(
user
)
allow
(
Gitlab
::
Database
).
to
receive
(
:read_only?
)
{
true
}
end
it
{
expect
{
push_access_check
}.
to
raise_unauthorized
(
described_class
::
ERROR_MESSAGES
[
:cannot_push_to_read_only
])
}
end
end
describe
'#ensure_project_on_push!'
do
let
(
:access
)
do
described_class
.
new
(
actor
,
project
,
protocol
,
authentication_abilities:
authentication_abilities
,
project_path:
project_path
,
namespace_path:
namespace_path
,
redirected_path:
redirected_path
)
end
context
'when push'
do
let
(
:cmd
)
{
'git-receive-pack'
}
context
'when project does not exist'
do
let
(
:project_path
)
{
"nonexistent"
}
let
(
:project
)
{
nil
}
context
'when changes is _any'
do
let
(
:changes
)
{
'_any'
}
context
'when authentication abilities include push code'
do
let
(
:authentication_abilities
)
{
[
:push_code
]
}
context
'when user can create project in namespace'
do
let
(
:namespace_path
)
{
user
.
namespace
.
path
}
it
'creates a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
to
change
{
Project
.
count
}.
by
(
1
)
end
end
context
'when user cannot create project in namespace'
do
let
(
:user2
)
{
create
(
:user
)
}
let
(
:namespace_path
)
{
user2
.
namespace
.
path
}
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
end
context
'when authentication abilities do not include push code'
do
let
(
:authentication_abilities
)
{
[]
}
context
'when user can create project in namespace'
do
let
(
:namespace_path
)
{
user
.
namespace
.
path
}
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
end
end
end
it
'does not block pull or push'
do
context
'when check contains actual changes'
do
aggregate_failures
do
let
(
:changes
)
{
"
#{
Gitlab
::
Git
::
BLANK_SHA
}
570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch"
}
expect
{
push_access_check
}.
not_to
raise_error
expect
{
pull_access_check
}.
not_to
raise_error
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
end
end
end
end
context
'when project exists'
do
let
(
:changes
)
{
'_any'
}
let!
(
:project
)
{
create
(
:project
)
}
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
context
'when deploy key is used'
do
let
(
:key
)
{
create
(
:deploy_key
,
user:
user
)
}
let
(
:actor
)
{
key
}
let
(
:project_path
)
{
"nonexistent"
}
let
(
:project
)
{
nil
}
let
(
:namespace_path
)
{
user
.
namespace
.
path
}
let
(
:changes
)
{
'_any'
}
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
end
end
context
'when project does not exist'
do
context
'when pull'
do
context
'when namespace exists'
do
let
(
:cmd
)
{
'git-upload-pack'
}
context
'when user is unable to push to namespace'
do
let
(
:changes
)
{
'_any'
}
let
(
:user2
)
{
create
(
:user
)
}
let
(
:access
)
{
described_class
.
new
(
actor
,
nil
,
protocol
,
authentication_abilities:
authentication_abilities
,
redirected_path:
redirected_path
,
target_namespace:
user2
.
namespace
)
}
it
'blocks push and pull'
do
context
'when project does not exist'
do
aggregate_failures
do
let
(
:project_path
)
{
"new-project"
}
expect
{
push_access_check
}.
to
raise_not_found
let
(
:namespace_path
)
{
user
.
namespace
.
path
}
expect
{
pull_access_check
}.
to
raise_not_found
let
(
:project
)
{
nil
}
end
end
it
'does not create a new project'
do
expect
{
access
.
send
(
:ensure_project_on_push!
,
cmd
,
changes
)
}.
not_to
change
{
Project
.
count
}
end
end
end
end
end
end
...
@@ -395,7 +540,9 @@ describe Gitlab::GitAccess do
...
@@ -395,7 +540,9 @@ describe Gitlab::GitAccess do
context
'when project is public'
do
context
'when project is public'
do
let
(
:public_project
)
{
create
(
:project
,
:public
,
:repository
)
}
let
(
:public_project
)
{
create
(
:project
,
:public
,
:repository
)
}
let
(
:access
)
{
described_class
.
new
(
nil
,
public_project
,
'web'
,
authentication_abilities:
[])
}
let
(
:project_path
)
{
public_project
.
path
}
let
(
:namespace_path
)
{
public_project
.
namespace
.
path
}
let
(
:access
)
{
described_class
.
new
(
nil
,
public_project
,
'web'
,
authentication_abilities:
[
:download_code
],
project_path:
project_path
,
namespace_path:
namespace_path
)
}
context
'when repository is enabled'
do
context
'when repository is enabled'
do
it
'give access to download code'
do
it
'give access to download code'
do
...
@@ -558,17 +705,15 @@ describe Gitlab::GitAccess do
...
@@ -558,17 +705,15 @@ describe Gitlab::GitAccess do
end
end
aggregate_failures
do
aggregate_failures
do
Gitlab
::
GitAccess
::
ALL_COMMANDS
.
each
do
|
cmd
|
matrix
.
each
do
|
action
,
allowed
|
matrix
.
each
do
|
action
,
allowed
|
check
=
->
{
access
.
send
(
:check_push_access!
,
changes
[
action
])
}
check
=
->
{
access
.
send
(
:check_push_access!
,
cmd
,
changes
[
action
])
}
if
allowed
if
allowed
expect
(
&
check
).
not_to
raise_error
,
expect
(
&
check
).
not_to
raise_error
,
->
{
"expected
#{
action
}
to be allowed"
}
->
{
"expected
#{
action
}
to be allowed"
}
else
else
expect
(
&
check
).
to
raise_error
(
Gitlab
::
GitAccess
::
UnauthorizedError
),
expect
(
&
check
).
to
raise_error
(
Gitlab
::
GitAccess
::
UnauthorizedError
),
->
{
"expected
#{
action
}
to be disallowed"
}
->
{
"expected
#{
action
}
to be disallowed"
}
end
end
end
end
end
end
end
...
@@ -697,19 +842,6 @@ describe Gitlab::GitAccess do
...
@@ -697,19 +842,6 @@ describe Gitlab::GitAccess do
admin:
{
push_protected_branch:
false
,
push_all:
false
,
merge_into_protected_branch:
false
}))
admin:
{
push_protected_branch:
false
,
push_all:
false
,
merge_into_protected_branch:
false
}))
end
end
end
end
context
"when in a read-only GitLab instance"
do
before
do
create
(
:protected_branch
,
name:
'feature'
,
project:
project
)
allow
(
Gitlab
::
Database
).
to
receive
(
:read_only?
)
{
true
}
end
# Only check admin; if an admin can't do it, other roles can't either
matrix
=
permissions_matrix
[
:admin
].
dup
matrix
.
each
{
|
key
,
_
|
matrix
[
key
]
=
false
}
run_permission_checks
(
admin:
matrix
)
end
end
end
describe
'build authentication abilities'
do
describe
'build authentication abilities'
do
...
...
spec/requests/api/internal_spec.rb
View file @
1e56b3f4
...
@@ -386,32 +386,6 @@ describe API::Internal do
...
@@ -386,32 +386,6 @@ describe API::Internal do
expect
(
json_response
[
"repository_path"
]).
to
eq
(
project
.
repository
.
path_to_repo
)
expect
(
json_response
[
"repository_path"
]).
to
eq
(
project
.
repository
.
path_to_repo
)
expect
(
json_response
[
"gl_repository"
]).
to
eq
(
"project-
#{
project
.
id
}
"
)
expect
(
json_response
[
"gl_repository"
]).
to
eq
(
"project-
#{
project
.
id
}
"
)
end
end
context
'when project does not exist'
do
it
'creates a new project'
do
path
=
"
#{
user
.
namespace
.
path
}
/notexist.git"
expect
do
push_with_path
(
key
,
path
)
end
.
to
change
{
Project
.
count
}.
by
(
1
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
"status"
]).
to
be_truthy
expect
(
json_response
[
"gitaly"
][
"repository"
][
"relative_path"
]).
to
eq
(
path
)
end
it
'handles project creation failure'
do
path
=
"
#{
user
.
namespace
.
path
}
/new.git"
expect
do
push_with_path
(
key
,
path
)
end
.
not_to
change
{
Project
.
count
}
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
"status"
]).
to
be_falsey
expect
(
json_response
[
"message"
]).
to
eq
(
"Could not create project: Path new is a reserved name"
)
end
end
end
end
end
end
end
end
...
...
spec/services/projects/create_from_push_service_spec.rb
deleted
100644 → 0
View file @
839829a7
require
'spec_helper'
describe
Projects
::
CreateFromPushService
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project_path
)
{
"nonexist"
}
let
(
:namespace
)
{
user
&
.
namespace
}
let
(
:protocol
)
{
'http'
}
subject
{
described_class
.
new
(
user
,
project_path
,
namespace
,
protocol
)
}
it
'creates project'
do
expect_any_instance_of
(
Projects
::
CreateService
).
to
receive
(
:execute
).
and_call_original
expect
{
subject
.
execute
}.
to
change
{
Project
.
count
}.
by
(
1
)
end
it
'raises project creation error when project creation fails'
do
allow_any_instance_of
(
Project
).
to
receive
(
:saved?
).
and_return
(
false
)
expect
{
subject
.
execute
}.
to
raise_error
(
Gitlab
::
GitAccess
::
ProjectCreationError
)
end
context
'when user is nil'
do
let
(
:user
)
{
nil
}
subject
{
described_class
.
new
(
user
,
project_path
,
namespace
,
protocol
)
}
it
'returns nil'
do
expect_any_instance_of
(
Projects
::
CreateService
).
not_to
receive
(
:execute
)
expect
(
subject
.
execute
).
to
be_nil
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment