Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
272b5c5f
Commit
272b5c5f
authored
4 years ago
by
Serena Fang
Committed by
Imre Farkas
4 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Delete project bot when token is revoked
parent
ade7aa1c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
90 additions
and
46 deletions
+90
-46
app/services/resource_access_tokens/revoke_service.rb
app/services/resource_access_tokens/revoke_service.rb
+15
-12
app/services/users/destroy_service.rb
app/services/users/destroy_service.rb
+1
-1
changelogs/unreleased/revoke-token-delete-project-bot.yml
changelogs/unreleased/revoke-token-delete-project-bot.yml
+5
-0
spec/controllers/projects/settings/access_tokens_controller_spec.rb
...ollers/projects/settings/access_tokens_controller_spec.rb
+10
-10
spec/services/resource_access_tokens/revoke_service_spec.rb
spec/services/resource_access_tokens/revoke_service_spec.rb
+51
-23
spec/services/users/destroy_service_spec.rb
spec/services/users/destroy_service_spec.rb
+8
-0
No files found.
app/services/resource_access_tokens/revoke_service.rb
View file @
272b5c5f
...
...
@@ -14,18 +14,15 @@ module ResourceAccessTokens
end
def
execute
return
error
(
"
#{
current_user
.
name
}
cannot delete
#{
bot_user
.
name
}
"
)
unless
can_destroy_bot_member?
return
error
(
"Failed to find bot user"
)
unless
find_member
PersonalAccessToken
.
transaction
do
access_token
.
revoke!
access_token
.
revoke!
raise
RevokeAccessTokenError
,
"Failed to remove
#{
bot_user
.
name
}
member from:
#{
resource
.
name
}
"
unless
remove_memb
er
destroy_bot_us
er
raise
RevokeAccessTokenError
,
"Migration to ghost user failed"
unless
migrate_to_ghost_user
end
success
(
"Revoked access token:
#{
access_token
.
name
}
"
)
rescue
ActiveRecord
::
ActiveRecordError
,
RevokeAccessTokenError
=>
error
success
(
"Access token
#{
access_token
.
name
}
has been revoked and the bot user has been scheduled for deletion."
)
rescue
StandardError
=>
error
log_error
(
"Failed to revoke access token for
#{
bot_user
.
name
}
:
#{
error
.
message
}
"
)
error
(
error
.
message
)
end
...
...
@@ -34,12 +31,18 @@ module ResourceAccessTokens
attr_reader
:current_user
,
:access_token
,
:bot_user
,
:resource
def
remove_memb
er
::
Members
::
DestroyService
.
new
(
current_user
).
execute
(
find_member
,
destroy_bot
:
true
)
def
destroy_bot_us
er
DeleteUserWorker
.
perform_async
(
current_user
.
id
,
bot_user
.
id
,
skip_authorization
:
true
)
end
def
migrate_to_ghost_user
::
Users
::
MigrateToGhostUserService
.
new
(
bot_user
).
execute
def
can_destroy_bot_member?
if
resource
.
is_a?
(
Project
)
can?
(
current_user
,
:admin_project_member
,
@resource
)
elsif
resource
.
is_a?
(
Group
)
can?
(
current_user
,
:admin_group_member
,
@resource
)
else
false
end
end
def
find_member
...
...
This diff is collapsed.
Click to expand it.
app/services/users/destroy_service.rb
View file @
272b5c5f
...
...
@@ -26,7 +26,7 @@ module Users
def
execute
(
user
,
options
=
{})
delete_solo_owned_groups
=
options
.
fetch
(
:delete_solo_owned_groups
,
options
[
:hard_delete
])
unless
Ability
.
allowed?
(
current_user
,
:destroy_user
,
user
)
unless
Ability
.
allowed?
(
current_user
,
:destroy_user
,
user
)
||
options
[
:skip_authorization
]
raise
Gitlab
::
Access
::
AccessDeniedError
,
"
#{
current_user
}
tried to destroy user
#{
user
}
!"
end
...
...
This diff is collapsed.
Click to expand it.
changelogs/unreleased/revoke-token-delete-project-bot.yml
0 → 100644
View file @
272b5c5f
---
title
:
Delete project bot when token is revoked
merge_request
:
43373
author
:
type
:
fixed
This diff is collapsed.
Click to expand it.
spec/controllers/projects/settings/access_tokens_controller_spec.rb
View file @
272b5c5f
...
...
@@ -143,15 +143,15 @@ RSpec.describe Projects::Settings::AccessTokensController do
it_behaves_like
'feature unavailable'
context
'when feature is available'
do
context
'when feature is available'
,
:sidekiq_inline
do
before
do
enable_feature
end
it
'
revokes token access
'
do
subject
it
'
calls delete user worker
'
do
expect
(
DeleteUserWorker
).
to
receive
(
:perform_async
).
with
(
user
.
id
,
bot_user
.
id
,
skip_authorization:
true
)
expect
(
project_access_token
.
reload
.
revoked?
).
to
be
true
subject
end
it
'removed membership of bot user'
do
...
...
@@ -160,12 +160,6 @@ RSpec.describe Projects::Settings::AccessTokensController do
expect
(
project
.
reload
.
bots
).
not_to
include
(
bot_user
)
end
it
'blocks project bot user'
do
subject
expect
(
bot_user
.
reload
.
blocked?
).
to
be
true
end
it
'converts issuables of the bot user to ghost user'
do
issue
=
create
(
:issue
,
author:
bot_user
)
...
...
@@ -173,6 +167,12 @@ RSpec.describe Projects::Settings::AccessTokensController do
expect
(
issue
.
reload
.
author
.
ghost?
).
to
be
true
end
it
'deletes project bot user'
do
subject
expect
(
User
.
exists?
(
bot_user
.
id
)).
to
be_falsy
end
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/services/resource_access_tokens/revoke_service_spec.rb
View file @
272b5c5f
...
...
@@ -8,17 +8,17 @@ RSpec.describe ResourceAccessTokens::RevokeService do
let_it_be
(
:user
)
{
create
(
:user
)
}
let
(
:access_token
)
{
create
(
:personal_access_token
,
user:
resource_bot
)
}
describe
'#execute'
do
describe
'#execute'
,
:sidekiq_inline
do
# Created shared_examples as it will easy to include specs for group bots in https://gitlab.com/gitlab-org/gitlab/-/issues/214046
shared_examples
'revokes access token'
do
it
{
expect
(
subject
.
success?
).
to
be
true
}
it
{
expect
(
subject
.
message
).
to
eq
(
"
Revoked access token:
#{
access_token
.
name
}
"
)
}
it
{
expect
(
subject
.
message
).
to
eq
(
"
Access token
#{
access_token
.
name
}
has been revoked and the bot user has been scheduled for deletion.
"
)
}
it
'
revokes token access
'
do
subject
it
'
calls delete user worker
'
do
expect
(
DeleteUserWorker
).
to
receive
(
:perform_async
).
with
(
user
.
id
,
resource_bot
.
id
,
skip_authorization:
true
)
expect
(
access_token
.
reload
.
revoked?
).
to
be
true
subject
end
it
'removes membership of bot user'
do
...
...
@@ -34,6 +34,12 @@ RSpec.describe ResourceAccessTokens::RevokeService do
expect
(
issue
.
reload
.
author
.
ghost?
).
to
be
true
end
it
'deletes project bot user'
do
subject
expect
(
User
.
exists?
(
resource_bot
.
id
)).
to
be_falsy
end
end
shared_examples
'rollback revoke steps'
do
...
...
@@ -56,49 +62,71 @@ RSpec.describe ResourceAccessTokens::RevokeService do
expect
(
issue
.
reload
.
author
.
ghost?
).
to
be
false
end
it
'does not destroy project bot user'
do
subject
expect
(
User
.
exists?
(
resource_bot
.
id
)).
to
be_truthy
end
end
context
'when resource is a project'
do
let_it_be
(
:resource
)
{
create
(
:project
,
:private
)
}
let
_it_be
(
:resource_bot
)
{
create
(
:user
,
:project_bot
)
}
let
(
:resource_bot
)
{
create
(
:user
,
:project_bot
)
}
before
_all
do
before
do
resource
.
add_maintainer
(
user
)
resource
.
add_maintainer
(
resource_bot
)
end
it_behaves_like
'revokes access token'
context
'when revoke fails'
do
context
'invalid resource type'
do
subject
{
described_class
.
new
(
user
,
resource
,
access_token
).
execute
}
context
'revoke fails'
do
let_it_be
(
:other_user
)
{
create
(
:user
)
}
let_it_be
(
:resource
)
{
double
}
let_it_be
(
:resource_bot
)
{
create
(
:user
,
:project_bot
)
}
context
'when access token does not belong to this project'
do
it
'does not find the bot'
do
other_access_token
=
create
(
:personal_access_token
,
user:
other_user
)
it
'returns error response'
do
response
=
subject
response
=
described_class
.
new
(
user
,
resource
,
other_access_token
).
execute
expect
(
response
.
success?
).
to
be
false
expect
(
response
.
message
).
to
eq
(
"Failed to find bot user"
)
expect
(
access_token
.
reload
.
revoked?
).
to
be
false
end
it
{
expect
{
subject
}.
not_to
change
(
access_token
.
reload
,
:revoked
)
}
end
context
'when migration to ghost user fails'
do
before
do
allow_next_instance_of
(
::
Members
::
DestroyService
)
do
|
service
|
allow
(
service
).
to
receive
(
:execute
).
and_return
(
false
)
context
'when user does not have permission to destroy bot'
do
context
'when non-project member tries to delete project bot'
do
it
'does not allow other user to delete bot'
do
response
=
described_class
.
new
(
other_user
,
resource
,
access_token
).
execute
expect
(
response
.
success?
).
to
be
false
expect
(
response
.
message
).
to
eq
(
"
#{
other_user
.
name
}
cannot delete
#{
access_token
.
user
.
name
}
"
)
expect
(
access_token
.
reload
.
revoked?
).
to
be
false
end
end
it_behaves_like
'rollback revoke steps'
context
'when non-maintainer project member tries to delete project bot'
do
let
(
:developer
)
{
create
(
:user
)
}
before
do
resource
.
add_developer
(
developer
)
end
it
'does not allow developer to delete bot'
do
response
=
described_class
.
new
(
developer
,
resource
,
access_token
).
execute
expect
(
response
.
success?
).
to
be
false
expect
(
response
.
message
).
to
eq
(
"
#{
developer
.
name
}
cannot delete
#{
access_token
.
user
.
name
}
"
)
expect
(
access_token
.
reload
.
revoked?
).
to
be
false
end
end
end
context
'when
migration to ghos
t user fails'
do
context
'when
deletion of bo
t user fails'
do
before
do
allow_next_instance_of
(
::
Users
::
MigrateToGhostUser
Service
)
do
|
service
|
allow_next_instance_of
(
::
ResourceAccessTokens
::
Revoke
Service
)
do
|
service
|
allow
(
service
).
to
receive
(
:execute
).
and_return
(
false
)
end
end
...
...
This diff is collapsed.
Click to expand it.
spec/services/users/destroy_service_spec.rb
View file @
272b5c5f
...
...
@@ -234,6 +234,14 @@ RSpec.describe Users::DestroyService do
expect
(
User
.
exists?
(
user
.
id
)).
to
be
(
false
)
end
it
'allows user to be deleted if skip_authorization: true'
do
other_user
=
create
(
:user
)
described_class
.
new
(
user
).
execute
(
other_user
,
skip_authorization:
true
)
expect
(
User
.
exists?
(
other_user
.
id
)).
to
be
(
false
)
end
end
context
"migrating associated records"
do
...
...
This diff is collapsed.
Click to expand it.
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