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
0
Merge Requests
0
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
Jérome Perrin
gitlab-ce
Commits
562fb460
Commit
562fb460
authored
Dec 08, 2017
by
Mayra Cabrera
Committed by
Douwe Maan
Dec 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow git pull/push on project redirects
parent
87300546
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
510 additions
and
52 deletions
+510
-52
GITLAB_SHELL_VERSION
GITLAB_SHELL_VERSION
+1
-1
app/models/namespace.rb
app/models/namespace.rb
+11
-0
app/models/redirect_route.rb
app/models/redirect_route.rb
+28
-0
app/models/route.rb
app/models/route.rb
+21
-5
changelogs/unreleased/35385-allow-git-pull-push-on-project-redirects.yml
...leased/35385-allow-git-pull-push-on-project-redirects.yml
+5
-0
db/migrate/20171204204233_add_permanent_to_redirect_route.rb
db/migrate/20171204204233_add_permanent_to_redirect_route.rb
+18
-0
db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb
...e/20171206221519_add_permanent_index_to_redirect_route.rb
+19
-0
db/schema.rb
db/schema.rb
+3
-1
lib/api/internal.rb
lib/api/internal.rb
+11
-2
lib/gitlab/checks/project_moved.rb
lib/gitlab/checks/project_moved.rb
+65
-0
lib/gitlab/git_access.rb
lib/gitlab/git_access.rb
+7
-10
lib/gitlab/identifier.rb
lib/gitlab/identifier.rb
+3
-2
spec/lib/gitlab/checks/project_moved_spec.rb
spec/lib/gitlab/checks/project_moved_spec.rb
+81
-0
spec/lib/gitlab/git_access_spec.rb
spec/lib/gitlab/git_access_spec.rb
+50
-10
spec/lib/gitlab/identifier_spec.rb
spec/lib/gitlab/identifier_spec.rb
+4
-0
spec/models/namespace_spec.rb
spec/models/namespace_spec.rb
+30
-0
spec/models/route_spec.rb
spec/models/route_spec.rb
+104
-0
spec/models/user_spec.rb
spec/models/user_spec.rb
+24
-0
spec/requests/api/internal_spec.rb
spec/requests/api/internal_spec.rb
+21
-17
spec/requests/git_http_spec.rb
spec/requests/git_http_spec.rb
+4
-4
No files found.
GITLAB_SHELL_VERSION
View file @
562fb460
5.10.
1
5.10.
2
app/models/namespace.rb
View file @
562fb460
...
@@ -40,6 +40,7 @@ class Namespace < ActiveRecord::Base
...
@@ -40,6 +40,7 @@ class Namespace < ActiveRecord::Base
namespace_path:
true
namespace_path:
true
validate
:nesting_level_allowed
validate
:nesting_level_allowed
validate
:allowed_path_by_redirects
delegate
:name
,
to: :owner
,
allow_nil:
true
,
prefix:
true
delegate
:name
,
to: :owner
,
allow_nil:
true
,
prefix:
true
...
@@ -257,4 +258,14 @@ class Namespace < ActiveRecord::Base
...
@@ -257,4 +258,14 @@ class Namespace < ActiveRecord::Base
Namespace
.
where
(
id:
descendants
.
select
(
:id
))
Namespace
.
where
(
id:
descendants
.
select
(
:id
))
.
update_all
(
share_with_group_lock:
true
)
.
update_all
(
share_with_group_lock:
true
)
end
end
def
allowed_path_by_redirects
return
if
path
.
nil?
errors
.
add
(
:path
,
"
#{
path
}
has been taken before. Please use another one"
)
if
namespace_previously_created_with_same_path?
end
def
namespace_previously_created_with_same_path?
RedirectRoute
.
permanent
.
exists?
(
path:
path
)
end
end
end
app/models/redirect_route.rb
View file @
562fb460
...
@@ -17,4 +17,32 @@ class RedirectRoute < ActiveRecord::Base
...
@@ -17,4 +17,32 @@ class RedirectRoute < ActiveRecord::Base
where
(
wheres
,
path
,
"
#{
sanitize_sql_like
(
path
)
}
/%"
)
where
(
wheres
,
path
,
"
#{
sanitize_sql_like
(
path
)
}
/%"
)
end
end
scope
:permanent
,
->
do
if
column_permanent_exists?
where
(
permanent:
true
)
else
none
end
end
scope
:temporary
,
->
do
if
column_permanent_exists?
where
(
permanent:
[
false
,
nil
])
else
all
end
end
default_value_for
:permanent
,
false
def
permanent
=
(
value
)
if
self
.
class
.
column_permanent_exists?
super
end
end
def
self
.
column_permanent_exists?
ActiveRecord
::
Base
.
connection
.
column_exists?
(
:redirect_routes
,
:permanent
)
end
end
end
app/models/route.rb
View file @
562fb460
...
@@ -8,6 +8,8 @@ class Route < ActiveRecord::Base
...
@@ -8,6 +8,8 @@ class Route < ActiveRecord::Base
presence:
true
,
presence:
true
,
uniqueness:
{
case_sensitive:
false
}
uniqueness:
{
case_sensitive:
false
}
validate
:ensure_permanent_paths
after_create
:delete_conflicting_redirects
after_create
:delete_conflicting_redirects
after_update
:delete_conflicting_redirects
,
if: :path_changed?
after_update
:delete_conflicting_redirects
,
if: :path_changed?
after_update
:create_redirect_for_old_path
after_update
:create_redirect_for_old_path
...
@@ -40,7 +42,7 @@ class Route < ActiveRecord::Base
...
@@ -40,7 +42,7 @@ class Route < ActiveRecord::Base
# We are not calling route.delete_conflicting_redirects here, in hopes
# We are not calling route.delete_conflicting_redirects here, in hopes
# of avoiding deadlocks. The parent (self, in this method) already
# of avoiding deadlocks. The parent (self, in this method) already
# called it, which deletes conflicts for all descendants.
# called it, which deletes conflicts for all descendants.
route
.
create_redirect
(
old_path
)
if
attributes
[
:path
]
route
.
create_redirect
(
old_path
,
permanent:
permanent_redirect?
)
if
attributes
[
:path
]
end
end
end
end
end
end
...
@@ -50,16 +52,30 @@ class Route < ActiveRecord::Base
...
@@ -50,16 +52,30 @@ class Route < ActiveRecord::Base
end
end
def
conflicting_redirects
def
conflicting_redirects
RedirectRoute
.
matching_path_and_descendants
(
path
)
RedirectRoute
.
temporary
.
matching_path_and_descendants
(
path
)
end
end
def
create_redirect
(
path
)
def
create_redirect
(
path
,
permanent:
false
)
RedirectRoute
.
create
(
source:
source
,
path:
path
)
RedirectRoute
.
create
(
source:
source
,
path:
path
,
permanent:
permanent
)
end
end
private
private
def
create_redirect_for_old_path
def
create_redirect_for_old_path
create_redirect
(
path_was
)
if
path_changed?
create_redirect
(
path_was
,
permanent:
permanent_redirect?
)
if
path_changed?
end
def
permanent_redirect?
source_type
!=
"Project"
end
def
ensure_permanent_paths
return
if
path
.
nil?
errors
.
add
(
:path
,
"
#{
path
}
has been taken before. Please use another one"
)
if
conflicting_redirect_exists?
end
def
conflicting_redirect_exists?
RedirectRoute
.
permanent
.
matching_path_and_descendants
(
path
).
exists?
end
end
end
end
changelogs/unreleased/35385-allow-git-pull-push-on-project-redirects.yml
0 → 100644
View file @
562fb460
---
title
:
Allow git pull/push on group/user/project redirects
merge_request
:
15670
author
:
type
:
added
db/migrate/20171204204233_add_permanent_to_redirect_route.rb
0 → 100644
View file @
562fb460
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
AddPermanentToRedirectRoute
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
disable_ddl_transaction!
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
def
up
add_column
(
:redirect_routes
,
:permanent
,
:boolean
)
end
def
down
remove_column
(
:redirect_routes
,
:permanent
)
end
end
db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb
0 → 100644
View file @
562fb460
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
AddPermanentIndexToRedirectRoute
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_concurrent_index
(
:redirect_routes
,
:permanent
)
end
def
down
remove_concurrent_index
(
:redirect_routes
,
:permanent
)
if
index_exists?
(
:redirect_routes
,
:permanent
)
end
end
db/schema.rb
View file @
562fb460
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
2017120
5190711
)
do
ActiveRecord
::
Schema
.
define
(
version:
2017120
6221519
)
do
# These are extensions that must be enabled in order to support this database
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
enable_extension
"plpgsql"
...
@@ -1526,10 +1526,12 @@ ActiveRecord::Schema.define(version: 20171205190711) do
...
@@ -1526,10 +1526,12 @@ ActiveRecord::Schema.define(version: 20171205190711) do
t
.
string
"path"
,
null:
false
t
.
string
"path"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
datetime
"updated_at"
,
null:
false
t
.
datetime
"updated_at"
,
null:
false
t
.
boolean
"permanent"
end
end
add_index
"redirect_routes"
,
[
"path"
],
name:
"index_redirect_routes_on_path"
,
unique:
true
,
using: :btree
add_index
"redirect_routes"
,
[
"path"
],
name:
"index_redirect_routes_on_path"
,
unique:
true
,
using: :btree
add_index
"redirect_routes"
,
[
"path"
],
name:
"index_redirect_routes_on_path_text_pattern_ops"
,
using: :btree
,
opclasses:
{
"path"
=>
"varchar_pattern_ops"
}
add_index
"redirect_routes"
,
[
"path"
],
name:
"index_redirect_routes_on_path_text_pattern_ops"
,
using: :btree
,
opclasses:
{
"path"
=>
"varchar_pattern_ops"
}
add_index
"redirect_routes"
,
[
"permanent"
],
name:
"index_redirect_routes_on_permanent"
,
using: :btree
add_index
"redirect_routes"
,
[
"source_type"
,
"source_id"
],
name:
"index_redirect_routes_on_source_type_and_source_id"
,
using: :btree
add_index
"redirect_routes"
,
[
"source_type"
,
"source_id"
],
name:
"index_redirect_routes_on_source_type_and_source_id"
,
using: :btree
create_table
"releases"
,
force: :cascade
do
|
t
|
create_table
"releases"
,
force: :cascade
do
|
t
|
...
...
lib/api/internal.rb
View file @
562fb460
...
@@ -4,6 +4,7 @@ module API
...
@@ -4,6 +4,7 @@ module API
before
{
authenticate_by_gitlab_shell_token!
}
before
{
authenticate_by_gitlab_shell_token!
}
helpers
::
API
::
Helpers
::
InternalHelpers
helpers
::
API
::
Helpers
::
InternalHelpers
helpers
::
Gitlab
::
Identifier
namespace
'internal'
do
namespace
'internal'
do
# Check if git command is allowed to project
# Check if git command is allowed to project
...
@@ -176,17 +177,25 @@ module API
...
@@ -176,17 +177,25 @@ module API
post
'/post_receive'
do
post
'/post_receive'
do
status
200
status
200
PostReceive
.
perform_async
(
params
[
:gl_repository
],
params
[
:identifier
],
PostReceive
.
perform_async
(
params
[
:gl_repository
],
params
[
:identifier
],
params
[
:changes
])
params
[
:changes
])
broadcast_message
=
BroadcastMessage
.
current
&
.
last
&
.
message
broadcast_message
=
BroadcastMessage
.
current
&
.
last
&
.
message
reference_counter_decreased
=
Gitlab
::
ReferenceCounter
.
new
(
params
[
:gl_repository
]).
decrease
reference_counter_decreased
=
Gitlab
::
ReferenceCounter
.
new
(
params
[
:gl_repository
]).
decrease
{
output
=
{
merge_request_urls:
merge_request_urls
,
merge_request_urls:
merge_request_urls
,
broadcast_message:
broadcast_message
,
broadcast_message:
broadcast_message
,
reference_counter_decreased:
reference_counter_decreased
reference_counter_decreased:
reference_counter_decreased
}
}
project
=
Gitlab
::
GlRepository
.
parse
(
params
[
:gl_repository
]).
first
user
=
identify
(
params
[
:identifier
])
redirect_message
=
Gitlab
::
Checks
::
ProjectMoved
.
fetch_redirect_message
(
user
.
id
,
project
.
id
)
if
redirect_message
output
[
:redirected_message
]
=
redirect_message
end
output
end
end
end
end
end
end
...
...
lib/gitlab/checks/project_moved.rb
0 → 100644
View file @
562fb460
module
Gitlab
module
Checks
class
ProjectMoved
REDIRECT_NAMESPACE
=
"redirect_namespace"
.
freeze
def
initialize
(
project
,
user
,
redirected_path
,
protocol
)
@project
=
project
@user
=
user
@redirected_path
=
redirected_path
@protocol
=
protocol
end
def
self
.
fetch_redirect_message
(
user_id
,
project_id
)
redirect_key
=
redirect_message_key
(
user_id
,
project_id
)
Gitlab
::
Redis
::
SharedState
.
with
do
|
redis
|
message
=
redis
.
get
(
redirect_key
)
redis
.
del
(
redirect_key
)
message
end
end
def
add_redirect_message
Gitlab
::
Redis
::
SharedState
.
with
do
|
redis
|
key
=
self
.
class
.
redirect_message_key
(
user
.
id
,
project
.
id
)
redis
.
setex
(
key
,
5
.
minutes
,
redirect_message
)
end
end
def
redirect_message
(
rejected:
false
)
<<~
MESSAGE
.
strip_heredoc
Project '
#{
redirected_path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote:
#{
remote_url_message
(
rejected
)
}
MESSAGE
end
def
permanent_redirect?
RedirectRoute
.
permanent
.
exists?
(
path:
redirected_path
)
end
private
attr_reader
:project
,
:redirected_path
,
:protocol
,
:user
def
self
.
redirect_message_key
(
user_id
,
project_id
)
"
#{
REDIRECT_NAMESPACE
}
:
#{
user_id
}
:
#{
project_id
}
"
end
def
remote_url_message
(
rejected
)
if
rejected
"git remote set-url origin
#{
url
}
and try again."
else
"git remote set-url origin
#{
url
}
"
end
end
def
url
protocol
==
'ssh'
?
project
.
ssh_url_to_repo
:
project
.
http_url_to_repo
end
end
end
end
lib/gitlab/git_access.rb
View file @
562fb460
...
@@ -102,18 +102,15 @@ module Gitlab
...
@@ -102,18 +102,15 @@ module Gitlab
end
end
def
check_project_moved!
def
check_project_moved!
return
unless
redirected_path
return
if
redirected_path
.
nil?
url
=
protocol
==
'ssh'
?
project
.
ssh_url_to_repo
:
project
.
http_url_to_repo
project_moved
=
Checks
::
ProjectMoved
.
new
(
project
,
user
,
redirected_path
,
protocol
)
message
=
<<-
MESSAGE
.
strip_heredoc
Project '
#{
redirected_path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote and try again:
if
project_moved
.
permanent_redirect?
project_moved
.
add_redirect_message
git remote set-url origin
#{
url
}
else
MESSAGE
raise
ProjectMovedError
,
project_moved
.
redirect_message
(
rejected:
true
)
end
raise
ProjectMovedError
,
message
end
end
def
check_command_disabled!
(
cmd
)
def
check_command_disabled!
(
cmd
)
...
...
lib/gitlab/identifier.rb
View file @
562fb460
...
@@ -2,9 +2,8 @@
...
@@ -2,9 +2,8 @@
# key-13 or user-36 or last commit
# key-13 or user-36 or last commit
module
Gitlab
module
Gitlab
module
Identifier
module
Identifier
def
identify
(
identifier
,
project
,
newrev
)
def
identify
(
identifier
,
project
=
nil
,
newrev
=
nil
)
if
identifier
.
blank?
if
identifier
.
blank?
# Local push from gitlab
identify_using_commit
(
project
,
newrev
)
identify_using_commit
(
project
,
newrev
)
elsif
identifier
=~
/\Auser-\d+\Z/
elsif
identifier
=~
/\Auser-\d+\Z/
# git push over http
# git push over http
...
@@ -17,6 +16,8 @@ module Gitlab
...
@@ -17,6 +16,8 @@ module Gitlab
# Tries to identify a user based on a commit SHA.
# Tries to identify a user based on a commit SHA.
def
identify_using_commit
(
project
,
ref
)
def
identify_using_commit
(
project
,
ref
)
return
if
project
.
nil?
&&
ref
.
nil?
commit
=
project
.
commit
(
ref
)
commit
=
project
.
commit
(
ref
)
return
if
!
commit
||
!
commit
.
author_email
return
if
!
commit
||
!
commit
.
author_email
...
...
spec/lib/gitlab/checks/project_moved_spec.rb
0 → 100644
View file @
562fb460
require
'rails_helper'
describe
Gitlab
::
Checks
::
ProjectMoved
,
:clean_gitlab_redis_shared_state
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
describe
'.fetch_redirct_message'
do
context
'with a redirect message queue'
do
it
'should return the redirect message'
do
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
project_moved
.
add_redirect_message
expect
(
described_class
.
fetch_redirect_message
(
user
.
id
,
project
.
id
)).
to
eq
(
project_moved
.
redirect_message
)
end
it
'should delete the redirect message from redis'
do
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
project_moved
.
add_redirect_message
expect
(
Gitlab
::
Redis
::
SharedState
.
with
{
|
redis
|
redis
.
get
(
"redirect_namespace:
#{
user
.
id
}
:
#{
project
.
id
}
"
)
}).
not_to
be_nil
described_class
.
fetch_redirect_message
(
user
.
id
,
project
.
id
)
expect
(
Gitlab
::
Redis
::
SharedState
.
with
{
|
redis
|
redis
.
get
(
"redirect_namespace:
#{
user
.
id
}
:
#{
project
.
id
}
"
)
}).
to
be_nil
end
end
context
'with no redirect message queue'
do
it
'should return nil'
do
expect
(
described_class
.
fetch_redirect_message
(
1
,
2
)).
to
be_nil
end
end
end
describe
'#add_redirect_message'
do
it
'should queue a redirect message'
do
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
expect
(
project_moved
.
add_redirect_message
).
to
eq
(
"OK"
)
end
end
describe
'#redirect_message'
do
context
'when the push is rejected'
do
it
'should return a redirect message telling the user to try again'
do
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
message
=
"Project 'foo/bar' was moved to '
#{
project
.
full_path
}
'."
+
"
\n\n
Please update your Git remote:"
+
"
\n\n
git remote set-url origin
#{
project
.
http_url_to_repo
}
and try again.
\n
"
expect
(
project_moved
.
redirect_message
(
rejected:
true
)).
to
eq
(
message
)
end
end
context
'when the push is not rejected'
do
it
'should return a redirect message'
do
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
message
=
"Project 'foo/bar' was moved to '
#{
project
.
full_path
}
'."
+
"
\n\n
Please update your Git remote:"
+
"
\n\n
git remote set-url origin
#{
project
.
http_url_to_repo
}
\n
"
expect
(
project_moved
.
redirect_message
).
to
eq
(
message
)
end
end
end
describe
'#permanent_redirect?'
do
context
'with a permanent RedirectRoute'
do
it
'should return true'
do
project
.
route
.
create_redirect
(
'foo/bar'
,
permanent:
true
)
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
expect
(
project_moved
.
permanent_redirect?
).
to
be_truthy
end
end
context
'without a permanent RedirectRoute'
do
it
'should return false'
do
project
.
route
.
create_redirect
(
'foo/bar'
)
project_moved
=
described_class
.
new
(
project
,
user
,
'foo/bar'
,
'http'
)
expect
(
project_moved
.
permanent_redirect?
).
to
be_falsy
end
end
end
end
spec/lib/gitlab/git_access_spec.rb
View file @
562fb460
...
@@ -193,7 +193,15 @@ describe Gitlab::GitAccess do
...
@@ -193,7 +193,15 @@ describe Gitlab::GitAccess do
let
(
:actor
)
{
build
(
:rsa_deploy_key_2048
,
user:
user
)
}
let
(
:actor
)
{
build
(
:rsa_deploy_key_2048
,
user:
user
)
}
end
end
describe
'#check_project_moved!'
do
shared_examples
'check_project_moved'
do
it
'enqueues a redirected message'
do
push_access_check
expect
(
Gitlab
::
Checks
::
ProjectMoved
.
fetch_redirect_message
(
user
.
id
,
project
.
id
)).
not_to
be_nil
end
end
describe
'#check_project_moved!'
,
:clean_gitlab_redis_shared_state
do
before
do
before
do
project
.
add_master
(
user
)
project
.
add_master
(
user
)
end
end
...
@@ -207,7 +215,40 @@ describe Gitlab::GitAccess do
...
@@ -207,7 +215,40 @@ describe Gitlab::GitAccess do
end
end
end
end
context
'when a redirect was followed to find the project'
do
context
'when a permanent redirect and ssh protocol'
do
let
(
:redirected_path
)
{
'some/other-path'
}
before
do
allow_any_instance_of
(
Gitlab
::
Checks
::
ProjectMoved
).
to
receive
(
:permanent_redirect?
).
and_return
(
true
)
end
it
'allows push and pull access'
do
aggregate_failures
do
expect
{
push_access_check
}.
not_to
raise_error
end
end
it_behaves_like
'check_project_moved'
end
context
'with a permanent redirect and http protocol'
do
let
(
:redirected_path
)
{
'some/other-path'
}
let
(
:protocol
)
{
'http'
}
before
do
allow_any_instance_of
(
Gitlab
::
Checks
::
ProjectMoved
).
to
receive
(
:permanent_redirect?
).
and_return
(
true
)
end
it
'allows_push and pull access'
do
aggregate_failures
do
expect
{
push_access_check
}.
not_to
raise_error
end
end
it_behaves_like
'check_project_moved'
end
context
'with a temporal redirect and ssh protocol'
do
let
(
:redirected_path
)
{
'some/other-path'
}
let
(
:redirected_path
)
{
'some/other-path'
}
it
'blocks push and pull access'
do
it
'blocks push and pull access'
do
...
@@ -219,16 +260,15 @@ describe Gitlab::GitAccess do
...
@@ -219,16 +260,15 @@ describe Gitlab::GitAccess do
expect
{
pull_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
ssh_url_to_repo
}
/
)
expect
{
pull_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
ssh_url_to_repo
}
/
)
end
end
end
end
end
context
'http protocol'
do
context
'with a temporal redirect and http protocol'
do
let
(
:protocol
)
{
'http'
}
let
(
:redirected_path
)
{
'some/other-path'
}
let
(
:protocol
)
{
'http'
}
it
'includes the path to the project using HTTP'
do
it
'does not allow to push and pull access'
do
aggregate_failures
do
expect
{
push_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
http_url_to_repo
}
/
)
expect
{
push_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
http_url_to_repo
}
/
)
expect
{
pull_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
http_url_to_repo
}
/
)
expect
{
pull_access_check
}.
to
raise_error
(
described_class
::
ProjectMovedError
,
/git remote set-url origin
#{
project
.
http_url_to_repo
}
/
)
end
end
end
end
end
end
end
end
...
...
spec/lib/gitlab/identifier_spec.rb
View file @
562fb460
...
@@ -70,6 +70,10 @@ describe Gitlab::Identifier do
...
@@ -70,6 +70,10 @@ describe Gitlab::Identifier do
expect
(
identifier
.
identify_using_commit
(
project
,
'123'
)).
to
eq
(
user
)
expect
(
identifier
.
identify_using_commit
(
project
,
'123'
)).
to
eq
(
user
)
end
end
end
end
it
'returns nil if the project & ref are not present'
do
expect
(
identifier
.
identify_using_commit
(
nil
,
nil
)).
to
be_nil
end
end
end
describe
'#identify_using_user'
do
describe
'#identify_using_user'
do
...
...
spec/models/namespace_spec.rb
View file @
562fb460
...
@@ -559,4 +559,34 @@ describe Namespace do
...
@@ -559,4 +559,34 @@ describe Namespace do
end
end
end
end
end
end
describe
"#allowed_path_by_redirects"
do
let
(
:namespace1
)
{
create
(
:namespace
,
path:
'foo'
)
}
context
"when the path has been taken before"
do
before
do
namespace1
.
path
=
'bar'
namespace1
.
save!
end
it
'should be invalid'
do
namespace2
=
build
(
:group
,
path:
'foo'
)
expect
(
namespace2
).
to
be_invalid
end
it
'should return an error on path'
do
namespace2
=
build
(
:group
,
path:
'foo'
)
namespace2
.
valid?
expect
(
namespace2
.
errors
.
messages
[
:path
].
first
).
to
eq
(
'foo has been taken before. Please use another one'
)
end
end
context
"when the path has not been taken before"
do
it
'should be valid'
do
expect
(
RedirectRoute
.
count
).
to
eq
(
0
)
namespace
=
build
(
:namespace
)
expect
(
namespace
).
to
be_valid
end
end
end
end
end
spec/models/route_spec.rb
View file @
562fb460
...
@@ -87,6 +87,7 @@ describe Route do
...
@@ -87,6 +87,7 @@ describe Route do
end
end
context
'when conflicting redirects exist'
do
context
'when conflicting redirects exist'
do
let
(
:route
)
{
create
(
:project
).
route
}
let!
(
:conflicting_redirect1
)
{
route
.
create_redirect
(
'bar/test'
)
}
let!
(
:conflicting_redirect1
)
{
route
.
create_redirect
(
'bar/test'
)
}
let!
(
:conflicting_redirect2
)
{
route
.
create_redirect
(
'bar/test/foo'
)
}
let!
(
:conflicting_redirect2
)
{
route
.
create_redirect
(
'bar/test/foo'
)
}
let!
(
:conflicting_redirect3
)
{
route
.
create_redirect
(
'gitlab-org'
)
}
let!
(
:conflicting_redirect3
)
{
route
.
create_redirect
(
'gitlab-org'
)
}
...
@@ -141,11 +142,50 @@ describe Route do
...
@@ -141,11 +142,50 @@ describe Route do
expect
(
redirect_route
.
source
).
to
eq
(
route
.
source
)
expect
(
redirect_route
.
source
).
to
eq
(
route
.
source
)
expect
(
redirect_route
.
path
).
to
eq
(
'foo'
)
expect
(
redirect_route
.
path
).
to
eq
(
'foo'
)
end
end
context
'when the source is a Project'
do
it
'creates a temporal RedirectRoute'
do
project
=
create
(
:project
)
route
=
project
.
route
redirect_route
=
route
.
create_redirect
(
'foo'
)
expect
(
redirect_route
.
permanent?
).
to
be_falsy
end
end
context
'when the source is not a project'
do
it
'creates a permanent RedirectRoute'
do
redirect_route
=
route
.
create_redirect
(
'foo'
,
permanent:
true
)
expect
(
redirect_route
.
permanent?
).
to
be_truthy
end
end
end
end
describe
'#delete_conflicting_redirects'
do
describe
'#delete_conflicting_redirects'
do
context
'with permanent redirect'
do
it
'does not delete the redirect'
do
route
.
create_redirect
(
"
#{
route
.
path
}
/foo"
,
permanent:
true
)
expect
do
route
.
delete_conflicting_redirects
end
.
not_to
change
{
RedirectRoute
.
count
}
end
end
context
'with temporal redirect'
do
let
(
:route
)
{
create
(
:project
).
route
}
it
'deletes the redirect'
do
route
.
create_redirect
(
"
#{
route
.
path
}
/foo"
)
expect
do
route
.
delete_conflicting_redirects
end
.
to
change
{
RedirectRoute
.
count
}.
by
(
-
1
)
end
end
context
'when a redirect route with the same path exists'
do
context
'when a redirect route with the same path exists'
do
context
'when the redirect route has matching case'
do
context
'when the redirect route has matching case'
do
let
(
:route
)
{
create
(
:project
).
route
}
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
)
}
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
)
}
it
'deletes the redirect'
do
it
'deletes the redirect'
do
...
@@ -169,6 +209,7 @@ describe Route do
...
@@ -169,6 +209,7 @@ describe Route do
end
end
context
'when the redirect route is differently cased'
do
context
'when the redirect route is differently cased'
do
let
(
:route
)
{
create
(
:project
).
route
}
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
.
upcase
)
}
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
.
upcase
)
}
it
'deletes the redirect'
do
it
'deletes the redirect'
do
...
@@ -185,7 +226,32 @@ describe Route do
...
@@ -185,7 +226,32 @@ describe Route do
expect
(
route
.
conflicting_redirects
).
to
be_an
(
ActiveRecord
::
Relation
)
expect
(
route
.
conflicting_redirects
).
to
be_an
(
ActiveRecord
::
Relation
)
end
end
context
'with permanent redirects'
do
it
'does not return anything'
do
route
.
create_redirect
(
"
#{
route
.
path
}
/foo"
,
permanent:
true
)
route
.
create_redirect
(
"
#{
route
.
path
}
/foo/bar"
,
permanent:
true
)
route
.
create_redirect
(
"
#{
route
.
path
}
/baz/quz"
,
permanent:
true
)
expect
(
route
.
conflicting_redirects
).
to
be_empty
end
end
context
'with temporal redirects'
do
let
(
:route
)
{
create
(
:project
).
route
}
it
'returns the redirect routes'
do
route
=
create
(
:project
).
route
redirect1
=
route
.
create_redirect
(
"
#{
route
.
path
}
/foo"
)
redirect2
=
route
.
create_redirect
(
"
#{
route
.
path
}
/foo/bar"
)
redirect3
=
route
.
create_redirect
(
"
#{
route
.
path
}
/baz/quz"
)
expect
(
route
.
conflicting_redirects
).
to
match_array
([
redirect1
,
redirect2
,
redirect3
])
end
end
context
'when a redirect route with the same path exists'
do
context
'when a redirect route with the same path exists'
do
let
(
:route
)
{
create
(
:project
).
route
}
context
'when the redirect route has matching case'
do
context
'when the redirect route has matching case'
do
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
)
}
let!
(
:redirect1
)
{
route
.
create_redirect
(
route
.
path
)
}
...
@@ -214,4 +280,42 @@ describe Route do
...
@@ -214,4 +280,42 @@ describe Route do
end
end
end
end
end
end
describe
"#conflicting_redirect_exists?"
do
context
'when a conflicting redirect exists'
do
let
(
:group1
)
{
create
(
:group
,
path:
'foo'
)
}
let
(
:group2
)
{
create
(
:group
,
path:
'baz'
)
}
it
'should not be saved'
do
group1
.
path
=
'bar'
group1
.
save
group2
.
path
=
'foo'
expect
(
group2
.
save
).
to
be_falsy
end
it
'should return an error on path'
do
group1
.
path
=
'bar'
group1
.
save
group2
.
path
=
'foo'
group2
.
valid?
expect
(
group2
.
errors
[
"route.path"
].
first
).
to
eq
(
'foo has been taken before. Please use another one'
)
end
end
context
'when a conflicting redirect does not exist'
do
let
(
:project1
)
{
create
(
:project
,
path:
'foo'
)
}
let
(
:project2
)
{
create
(
:project
,
path:
'baz'
)
}
it
'should be saved'
do
project1
.
path
=
'bar'
project1
.
save
project2
.
path
=
'foo'
expect
(
project2
.
save
).
to
be_truthy
end
end
end
end
end
spec/models/user_spec.rb
View file @
562fb460
...
@@ -2592,4 +2592,28 @@ describe User do
...
@@ -2592,4 +2592,28 @@ describe User do
include_examples
'max member access for groups'
include_examples
'max member access for groups'
end
end
end
end
describe
"#username_previously_taken?"
do
let
(
:user1
)
{
create
(
:user
,
username:
'foo'
)
}
context
'when the username has been taken before'
do
before
do
user1
.
username
=
'bar'
user1
.
save!
end
it
'should raise an ActiveRecord::RecordInvalid exception'
do
user2
=
build
(
:user
,
username:
'foo'
)
expect
{
user2
.
save!
}.
to
raise_error
(
ActiveRecord
::
RecordInvalid
,
/Path foo has been taken before/
)
end
end
context
'when the username has not been taken before'
do
it
'should be valid'
do
expect
(
RedirectRoute
.
count
).
to
eq
(
0
)
user2
=
build
(
:user
,
username:
'baz'
)
expect
(
user2
).
to
be_valid
end
end
end
end
end
spec/requests/api/internal_spec.rb
View file @
562fb460
...
@@ -537,16 +537,7 @@ describe API::Internal do
...
@@ -537,16 +537,7 @@ describe API::Internal do
context
'the project path was changed'
do
context
'the project path was changed'
do
let!
(
:old_path_to_repo
)
{
project
.
repository
.
path_to_repo
}
let!
(
:old_path_to_repo
)
{
project
.
repository
.
path_to_repo
}
let!
(
:old_full_path
)
{
project
.
full_path
}
let!
(
:repository
)
{
project
.
repository
}
let
(
:project_moved_message
)
do
<<-
MSG
.
strip_heredoc
Project '
#{
old_full_path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote and try again:
git remote set-url origin
#{
project
.
ssh_url_to_repo
}
MSG
end
before
do
before
do
project
.
team
<<
[
user
,
:developer
]
project
.
team
<<
[
user
,
:developer
]
...
@@ -555,19 +546,17 @@ describe API::Internal do
...
@@ -555,19 +546,17 @@ describe API::Internal do
end
end
it
'rejects the push'
do
it
'rejects the push'
do
push
_with_path
(
key
,
old_path_to_repo
)
push
(
key
,
project
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'status'
]).
to
be_falsey
expect
(
json_response
[
'status'
]).
to
be_falsy
expect
(
json_response
[
'message'
]).
to
eq
(
project_moved_message
)
end
end
it
'rejects the SSH pull'
do
it
'rejects the SSH pull'
do
pull
_with_path
(
key
,
old_path_to_repo
)
pull
(
key
,
project
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'status'
]).
to
be_falsey
expect
(
json_response
[
'status'
]).
to
be_falsy
expect
(
json_response
[
'message'
]).
to
eq
(
project_moved_message
)
end
end
end
end
end
end
...
@@ -695,7 +684,7 @@ describe API::Internal do
...
@@ -695,7 +684,7 @@ describe API::Internal do
# end
# end
# end
# end
describe
'POST /internal/post_receive'
do
describe
'POST /internal/post_receive'
,
:clean_gitlab_redis_shared_state
do
let
(
:identifier
)
{
'key-123'
}
let
(
:identifier
)
{
'key-123'
}
let
(
:valid_params
)
do
let
(
:valid_params
)
do
...
@@ -713,6 +702,8 @@ describe API::Internal do
...
@@ -713,6 +702,8 @@ describe API::Internal do
before
do
before
do
project
.
team
<<
[
user
,
:developer
]
project
.
team
<<
[
user
,
:developer
]
allow
(
described_class
).
to
receive
(
:identify
).
and_return
(
user
)
allow_any_instance_of
(
Gitlab
::
Identifier
).
to
receive
(
:identify
).
and_return
(
user
)
end
end
it
'enqueues a PostReceive worker job'
do
it
'enqueues a PostReceive worker job'
do
...
@@ -780,6 +771,19 @@ describe API::Internal do
...
@@ -780,6 +771,19 @@ describe API::Internal do
expect
(
json_response
[
'broadcast_message'
]).
to
eq
(
nil
)
expect
(
json_response
[
'broadcast_message'
]).
to
eq
(
nil
)
end
end
end
end
context
'with a redirected data'
do
it
'returns redirected message on the response'
do
project_moved
=
Gitlab
::
Checks
::
ProjectMoved
.
new
(
project
,
user
,
'foo/baz'
,
'http'
)
project_moved
.
add_redirect_message
post
api
(
"/internal/post_receive"
),
valid_params
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
"redirected_message"
]).
to
be_present
expect
(
json_response
[
"redirected_message"
]).
to
eq
(
project_moved
.
redirect_message
)
end
end
end
end
describe
'POST /internal/pre_receive'
do
describe
'POST /internal/pre_receive'
do
...
...
spec/requests/git_http_spec.rb
View file @
562fb460
...
@@ -324,9 +324,9 @@ describe 'Git HTTP requests' do
...
@@ -324,9 +324,9 @@ describe 'Git HTTP requests' do
<<-
MSG
.
strip_heredoc
<<-
MSG
.
strip_heredoc
Project '
#{
redirect
.
path
}
' was moved to '
#{
project
.
full_path
}
'.
Project '
#{
redirect
.
path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote
and try again
:
Please update your Git remote:
git remote set-url origin
#{
project
.
http_url_to_repo
}
git remote set-url origin
#{
project
.
http_url_to_repo
}
and try again.
MSG
MSG
end
end
...
@@ -533,9 +533,9 @@ describe 'Git HTTP requests' do
...
@@ -533,9 +533,9 @@ describe 'Git HTTP requests' do
<<-
MSG
.
strip_heredoc
<<-
MSG
.
strip_heredoc
Project '
#{
redirect
.
path
}
' was moved to '
#{
project
.
full_path
}
'.
Project '
#{
redirect
.
path
}
' was moved to '
#{
project
.
full_path
}
'.
Please update your Git remote
and try again
:
Please update your Git remote:
git remote set-url origin
#{
project
.
http_url_to_repo
}
git remote set-url origin
#{
project
.
http_url_to_repo
}
and try again.
MSG
MSG
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