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
4bcd5c6e
Commit
4bcd5c6e
authored
Sep 28, 2021
by
Manoj M J
Committed by
Max Woolf
Sep 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Async auth refresh during member destroy
parent
af9e7094
Changes
27
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
268 additions
and
124 deletions
+268
-124
app/models/member.rb
app/models/member.rb
+9
-3
app/models/members/group_member.rb
app/models/members/group_member.rb
+3
-3
app/models/members/project_member.rb
app/models/members/project_member.rb
+9
-5
app/workers/all_queues.yml
app/workers/all_queues.yml
+9
-0
app/workers/authorized_project_update/project_recalculate_per_user_worker.rb
...zed_project_update/project_recalculate_per_user_worker.rb
+25
-0
app/workers/authorized_project_update/project_recalculate_worker.rb
...s/authorized_project_update/project_recalculate_worker.rb
+3
-1
config/feature_flags/ops/member_destroy_async_auth_refresh.yml
...g/feature_flags/ops/member_destroy_async_auth_refresh.yml
+8
-0
ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb
ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb
+1
-1
ee/spec/models/approval_state_spec.rb
ee/spec/models/approval_state_spec.rb
+1
-1
ee/spec/services/todo_service_spec.rb
ee/spec/services/todo_service_spec.rb
+1
-1
spec/controllers/projects/branches_controller_spec.rb
spec/controllers/projects/branches_controller_spec.rb
+1
-1
spec/controllers/projects/compare_controller_spec.rb
spec/controllers/projects/compare_controller_spec.rb
+1
-1
spec/graphql/types/project_type_spec.rb
spec/graphql/types/project_type_spec.rb
+5
-5
spec/lib/gitlab/middleware/go_spec.rb
spec/lib/gitlab/middleware/go_spec.rb
+1
-1
spec/lib/gitlab/slash_commands/issue_move_spec.rb
spec/lib/gitlab/slash_commands/issue_move_spec.rb
+1
-1
spec/models/member_spec.rb
spec/models/member_spec.rb
+27
-27
spec/models/members/project_member_spec.rb
spec/models/members/project_member_spec.rb
+25
-5
spec/models/user_spec.rb
spec/models/user_spec.rb
+60
-60
spec/requests/api/package_files_spec.rb
spec/requests/api/package_files_spec.rb
+1
-1
spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
...rializers/merge_request_poll_cached_widget_entity_spec.rb
+1
-1
spec/services/merge_requests/assign_issues_service_spec.rb
spec/services/merge_requests/assign_issues_service_spec.rb
+1
-1
spec/services/merge_requests/build_service_spec.rb
spec/services/merge_requests/build_service_spec.rb
+1
-1
spec/services/merge_requests/push_options_handler_service_spec.rb
...vices/merge_requests/push_options_handler_service_spec.rb
+1
-1
spec/services/notes/quick_actions_service_spec.rb
spec/services/notes/quick_actions_service_spec.rb
+1
-1
spec/services/notification_service_spec.rb
spec/services/notification_service_spec.rb
+1
-1
spec/services/projects/move_access_service_spec.rb
spec/services/projects/move_access_service_spec.rb
+1
-1
spec/workers/authorized_project_update/project_recalculate_per_user_worker_spec.rb
...roject_update/project_recalculate_per_user_worker_spec.rb
+70
-0
No files found.
app/models/member.rb
View file @
4bcd5c6e
...
@@ -178,7 +178,13 @@ class Member < ApplicationRecord
...
@@ -178,7 +178,13 @@ class Member < ApplicationRecord
after_destroy
:post_destroy_hook
,
unless: :pending?
,
if: :hook_prerequisites_met?
after_destroy
:post_destroy_hook
,
unless: :pending?
,
if: :hook_prerequisites_met?
after_save
:log_invitation_token_cleanup
after_save
:log_invitation_token_cleanup
after_commit
:refresh_member_authorized_projects
,
unless: :importing?
after_commit
on:
[
:create
,
:update
],
unless: :importing?
do
refresh_member_authorized_projects
(
blocking:
true
)
end
after_commit
on:
[
:destroy
],
unless: :importing?
do
refresh_member_authorized_projects
(
blocking:
Feature
.
disabled?
(
:member_destroy_async_auth_refresh
,
type: :ops
))
end
default_value_for
:notification_level
,
NotificationSetting
.
levels
[
:global
]
default_value_for
:notification_level
,
NotificationSetting
.
levels
[
:global
]
...
@@ -395,8 +401,8 @@ class Member < ApplicationRecord
...
@@ -395,8 +401,8 @@ class Member < ApplicationRecord
# transaction has been committed, resulting in the job either throwing an
# transaction has been committed, resulting in the job either throwing an
# error or not doing any meaningful work.
# error or not doing any meaningful work.
# rubocop: disable CodeReuse/ServiceClass
# rubocop: disable CodeReuse/ServiceClass
def
refresh_member_authorized_projects
def
refresh_member_authorized_projects
(
blocking
:)
UserProjectAccessChangedService
.
new
(
user_id
).
execute
UserProjectAccessChangedService
.
new
(
user_id
).
execute
(
blocking:
blocking
)
end
end
# rubocop: enable CodeReuse/ServiceClass
# rubocop: enable CodeReuse/ServiceClass
...
...
app/models/members/group_member.rb
View file @
4bcd5c6e
...
@@ -50,8 +50,10 @@ class GroupMember < Member
...
@@ -50,8 +50,10 @@ class GroupMember < Member
{
group:
group
}
{
group:
group
}
end
end
private
override
:refresh_member_authorized_projects
override
:refresh_member_authorized_projects
def
refresh_member_authorized_projects
def
refresh_member_authorized_projects
(
blocking
:)
# Here, `destroyed_by_association` will be present if the
# Here, `destroyed_by_association` will be present if the
# GroupMember is being destroyed due to the `dependent: :destroy`
# GroupMember is being destroyed due to the `dependent: :destroy`
# callback on Group. In this case, there is no need to refresh the
# callback on Group. In this case, there is no need to refresh the
...
@@ -63,8 +65,6 @@ class GroupMember < Member
...
@@ -63,8 +65,6 @@ class GroupMember < Member
super
super
end
end
private
def
access_level_inclusion
def
access_level_inclusion
return
if
access_level
.
in?
(
Gitlab
::
Access
.
all_values
)
return
if
access_level
.
in?
(
Gitlab
::
Access
.
all_values
)
...
...
app/models/members/project_member.rb
View file @
4bcd5c6e
...
@@ -90,24 +90,28 @@ class ProjectMember < Member
...
@@ -90,24 +90,28 @@ class ProjectMember < Member
{
project:
project
}
{
project:
project
}
end
end
private
override
:refresh_member_authorized_projects
override
:refresh_member_authorized_projects
def
refresh_member_authorized_projects
def
refresh_member_authorized_projects
(
blocking
:)
return
super
unless
Feature
.
enabled?
(
:specialized_service_for_project_member_auth_refresh
)
return
super
unless
Feature
.
enabled?
(
:specialized_service_for_project_member_auth_refresh
)
return
unless
user
return
unless
user
# rubocop:disable CodeReuse/ServiceClass
# rubocop:disable CodeReuse/ServiceClass
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserService
.
new
(
project
,
user
).
execute
if
blocking
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserService
.
new
(
project
,
user
).
execute
else
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserWorker
.
perform_async
(
project
.
id
,
user
.
id
)
end
# Until we compare the inconsistency rates of the new, specialized service and
# Until we compare the inconsistency rates of the new, specialized service and
# the old approach, we still run AuthorizedProjectsWorker
# the old approach, we still run AuthorizedProjectsWorker
# but with some delay and lower urgency as a safety net.
# but with some delay and lower urgency as a safety net.
UserProjectAccessChangedService
.
new
(
user_id
)
UserProjectAccessChangedService
.
new
(
user_id
)
.
execute
(
blocking:
false
,
priority:
UserProjectAccessChangedService
::
LOW_PRIORITY
)
.
execute
(
blocking:
false
,
priority:
UserProjectAccessChangedService
::
LOW_PRIORITY
)
# rubocop:enable CodeReuse/ServiceClass
# rubocop:enable CodeReuse/ServiceClass
end
end
private
def
send_invite
def
send_invite
run_after_commit_or_now
{
notification_service
.
invite_project_member
(
self
,
@raw_invite_token
)
}
run_after_commit_or_now
{
notification_service
.
invite_project_member
(
self
,
@raw_invite_token
)
}
...
...
app/workers/all_queues.yml
View file @
4bcd5c6e
...
@@ -30,6 +30,15 @@
...
@@ -30,6 +30,15 @@
:weight:
1
:weight:
1
:idempotent:
true
:idempotent:
true
:tags: []
:tags: []
-
:name: authorized_project_update:authorized_project_update_project_recalculate_per_user
:worker_name: AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker
:feature_category: :authentication_and_authorization
:has_external_dependencies:
:urgency: :high
:resource_boundary: :unknown
:weight:
1
:idempotent:
true
:tags: []
-
:name: authorized_project_update:authorized_project_update_user_refresh_from_replica
-
:name: authorized_project_update:authorized_project_update_user_refresh_from_replica
:worker_name: AuthorizedProjectUpdate::UserRefreshFromReplicaWorker
:worker_name: AuthorizedProjectUpdate::UserRefreshFromReplicaWorker
:feature_category: :authentication_and_authorization
:feature_category: :authentication_and_authorization
...
...
app/workers/authorized_project_update/project_recalculate_per_user_worker.rb
0 → 100644
View file @
4bcd5c6e
# frozen_string_literal: true
module
AuthorizedProjectUpdate
class
ProjectRecalculatePerUserWorker
<
ProjectRecalculateWorker
data_consistency
:always
feature_category
:authentication_and_authorization
urgency
:high
queue_namespace
:authorized_project_update
deduplicate
:until_executing
,
including_scheduled:
true
idempotent!
def
perform
(
project_id
,
user_id
)
project
=
Project
.
find_by_id
(
project_id
)
user
=
User
.
find_by_id
(
user_id
)
return
unless
project
&&
user
in_lock
(
lock_key
(
project
),
ttl:
10
.
seconds
)
do
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserService
.
new
(
project
,
user
).
execute
end
end
end
end
app/workers/authorized_project_update/project_recalculate_worker.rb
View file @
4bcd5c6e
...
@@ -26,7 +26,9 @@ module AuthorizedProjectUpdate
...
@@ -26,7 +26,9 @@ module AuthorizedProjectUpdate
private
private
def
lock_key
(
project
)
def
lock_key
(
project
)
"
#{
self
.
class
.
name
.
underscore
}
/projects/
#{
project
.
id
}
"
# The self.class.name.underscore value is hardcoded here as the prefix, so that the same
# lock_key for this superclass will be used by the ProjectRecalculatePerUserWorker subclass.
"authorized_project_update/project_recalculate_worker/projects/
#{
project
.
id
}
"
end
end
end
end
end
end
config/feature_flags/ops/member_destroy_async_auth_refresh.yml
0 → 100644
View file @
4bcd5c6e
---
name
:
member_destroy_async_auth_refresh
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66424
rollout_issue_url
:
milestone
:
'
14.4'
type
:
ops
group
:
group::access
default_enabled
:
false
ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb
View file @
4bcd5c6e
...
@@ -282,7 +282,7 @@ RSpec.describe EE::Gitlab::Auth::Ldap::Sync::Group do
...
@@ -282,7 +282,7 @@ RSpec.describe EE::Gitlab::Auth::Ldap::Sync::Group do
.
to
eq
(
::
Gitlab
::
Access
::
OWNER
)
.
to
eq
(
::
Gitlab
::
Access
::
OWNER
)
end
end
it
'updates projects authorizations'
do
it
'updates projects authorizations'
,
:sidekiq_inline
do
project
=
create
(
:project
,
namespace:
group
)
project
=
create
(
:project
,
namespace:
group
)
group
.
add_user
(
user
,
Gitlab
::
Access
::
MAINTAINER
)
group
.
add_user
(
user
,
Gitlab
::
Access
::
MAINTAINER
)
...
...
ee/spec/models/approval_state_spec.rb
View file @
4bcd5c6e
...
@@ -1336,7 +1336,7 @@ RSpec.describe ApprovalState do
...
@@ -1336,7 +1336,7 @@ RSpec.describe ApprovalState do
expect
(
subject
.
can_approve?
(
nil
)).
to
be_falsey
expect
(
subject
.
can_approve?
(
nil
)).
to
be_falsey
end
end
context
'when an approver does not have access to the merge request'
do
context
'when an approver does not have access to the merge request'
,
:sidekiq_inline
do
before
do
before
do
project
.
members
.
find_by
(
user_id:
developer
.
id
).
destroy!
project
.
members
.
find_by
(
user_id:
developer
.
id
).
destroy!
end
end
...
...
ee/spec/services/todo_service_spec.rb
View file @
4bcd5c6e
...
@@ -324,7 +324,7 @@ RSpec.describe TodoService do
...
@@ -324,7 +324,7 @@ RSpec.describe TodoService do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
,
author:
author
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
,
author:
author
)
}
context
'an approver has lost access to the project'
do
context
'an approver has lost access to the project'
,
:sidekiq_inline
do
before
do
before
do
create
(
:approver
,
user:
non_member
,
target:
project
)
create
(
:approver
,
user:
non_member
,
target:
project
)
project
.
members
.
find_by
(
user_id:
non_member
.
id
).
destroy
project
.
members
.
find_by
(
user_id:
non_member
.
id
).
destroy
...
...
spec/controllers/projects/branches_controller_spec.rb
View file @
4bcd5c6e
...
@@ -239,7 +239,7 @@ RSpec.describe Projects::BranchesController do
...
@@ -239,7 +239,7 @@ RSpec.describe Projects::BranchesController do
end
end
end
end
context
'without issue feature access'
do
context
'without issue feature access'
,
:sidekiq_inline
do
before
do
before
do
project
.
update!
(
visibility_level:
Gitlab
::
VisibilityLevel
::
PUBLIC
)
project
.
update!
(
visibility_level:
Gitlab
::
VisibilityLevel
::
PUBLIC
)
project
.
project_feature
.
update!
(
issues_access_level:
ProjectFeature
::
PRIVATE
)
project
.
project_feature
.
update!
(
issues_access_level:
ProjectFeature
::
PRIVATE
)
...
...
spec/controllers/projects/compare_controller_spec.rb
View file @
4bcd5c6e
...
@@ -409,7 +409,7 @@ RSpec.describe Projects::CompareController do
...
@@ -409,7 +409,7 @@ RSpec.describe Projects::CompareController do
end
end
end
end
context
'when the user does not have access to the project'
do
context
'when the user does not have access to the project'
,
:sidekiq_inline
do
before
do
before
do
project
.
team
.
truncate
project
.
team
.
truncate
project
.
update!
(
visibility:
'private'
)
project
.
update!
(
visibility:
'private'
)
...
...
spec/graphql/types/project_type_spec.rb
View file @
4bcd5c6e
...
@@ -186,7 +186,7 @@ RSpec.describe GitlabSchema.types['Project'] do
...
@@ -186,7 +186,7 @@ RSpec.describe GitlabSchema.types['Project'] do
expect
(
analyzer
[
'enabled'
]).
to
eq
(
true
)
expect
(
analyzer
[
'enabled'
]).
to
eq
(
true
)
end
end
context
"with guest user"
do
context
'with guest user'
do
before
do
before
do
project
.
add_guest
(
user
)
project
.
add_guest
(
user
)
end
end
...
@@ -194,7 +194,7 @@ RSpec.describe GitlabSchema.types['Project'] do
...
@@ -194,7 +194,7 @@ RSpec.describe GitlabSchema.types['Project'] do
context
'when project is private'
do
context
'when project is private'
do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
it
"returns no configuration"
do
it
'returns no configuration'
do
secure_analyzers_prefix
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
)
secure_analyzers_prefix
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
)
expect
(
secure_analyzers_prefix
).
to
be_nil
expect
(
secure_analyzers_prefix
).
to
be_nil
end
end
...
@@ -214,7 +214,7 @@ RSpec.describe GitlabSchema.types['Project'] do
...
@@ -214,7 +214,7 @@ RSpec.describe GitlabSchema.types['Project'] do
end
end
end
end
context
"with non-member user"
do
context
'with non-member user'
,
:sidekiq_inline
do
before
do
before
do
project
.
team
.
truncate
project
.
team
.
truncate
end
end
...
@@ -222,7 +222,7 @@ RSpec.describe GitlabSchema.types['Project'] do
...
@@ -222,7 +222,7 @@ RSpec.describe GitlabSchema.types['Project'] do
context
'when project is private'
do
context
'when project is private'
do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
it
"returns no configuration"
do
it
'returns no configuration'
do
secure_analyzers_prefix
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
)
secure_analyzers_prefix
=
subject
.
dig
(
'data'
,
'project'
,
'sastCiConfiguration'
)
expect
(
secure_analyzers_prefix
).
to
be_nil
expect
(
secure_analyzers_prefix
).
to
be_nil
end
end
...
@@ -240,7 +240,7 @@ RSpec.describe GitlabSchema.types['Project'] do
...
@@ -240,7 +240,7 @@ RSpec.describe GitlabSchema.types['Project'] do
end
end
context
'when repository is accessible only by team members'
do
context
'when repository is accessible only by team members'
do
it
"returns no configuration"
do
it
'returns no configuration'
do
project
.
project_feature
.
update!
(
project
.
project_feature
.
update!
(
merge_requests_access_level:
ProjectFeature
::
DISABLED
,
merge_requests_access_level:
ProjectFeature
::
DISABLED
,
builds_access_level:
ProjectFeature
::
DISABLED
,
builds_access_level:
ProjectFeature
::
DISABLED
,
...
...
spec/lib/gitlab/middleware/go_spec.rb
View file @
4bcd5c6e
...
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::Middleware::Go do
...
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::Middleware::Go do
end
end
end
end
context
'without access to the project'
do
context
'without access to the project'
,
:sidekiq_inline
do
before
do
before
do
project
.
team
.
find_member
(
current_user
).
destroy
project
.
team
.
find_member
(
current_user
).
destroy
end
end
...
...
spec/lib/gitlab/slash_commands/issue_move_spec.rb
View file @
4bcd5c6e
...
@@ -95,7 +95,7 @@ RSpec.describe Gitlab::SlashCommands::IssueMove, service: true do
...
@@ -95,7 +95,7 @@ RSpec.describe Gitlab::SlashCommands::IssueMove, service: true do
end
end
end
end
context
'when the user cannot see the target project'
do
context
'when the user cannot see the target project'
,
:sidekiq_inline
do
it
'returns not found'
do
it
'returns not found'
do
message
=
"issue move
#{
issue
.
iid
}
#{
other_project
.
full_path
}
"
message
=
"issue move
#{
issue
.
iid
}
#{
other_project
.
full_path
}
"
other_project
.
team
.
truncate
other_project
.
team
.
truncate
...
...
spec/models/member_spec.rb
View file @
4bcd5c6e
...
@@ -7,11 +7,11 @@ RSpec.describe Member do
...
@@ -7,11 +7,11 @@ RSpec.describe Member do
using
RSpec
::
Parameterized
::
TableSyntax
using
RSpec
::
Parameterized
::
TableSyntax
describe
"Associations"
do
describe
'Associations'
do
it
{
is_expected
.
to
belong_to
(
:user
)
}
it
{
is_expected
.
to
belong_to
(
:user
)
}
end
end
describe
"Validation"
do
describe
'Validation'
do
subject
{
described_class
.
new
(
access_level:
Member
::
GUEST
)
}
subject
{
described_class
.
new
(
access_level:
Member
::
GUEST
)
}
it
{
is_expected
.
to
validate_presence_of
(
:user
)
}
it
{
is_expected
.
to
validate_presence_of
(
:user
)
}
...
@@ -28,7 +28,7 @@ RSpec.describe Member do
...
@@ -28,7 +28,7 @@ RSpec.describe Member do
subject
{
build
(
:project_member
)
}
subject
{
build
(
:project_member
)
}
end
end
context
"when an invite email is provided"
do
context
'when an invite email is provided'
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:member
)
{
build
(
:project_member
,
source:
project
,
invite_email:
"user@example.com"
,
user:
nil
)
}
let
(
:member
)
{
build
(
:project_member
,
source:
project
,
invite_email:
"user@example.com"
,
user:
nil
)
}
...
@@ -37,29 +37,29 @@ RSpec.describe Member do
...
@@ -37,29 +37,29 @@ RSpec.describe Member do
expect
(
member
).
to
be_valid
expect
(
member
).
to
be_valid
end
end
it
"requires a valid invite email"
do
it
'requires a valid invite email'
do
member
.
invite_email
=
"nope"
member
.
invite_email
=
"nope"
expect
(
member
).
not_to
be_valid
expect
(
member
).
not_to
be_valid
end
end
it
"requires a unique invite email scoped to this source"
do
it
'requires a unique invite email scoped to this source'
do
create
(
:project_member
,
source:
member
.
source
,
invite_email:
member
.
invite_email
)
create
(
:project_member
,
source:
member
.
source
,
invite_email:
member
.
invite_email
)
expect
(
member
).
not_to
be_valid
expect
(
member
).
not_to
be_valid
end
end
end
end
context
"when an invite email is not provided"
do
context
'when an invite email is not provided'
do
let
(
:member
)
{
build
(
:project_member
)
}
let
(
:member
)
{
build
(
:project_member
)
}
it
"requires a user"
do
it
'requires a user'
do
member
.
user
=
nil
member
.
user
=
nil
expect
(
member
).
not_to
be_valid
expect
(
member
).
not_to
be_valid
end
end
it
"is valid otherwise"
do
it
'is valid otherwise'
do
expect
(
member
).
to
be_valid
expect
(
member
).
to
be_valid
end
end
end
end
...
@@ -107,13 +107,13 @@ RSpec.describe Member do
...
@@ -107,13 +107,13 @@ RSpec.describe Member do
end
end
end
end
context
"when a child member inherits its access level"
do
context
'when a child member inherits its access level'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:member
)
{
create
(
:group_member
,
:developer
,
user:
user
)
}
let
(
:member
)
{
create
(
:group_member
,
:developer
,
user:
user
)
}
let
(
:child_group
)
{
create
(
:group
,
parent:
member
.
group
)
}
let
(
:child_group
)
{
create
(
:group
,
parent:
member
.
group
)
}
let
(
:child_member
)
{
build
(
:group_member
,
group:
child_group
,
user:
user
)
}
let
(
:child_member
)
{
build
(
:group_member
,
group:
child_group
,
user:
user
)
}
it
"requires a higher level"
do
it
'requires a higher level'
do
child_member
.
access_level
=
GroupMember
::
REPORTER
child_member
.
access_level
=
GroupMember
::
REPORTER
child_member
.
validate
child_member
.
validate
...
@@ -123,7 +123,7 @@ RSpec.describe Member do
...
@@ -123,7 +123,7 @@ RSpec.describe Member do
# Membership in a subgroup confers certain access rights, such as being
# Membership in a subgroup confers certain access rights, such as being
# able to merge or push code to protected branches.
# able to merge or push code to protected branches.
it
"is valid with an equal level"
do
it
'is valid with an equal level'
do
child_member
.
access_level
=
GroupMember
::
DEVELOPER
child_member
.
access_level
=
GroupMember
::
DEVELOPER
child_member
.
validate
child_member
.
validate
...
@@ -131,7 +131,7 @@ RSpec.describe Member do
...
@@ -131,7 +131,7 @@ RSpec.describe Member do
expect
(
child_member
).
to
be_valid
expect
(
child_member
).
to
be_valid
end
end
it
"is valid with a higher level"
do
it
'is valid with a higher level'
do
child_member
.
access_level
=
GroupMember
::
MAINTAINER
child_member
.
access_level
=
GroupMember
::
MAINTAINER
child_member
.
validate
child_member
.
validate
...
@@ -538,7 +538,7 @@ RSpec.describe Member do
...
@@ -538,7 +538,7 @@ RSpec.describe Member do
end
end
end
end
describe
"Delegate methods"
do
describe
'Delegate methods'
do
it
{
is_expected
.
to
respond_to
(
:user_name
)
}
it
{
is_expected
.
to
respond_to
(
:user_name
)
}
it
{
is_expected
.
to
respond_to
(
:user_email
)
}
it
{
is_expected
.
to
respond_to
(
:user_email
)
}
end
end
...
@@ -608,29 +608,29 @@ RSpec.describe Member do
...
@@ -608,29 +608,29 @@ RSpec.describe Member do
end
end
end
end
describe
"#accept_invite!"
do
describe
'#accept_invite!'
do
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
it
"resets the invite token"
do
it
'resets the invite token'
do
member
.
accept_invite!
(
user
)
member
.
accept_invite!
(
user
)
expect
(
member
.
invite_token
).
to
be_nil
expect
(
member
.
invite_token
).
to
be_nil
end
end
it
"sets the invite accepted timestamp"
do
it
'sets the invite accepted timestamp'
do
member
.
accept_invite!
(
user
)
member
.
accept_invite!
(
user
)
expect
(
member
.
invite_accepted_at
).
not_to
be_nil
expect
(
member
.
invite_accepted_at
).
not_to
be_nil
end
end
it
"sets the user"
do
it
'sets the user'
do
member
.
accept_invite!
(
user
)
member
.
accept_invite!
(
user
)
expect
(
member
.
user
).
to
eq
(
user
)
expect
(
member
.
user
).
to
eq
(
user
)
end
end
it
"calls #after_accept_invite"
do
it
'calls #after_accept_invite'
do
expect
(
member
).
to
receive
(
:after_accept_invite
)
expect
(
member
).
to
receive
(
:after_accept_invite
)
member
.
accept_invite!
(
user
)
member
.
accept_invite!
(
user
)
...
@@ -657,26 +657,26 @@ RSpec.describe Member do
...
@@ -657,26 +657,26 @@ RSpec.describe Member do
end
end
end
end
describe
"#decline_invite!"
do
describe
'#decline_invite!'
do
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
it
"destroys the member"
do
it
'destroys the member'
do
member
.
decline_invite!
member
.
decline_invite!
expect
(
member
).
to
be_destroyed
expect
(
member
).
to
be_destroyed
end
end
it
"calls #after_decline_invite"
do
it
'calls #after_decline_invite'
do
expect
(
member
).
to
receive
(
:after_decline_invite
)
expect
(
member
).
to
receive
(
:after_decline_invite
)
member
.
decline_invite!
member
.
decline_invite!
end
end
end
end
describe
"#generate_invite_token"
do
describe
'#generate_invite_token'
do
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
let!
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
user:
nil
)
}
it
"sets the invite token"
do
it
'sets the invite token'
do
expect
{
member
.
generate_invite_token
}.
to
change
{
member
.
invite_token
}
expect
{
member
.
generate_invite_token
}.
to
change
{
member
.
invite_token
}
end
end
end
end
...
@@ -684,12 +684,12 @@ RSpec.describe Member do
...
@@ -684,12 +684,12 @@ RSpec.describe Member do
describe
'generate invite token on create'
do
describe
'generate invite token on create'
do
let!
(
:member
)
{
build
(
:project_member
,
invite_email:
"user@example.com"
)
}
let!
(
:member
)
{
build
(
:project_member
,
invite_email:
"user@example.com"
)
}
it
"sets the invite token"
do
it
'sets the invite token'
do
expect
{
member
.
save!
}.
to
change
{
member
.
invite_token
}.
to
(
kind_of
(
String
))
expect
{
member
.
save!
}.
to
change
{
member
.
invite_token
}.
to
(
kind_of
(
String
))
end
end
context
'when invite was already accepted'
do
context
'when invite was already accepted'
do
it
"does not set invite token"
do
it
'does not set invite token'
do
member
.
invite_accepted_at
=
1
.
day
.
ago
member
.
invite_accepted_at
=
1
.
day
.
ago
expect
{
member
.
save!
}.
not_to
change
{
member
.
invite_token
}.
from
(
nil
)
expect
{
member
.
save!
}.
not_to
change
{
member
.
invite_token
}.
from
(
nil
)
...
@@ -744,7 +744,7 @@ RSpec.describe Member do
...
@@ -744,7 +744,7 @@ RSpec.describe Member do
end
end
end
end
describe
"#invite_to_unknown_user?"
do
describe
'#invite_to_unknown_user?'
do
subject
{
member
.
invite_to_unknown_user?
}
subject
{
member
.
invite_to_unknown_user?
}
let
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
invite_token:
'1234'
,
user:
user
)
}
let
(
:member
)
{
create
(
:project_member
,
invite_email:
"user@example.com"
,
invite_token:
'1234'
,
user:
user
)
}
...
@@ -762,7 +762,7 @@ RSpec.describe Member do
...
@@ -762,7 +762,7 @@ RSpec.describe Member do
end
end
end
end
describe
"destroying a record"
,
:delet
e
do
describe
'destroying a record'
,
:delete
,
:sidekiq_inlin
e
do
it
"refreshes user's authorized projects"
do
it
"refreshes user's authorized projects"
do
project
=
create
(
:project
,
:private
)
project
=
create
(
:project
,
:private
)
user
=
create
(
:user
)
user
=
create
(
:user
)
...
...
spec/models/members/project_member_spec.rb
View file @
4bcd5c6e
...
@@ -244,12 +244,32 @@ RSpec.describe ProjectMember do
...
@@ -244,12 +244,32 @@ RSpec.describe ProjectMember do
project
.
add_user
(
user
,
Gitlab
::
Access
::
GUEST
)
project
.
add_user
(
user
,
Gitlab
::
Access
::
GUEST
)
end
end
it
'changes access level'
do
context
'when :member_destroy_async_auth_refresh feature flag is enabled'
do
expect
{
action
}.
to
change
{
user
.
can?
(
:guest_access
,
project
)
}.
from
(
true
).
to
(
false
)
it
'changes access level'
,
:sidekiq_inline
do
expect
{
action
}.
to
change
{
user
.
can?
(
:guest_access
,
project
)
}.
from
(
true
).
to
(
false
)
end
it
'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker to recalculate authorizations'
do
expect
(
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserWorker
).
to
receive
(
:perform_async
).
with
(
project
.
id
,
user
.
id
)
action
end
it_behaves_like
'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
end
end
it_behaves_like
'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserService to recalculate authorizations'
context
'when :member_destroy_async_auth_refresh feature flag is disabled'
do
it_behaves_like
'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
before
do
stub_feature_flags
(
member_destroy_async_auth_refresh:
false
)
end
it
'changes access level'
do
expect
{
action
}.
to
change
{
user
.
can?
(
:guest_access
,
project
)
}.
from
(
true
).
to
(
false
)
end
it_behaves_like
'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserService to recalculate authorizations'
it_behaves_like
'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
end
end
end
context
'when the feature flag `specialized_service_for_project_member_auth_refresh` is disabled'
do
context
'when the feature flag `specialized_service_for_project_member_auth_refresh` is disabled'
do
...
@@ -298,7 +318,7 @@ RSpec.describe ProjectMember do
...
@@ -298,7 +318,7 @@ RSpec.describe ProjectMember do
project
.
add_user
(
user
,
Gitlab
::
Access
::
GUEST
)
project
.
add_user
(
user
,
Gitlab
::
Access
::
GUEST
)
end
end
it
'changes access level'
do
it
'changes access level'
,
:sidekiq_inline
do
expect
{
action
}.
to
change
{
user
.
can?
(
:guest_access
,
project
)
}.
from
(
true
).
to
(
false
)
expect
{
action
}.
to
change
{
user
.
can?
(
:guest_access
,
project
)
}.
from
(
true
).
to
(
false
)
end
end
...
...
spec/models/user_spec.rb
View file @
4bcd5c6e
This diff is collapsed.
Click to expand it.
spec/requests/api/package_files_spec.rb
View file @
4bcd5c6e
...
@@ -38,7 +38,7 @@ RSpec.describe API::PackageFiles do
...
@@ -38,7 +38,7 @@ RSpec.describe API::PackageFiles do
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
it
'returns 404 for a user without access to the project'
do
it
'returns 404 for a user without access to the project'
,
:sidekiq_inline
do
project
.
team
.
truncate
project
.
team
.
truncate
get
api
(
url
,
user
)
get
api
(
url
,
user
)
...
...
spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
View file @
4bcd5c6e
...
@@ -275,7 +275,7 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
...
@@ -275,7 +275,7 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
expect
(
subject
[
:merge_pipeline
]).
to
be_nil
expect
(
subject
[
:merge_pipeline
]).
to
be_nil
end
end
context
'when is merged'
do
context
'when is merged'
,
:sidekiq_inline
do
let
(
:resource
)
{
create
(
:merged_merge_request
,
source_project:
project
,
merge_commit_sha:
project
.
commit
.
id
)
}
let
(
:resource
)
{
create
(
:merged_merge_request
,
source_project:
project
,
merge_commit_sha:
project
.
commit
.
id
)
}
let
(
:pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
,
ref:
resource
.
target_branch
,
sha:
resource
.
merge_commit_sha
)
}
let
(
:pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
,
ref:
resource
.
target_branch
,
sha:
resource
.
merge_commit_sha
)
}
...
...
spec/services/merge_requests/assign_issues_service_spec.rb
View file @
4bcd5c6e
...
@@ -17,7 +17,7 @@ RSpec.describe MergeRequests::AssignIssuesService do
...
@@ -17,7 +17,7 @@ RSpec.describe MergeRequests::AssignIssuesService do
expect
(
service
.
assignable_issues
.
map
(
&
:id
)).
to
include
(
issue
.
id
)
expect
(
service
.
assignable_issues
.
map
(
&
:id
)).
to
include
(
issue
.
id
)
end
end
it
'ignores issues the user cannot update assignee on'
do
it
'ignores issues the user cannot update assignee on'
,
:sidekiq_inline
do
project
.
team
.
truncate
project
.
team
.
truncate
expect
(
service
.
assignable_issues
).
to
be_empty
expect
(
service
.
assignable_issues
).
to
be_empty
...
...
spec/services/merge_requests/build_service_spec.rb
View file @
4bcd5c6e
...
@@ -440,7 +440,7 @@ RSpec.describe MergeRequests::BuildService do
...
@@ -440,7 +440,7 @@ RSpec.describe MergeRequests::BuildService do
expect
(
merge_request
.
title
).
to
eq
(
'Closes #1234 Second commit'
)
expect
(
merge_request
.
title
).
to
eq
(
'Closes #1234 Second commit'
)
end
end
it
'adds the remaining lines of the first multi-line commit message as the description'
do
it
'adds the remaining lines of the first multi-line commit message as the description'
,
:sidekiq_inline
do
expect
(
merge_request
.
description
).
to
eq
(
'Create the app'
)
expect
(
merge_request
.
description
).
to
eq
(
'Create the app'
)
end
end
end
end
...
...
spec/services/merge_requests/push_options_handler_service_spec.rb
View file @
4bcd5c6e
...
@@ -701,7 +701,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
...
@@ -701,7 +701,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
let
(
:push_options
)
{
{
create:
true
}
}
let
(
:push_options
)
{
{
create:
true
}
}
let
(
:changes
)
{
new_branch_changes
}
let
(
:changes
)
{
new_branch_changes
}
it
'records an error'
do
it
'records an error'
,
:sidekiq_inline
do
Members
::
DestroyService
.
new
(
user1
).
execute
(
ProjectMember
.
find_by!
(
user_id:
user1
.
id
))
Members
::
DestroyService
.
new
(
user1
).
execute
(
ProjectMember
.
find_by!
(
user_id:
user1
.
id
))
service
.
execute
service
.
execute
...
...
spec/services/notes/quick_actions_service_spec.rb
View file @
4bcd5c6e
...
@@ -47,7 +47,7 @@ RSpec.describe Notes::QuickActionsService do
...
@@ -47,7 +47,7 @@ RSpec.describe Notes::QuickActionsService do
let
(
:note_text
)
{
"/relate
#{
other_issue
.
to_reference
}
"
}
let
(
:note_text
)
{
"/relate
#{
other_issue
.
to_reference
}
"
}
let
(
:note
)
{
create
(
:note_on_issue
,
noteable:
issue
,
project:
project
,
note:
note_text
)
}
let
(
:note
)
{
create
(
:note_on_issue
,
noteable:
issue
,
project:
project
,
note:
note_text
)
}
context
'user cannot relate issues'
do
context
'user cannot relate issues'
,
:sidekiq_inline
do
before
do
before
do
project
.
team
.
find_member
(
maintainer
.
id
).
destroy!
project
.
team
.
find_member
(
maintainer
.
id
).
destroy!
project
.
update!
(
visibility:
Gitlab
::
VisibilityLevel
::
PUBLIC
)
project
.
update!
(
visibility:
Gitlab
::
VisibilityLevel
::
PUBLIC
)
...
...
spec/services/notification_service_spec.rb
View file @
4bcd5c6e
...
@@ -3155,7 +3155,7 @@ RSpec.describe NotificationService, :mailer do
...
@@ -3155,7 +3155,7 @@ RSpec.describe NotificationService, :mailer do
notification
.
pipeline_finished
(
pipeline
)
notification
.
pipeline_finished
(
pipeline
)
end
end
it
'does not send emails'
do
it
'does not send emails'
,
:sidekiq_inline
do
should_not_email_anyone
should_not_email_anyone
end
end
end
end
...
...
spec/services/projects/move_access_service_spec.rb
View file @
4bcd5c6e
...
@@ -26,7 +26,7 @@ RSpec.describe Projects::MoveAccessService do
...
@@ -26,7 +26,7 @@ RSpec.describe Projects::MoveAccessService do
describe
'#execute'
do
describe
'#execute'
do
shared_examples
'move the accesses'
do
shared_examples
'move the accesses'
do
it
do
it
'moves the accesses'
,
:sidekiq_inline
do
expect
(
project_with_access
.
project_members
.
count
).
to
eq
4
expect
(
project_with_access
.
project_members
.
count
).
to
eq
4
expect
(
project_with_access
.
project_group_links
.
count
).
to
eq
3
expect
(
project_with_access
.
project_group_links
.
count
).
to
eq
3
expect
(
project_with_access
.
authorized_users
.
count
).
to
eq
4
expect
(
project_with_access
.
authorized_users
.
count
).
to
eq
4
...
...
spec/workers/authorized_project_update/project_recalculate_per_user_worker_spec.rb
0 → 100644
View file @
4bcd5c6e
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserWorker
do
include
ExclusiveLeaseHelpers
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:user
)
{
create
(
:user
)
}
subject
(
:worker
)
{
described_class
.
new
}
include_examples
'an idempotent worker'
do
let
(
:job_args
)
{
[
project
.
id
,
user
.
id
]
}
it
'does not change authorizations when run twice'
do
project
.
add_developer
(
user
)
user
.
project_authorizations
.
delete_all
expect
{
worker
.
perform
(
project
.
id
,
user
.
id
)
}.
to
change
{
project
.
project_authorizations
.
reload
.
size
}.
by
(
1
)
expect
{
worker
.
perform
(
project
.
id
,
user
.
id
)
}.
not_to
change
{
project
.
project_authorizations
.
reload
.
size
}
end
end
describe
'#perform'
do
it
'does not fail if the project does not exist'
do
expect
do
worker
.
perform
(
non_existing_record_id
,
user
.
id
)
end
.
not_to
raise_error
end
it
'does not fail if the user does not exist'
do
expect
do
worker
.
perform
(
project
.
id
,
non_existing_record_id
)
end
.
not_to
raise_error
end
it
'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserService'
do
expect_next_instance_of
(
AuthorizedProjectUpdate
::
ProjectRecalculatePerUserService
,
project
,
user
)
do
|
service
|
expect
(
service
).
to
receive
(
:execute
)
end
worker
.
perform
(
project
.
id
,
user
.
id
)
end
context
'exclusive lease'
do
let
(
:lock_key
)
{
"
#{
described_class
.
superclass
.
name
.
underscore
}
/projects/
#{
project
.
id
}
"
}
let
(
:timeout
)
{
10
.
seconds
}
context
'when exclusive lease has not been taken'
do
it
'obtains a new exclusive lease'
do
expect_to_obtain_exclusive_lease
(
lock_key
,
timeout:
timeout
)
worker
.
perform
(
project
.
id
,
user
.
id
)
end
end
context
'when exclusive lease has already been taken'
do
before
do
stub_exclusive_lease_taken
(
lock_key
,
timeout:
timeout
)
end
it
'raises an error'
do
expect
{
worker
.
perform
(
project
.
id
,
user
.
id
)
}.
to
raise_error
(
Gitlab
::
ExclusiveLeaseHelpers
::
FailedToObtainLockError
)
end
end
end
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