Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
877e42ecd457
Commit
877e42ec
authored
Apr 18, 2016
by
Rémy Coutable
Browse files
Add request access for groups
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
58f08aa9e328
Changes
77
Hide whitespace changes
Inline
Side-by-side
app/assets/stylesheets/pages/projects.scss
View file @
877e42ec
...
...
@@ -286,10 +286,6 @@
color
:
#555
;
}
.project_member_row
form
{
margin
:
0
;
}
.transfer-project
.select2-container
{
min-width
:
200px
;
}
...
...
app/controllers/groups/group_members_controller.rb
View file @
877e42ec
class
Groups::GroupMembersController
<
Groups
::
ApplicationController
# Authorize
before_action
:authorize_admin_group_member!
,
except:
[
:index
,
:leave
]
before_action
:authorize_admin_group_member!
,
except:
[
:index
,
:leave
,
:request_access
]
def
index
@project
=
@group
.
projects
.
find
(
params
[
:project_id
])
if
params
[
:project_id
]
@members
=
@group
.
group_members
...
...
@@ -4,8 +4,8 @@
def
index
@project
=
@group
.
projects
.
find
(
params
[
:project_id
])
if
params
[
:project_id
]
@members
=
@group
.
group_members
@members
=
@members
.
non_
invite
unless
can?
(
current_user
,
:admin_group
,
@group
)
@members
=
@members
.
non_
pending
unless
can?
(
current_user
,
:admin_group
,
@group
)
if
params
[
:search
].
present?
users
=
@group
.
users
.
search
(
params
[
:search
]).
to_a
...
...
@@ -36,7 +36,7 @@
return
render_403
unless
can?
(
current_user
,
:destroy_group_member
,
@group_member
)
@group_member
.
destroy
@group_member
.
request?
?
@group_member
.
decline_request
:
@group_member
.
destroy
respond_to
do
|
format
|
format
.
html
{
redirect_to
group_group_members_path
(
@group
),
notice:
'User was successfully removed from group.'
}
...
...
@@ -59,6 +59,8 @@
end
def
leave
@group_member
=
@group
.
group_members
.
find_by
(
user_id:
current_user
)
@group_member
=
@group
.
group_members
.
find_by
(
user_id:
current_user
.
id
)
||
@group
.
group_members
.
find_by
(
created_by_id:
current_user
.
id
)
if
can?
(
current_user
,
:destroy_group_member
,
@group_member
)
...
...
@@ -63,4 +65,10 @@
if
can?
(
current_user
,
:destroy_group_member
,
@group_member
)
notice
=
if
@group_member
.
request?
'You withdrawn your access request to the group.'
else
"You left
#{
@group
.
name
}
group."
end
@group_member
.
destroy
...
...
@@ -65,6 +73,6 @@
@group_member
.
destroy
redirect_to
(
dashboard_groups_path
,
notice:
"You left
#{
group
.
name
}
group."
)
redirect_to
dashboard_groups_path
,
notice:
notice
else
if
@group
.
last_owner?
(
current_user
)
redirect_to
(
dashboard_groups_path
,
alert:
"You can not leave
#{
group
.
name
}
group because you're the last owner. Transfer or delete the group."
)
...
...
@@ -74,6 +82,22 @@
end
end
def
request_access
@group
.
request_access
(
current_user
)
redirect_to
group_path
(
@group
),
notice:
'Your request for access has been queued for review.'
end
def
approve
@group_member
=
@group
.
group_members
.
request
.
find
(
params
[
:id
])
return
render_403
unless
can?
(
current_user
,
:update_group_member
,
@group_member
)
@group_member
.
accept_request
redirect_to
group_group_members_path
(
@group
)
end
protected
def
member_params
...
...
app/controllers/projects/project_members_controller.rb
View file @
877e42ec
...
...
@@ -14,5 +14,6 @@
@project_members
=
@project_members
.
order
(
'access_level DESC'
)
@group
=
@project
.
group
if
@group
@group_members
=
@group
.
group_members
...
...
@@ -17,6 +18,6 @@
if
@group
@group_members
=
@group
.
group_members
@group_members
=
@group_members
.
non_
invite
unless
can?
(
current_user
,
:admin_group
,
@group
)
@group_members
=
@group_members
.
non_
pending
unless
can?
(
current_user
,
:admin_group
,
@group
)
if
params
[
:search
].
present?
users
=
@group
.
users
.
search
(
params
[
:search
]).
to_a
...
...
@@ -49,7 +50,7 @@
return
render_403
unless
can?
(
current_user
,
:destroy_project_member
,
@project_member
)
@project_member
.
destroy
@project_member
.
request?
?
@project_member
.
decline_request
:
@project_member
.
destroy
respond_to
do
|
format
|
format
.
html
do
...
...
@@ -74,6 +75,8 @@
end
def
leave
@project_member
=
@project
.
project_members
.
find_by
(
user_id:
current_user
)
@project_member
=
@project
.
project_members
.
find_by
(
user_id:
current_user
.
id
)
||
@project
.
project_members
.
find_by
(
created_by_id:
current_user
.
id
)
if
can?
(
current_user
,
:destroy_project_member
,
@project_member
)
...
...
@@ -78,4 +81,10 @@
if
can?
(
current_user
,
:destroy_project_member
,
@project_member
)
notice
=
if
@project_member
.
request?
'You withdrawn your access request to the project.'
else
'You left the project.'
end
@project_member
.
destroy
...
...
@@ -80,9 +89,6 @@
@project_member
.
destroy
respond_to
do
|
format
|
format
.
html
{
redirect_to
dashboard_projects_path
,
notice:
"You left the project."
}
format
.
js
{
head
:ok
}
end
redirect_to
dashboard_projects_path
,
notice:
notice
else
if
current_user
==
@project
.
owner
message
=
'You can not leave your own project. Transfer or delete the project.'
...
...
@@ -94,9 +100,5 @@
end
def
request_access
redirect_path
=
namespace_project_path
(
@project
.
namespace
,
@project
)
# current_user
# @project
@project_member
=
ProjectMember
.
new
(
source:
@project
,
access_level:
ProjectMember
::
DEVELOPER
,
user_id:
current_user
.
id
,
created_by_id:
current_user
.
id
,
requested:
true
)
@project_member
.
save!
@project
.
request_access
(
current_user
)
...
...
@@ -102,5 +104,5 @@
redirect_to
redirect_path
,
notice:
'Your request for access has been queued for review.'
redirect_to
namespace_project_path
(
@project
.
namespace
,
@project
),
notice:
'Your request for access has been queued for review.'
end
...
...
@@ -105,7 +107,7 @@
end
def
approv
al
@project_member
=
@project
.
project_members
.
find
(
params
[
:id
])
def
approv
e
@project_member
=
@project
.
project_members
.
request
.
find
(
params
[
:id
])
return
render_403
unless
can?
(
current_user
,
:update_project_member
,
@project_member
)
...
...
@@ -109,6 +111,5 @@
return
render_403
unless
can?
(
current_user
,
:update_project_member
,
@project_member
)
@project_member
.
requested
=
nil
@project_member
.
save!
@project_member
.
accept_request
...
...
@@ -114,10 +115,5 @@
respond_to
do
|
format
|
format
.
html
do
redirect_to
namespace_project_project_members_path
(
@project
.
namespace
,
@project
)
end
format
.
js
{
render
nothing:
true
}
end
redirect_to
namespace_project_project_members_path
(
@project
.
namespace
,
@project
)
end
def
apply_import
...
...
app/helpers/groups_helper.rb
View file @
877e42ec
module
GroupsHelper
def
remove_user_from_group_message
(
group
,
member
)
if
member
.
user
"Are you sure you want to remove
\"
#{
member
.
user
.
name
}
\"
from
\"
#{
group
.
name
}
\"
?"
else
"Are you sure you want to revoke the invitation for
\"
#{
member
.
invite_email
}
\"
to join
\"
#{
group
.
name
}
\"
?"
end
end
def
leave_group_message
(
group
)
"Are you sure you want to leave
\"
#{
group
}
\"
group?"
end
def
should_user_see_group_roles?
(
user
,
group
)
if
user
user
.
is_admin?
||
group
.
members
.
exists?
(
user_id:
user
.
id
)
else
false
end
end
def
can_change_group_visibility_level?
(
group
)
can?
(
current_user
,
:change_visibility_level
,
group
)
end
...
...
app/helpers/members_helper.rb
0 → 100644
View file @
877e42ec
module
MembersHelper
def
member_class
(
member
)
"
#{
member
.
source
.
class
.
to_s
}
Member"
.
constantize
end
def
members_association
(
entity
)
"
#{
entity
.
class
.
to_s
.
underscore
}
_members"
.
to_sym
end
def
action_member_permission
(
action
,
member
)
"
#{
action
}
_
#{
member
.
source
.
class
.
to_s
.
underscore
}
_member"
.
to_sym
end
def
can_see_entity_roles?
(
user
,
entity
)
return
false
unless
user
user
.
is_admin?
||
entity
.
send
(
members_association
(
entity
)).
exists?
(
user_id:
user
.
id
)
end
def
member_path
(
member
)
case
member
.
source
when
Project
namespace_project_project_member_path
(
member
.
source
.
namespace
,
member
.
source
,
member
)
when
Group
group_group_member_path
(
member
.
source
,
member
)
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
def
resend_invite_member_path
(
member
)
case
member
.
source
when
Project
resend_invite_namespace_project_project_member_path
(
member
.
source
.
namespace
,
member
.
source
,
member
)
when
Group
resend_invite_group_group_member_path
(
member
.
source
,
member
)
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
def
request_access_path
(
entity
)
case
entity
when
Project
request_access_namespace_project_project_members_path
(
entity
.
namespace
,
entity
)
when
Group
request_access_group_group_members_path
(
entity
)
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
def
approve_request_member_path
(
member
)
case
member
.
source
when
Project
approve_namespace_project_project_member_path
(
member
.
source
.
namespace
,
member
.
source
,
member
)
when
Group
approve_group_group_member_path
(
member
.
source
,
member
)
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
def
leave_path
(
entity
)
case
entity
when
Project
leave_namespace_project_project_members_path
(
entity
.
namespace
,
entity
)
when
Group
leave_group_group_members_path
(
entity
)
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
def
withdraw_request_message
(
entity
)
"Are you sure you want to withdraw your access request for the
\"
#{
entity_name
(
entity
)
}
\"
#{
entity_type
(
entity
)
}
?"
end
def
remove_member_message
(
member
)
entity
=
member
.
source
entity_type
=
entity_type
(
entity
)
entity_name
=
entity_name
(
entity
)
if
member
.
request?
"You are going to deny
#{
member
.
created_by
.
name
}
's request to join the
#{
entity_name
}
#{
entity_type
}
. Are you sure?"
elsif
member
.
invite?
"You are going to revoke the invitation for
#{
member
.
invite_email
}
to join the
#{
entity_name
}
#{
entity_type
}
. Are you sure?"
else
"You are going to remove
#{
member
.
user
.
name
}
from the
#{
entity_name
}
#{
entity_type
}
. Are you sure?"
end
end
def
remove_member_title
(
member
)
member
.
request?
?
'Deny access request'
:
'Remove user'
end
def
leave_confirmation_message
(
entity
)
"Are you sure you want to leave
\"
#{
entity_name
(
entity
)
}
\"
#{
entity_type
(
entity
)
}
?"
end
private
def
entity_type
(
entity
)
entity
.
class
.
to_s
.
underscore
end
def
entity_name
(
entity
)
case
entity
when
Project
entity
.
name_with_namespace
when
Group
entity
.
name
else
raise
ArgumentError
.
new
(
'Unknown object class'
)
end
end
end
app/helpers/projects_helper.rb
View file @
877e42ec
module
ProjectsHelper
def
remove_from_project_team_message
(
project
,
member
)
if
!
member
.
user
"You are going to revoke the invitation for
#{
member
.
invite_email
}
to join
#{
project
.
name
}
project team. Are you sure?"
elsif
member
.
request?
"You are going to deny
#{
member
.
user
.
name
}
's request to join
#{
project
.
name
}
project team. Are you sure?"
else
"You are going to remove
#{
member
.
user
.
name
}
from
#{
project
.
name
}
project team. Are you sure?"
end
end
def
approve_for_project_team_message
(
project
,
member
)
"You are going to approve
#{
member
.
user
.
name
}
's request for
#{
member
.
human_access
}
access to the
#{
project
.
name
}
project team. Are you sure?"
def
max_access_level
(
project
,
user
)
Gitlab
::
Access
.
options_with_owner
.
key
(
project
.
team
.
max_member_access
(
user
.
id
))
end
def
link_to_project
(
project
)
...
...
@@ -121,14 +111,6 @@
end
end
def
user_max_access_in_project
(
user_id
,
project
)
level
=
project
.
team
.
max_member_access
(
user_id
)
if
level
Gitlab
::
Access
.
options_with_owner
.
key
(
level
)
end
end
def
license_short_name
(
project
)
return
'LICENSE'
if
project
.
repository
.
license_key
.
nil?
...
...
@@ -292,10 +274,6 @@
end
end
def
leave_project_message
(
project
)
"Are you sure you want to leave
\"
#{
project
.
name
}
\"
project?"
end
def
new_readme_path
ref
=
@repository
.
root_ref
if
@repository
ref
||=
'master'
...
...
app/mailers/emails/groups.rb
View file @
877e42ec
module
Emails
module
Groups
def
group_access_requested_email
(
group_member_id
)
setup_group_member_mail
(
group_member_id
)
@requester
=
@group_member
.
created_by
group_admins
=
User
.
where
(
id:
@group
.
group_members
.
admins
.
pluck
(
:user_id
)).
pluck
(
:notification_email
)
mail
(
to:
group_admins
,
subject:
subject
(
"Request to join
#{
@group
.
name
}
group"
))
end
def
group_access_granted_email
(
group_member_id
)
...
...
@@ -3,4 +14,3 @@
def
group_access_granted_email
(
group_member_id
)
@group_member
=
GroupMember
.
find
(
group_member_id
)
@group
=
@group_member
.
group
setup_group_member_mail
(
group_member_id
)
...
...
@@ -6,4 +16,3 @@
@target_url
=
group_url
(
@group
)
@current_user
=
@group_member
.
user
...
...
@@ -8,7 +17,16 @@
@current_user
=
@group_member
.
user
mail
(
to:
@group_member
.
user
.
notification_email
,
subject:
subject
(
"Access to group was granted"
))
mail
(
to:
@current_user
.
notification_email
,
subject:
subject
(
"Access to
#{
@group
.
name
}
group was granted"
))
end
def
group_access_denied_email
(
group_id
,
user_id
)
@group
=
Group
.
find
(
group_id
)
@current_user
=
User
.
find
(
user_id
)
@target_url
=
group_url
(
@group
)
mail
(
to:
@current_user
.
notification_email
,
subject:
subject
(
"Access to
#{
@group
.
name
}
group was denied"
))
end
def
group_member_invited_email
(
group_member_id
,
token
)
...
...
@@ -12,6 +30,6 @@
end
def
group_member_invited_email
(
group_member_id
,
token
)
@
group_member
=
GroupMember
.
find
group_member_id
@group
=
@group_member
.
group
setup_
group_member
_mail
(
group_member_id
)
@token
=
token
...
...
@@ -17,6 +35,4 @@
@token
=
token
@target_url
=
group_url
(
@group
)
@current_user
=
@group_member
.
user
mail
(
to:
@group_member
.
invite_email
,
...
...
@@ -24,6 +40,6 @@
end
def
group_invite_accepted_email
(
group_member_id
)
@
group_member
=
GroupMember
.
find
group_member_id
setup_
group_member
_mail
(
group_member_id
)
return
if
@group_member
.
created_by
.
nil?
...
...
@@ -28,7 +44,4 @@
return
if
@group_member
.
created_by
.
nil?
@group
=
@group_member
.
group
@target_url
=
group_url
(
@group
)
@current_user
=
@group_member
.
created_by
...
...
@@ -33,6 +46,6 @@
@current_user
=
@group_member
.
created_by
mail
(
to:
@
group_member
.
created_by
.
notification_email
,
mail
(
to:
@
current_user
.
notification_email
,
subject:
subject
(
"Invitation accepted"
))
end
...
...
@@ -43,8 +56,8 @@
@current_user
=
@created_by
=
User
.
find
(
created_by_id
)
@access_level
=
access_level
@invite_email
=
invite_email
@target_url
=
group_url
(
@group
)
mail
(
to:
@created_by
.
notification_email
,
subject:
subject
(
"Invitation declined"
))
end
...
...
@@ -47,6 +60,14 @@
@target_url
=
group_url
(
@group
)
mail
(
to:
@created_by
.
notification_email
,
subject:
subject
(
"Invitation declined"
))
end
private
def
setup_group_member_mail
(
group_member_id
)
@group_member
=
GroupMember
.
find
(
group_member_id
)
@group
=
@group_member
.
group
@target_url
=
group_url
(
@group
)
end
end
end
app/mailers/emails/projects.rb
View file @
877e42ec
module
Emails
module
Projects
def
project_access_granted_email
(
project_member_id
)
@project_member
=
ProjectMember
.
find
project_member_id
@project
=
@project_member
.
project
def
project_access_requested_email
(
project_member_id
)
setup_project_member_mail
(
project_member_id
)
...
...
@@ -6,8 +5,3 @@
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
@current_user
=
@project_member
.
user
mail
(
to:
@project_member
.
user
.
notification_email
,
subject:
subject
(
"Access to project was granted"
))
end
@requester
=
@project_member
.
created_by
...
...
@@ -13,6 +7,3 @@
def
project_member_requested_access
(
project_member_id
)
@project_member
=
ProjectMember
.
find
project_member_id
@project
=
@project_member
.
project
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
project_admins
=
User
.
where
(
id:
@project
.
project_members
.
admins
.
pluck
(
:user_id
)).
pluck
(
:notification_email
)
...
...
@@ -18,11 +9,5 @@
project_admins
=
ProjectMember
.
in_project
(
@project
)
.
where
(
access_level:
[
Gitlab
::
Access
::
OWNER
,
Gitlab
::
Access
::
MASTER
])
.
pluck
(
:notification_email
)
project_admins
.
each
do
|
address
|
mail
(
to:
address
,
subject:
subject
(
"Request to join project:
#{
@project
.
name_with_namespace
}
"
))
end
mail
(
to:
project_admins
,
subject:
subject
(
"Request to join
#{
@project
.
name_with_namespace
}
project"
))
end
...
...
@@ -27,8 +12,5 @@
end
def
project_request_access_accepted_email
(
project_member_id
)
@project_member
=
ProjectMember
.
find
project_member_id
return
if
@project_member
.
created_by
.
nil?
@project
=
@project_member
.
project
def
project_access_granted_email
(
project_member_id
)
setup_project_member_mail
(
project_member_id
)
...
...
@@ -34,4 +16,3 @@
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
@current_user
=
@project_member
.
created_by
@current_user
=
@project_member
.
user
...
...
@@ -37,5 +18,5 @@
mail
(
to:
@
project_member
.
created_by
.
notification_email
,
subject:
subject
(
'Request for acces
s granted
'
))
mail
(
to:
@
current_user
.
notification_email
,
subject:
subject
(
"Access to
#{
@project
.
name_with_namespace
}
project wa
s granted
"
))
end
...
...
@@ -40,8 +21,7 @@
end
def
project_request_access_declined_email
(
project_member_id
)
@project_member
=
ProjectMember
.
find
project_member_id
return
if
@project_member
.
created_by
.
nil?
@project
=
@project_member
.
project
def
project_access_denied_email
(
project_id
,
user_id
)
@project
=
Project
.
find
(
project_id
)
@current_user
=
User
.
find
(
user_id
)
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
...
...
@@ -47,8 +27,5 @@
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
@current_user
=
@project_member
.
created_by
mail
(
to:
@project_member
.
created_by
.
notification_email
,
subject:
subject
(
'Request for access declined'
))
mail
(
to:
@current_user
.
notification_email
,
subject:
subject
(
"Access to
#{
@project
.
name_with_namespace
}
project was denied"
))
end
...
...
@@ -53,3 +30,5 @@
end
def
project_member_invited_email
(
project_member_id
,
token
)
setup_project_member_mail
(
project_member_id
)
...
...
@@ -55,5 +34,2 @@
def
project_member_invited_email
(
project_member_id
,
token
)
@project_member
=
ProjectMember
.
find
project_member_id
@project
=
@project_member
.
project
@token
=
token
...
...
@@ -59,6 +35,4 @@
@token
=
token
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
@current_user
=
@project_member
.
user
mail
(
to:
@project_member
.
invite_email
,
...
...
@@ -66,6 +40,6 @@
end
def
project_invite_accepted_email
(
project_member_id
)
@
project_member
=
ProjectMember
.
find
project_member_id
setup_
project_member
_mail
(
project_member_id
)
return
if
@project_member
.
created_by
.
nil?
...
...
@@ -70,8 +44,5 @@
return
if
@project_member
.
created_by
.
nil?
@project
=
@project_member
.
project
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
@current_user
=
@project_member
.
created_by
mail
(
to:
@project_member
.
created_by
.
notification_email
,
...
...
@@ -117,5 +88,13 @@
reply_to:
@message
.
reply_to
,
subject:
@message
.
subject
)
end
private
def
setup_project_member_mail
(
project_member_id
)
@project_member
=
ProjectMember
.
find
(
project_member_id
)
@project
=
@project_member
.
project
@target_url
=
namespace_project_url
(
@project
.
namespace
,
@project
)
end
end
end
app/models/ability.rb
View file @
877e42ec
...
...
@@ -153,7 +153,7 @@