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
1c88d92b
Commit
1c88d92b
authored
Feb 16, 2018
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve Member services
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
e82f629b
Changes
24
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
251 additions
and
326 deletions
+251
-326
app/controllers/admin/groups_controller.rb
app/controllers/admin/groups_controller.rb
+1
-1
app/controllers/concerns/membership_actions.rb
app/controllers/concerns/membership_actions.rb
+38
-15
app/controllers/groups/group_members_controller.rb
app/controllers/groups/group_members_controller.rb
+0
-20
app/controllers/projects/project_members_controller.rb
app/controllers/projects/project_members_controller.rb
+0
-20
app/models/concerns/access_requestable.rb
app/models/concerns/access_requestable.rb
+1
-1
app/models/member.rb
app/models/member.rb
+6
-3
app/services/members/approve_access_request_service.rb
app/services/members/approve_access_request_service.rb
+5
-10
app/services/members/authorized_destroy_service.rb
app/services/members/authorized_destroy_service.rb
+0
-59
app/services/members/base_service.rb
app/services/members/base_service.rb
+2
-6
app/services/members/create_service.rb
app/services/members/create_service.rb
+2
-2
app/services/members/destroy_service.rb
app/services/members/destroy_service.rb
+48
-4
app/services/members/request_access_service.rb
app/services/members/request_access_service.rb
+2
-2
app/services/members/update_service.rb
app/services/members/update_service.rb
+1
-2
app/views/shared/members/update.js.haml
app/views/shared/members/update.js.haml
+5
-3
app/workers/remove_expired_members_worker.rb
app/workers/remove_expired_members_worker.rb
+1
-1
lib/api/access_requests.rb
lib/api/access_requests.rb
+2
-2
lib/api/members.rb
lib/api/members.rb
+4
-6
lib/api/v3/members.rb
lib/api/v3/members.rb
+1
-1
spec/services/members/approve_access_request_service_spec.rb
spec/services/members/approve_access_request_service_spec.rb
+9
-22
spec/services/members/authorized_destroy_service_spec.rb
spec/services/members/authorized_destroy_service_spec.rb
+0
-110
spec/services/members/create_service_spec.rb
spec/services/members/create_service_spec.rb
+3
-3
spec/services/members/destroy_service_spec.rb
spec/services/members/destroy_service_spec.rb
+115
-28
spec/services/members/request_access_service_spec.rb
spec/services/members/request_access_service_spec.rb
+3
-3
spec/services/members/update_service_spec.rb
spec/services/members/update_service_spec.rb
+2
-2
No files found.
app/controllers/admin/groups_controller.rb
View file @
1c88d92b
...
@@ -48,7 +48,7 @@ class Admin::GroupsController < Admin::ApplicationController
...
@@ -48,7 +48,7 @@ class Admin::GroupsController < Admin::ApplicationController
def
members_update
def
members_update
member_params
=
params
.
permit
(
:user_ids
,
:access_level
,
:expires_at
)
member_params
=
params
.
permit
(
:user_ids
,
:access_level
,
:expires_at
)
result
=
Members
::
CreateService
.
new
(
@group
,
current_user
,
member_params
.
merge
(
limit:
-
1
)).
execute
result
=
Members
::
CreateService
.
new
(
current_user
,
member_params
.
merge
(
limit:
-
1
)).
execute
(
@group
)
if
result
[
:status
]
==
:success
if
result
[
:status
]
==
:success
redirect_to
[
:admin
,
@group
],
notice:
'Users were successfully added.'
redirect_to
[
:admin
,
@group
],
notice:
'Users were successfully added.'
...
...
app/controllers/concerns/membership_actions.rb
View file @
1c88d92b
...
@@ -3,33 +3,31 @@ module MembershipActions
...
@@ -3,33 +3,31 @@ module MembershipActions
def
create
def
create
create_params
=
params
.
permit
(
:user_ids
,
:access_level
,
:expires_at
)
create_params
=
params
.
permit
(
:user_ids
,
:access_level
,
:expires_at
)
result
=
Members
::
CreateService
.
new
(
membershipable
,
current_user
,
create_params
).
execute
result
=
Members
::
CreateService
.
new
(
current_user
,
create_params
).
execute
(
membershipable
)
redirect_url
=
members_page_url
if
result
[
:status
]
==
:success
if
result
[
:status
]
==
:success
redirect_to
redirect
_url
,
notice:
'Users were successfully added.'
redirect_to
members_page
_url
,
notice:
'Users were successfully added.'
else
else
redirect_to
redirect
_url
,
alert:
result
[
:message
]
redirect_to
members_page
_url
,
alert:
result
[
:message
]
end
end
end
end
def
update
def
update
update_params
=
params
.
require
(
root_params_key
).
permit
(
:access_level
,
:expires_at
)
member
=
membershipable
.
members_and_requesters
.
find
(
params
[
:id
])
member
=
membershipable
.
members_and_requesters
.
find
(
params
[
:id
])
@
member
=
Members
::
UpdateService
member
=
Members
::
UpdateService
.
new
(
membershipable
,
current_user
,
member
_params
)
.
new
(
current_user
,
update
_params
)
.
execute
(
member
)
.
execute
(
member
)
.
present
(
current_user:
current_user
)
.
present
(
current_user:
current_user
)
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
js
{
render
'shared/members/update'
}
format
.
js
{
render
'shared/members/update'
,
locals:
{
member:
member
}
}
end
end
end
end
def
destroy
def
destroy
member
=
membershipable
.
members_and_requesters
.
find
(
params
[
:id
])
member
=
membershipable
.
members_and_requesters
.
find
(
params
[
:id
])
Members
::
DestroyService
.
new
(
membershipable
,
current_user
,
params
)
Members
::
DestroyService
.
new
(
current_user
).
execute
(
member
)
.
execute
(
member
)
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
do
format
.
html
do
...
@@ -51,7 +49,7 @@ module MembershipActions
...
@@ -51,7 +49,7 @@ module MembershipActions
def
approve_access_request
def
approve_access_request
access_requester
=
membershipable
.
requesters
.
find
(
params
[
:id
])
access_requester
=
membershipable
.
requesters
.
find
(
params
[
:id
])
Members
::
ApproveAccessRequestService
Members
::
ApproveAccessRequestService
.
new
(
membershipable
,
current_user
,
params
)
.
new
(
current_user
,
params
)
.
execute
(
access_requester
)
.
execute
(
access_requester
)
redirect_to
members_page_url
redirect_to
members_page_url
...
@@ -59,8 +57,7 @@ module MembershipActions
...
@@ -59,8 +57,7 @@ module MembershipActions
def
leave
def
leave
member
=
membershipable
.
members_and_requesters
.
find_by!
(
user_id:
current_user
.
id
)
member
=
membershipable
.
members_and_requesters
.
find_by!
(
user_id:
current_user
.
id
)
Members
::
DestroyService
.
new
(
membershipable
,
current_user
)
Members
::
DestroyService
.
new
(
current_user
).
execute
(
member
)
.
execute
(
member
)
notice
=
notice
=
if
member
.
request?
if
member
.
request?
...
@@ -79,17 +76,43 @@ module MembershipActions
...
@@ -79,17 +76,43 @@ module MembershipActions
end
end
end
end
def
resend_invite
member
=
membershipable
.
members
.
find
(
params
[
:id
])
if
member
.
invite?
member
.
resend_invite
redirect_to
members_page_url
,
notice:
'The invitation was successfully resent.'
else
redirect_to
members_page_url
,
alert:
'The invitation has already been accepted.'
end
end
protected
protected
def
membershipable
def
membershipable
raise
NotImplementedError
raise
NotImplementedError
end
end
def
root_params_key
case
membershipable
when
Namespace
:group_member
when
Project
:project_member
else
raise
"Unknown membershipable type:
#{
membershipable
}
!"
end
end
def
members_page_url
def
members_page_url
if
membershipable
.
is_a?
(
Project
)
case
membershipable
when
Namespace
polymorphic_url
([
membershipable
,
:members
])
when
Project
project_project_members_path
(
membershipable
)
project_project_members_path
(
membershipable
)
else
else
polymorphic_url
([
membershipable
,
:members
])
raise
"Unknown membershipable type:
#{
membershipable
}
!"
end
end
end
end
...
...
app/controllers/groups/group_members_controller.rb
View file @
1c88d92b
...
@@ -27,26 +27,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
...
@@ -27,26 +27,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
@group_member
=
@group
.
group_members
.
new
@group_member
=
@group
.
group_members
.
new
end
end
def
resend_invite
redirect_path
=
group_group_members_path
(
@group
)
@group_member
=
@group
.
group_members
.
find
(
params
[
:id
])
if
@group_member
.
invite?
@group_member
.
resend_invite
redirect_to
redirect_path
,
notice:
'The invitation was successfully resent.'
else
redirect_to
redirect_path
,
alert:
'The invitation has already been accepted.'
end
end
protected
def
member_params
params
.
require
(
:group_member
).
permit
(
:access_level
,
:user_id
,
:expires_at
)
end
# MembershipActions concern
# MembershipActions concern
alias_method
:membershipable
,
:group
alias_method
:membershipable
,
:group
end
end
app/controllers/projects/project_members_controller.rb
View file @
1c88d92b
...
@@ -26,20 +26,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
...
@@ -26,20 +26,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
@project_member
=
@project
.
project_members
.
new
@project_member
=
@project
.
project_members
.
new
end
end
def
resend_invite
redirect_path
=
project_project_members_path
(
@project
)
@project_member
=
@project
.
project_members
.
find
(
params
[
:id
])
if
@project_member
.
invite?
@project_member
.
resend_invite
redirect_to
redirect_path
,
notice:
'The invitation was successfully resent.'
else
redirect_to
redirect_path
,
alert:
'The invitation has already been accepted.'
end
end
def
import
def
import
@projects
=
current_user
.
authorized_projects
.
order_id_desc
@projects
=
current_user
.
authorized_projects
.
order_id_desc
end
end
...
@@ -58,12 +44,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
...
@@ -58,12 +44,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
notice:
notice
)
notice:
notice
)
end
end
protected
def
member_params
params
.
require
(
:project_member
).
permit
(
:user_id
,
:access_level
,
:expires_at
)
end
# MembershipActions concern
# MembershipActions concern
alias_method
:membershipable
,
:project
alias_method
:membershipable
,
:project
end
end
app/models/concerns/access_requestable.rb
View file @
1c88d92b
...
@@ -8,6 +8,6 @@ module AccessRequestable
...
@@ -8,6 +8,6 @@ module AccessRequestable
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
def
request_access
(
user
)
def
request_access
(
user
)
Members
::
RequestAccessService
.
new
(
self
,
user
).
execute
Members
::
RequestAccessService
.
new
(
user
).
execute
(
self
)
end
end
end
end
app/models/member.rb
View file @
1c88d92b
...
@@ -128,7 +128,7 @@ class Member < ActiveRecord::Base
...
@@ -128,7 +128,7 @@ class Member < ActiveRecord::Base
find_by
(
invite_token:
invite_token
)
find_by
(
invite_token:
invite_token
)
end
end
def
add_user
(
source
,
user
,
access_level
,
existing_members:
nil
,
current_user:
nil
,
expires_at:
nil
)
def
add_user
(
source
,
user
,
access_level
,
existing_members:
nil
,
current_user:
nil
,
expires_at:
nil
,
ldap:
false
)
# `user` can be either a User object, User ID or an email to be invited
# `user` can be either a User object, User ID or an email to be invited
member
=
retrieve_member
(
source
,
user
,
existing_members
)
member
=
retrieve_member
(
source
,
user
,
existing_members
)
access_level
=
retrieve_access_level
(
access_level
)
access_level
=
retrieve_access_level
(
access_level
)
...
@@ -143,10 +143,13 @@ class Member < ActiveRecord::Base
...
@@ -143,10 +143,13 @@ class Member < ActiveRecord::Base
if
member
.
request?
if
member
.
request?
::
Members
::
ApproveAccessRequestService
.
new
(
::
Members
::
ApproveAccessRequestService
.
new
(
source
,
current_user
,
current_user
,
access_level:
access_level
access_level:
access_level
).
execute
(
member
)
).
execute
(
member
,
skip_authorization:
ldap
,
skip_log_audit_event:
ldap
)
else
else
member
.
save
member
.
save
end
end
...
...
app/services/members/approve_access_request_service.rb
View file @
1c88d92b
module
Members
module
Members
class
ApproveAccessRequestService
<
Members
::
BaseService
class
ApproveAccessRequestService
<
Members
::
BaseService
# opts - A hash of options
def
execute
(
access_requester
,
skip_authorization:
false
,
skip_log_audit_event:
false
)
# :ldap - The call is from a LDAP sync: current_user can be nil in that case
raise
Gitlab
::
Access
::
AccessDeniedError
unless
skip_authorization
||
can_update_access_requester?
(
access_requester
)
def
execute
(
access_requester
,
opts
=
{})
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can_update_access_requester?
(
access_requester
,
opts
[
:ldap
])
access_requester
.
access_level
=
params
[
:access_level
]
if
params
[
:access_level
]
access_requester
.
access_level
=
params
[
:access_level
]
if
params
[
:access_level
]
access_requester
.
accept_request
access_requester
.
accept_request
after_execute
(
member:
access_requester
,
**
opts
)
after_execute
(
member:
access_requester
,
skip_log_audit_event:
skip_log_audit_event
)
access_requester
access_requester
end
end
private
private
def
can_update_access_requester?
(
access_requester
,
ldap
)
def
can_update_access_requester?
(
access_requester
)
access_requester
&&
(
ldap
||
can?
(
current_user
,
update_member_permission
(
access_requester
),
access_requester
)
can?
(
current_user
,
update_member_permission
(
access_requester
),
access_requester
)
)
end
end
end
end
end
end
app/services/members/authorized_destroy_service.rb
deleted
100644 → 0
View file @
e82f629b
module
Members
class
AuthorizedDestroyService
<
BaseService
def
initialize
(
current_user
=
nil
)
@current_user
=
current_user
end
def
execute
(
member
)
return
false
if
member
.
is_a?
(
GroupMember
)
&&
member
.
source
.
last_owner?
(
member
.
user
)
Member
.
transaction
do
unassign_issues_and_merge_requests
(
member
)
unless
member
.
invite?
member
.
notification_setting
&
.
destroy
member
.
destroy
end
if
member
.
request?
&&
member
.
user
!=
current_user
notification_service
.
decline_access_request
(
member
)
end
member
end
private
def
unassign_issues_and_merge_requests
(
member
)
if
member
.
is_a?
(
GroupMember
)
issues
=
Issue
.
unscoped
.
select
(
1
)
.
joins
(
:project
)
.
where
(
'issues.id = issue_assignees.issue_id AND projects.namespace_id = ?'
,
member
.
source_id
)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee
.
unscoped
.
where
(
'user_id = :user_id AND EXISTS (:sub)'
,
user_id:
member
.
user_id
,
sub:
issues
)
.
delete_all
MergeRequestsFinder
.
new
(
current_user
,
group_id:
member
.
source_id
,
assignee_id:
member
.
user_id
)
.
execute
.
update_all
(
assignee_id:
nil
)
else
project
=
member
.
source
# SELECT 1 FROM issues WHERE issues.id = issue_assignees.issue_id AND issues.project_id = X
issues
=
Issue
.
unscoped
.
select
(
1
)
.
where
(
'issues.id = issue_assignees.issue_id'
)
.
where
(
project_id:
project
.
id
)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee
.
unscoped
.
where
(
'user_id = :user_id AND EXISTS (:sub)'
,
user_id:
member
.
user_id
,
sub:
issues
)
.
delete_all
project
.
merge_requests
.
opened
.
assigned_to
(
member
.
user
).
update_all
(
assignee_id:
nil
)
end
member
.
user
.
invalidate_cache_counts
end
end
end
app/services/members/base_service.rb
View file @
1c88d92b
module
Members
module
Members
class
BaseService
<
::
BaseService
class
BaseService
<
::
BaseService
attr_accessor
:source
# source - The source object that respond to `#members` (e.g. project or group)
# current_user - The user that performs the action
# current_user - The user that performs the action
# params - A hash of parameters
# params - A hash of parameters
def
initialize
(
source
,
current_user
,
params
=
{})
def
initialize
(
current_user
=
nil
,
params
=
{})
@source
=
source
@current_user
=
current_user
@current_user
=
current_user
@params
=
params
@params
=
params
end
end
def
after_execute
(
**
args
)
def
after_execute
(
args
)
# overriden in EE::Members modules
# overriden in EE::Members modules
end
end
...
...
app/services/members/create_service.rb
View file @
1c88d92b
...
@@ -2,7 +2,7 @@ module Members
...
@@ -2,7 +2,7 @@ module Members
class
CreateService
<
Members
::
BaseService
class
CreateService
<
Members
::
BaseService
DEFAULT_LIMIT
=
100
DEFAULT_LIMIT
=
100
def
execute
def
execute
(
source
)
return
error
(
'No users specified.'
)
if
params
[
:user_ids
].
blank?
return
error
(
'No users specified.'
)
if
params
[
:user_ids
].
blank?
user_ids
=
params
[
:user_ids
].
split
(
','
).
uniq
user_ids
=
params
[
:user_ids
].
split
(
','
).
uniq
...
@@ -17,7 +17,7 @@ module Members
...
@@ -17,7 +17,7 @@ module Members
current_user:
current_user
current_user:
current_user
)
)
members
.
compact
.
each
{
|
member
|
after_execute
(
member:
member
)
}
members
.
each
{
|
member
|
after_execute
(
member:
member
)
}
success
success
end
end
...
...
app/services/members/destroy_service.rb
View file @
1c88d92b
module
Members
module
Members
class
DestroyService
<
Members
::
BaseService
class
DestroyService
<
Members
::
BaseService
def
execute
(
member
)
def
execute
(
member
,
skip_authorization:
false
)
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can_destroy_member?
(
member
)
raise
Gitlab
::
Access
::
AccessDeniedError
unless
skip_authorization
||
can_destroy_member?
(
member
)
AuthorizedDestroyService
.
new
(
current_user
).
execute
(
member
)
return
member
if
member
.
is_a?
(
GroupMember
)
&&
member
.
source
.
last_owner?
(
member
.
user
)
Member
.
transaction
do
unassign_issues_and_merge_requests
(
member
)
unless
member
.
invite?
member
.
notification_setting
&
.
destroy
member
.
destroy
end
if
member
.
request?
&&
member
.
user
!=
current_user
notification_service
.
decline_access_request
(
member
)
end
after_execute
(
member:
member
)
after_execute
(
member:
member
)
...
@@ -13,7 +24,7 @@ module Members
...
@@ -13,7 +24,7 @@ module Members
private
private
def
can_destroy_member?
(
member
)
def
can_destroy_member?
(
member
)
member
&&
can?
(
current_user
,
destroy_member_permission
(
member
),
member
)
can?
(
current_user
,
destroy_member_permission
(
member
),
member
)
end
end
def
destroy_member_permission
(
member
)
def
destroy_member_permission
(
member
)
...
@@ -26,5 +37,38 @@ module Members
...
@@ -26,5 +37,38 @@ module Members
raise
"Unknown member type:
#{
member
}
!"
raise
"Unknown member type:
#{
member
}
!"
end
end
end
end
def
unassign_issues_and_merge_requests
(
member
)
if
member
.
is_a?
(
GroupMember
)
issues
=
Issue
.
unscoped
.
select
(
1
)
.
joins
(
:project
)
.
where
(
'issues.id = issue_assignees.issue_id AND projects.namespace_id = ?'
,
member
.
source_id
)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee
.
unscoped
.
where
(
'user_id = :user_id AND EXISTS (:sub)'
,
user_id:
member
.
user_id
,
sub:
issues
)
.
delete_all
MergeRequestsFinder
.
new
(
current_user
,
group_id:
member
.
source_id
,
assignee_id:
member
.
user_id
)
.
execute
.
update_all
(
assignee_id:
nil
)
else
project
=
member
.
source
# SELECT 1 FROM issues WHERE issues.id = issue_assignees.issue_id AND issues.project_id = X
issues
=
Issue
.
unscoped
.
select
(
1
)
.
where
(
'issues.id = issue_assignees.issue_id'
)
.
where
(
project_id:
project
.
id
)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee
.
unscoped
.
where
(
'user_id = :user_id AND EXISTS (:sub)'
,
user_id:
member
.
user_id
,
sub:
issues
)
.
delete_all
project
.
merge_requests
.
opened
.
assigned_to
(
member
.
user
).
update_all
(
assignee_id:
nil
)
end
member
.
user
.
invalidate_cache_counts
end
end
end
end
end
app/services/members/request_access_service.rb
View file @
1c88d92b
module
Members
module
Members
class
RequestAccessService
<
Members
::
BaseService
class
RequestAccessService
<
Members
::
BaseService
def
execute
def
execute
(
source
)
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can_request_access?
(
source
)
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can_request_access?
(
source
)
source
.
members
.
create
(
source
.
members
.
create
(
...
@@ -12,7 +12,7 @@ module Members
...
@@ -12,7 +12,7 @@ module Members
private
private
def
can_request_access?
(
source
)
def
can_request_access?
(
source
)
source
&&
can?
(
current_user
,
:request_access
,
source
)
can?
(
current_user
,
:request_access
,
source
)
end
end
end
end
end
end
app/services/members/update_service.rb
View file @
1c88d92b
...
@@ -2,8 +2,7 @@ module Members
...
@@ -2,8 +2,7 @@ module Members
class
UpdateService
<
Members
::
BaseService
class
UpdateService
<
Members
::
BaseService
# returns the updated member
# returns the updated member
def
execute
(
member
,
permission: :update
)
def
execute
(
member
,
permission: :update
)
permission_target
=
permission
==
:override
?
source
:
member
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can?
(
current_user
,
action_member_permission
(
permission
,
member
),
member
)
raise
Gitlab
::
Access
::
AccessDeniedError
unless
can?
(
current_user
,
action_member_permission
(
permission
,
member
),
permission_target
)
old_access_level
=
member
.
human_access
old_access_level
=
member
.
human_access
...
...
app/views/shared/members/update.js.haml
View file @
1c88d92b
-
member
=
local_assigns
.
fetch
(
:member
)
:plain
:plain
var $listItem = $('
#{
escape_javascript
(
render
(
'shared/members/member'
,
member:
@
member
))
}
');
var $listItem = $('
#{
escape_javascript
(
render
(
'shared/members/member'
,
member:
member
))
}
');
$("##{dom_id(
@
member)} .list-item-name").replaceWith($listItem.find('.list-item-name'));
$("##{dom_id(member)} .list-item-name").replaceWith($listItem.find('.list-item-name'));
gl.utils.localTimeAgo($('.js-timeago'), $("##{dom_id(
@
member)}"));
gl.utils.localTimeAgo($('.js-timeago'), $("##{dom_id(member)}"));
app/workers/remove_expired_members_worker.rb
View file @
1c88d92b
...
@@ -5,7 +5,7 @@ class RemoveExpiredMembersWorker
...
@@ -5,7 +5,7 @@ class RemoveExpiredMembersWorker
def
perform
def
perform
Member
.
expired
.
find_each
do
|
member
|
Member
.
expired
.
find_each
do
|
member
|
begin
begin
Members
::
AuthorizedDestroyService
.
new
.
execute
(
member
)
Members
::
DestroyService
.
new
.
execute
(
member
,
skip_authorization:
true
)
rescue
=>
ex
rescue
=>
ex
logger
.
error
(
"Expired Member ID=
#{
member
.
id
}
cannot be removed -
#{
ex
}
"
)
logger
.
error
(
"Expired Member ID=
#{
member
.
id
}
cannot be removed -
#{
ex
}
"
)
end
end
...
...
lib/api/access_requests.rb
View file @
1c88d92b
...
@@ -55,7 +55,7 @@ module API
...
@@ -55,7 +55,7 @@ module API
access_requester
=
source
.
requesters
.
find_by!
(
user_id:
params
[
:user_id
])
access_requester
=
source
.
requesters
.
find_by!
(
user_id:
params
[
:user_id
])
member
=
::
Members
::
ApproveAccessRequestService
member
=
::
Members
::
ApproveAccessRequestService
.
new
(
source
,
current_user
,
declared_params
)
.
new
(
current_user
,
declared_params
)
.
execute
(
access_requester
)
.
execute
(
access_requester
)
status
:created
status
:created
...
@@ -73,7 +73,7 @@ module API
...
@@ -73,7 +73,7 @@ module API
member
=
source
.
requesters
.
find_by!
(
user_id:
params
[
:user_id
])
member
=
source
.
requesters
.
find_by!
(
user_id:
params
[
:user_id
])
destroy_conditionally!
(
member
)
do
destroy_conditionally!
(
member
)
do
::
Members
::
DestroyService
.
new
(
source
,
current_user
).
execute
(
member
)
::
Members
::
DestroyService
.
new
(
current_user
).
execute
(
member
)
end
end
end
end
end
end
...
...
lib/api/members.rb
View file @
1c88d92b
...
@@ -83,11 +83,9 @@ module API
...
@@ -83,11 +83,9 @@ module API
member
=
source
.
members
.
find_by!
(
user_id:
params
[
:user_id
])
member
=
source
.
members
.
find_by!
(
user_id:
params
[
:user_id
])
updated_member
=
updated_member
=
::
Members
::
UpdateService
.
new
(
::
Members
::
UpdateService
source
,
.
new
(
current_user
,
declared_params
(
include_missing:
false
))
current_user
,
.
execute
(
member
)
declared_params
(
include_missing:
false
)
).
execute
(
member
)
if
updated_member
.
valid?
if
updated_member
.
valid?
present
updated_member
,
with:
Entities
::
Member
present
updated_member
,
with:
Entities
::
Member
...
@@ -105,7 +103,7 @@ module API
...
@@ -105,7 +103,7 @@ module API
member
=
source
.
members
.
find_by!
(
user_id:
params
[
:user_id
])
member
=
source
.
members
.
find_by!
(
user_id:
params
[
:user_id
])
destroy_conditionally!
(
member
)
do
destroy_conditionally!
(
member
)
do
::
Members
::
DestroyService
.
new
(
source
,
current_user
).
execute
(
member
)
::
Members
::
DestroyService
.
new
(
current_user
).
execute
(
member
)
end
end
end
end
end
end
...
...
lib/api/v3/members.rb
View file @
1c88d92b
...
@@ -124,7 +124,7 @@ module API
...
@@ -124,7 +124,7 @@ module API
status
(
200
)
status
(
200
)
{
message:
"Access revoked"
,
id:
params
[
:user_id
].
to_i
}
{
message:
"Access revoked"
,
id:
params
[
:user_id
].
to_i
}
else
else
::
Members
::
DestroyService
.
new
(
source
,
current_user
).
execute
(
member
)
::
Members
::
DestroyService
.
new
(
current_user
).
execute
(
member
)
present
member
,
with:
::
API
::
Entities
::
Member
present
member
,
with:
::
API
::
Entities
::
Member
end
end
...
...
spec/services/members/approve_access_request_service_spec.rb
View file @
1c88d92b
...
@@ -6,28 +6,27 @@ describe Members::ApproveAccessRequestService do
...
@@ -6,28 +6,27 @@ describe Members::ApproveAccessRequestService do
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:access_requester_user
)
{
create
(
:user
)
}
let
(
:access_requester_user
)
{
create
(
:user
)
}
let
(
:access_requester
)
{
source
.
requesters
.
find_by!
(
user_id:
access_requester_user
.
id
)
}
let
(
:access_requester
)
{
source
.
requesters
.
find_by!
(
user_id:
access_requester_user
.
id
)
}
let
(
:params
)
{
{}
}
let
(
:opts
)
{
{}
}
let
(
:opts
)
{
{}
}
shared_examples
'a service raising ActiveRecord::RecordNotFound'
do
shared_examples
'a service raising ActiveRecord::RecordNotFound'
do
it
'raises ActiveRecord::RecordNotFound'
do
it
'raises ActiveRecord::RecordNotFound'
do
expect
{
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
access_requester
,
opts
)
}.
to
raise_error
(
ActiveRecord
::
RecordNotFound
)
expect
{
described_class
.
new
(
current_user
).
execute
(
access_requester
,
opts
)
}.
to
raise_error
(
ActiveRecord
::
RecordNotFound
)
end
end
end
end
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
expect
{
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
access_requester
,
opts
)
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
expect
{
described_class
.
new
(
current_user
).
execute
(
access_requester
,
opts
)
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
end
end
end
end
shared_examples
'a service approving an access request'
do
shared_examples
'a service approving an access request'
do
it
'succeeds'
do
it
'succeeds'
do
expect
{
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
access_requester
,
opts
)
}.
to
change
{
source
.
requesters
.
count
}.
by
(
-
1
)
expect
{
described_class
.
new
(
current_user
).
execute
(
access_requester
,
opts
)
}.
to
change
{
source
.
requesters
.
count
}.
by
(
-
1
)
end
end
it
'returns a <Source>Member'
do
it
'returns a <Source>Member'
do
member
=
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
access_requester
,
opts
)
member
=
described_class
.
new
(
current_user
).
execute
(
access_requester
,
opts
)
expect
(
member
).
to
be_a
"
#{
source
.
class
}
Member"
.
constantize
expect
(
member
).
to
be_a
"
#{
source
.
class
}
Member"
.
constantize
expect
(
member
.
requested_at
).
to
be_nil
expect
(
member
.
requested_at
).
to
be_nil
...
@@ -35,7 +34,7 @@ describe Members::ApproveAccessRequestService do
...
@@ -35,7 +34,7 @@ describe Members::ApproveAccessRequestService do
context
'with a custom access level'
do
context
'with a custom access level'
do
it
'returns a ProjectMember with the custom access level'
do
it
'returns a ProjectMember with the custom access level'
do
member
=
described_class
.
new
(
source
,
current_user
,
params
.
merge
(
access_level:
Gitlab
::
Access
::
MASTER
)
).
execute
(
access_requester
,
opts
)
member
=
described_class
.
new
(
current_user
,
access_level:
Gitlab
::
Access
::
MASTER
).
execute
(
access_requester
,
opts
)
expect
(
member
.
access_level
).
to
eq
(
Gitlab
::
Access
::
MASTER
)
expect
(
member
.
access_level
).
to
eq
(
Gitlab
::
Access
::
MASTER
)
end
end
...
@@ -61,8 +60,8 @@ describe Members::ApproveAccessRequestService do
...
@@ -61,8 +60,8 @@ describe Members::ApproveAccessRequestService do
end
end
end
end
context
'and :
ldap
option is false'
do
context
'and :
skip_authorization
option is false'
do
let
(
:opts
)
{
{
ldap
:
false
}
}
let
(
:opts
)
{
{
skip_authorization
:
false
}
}
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
project
}
let
(
:source
)
{
project
}
...
@@ -73,8 +72,8 @@ describe Members::ApproveAccessRequestService do
...
@@ -73,8 +72,8 @@ describe Members::ApproveAccessRequestService do
end
end
end
end
context
'and :
ldap
option is true'
do
context
'and :
skip_authorization
option is true'
do
let
(
:opts
)
{
{
ldap
:
true
}
}
let
(
:opts
)
{
{
skip_authorization
:
true
}
}
it_behaves_like
'a service approving an access request'
do
it_behaves_like
'a service approving an access request'
do
let
(
:source
)
{
project
}
let
(
:source
)
{
project
}
...
@@ -84,18 +83,6 @@ describe Members::ApproveAccessRequestService do
...
@@ -84,18 +83,6 @@ describe Members::ApproveAccessRequestService do
let
(
:source
)
{
group
}
let
(
:source
)
{
group
}
end
end
end
end
context
'and :ldap param is true'
do
let
(
:params
)
{
{
ldap:
true
}
}
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
project
}
end
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
group
}
end
end
end
end
context
'when current user cannot approve access request to the project'
do
context
'when current user cannot approve access request to the project'
do
...
...
spec/services/members/authorized_destroy_service_spec.rb
deleted
100644 → 0
View file @
e82f629b
require
'spec_helper'
describe
Members
::
AuthorizedDestroyService
do
let
(
:member_user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:group
)
{
create
(
:group
,
:public
)
}
let
(
:group_project
)
{
create
(
:project
,
:public
,
group:
group
)
}
def
number_of_assigned_issuables
(
user
)
Issue
.
assigned_to
(
user
).
count
+
MergeRequest
.
assigned_to
(
user
).
count
end
context
'Invited users'
do
# Regression spec for issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/32504
it
'destroys invited project member'
do
project
.
add_developer
(
member_user
)
member
=
create
:project_member
,
:invited
,
project:
project
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
Member
.
count
}.
from
(
3
).
to
(
2
)
end
it
"doesn't destroy invited project member notification_settings"
do
project
.
add_developer
(
member_user
)
member
=
create
:project_member
,
:invited
,
project:
project
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
not_to
change
{
NotificationSetting
.
count
}
end
it
'destroys invited group member'
do
group
.
add_developer
(
member_user
)
member
=
create
:group_member
,
:invited
,
group:
group
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
Member
.
count
}.
from
(
2
).
to
(
1
)
end
it
"doesn't destroy invited group member notification_settings"
do
group
.
add_developer
(
member_user
)
member
=
create
:group_member
,
:invited
,
group:
group
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
not_to
change
{
NotificationSetting
.
count
}
end
end
context
'Requested user'
do
it
"doesn't destroy member notification_settings"
do
member
=
create
(
:project_member
,
user:
member_user
,
requested_at:
Time
.
now
)
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
not_to
change
{
NotificationSetting
.
count
}
end
end
context
'Group member'
do
let
(
:member
)
{
group
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
before
do
group
.
add_developer
(
member_user
)
end
it
"unassigns issues and merge requests"
do
issue
=
create
:issue
,
project:
group_project
,
assignees:
[
member_user
]
create
:issue
,
assignees:
[
member_user
]
merge_request
=
create
:merge_request
,
target_project:
group_project
,
source_project:
group_project
,
assignee:
member_user
create
:merge_request
,
target_project:
project
,
source_project:
project
,
assignee:
member_user
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
number_of_assigned_issuables
(
member_user
)
}.
from
(
4
).
to
(
2
)
expect
(
issue
.
reload
.
assignee_ids
).
to
be_empty
expect
(
merge_request
.
reload
.
assignee_id
).
to
be_nil
end
it
'destroys member notification_settings'
do
group
.
add_developer
(
member_user
)
member
=
group
.
members
.
find_by
(
user_id:
member_user
.
id
)
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
member_user
.
notification_settings
.
count
}.
by
(
-
1
)
end
end
context
'Project member'
do
let
(
:member
)
{
project
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
before
do
project
.
add_developer
(
member_user
)
end
it
"unassigns issues and merge requests"
do
create
:issue
,
project:
project
,
assignees:
[
member_user
]
create
:merge_request
,
target_project:
project
,
source_project:
project
,
assignee:
member_user
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
number_of_assigned_issuables
(
member_user
)
}.
from
(
2
).
to
(
0
)
end
it
'destroys member notification_settings'
do
expect
{
described_class
.
new
(
member_user
).
execute
(
member
)
}
.
to
change
{
member_user
.
notification_settings
.
count
}.
by
(
-
1
)
end
end
end
spec/services/members/create_service_spec.rb
View file @
1c88d92b
...
@@ -11,7 +11,7 @@ describe Members::CreateService do
...
@@ -11,7 +11,7 @@ describe Members::CreateService do
it
'adds user to members'
do
it
'adds user to members'
do
params
=
{
user_ids:
project_user
.
id
.
to_s
,
access_level:
Gitlab
::
Access
::
GUEST
}
params
=
{
user_ids:
project_user
.
id
.
to_s
,
access_level:
Gitlab
::
Access
::
GUEST
}
result
=
described_class
.
new
(
project
,
user
,
params
).
execute
result
=
described_class
.
new
(
user
,
params
).
execute
(
project
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
users
).
to
include
project_user
expect
(
project
.
users
).
to
include
project_user
...
@@ -19,7 +19,7 @@ describe Members::CreateService do
...
@@ -19,7 +19,7 @@ describe Members::CreateService do
it
'adds no user to members'
do
it
'adds no user to members'
do
params
=
{
user_ids:
''
,
access_level:
Gitlab
::
Access
::
GUEST
}
params
=
{
user_ids:
''
,
access_level:
Gitlab
::
Access
::
GUEST
}
result
=
described_class
.
new
(
project
,
user
,
params
).
execute
result
=
described_class
.
new
(
user
,
params
).
execute
(
project
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
]).
to
be_present
expect
(
result
[
:message
]).
to
be_present
...
@@ -30,7 +30,7 @@ describe Members::CreateService do
...
@@ -30,7 +30,7 @@ describe Members::CreateService do
user_ids
=
1
.
upto
(
101
).
to_a
.
join
(
','
)
user_ids
=
1
.
upto
(
101
).
to_a
.
join
(
','
)
params
=
{
user_ids:
user_ids
,
access_level:
Gitlab
::
Access
::
GUEST
}
params
=
{
user_ids:
user_ids
,
access_level:
Gitlab
::
Access
::
GUEST
}
result
=
described_class
.
new
(
project
,
user
,
params
).
execute
result
=
described_class
.
new
(
user
,
params
).
execute
(
project
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
]).
to
be_present
expect
(
result
[
:message
]).
to
be_present
...
...
spec/services/members/destroy_service_spec.rb
View file @
1c88d92b
...
@@ -3,113 +3,200 @@ require 'spec_helper'
...
@@ -3,113 +3,200 @@ require 'spec_helper'
describe
Members
::
DestroyService
do
describe
Members
::
DestroyService
do
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:member_user
)
{
create
(
:user
)
}
let
(
:member_user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:group
)
{
create
(
:group
,
:public
)
}
let
(
:group
)
{
create
(
:group
,
:public
)
}
let
(
:group_project
)
{
create
(
:project
,
:public
,
group:
group
)
}
let
(
:opts
)
{
{}
}
shared_examples
'a service raising ActiveRecord::RecordNotFound'
do
shared_examples
'a service raising ActiveRecord::RecordNotFound'
do
it
'raises ActiveRecord::RecordNotFound'
do
it
'raises ActiveRecord::RecordNotFound'
do
expect
{
described_class
.
new
(
source
,
current_user
).
execute
(
member
)
}.
to
raise_error
(
ActiveRecord
::
RecordNotFound
)
expect
{
described_class
.
new
(
current_user
).
execute
(
member
)
}.
to
raise_error
(
ActiveRecord
::
RecordNotFound
)
end
end
end
end
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
expect
{
described_class
.
new
(
source
,
current_user
).
execute
(
member
)
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
expect
{
described_class
.
new
(
current_user
).
execute
(
member
)
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
end
end
end
end
def
number_of_assigned_issuables
(
user
)
Issue
.
assigned_to
(
user
).
count
+
MergeRequest
.
assigned_to
(
user
).
count
end
shared_examples
'a service destroying a member'
do
shared_examples
'a service destroying a member'
do
it
'destroys the member'
do
it
'destroys the member'
do
expect
{
described_class
.
new
(
source
,
current_user
).
execute
(
member
)
}.
to
change
{
source
.
members
.
count
}.
by
(
-
1
)
expect
{
described_class
.
new
(
current_user
).
execute
(
member
,
opts
)
}.
to
change
{
member
.
source
.
members_and_requesters
.
count
}.
by
(
-
1
)
end
it
'unassigns issues and merge requests'
do
if
member
.
invite?
expect
{
described_class
.
new
(
current_user
).
execute
(
member
,
opts
)
}
.
not_to
change
{
number_of_assigned_issuables
(
member_user
)
}
else
create
:issue
,
assignees:
[
member_user
]
issue
=
create
:issue
,
project:
group_project
,
assignees:
[
member_user
]
merge_request
=
create
:merge_request
,
target_project:
group_project
,
source_project:
group_project
,
assignee:
member_user
expect
{
described_class
.
new
(
current_user
).
execute
(
member
,
opts
)
}
.
to
change
{
number_of_assigned_issuables
(
member_user
)
}.
from
(
3
).
to
(
1
)
expect
(
issue
.
reload
.
assignee_ids
).
to
be_empty
expect
(
merge_request
.
reload
.
assignee_id
).
to
be_nil
end
end
end
end
shared_examples
'a service destroying an access requester'
do
it
'destroys member notification_settings'
do
it
'destroys the access requester'
do
if
member_user
.
notification_settings
.
any?
expect
{
described_class
.
new
(
source
,
current_user
).
execute
(
access_requester
)
}.
to
change
{
source
.
requesters
.
count
}.
by
(
-
1
)
expect
{
described_class
.
new
(
current_user
).
execute
(
member
,
opts
)
}
.
to
change
{
member_user
.
notification_settings
.
count
}.
by
(
-
1
)
else
expect
{
described_class
.
new
(
current_user
).
execute
(
member
,
opts
)
}
.
not_to
change
{
member_user
.
notification_settings
.
count
}
end
end
end
end
shared_examples
'a service destroying an access requester'
do
it_behaves_like
'a service destroying a member'
it
'calls Member#after_decline_request'
do
it
'calls Member#after_decline_request'
do
expect_any_instance_of
(
NotificationService
).
to
receive
(
:decline_access_request
).
with
(
access_request
er
)
expect_any_instance_of
(
NotificationService
).
to
receive
(
:decline_access_request
).
with
(
memb
er
)
described_class
.
new
(
source
,
current_user
).
execute
(
access_request
er
)
described_class
.
new
(
current_user
).
execute
(
memb
er
)
end
end
context
'when current user is the member'
do
context
'when current user is the member'
do
it
'does not call Member#after_decline_request'
do
it
'does not call Member#after_decline_request'
do
expect_any_instance_of
(
NotificationService
).
not_to
receive
(
:decline_access_request
).
with
(
access_request
er
)
expect_any_instance_of
(
NotificationService
).
not_to
receive
(
:decline_access_request
).
with
(
memb
er
)
described_class
.
new
(
source
,
member_user
).
execute
(
access_request
er
)
described_class
.
new
(
member_user
).
execute
(
memb
er
)
end
end
end
end
end
end
context
'with a member'
do
context
'with a member'
do
before
do
before
do
project
.
add_developer
(
member_user
)
group_
project
.
add_developer
(
member_user
)
group
.
add_developer
(
member_user
)
group
.
add_developer
(
member_user
)
end
end
let
(
:member
)
{
source
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
context
'when current user cannot destroy the given member'
do
context
'when current user cannot destroy the given member'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
project
}
let
(
:member
)
{
group_project
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
group_project
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
group
}
let
(
:member
)
{
group
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
group
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
end
end
context
'when current user can destroy the given member'
do
context
'when current user can destroy the given member'
do
before
do
before
do
project
.
add_master
(
current_user
)
group_
project
.
add_master
(
current_user
)
group
.
add_owner
(
current_user
)
group
.
add_owner
(
current_user
)
end
end
it_behaves_like
'a service destroying a member'
do
it_behaves_like
'a service destroying a member'
do
let
(
:
source
)
{
project
}
let
(
:
member
)
{
group_project
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
it_behaves_like
'a service destroying a member'
do
it_behaves_like
'a service destroying a member'
do
let
(
:
source
)
{
group
}
let
(
:
member
)
{
group
.
members
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
end
end
end
end
context
'with an access requester'
do
context
'with an access requester'
do
before
do
before
do
project
.
update_attributes
(
request_access_enabled:
true
)
group_
project
.
update_attributes
(
request_access_enabled:
true
)
group
.
update_attributes
(
request_access_enabled:
true
)
group
.
update_attributes
(
request_access_enabled:
true
)
project
.
request_access
(
member_user
)
group_
project
.
request_access
(
member_user
)
group
.
request_access
(
member_user
)
group
.
request_access
(
member_user
)
end
end
let
(
:access_requester
)
{
source
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
context
'when current user cannot destroy the given access requester'
do
context
'when current user cannot destroy the given access requester'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
project
}
let
(
:member
)
{
group_project
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
let
(
:member
)
{
access_requester
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
group_project
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:source
)
{
group
}
let
(
:member
)
{
group
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
let
(
:member
)
{
access_requester
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
group
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
end
end
context
'when current user can destroy the given access requester'
do
context
'when current user can destroy the given access requester'
do
before
do
before
do
project
.
add_master
(
current_user
)
group_
project
.
add_master
(
current_user
)
group
.
add_owner
(
current_user
)
group
.
add_owner
(
current_user
)
end
end
it_behaves_like
'a service destroying an access requester'
do
it_behaves_like
'a service destroying an access requester'
do
let
(
:
source
)
{
project
}
let
(
:
member
)
{
group_project
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
it_behaves_like
'a service destroying an access requester'
do
it_behaves_like
'a service destroying an access requester'
do
let
(
:source
)
{
group
}
let
(
:member
)
{
group
.
requesters
.
find_by
(
user_id:
member_user
.
id
)
}
end
end
end
context
'with an invited user'
do
let
(
:project_invited_member
)
{
create
(
:project_member
,
:invited
,
project:
group_project
)
}
let
(
:group_invited_member
)
{
create
(
:group_member
,
:invited
,
group:
group
)
}
context
'when current user cannot destroy the given invited user'
do
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:member
)
{
project_invited_member
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
project_invited_member
}
end
it_behaves_like
'a service raising Gitlab::Access::AccessDeniedError'
do
let
(
:member
)
{
group_invited_member
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:opts
)
{
{
skip_authorization:
true
}
}
let
(
:member
)
{
group_invited_member
}
end
end
context
'when current user can destroy the given invited user'
do
before
do
group_project
.
add_master
(
current_user
)
group
.
add_owner
(
current_user
)
end
# Regression spec for issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/32504
it_behaves_like
'a service destroying a member'
do
let
(
:member
)
{
project_invited_member
}
end
it_behaves_like
'a service destroying a member'
do
let
(
:member
)
{
group_invited_member
}
end
end
end
end
end
end
...
...
spec/services/members/request_access_service_spec.rb
View file @
1c88d92b
...
@@ -5,17 +5,17 @@ describe Members::RequestAccessService do
...
@@ -5,17 +5,17 @@ describe Members::RequestAccessService do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
expect
{
described_class
.
new
(
source
,
user
).
execute
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
expect
{
described_class
.
new
(
user
).
execute
(
source
)
}.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
end
end
end
end
shared_examples
'a service creating a access request'
do
shared_examples
'a service creating a access request'
do
it
'succeeds'
do
it
'succeeds'
do
expect
{
described_class
.
new
(
source
,
user
).
execute
}.
to
change
{
source
.
requesters
.
count
}.
by
(
1
)
expect
{
described_class
.
new
(
user
).
execute
(
source
)
}.
to
change
{
source
.
requesters
.
count
}.
by
(
1
)
end
end
it
'returns a <Source>Member'
do
it
'returns a <Source>Member'
do
member
=
described_class
.
new
(
source
,
user
).
execute
member
=
described_class
.
new
(
user
).
execute
(
source
)
expect
(
member
).
to
be_a
"
#{
source
.
class
}
Member"
.
constantize
expect
(
member
).
to
be_a
"
#{
source
.
class
}
Member"
.
constantize
expect
(
member
.
requested_at
).
to
be_present
expect
(
member
.
requested_at
).
to
be_present
...
...
spec/services/members/update_service_spec.rb
View file @
1c88d92b
...
@@ -13,14 +13,14 @@ describe Members::UpdateService do
...
@@ -13,14 +13,14 @@ describe Members::UpdateService do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
shared_examples
'a service raising Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
it
'raises Gitlab::Access::AccessDeniedError'
do
expect
{
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
member
,
permission:
permission
)
}
expect
{
described_class
.
new
(
current_user
,
params
).
execute
(
member
,
permission:
permission
)
}
.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
.
to
raise_error
(
Gitlab
::
Access
::
AccessDeniedError
)
end
end
end
end
shared_examples
'a service updating a member'
do
shared_examples
'a service updating a member'
do
it
'updates the member'
do
it
'updates the member'
do
updated_member
=
described_class
.
new
(
source
,
current_user
,
params
).
execute
(
member
,
permission:
permission
)
updated_member
=
described_class
.
new
(
current_user
,
params
).
execute
(
member
,
permission:
permission
)
expect
(
updated_member
).
to
be_valid
expect
(
updated_member
).
to
be_valid
expect
(
updated_member
.
access_level
).
to
eq
(
Gitlab
::
Access
::
MASTER
)
expect
(
updated_member
.
access_level
).
to
eq
(
Gitlab
::
Access
::
MASTER
)
...
...
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