BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
13cbc82a
Commit
13cbc82a
authored
May 28, 2014
by
Dmitriy Zaporozhets
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master-create-group-projects' into 'master'
Master can create group projects It also includes Project transfer refactoring Fixes #1284
parents
64b1956b
cea0fc1d
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
111 additions
and
195 deletions
+111
-195
projects_controller.rb
app/controllers/projects_controller.rb
+1
-1
namespaces_helper.rb
app/helpers/namespaces_helper.rb
+1
-1
ability.rb
app/models/ability.rb
+8
-0
group.rb
app/models/group.rb
+4
-0
project.rb
app/models/project.rb
+0
-4
user.rb
app/models/user.rb
+2
-0
project_transfer_service.rb
app/services/project_transfer_service.rb
+0
-46
create_service.rb
app/services/projects/create_service.rb
+1
-1
transfer_service.rb
app/services/projects/transfer_service.rb
+61
-12
_projects.html.haml
app/views/groups/_projects.html.haml
+1
-1
permissions.md
doc/permissions/permissions.md
+1
-1
groups.rb
lib/api/groups.rb
+5
-3
enable_namespaces.rake
lib/tasks/gitlab/enable_namespaces.rake
+0
-111
project_spec.rb
spec/models/project_spec.rb
+0
-1
groups_spec.rb
spec/requests/api/groups_spec.rb
+2
-2
transfer_service_spec.rb
spec/services/projects/transfer_service_spec.rb
+24
-11
No files found.
app/controllers/projects_controller.rb
View file @
13cbc82a
...
@@ -46,7 +46,7 @@ class ProjectsController < ApplicationController
...
@@ -46,7 +46,7 @@ class ProjectsController < ApplicationController
end
end
def
transfer
def
transfer
::
Projects
::
TransferService
.
new
(
project
,
current_user
,
params
).
execute
::
Projects
::
TransferService
.
new
(
project
,
current_user
,
params
[
:project
]
).
execute
end
end
def
show
def
show
...
...
app/helpers/namespaces_helper.rb
View file @
13cbc82a
module
NamespacesHelper
module
NamespacesHelper
def
namespaces_options
(
selected
=
:current_user
,
scope
=
:default
)
def
namespaces_options
(
selected
=
:current_user
,
scope
=
:default
)
groups
=
current_user
.
owned_groups
groups
=
current_user
.
owned_groups
+
current_user
.
masters_groups
users
=
[
current_user
.
namespace
]
users
=
[
current_user
.
namespace
]
group_opts
=
[
"Groups"
,
groups
.
sort_by
(
&
:human_name
).
map
{
|
g
|
[
g
.
human_name
,
g
.
id
]}
]
group_opts
=
[
"Groups"
,
groups
.
sort_by
(
&
:human_name
).
map
{
|
g
|
[
g
.
human_name
,
g
.
id
]}
]
...
...
app/models/ability.rb
View file @
13cbc82a
...
@@ -188,6 +188,13 @@ class Ability
...
@@ -188,6 +188,13 @@ class Ability
rules
<<
:read_group
rules
<<
:read_group
end
end
# Only group masters and group owners can create new projects in group
if
group
.
has_master?
(
user
)
||
group
.
has_owner?
(
user
)
||
user
.
admin?
rules
+=
[
:create_projects
,
]
end
# Only group owner and administrators can manage group
# Only group owner and administrators can manage group
if
group
.
has_owner?
(
user
)
||
user
.
admin?
if
group
.
has_owner?
(
user
)
||
user
.
admin?
rules
+=
[
rules
+=
[
...
@@ -205,6 +212,7 @@ class Ability
...
@@ -205,6 +212,7 @@ class Ability
# Only namespace owner and administrators can manage it
# Only namespace owner and administrators can manage it
if
namespace
.
owner
==
user
||
user
.
admin?
if
namespace
.
owner
==
user
||
user
.
admin?
rules
+=
[
rules
+=
[
:create_projects
,
:manage_namespace
:manage_namespace
]
]
end
end
...
...
app/models/group.rb
View file @
13cbc82a
...
@@ -60,6 +60,10 @@ class Group < Namespace
...
@@ -60,6 +60,10 @@ class Group < Namespace
owners
.
include?
(
user
)
owners
.
include?
(
user
)
end
end
def
has_master?
(
user
)
members
.
masters
.
where
(
user_id:
user
).
any?
end
def
last_owner?
(
user
)
def
last_owner?
(
user
)
has_owner?
(
user
)
&&
owners
.
size
==
1
has_owner?
(
user
)
&&
owners
.
size
==
1
end
end
...
...
app/models/project.rb
View file @
13cbc82a
...
@@ -387,10 +387,6 @@ class Project < ActiveRecord::Base
...
@@ -387,10 +387,6 @@ class Project < ActiveRecord::Base
end
end
end
end
def
transfer
(
new_namespace
)
ProjectTransferService
.
new
.
transfer
(
self
,
new_namespace
)
end
def
execute_hooks
(
data
,
hooks_scope
=
:push_hooks
)
def
execute_hooks
(
data
,
hooks_scope
=
:push_hooks
)
hooks
.
send
(
hooks_scope
).
each
do
|
hook
|
hooks
.
send
(
hooks_scope
).
each
do
|
hook
|
hook
.
async_execute
(
data
)
hook
.
async_execute
(
data
)
...
...
app/models/user.rb
View file @
13cbc82a
...
@@ -90,6 +90,8 @@ class User < ActiveRecord::Base
...
@@ -90,6 +90,8 @@ class User < ActiveRecord::Base
has_many
:users_groups
,
dependent: :destroy
has_many
:users_groups
,
dependent: :destroy
has_many
:groups
,
through: :users_groups
has_many
:groups
,
through: :users_groups
has_many
:owned_groups
,
->
{
where
users_groups:
{
group_access:
UsersGroup
::
OWNER
}
},
through: :users_groups
,
source: :group
has_many
:owned_groups
,
->
{
where
users_groups:
{
group_access:
UsersGroup
::
OWNER
}
},
through: :users_groups
,
source: :group
has_many
:masters_groups
,
->
{
where
users_groups:
{
group_access:
UsersGroup
::
MASTER
}
},
through: :users_groups
,
source: :group
# Projects
# Projects
has_many
:groups_projects
,
through: :groups
,
source: :projects
has_many
:groups_projects
,
through: :groups
,
source: :projects
has_many
:personal_projects
,
through: :namespace
,
source: :projects
has_many
:personal_projects
,
through: :namespace
,
source: :projects
...
...
app/services/project_transfer_service.rb
deleted
100644 → 0
View file @
64b1956b
# ProjectTransferService class
#
# Used for transfer project to another namespace
#
class
ProjectTransferService
include
Gitlab
::
ShellAdapter
class
TransferError
<
StandardError
;
end
attr_accessor
:project
def
transfer
(
project
,
new_namespace
)
Project
.
transaction
do
old_path
=
project
.
path_with_namespace
new_path
=
File
.
join
(
new_namespace
.
try
(
:path
)
||
''
,
project
.
path
)
if
Project
.
where
(
path:
project
.
path
,
namespace_id:
new_namespace
.
try
(
:id
)).
present?
raise
TransferError
.
new
(
"Project with same path in target namespace already exists"
)
end
# Remove old satellite
project
.
satellite
.
destroy
# Apply new namespace id
project
.
namespace
=
new_namespace
project
.
save!
# Move main repository
unless
gitlab_shell
.
mv_repository
(
old_path
,
new_path
)
raise
TransferError
.
new
(
'Cannot move project'
)
end
# Move wiki repo also if present
gitlab_shell
.
mv_repository
(
"
#{
old_path
}
.wiki"
,
"
#{
new_path
}
.wiki"
)
# Create a new satellite (reload project from DB)
Project
.
find
(
project
.
id
).
ensure_satellite_exists
# clear project cached events
project
.
reset_events_cache
true
end
end
end
app/services/projects/create_service.rb
View file @
13cbc82a
...
@@ -97,7 +97,7 @@ module Projects
...
@@ -97,7 +97,7 @@ module Projects
def
allowed_namespace?
(
user
,
namespace_id
)
def
allowed_namespace?
(
user
,
namespace_id
)
namespace
=
Namespace
.
find_by
(
id:
namespace_id
)
namespace
=
Namespace
.
find_by
(
id:
namespace_id
)
current_user
.
can?
(
:
manage_namespace
,
namespace
)
current_user
.
can?
(
:
create_projects
,
namespace
)
end
end
end
end
end
end
app/services/projects/transfer_service.rb
View file @
13cbc82a
# Projects::TransferService class
#
# Used for transfer project to another namespace
#
# Ex.
# # Move projects to namespace with ID 17 by user
# Projects::TransferService.new(project, user, namespace_id: 17).execute
#
module
Projects
module
Projects
class
TransferService
<
BaseService
class
TransferService
<
BaseService
def
execute
(
role
=
:default
)
include
Gitlab
::
ShellAdapter
namespace_id
=
params
[
:project
].
delete
(
:namespace_id
)
class
TransferError
<
StandardError
;
end
allowed_transfer
=
can?
(
current_user
,
:change_namespace
,
project
)
||
role
==
:admin
if
allowed_transfer
&&
namespace_id
.
present?
def
execute
if
namespace_id
.
to_i
!=
project
.
namespace_id
namespace_id
=
params
.
delete
(
:namespace_id
)
# Transfer to someone namespace
namespace
=
Namespace
.
find_by
(
id:
namespace_id
)
namespace
=
Namespace
.
find
(
namespace_id
)
project
.
transfer
(
namespace
)
end
end
rescue
ProjectTransferService
::
TransferError
=>
ex
if
allowed_transfer?
(
current_user
,
project
,
namespace
)
transfer
(
project
,
namespace
)
else
project
.
errors
.
add
(
:namespace
,
'is invalid'
)
false
end
rescue
Projects
::
TransferService
::
TransferError
=>
ex
project
.
reload
project
.
reload
project
.
errors
.
add
(
:namespace_id
,
ex
.
message
)
project
.
errors
.
add
(
:namespace_id
,
ex
.
message
)
false
false
end
end
def
transfer
(
project
,
new_namespace
)
Project
.
transaction
do
old_path
=
project
.
path_with_namespace
new_path
=
File
.
join
(
new_namespace
.
try
(
:path
)
||
''
,
project
.
path
)
if
Project
.
where
(
path:
project
.
path
,
namespace_id:
new_namespace
.
try
(
:id
)).
present?
raise
TransferError
.
new
(
"Project with same path in target namespace already exists"
)
end
# Remove old satellite
project
.
satellite
.
destroy
# Apply new namespace id
project
.
namespace
=
new_namespace
project
.
save!
# Move main repository
unless
gitlab_shell
.
mv_repository
(
old_path
,
new_path
)
raise
TransferError
.
new
(
'Cannot move project'
)
end
# Move wiki repo also if present
gitlab_shell
.
mv_repository
(
"
#{
old_path
}
.wiki"
,
"
#{
new_path
}
.wiki"
)
# Create a new satellite (reload project from DB)
Project
.
find
(
project
.
id
).
ensure_satellite_exists
# clear project cached events
project
.
reset_events_cache
true
end
end
end
end
def
allowed_transfer?
(
current_user
,
project
,
namespace
)
namespace
&&
can?
(
current_user
,
:change_namespace
,
project
)
&&
namespace
.
id
!=
project
.
namespace_id
&&
current_user
.
can?
(
:create_projects
,
namespace
)
end
end
end
app/views/groups/_projects.html.haml
View file @
13cbc82a
.ui-box
.ui-box
.title
.title
Projects (
#{
projects
.
count
}
)
Projects (
#{
projects
.
count
}
)
-
if
can?
current_user
,
:
manage_group
,
@group
-
if
can?
current_user
,
:
create_projects
,
@group
%span
.pull-right
%span
.pull-right
=
link_to
new_project_path
(
namespace_id:
@group
.
id
),
class:
"btn btn-new"
do
=
link_to
new_project_path
(
namespace_id:
@group
.
id
),
class:
"btn btn-new"
do
%i
.icon-plus
%i
.icon-plus
...
...
doc/permissions/permissions.md
View file @
13cbc82a
...
@@ -40,7 +40,7 @@ If a user is a GitLab administrator they receive all permissions.
...
@@ -40,7 +40,7 @@ If a user is a GitLab administrator they receive all permissions.
|------|-----|--------|---------|------|-----|
|------|-----|--------|---------|------|-----|
|Browse group|✓|✓|✓|✓|✓|
|Browse group|✓|✓|✓|✓|✓|
|Edit group|||||✓|
|Edit group|||||✓|
|Create project in group|||||✓|
|Create project in group||||
✓
|✓|
|Manage group members|||||✓|
|Manage group members|||||✓|
|Remove group|||||✓|
|Remove group|||||✓|
...
...
lib/api/groups.rb
View file @
13cbc82a
...
@@ -87,10 +87,12 @@ module API
...
@@ -87,10 +87,12 @@ module API
# POST /groups/:id/projects/:project_id
# POST /groups/:id/projects/:project_id
post
":id/projects/:project_id"
do
post
":id/projects/:project_id"
do
authenticated_as_admin!
authenticated_as_admin!
@
group
=
Group
.
find
(
params
[
:id
])
group
=
Group
.
find
(
params
[
:id
])
project
=
Project
.
find
(
params
[
:project_id
])
project
=
Project
.
find
(
params
[
:project_id
])
if
project
.
transfer
(
@group
)
result
=
::
Projects
::
TransferService
.
new
(
project
,
current_user
,
namespace_id:
group
.
id
).
execute
present
@group
if
result
present
group
else
else
not_found!
not_found!
end
end
...
...
lib/tasks/gitlab/enable_namespaces.rake
deleted
100644 → 0
View file @
64b1956b
namespace
:gitlab
do
desc
"GITLAB | Enable usernames and namespaces for user projects"
task
enable_namespaces: :environment
do
warn_user_is_not_gitlab
migrate_user_namespaces
migrate_groups
migrate_projects
end
def
migrate_user_namespaces
puts
"
\n
Generate usernames for users without one: "
.
blue
User
.
find_each
(
batch_size:
500
)
do
|
user
|
if
user
.
namespace
print
'-'
.
cyan
next
end
username
=
if
user
.
username
.
present?
# if user already has username filled
user
.
username
else
build_username
(
user
)
end
begin
User
.
transaction
do
user
.
update_attributes!
(
username:
username
)
print
'.'
.
green
end
rescue
print
'F'
.
red
end
end
puts
"
\n
Done"
end
def
build_username
(
user
)
username
=
nil
# generate username
username
=
user
.
email
.
match
(
/^[^@]*/
)[
0
]
username
.
gsub!
(
"+"
,
"."
)
# return username if no matches
return
username
unless
User
.
find_by
(
username:
username
)
# look for same username
(
1
..
10
).
each
do
|
i
|
suffixed_username
=
"
#{
username
}#{
i
}
"
return
suffixed_username
unless
User
.
find_by
(
username:
suffixed_username
)
end
end
def
migrate_groups
puts
"
\n
Create directories for groups: "
.
blue
Group
.
find_each
(
batch_size:
500
)
do
|
group
|
begin
if
group
.
dir_exists?
print
'-'
.
cyan
else
if
group
.
ensure_dir_exist
print
'.'
.
green
else
print
'F'
.
red
end
end
rescue
print
'F'
.
red
end
end
puts
"
\n
Done"
end
def
migrate_projects
git_path
=
Gitlab
.
config
.
gitlab_shell
.
repos_path
puts
"
\n
Move projects in groups into respective directories ... "
.
blue
Project
.
where
(
'namespace_id IS NOT NULL'
).
find_each
(
batch_size:
500
)
do
|
project
|
next
unless
project
.
group
group
=
project
.
group
print
"
#{
project
.
name_with_namespace
.
yellow
}
... "
new_path
=
File
.
join
(
git_path
,
project
.
path_with_namespace
+
'.git'
)
if
File
.
exists?
(
new_path
)
puts
"already at
#{
new_path
}
"
.
green
next
end
old_path
=
File
.
join
(
git_path
,
project
.
path
+
'.git'
)
unless
File
.
exists?
(
old_path
)
puts
"couldn't find it at
#{
old_path
}
"
.
red
next
end
begin
project
.
transfer
(
group
.
path
)
puts
"moved to
#{
new_path
}
"
.
green
rescue
puts
"failed moving to
#{
new_path
}
"
.
red
end
end
puts
"
\n
Done"
end
end
spec/models/project_spec.rb
View file @
13cbc82a
...
@@ -84,7 +84,6 @@ describe Project do
...
@@ -84,7 +84,6 @@ describe Project do
it
{
should
respond_to
(
:satellite
)
}
it
{
should
respond_to
(
:satellite
)
}
it
{
should
respond_to
(
:update_merge_requests
)
}
it
{
should
respond_to
(
:update_merge_requests
)
}
it
{
should
respond_to
(
:execute_hooks
)
}
it
{
should
respond_to
(
:execute_hooks
)
}
it
{
should
respond_to
(
:transfer
)
}
it
{
should
respond_to
(
:name_with_namespace
)
}
it
{
should
respond_to
(
:name_with_namespace
)
}
it
{
should
respond_to
(
:owner
)
}
it
{
should
respond_to
(
:owner
)
}
it
{
should
respond_to
(
:path_with_namespace
)
}
it
{
should
respond_to
(
:path_with_namespace
)
}
...
...
spec/requests/api/groups_spec.rb
View file @
13cbc82a
...
@@ -147,7 +147,7 @@ describe API::API, api: true do
...
@@ -147,7 +147,7 @@ describe API::API, api: true do
describe
"POST /groups/:id/projects/:project_id"
do
describe
"POST /groups/:id/projects/:project_id"
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:project
)
{
create
(
:project
)
}
before
(
:each
)
do
before
(
:each
)
do
project
.
stub
(
:transfer
).
and_return
(
true
)
Projects
::
TransferService
.
any_instance
.
stub
(
execute:
true
)
Project
.
stub
(
:find
).
and_return
(
project
)
Project
.
stub
(
:find
).
and_return
(
project
)
end
end
...
@@ -160,8 +160,8 @@ describe API::API, api: true do
...
@@ -160,8 +160,8 @@ describe API::API, api: true do
context
"when authenticated as admin"
do
context
"when authenticated as admin"
do
it
"should transfer project to group"
do
it
"should transfer project to group"
do
project
.
should_receive
(
:transfer
)
post
api
(
"/groups/
#{
group1
.
id
}
/projects/
#{
project
.
id
}
"
,
admin
)
post
api
(
"/groups/
#{
group1
.
id
}
/projects/
#{
project
.
id
}
"
,
admin
)
response
.
status
.
should
==
201
end
end
end
end
end
end
...
...
spec/services/projects/transfer_service_spec.rb
View file @
13cbc82a
require
'spec_helper'
require
'spec_helper'
describe
ProjectTransferService
do
describe
Project
s
::
TransferService
do
before
(
:each
)
{
enable_observers
}
before
(
:each
)
{
enable_observers
}
after
(
:each
)
{
disable_observers
}
after
(
:each
)
{
disable_observers
}
context
'namespace -> namespace'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:group2
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
context
'namespace -> namespace'
do
before
do
before
do
@result
=
service
.
transfer
(
project
,
group
)
group
.
add_owner
(
user
)
@service
=
Projects
::
TransferService
.
new
(
project
,
user
,
namespace_id:
group
.
id
)
@service
.
gitlab_shell
.
stub
(
mv_repository:
true
)
@result
=
@service
.
execute
end
end
it
{
@result
.
should
be_true
}
it
{
@result
.
should
be_true
}
...
@@ -18,16 +22,25 @@ describe ProjectTransferService do
...
@@ -18,16 +22,25 @@ describe ProjectTransferService do
end
end
context
'namespace -> no namespace'
do
context
'namespace -> no namespace'
do
let
(
:user
)
{
create
(
:user
)
}
before
do
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
group
.
add_owner
(
user
)
@service
=
Projects
::
TransferService
.
new
(
project
,
user
,
namespace_id:
nil
)
@service
.
gitlab_shell
.
stub
(
mv_repository:
true
)
@result
=
@service
.
execute
end
it
{
lambda
{
service
.
transfer
(
project
,
nil
)}.
should
raise_error
(
ActiveRecord
::
RecordInvalid
)
}
it
{
@result
.
should
be_false
}
it
{
project
.
namespace
.
should
==
user
.
namespace
}
end
end
def
service
context
'namespace -> not allowed namespace'
do
service
=
ProjectTransferService
.
new
before
do
service
.
gitlab_shell
.
stub
(
mv_repository:
true
)
@service
=
Projects
::
TransferService
.
new
(
project
,
user
,
namespace_id:
group2
.
id
)
service
@service
.
gitlab_shell
.
stub
(
mv_repository:
true
)
@result
=
@service
.
execute
end
end
end
it
{
@result
.
should
be_false
}
it
{
project
.
namespace
.
should
==
user
.
namespace
}
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