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
13727686
Commit
13727686
authored
Mar 31, 2021
by
Doug Stull
Committed by
Igor Drozdov
Mar 31, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add OnboardingProgress to Invite Service
- aligning with standard member creation process.
parent
990fd614
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
76 additions
and
40 deletions
+76
-40
app/models/members/group_member.rb
app/models/members/group_member.rb
+1
-1
app/models/members/project_member.rb
app/models/members/project_member.rb
+2
-0
app/services/members/invite_service.rb
app/services/members/invite_service.rb
+11
-3
changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml
...combine-concepts-in-inviting-member-service-classes-3.yml
+5
-0
ee/spec/services/ee/members/invite_service_spec.rb
ee/spec/services/ee/members/invite_service_spec.rb
+4
-3
lib/api/invitations.rb
lib/api/invitations.rb
+3
-3
spec/models/members/group_member_spec.rb
spec/models/members/group_member_spec.rb
+6
-0
spec/models/members/project_member_spec.rb
spec/models/members/project_member_spec.rb
+4
-0
spec/services/members/invite_service_spec.rb
spec/services/members/invite_service_spec.rb
+40
-30
No files found.
app/models/members/group_member.rb
View file @
13727686
...
@@ -7,7 +7,7 @@ class GroupMember < Member
...
@@ -7,7 +7,7 @@ class GroupMember < Member
SOURCE_TYPE
=
'Namespace'
SOURCE_TYPE
=
'Namespace'
belongs_to
:group
,
foreign_key:
'source_id'
belongs_to
:group
,
foreign_key:
'source_id'
alias_attribute
:namespace_id
,
:source_id
delegate
:update_two_factor_requirement
,
to: :user
delegate
:update_two_factor_requirement
,
to: :user
# Make sure group member points only to group as it source
# Make sure group member points only to group as it source
...
...
app/models/members/project_member.rb
View file @
13727686
...
@@ -5,6 +5,8 @@ class ProjectMember < Member
...
@@ -5,6 +5,8 @@ class ProjectMember < Member
belongs_to
:project
,
foreign_key:
'source_id'
belongs_to
:project
,
foreign_key:
'source_id'
delegate
:namespace_id
,
to: :project
# Make sure project member points only to project as it source
# Make sure project member points only to project as it source
default_value_for
:source_type
,
SOURCE_TYPE
default_value_for
:source_type
,
SOURCE_TYPE
validates
:source_type
,
format:
{
with:
/\AProject\z/
}
validates
:source_type
,
format:
{
with:
/\AProject\z/
}
...
...
app/services/members/invite_service.rb
View file @
13727686
...
@@ -10,13 +10,14 @@ module Members
...
@@ -10,13 +10,14 @@ module Members
@errors
=
{}
@errors
=
{}
@emails
=
params
[
:email
]
&
.
split
(
','
)
&
.
uniq
&
.
flatten
@emails
=
params
[
:email
]
&
.
split
(
','
)
&
.
uniq
&
.
flatten
@source
=
params
[
:source
]
end
end
def
execute
(
source
)
def
execute
@source
=
source
validate_emails!
validate_emails!
emails
.
each
(
&
method
(
:process_email
))
emails
.
each
(
&
method
(
:process_email
))
enqueue_onboarding_progress_action
result
result
rescue
BlankEmailsError
,
TooManyEmailsError
=>
e
rescue
BlankEmailsError
,
TooManyEmailsError
=>
e
error
(
e
.
message
)
error
(
e
.
message
)
...
@@ -24,7 +25,7 @@ module Members
...
@@ -24,7 +25,7 @@ module Members
private
private
attr_reader
:source
,
:errors
,
:emails
attr_reader
:source
,
:errors
,
:emails
,
:member_created_namespace_id
def
validate_emails!
def
validate_emails!
raise
BlankEmailsError
,
s_
(
'AddMember|Email cannot be blank'
)
if
emails
.
blank?
raise
BlankEmailsError
,
s_
(
'AddMember|Email cannot be blank'
)
if
emails
.
blank?
...
@@ -88,6 +89,7 @@ module Members
...
@@ -88,6 +89,7 @@ module Members
errors
[
email
]
=
new_member
.
errors
.
full_messages
.
to_sentence
errors
[
email
]
=
new_member
.
errors
.
full_messages
.
to_sentence
else
else
after_execute
(
member:
new_member
)
after_execute
(
member:
new_member
)
@member_created_namespace_id
||=
new_member
.
namespace_id
end
end
end
end
...
@@ -98,6 +100,12 @@ module Members
...
@@ -98,6 +100,12 @@ module Members
success
success
end
end
end
end
def
enqueue_onboarding_progress_action
return
unless
member_created_namespace_id
Namespaces
::
OnboardingUserAddedWorker
.
perform_async
(
member_created_namespace_id
)
end
end
end
end
end
...
...
changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml
0 → 100644
View file @
13727686
---
title
:
Add enqueueing of Onboarding Progress to the Invite Service
merge_request
:
57372
author
:
type
:
other
ee/spec/services/ee/members/invite_service_spec.rb
View file @
13727686
...
@@ -9,9 +9,10 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -9,9 +9,10 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let_it_be
(
:subgroup
)
{
create
(
:group
,
parent:
root_ancestor
)
}
let_it_be
(
:subgroup
)
{
create
(
:group
,
parent:
root_ancestor
)
}
let_it_be
(
:subgroup_project
)
{
create
(
:project
,
group:
subgroup
)
}
let_it_be
(
:subgroup_project
)
{
create
(
:project
,
group:
subgroup
)
}
let
(
:params
)
{
{
email:
%w[email@example.org email2@example.org]
,
access_level:
Gitlab
::
Access
::
GUEST
}
}
let
(
:base_params
)
{
{
access_level:
Gitlab
::
Access
::
GUEST
,
source:
project
}
}
let
(
:params
)
{
{
email:
%w[email@example.org email2@example.org]
}
}
subject
(
:result
)
{
described_class
.
new
(
user
,
params
).
execute
(
project
)
}
subject
(
:result
)
{
described_class
.
new
(
user
,
base_params
.
merge
(
params
)).
execute
}
before_all
do
before_all
do
project
.
add_maintainer
(
user
)
project
.
add_maintainer
(
user
)
...
@@ -90,7 +91,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -90,7 +91,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
end
end
context
'when there are some invalid members'
do
context
'when there are some invalid members'
do
let
(
:params
)
{
{
email:
%w[_bogus_ email2@example.org]
,
access_level:
Gitlab
::
Access
::
GUEST
}
}
let
(
:params
)
{
{
email:
%w[_bogus_ email2@example.org]
}
}
it
'only creates Audit Events for valid members'
do
it
'only creates Audit Events for valid members'
do
expect
{
result
}.
to
change
{
AuditEvent
.
count
}.
by
(
1
)
expect
{
result
}.
to
change
{
AuditEvent
.
count
}.
by
(
1
)
...
...
lib/api/invitations.rb
View file @
13727686
...
@@ -25,11 +25,11 @@ module API
...
@@ -25,11 +25,11 @@ module API
optional
:expires_at
,
type:
DateTime
,
desc:
'Date string in the format YEAR-MONTH-DAY'
optional
:expires_at
,
type:
DateTime
,
desc:
'Date string in the format YEAR-MONTH-DAY'
end
end
post
":id/invitations"
do
post
":id/invitations"
do
source
=
find_source
(
source_type
,
params
[
:id
])
params
[
:source
]
=
find_source
(
source_type
,
params
[
:id
])
authorize_admin_source!
(
source_type
,
source
)
authorize_admin_source!
(
source_type
,
params
[
:source
]
)
::
Members
::
InviteService
.
new
(
current_user
,
params
).
execute
(
source
)
::
Members
::
InviteService
.
new
(
current_user
,
params
).
execute
end
end
desc
'Get a list of group or project invitations viewable by the authenticated user'
do
desc
'Get a list of group or project invitations viewable by the authenticated user'
do
...
...
spec/models/members/group_member_spec.rb
View file @
13727686
...
@@ -66,6 +66,12 @@ RSpec.describe GroupMember do
...
@@ -66,6 +66,12 @@ RSpec.describe GroupMember do
it_behaves_like
'members notifications'
,
:group
it_behaves_like
'members notifications'
,
:group
describe
'#namespace_id'
do
subject
{
build
(
:group_member
,
source_id:
1
).
namespace_id
}
it
{
is_expected
.
to
eq
1
}
end
describe
'#real_source_type'
do
describe
'#real_source_type'
do
subject
{
create
(
:group_member
).
real_source_type
}
subject
{
create
(
:group_member
).
real_source_type
}
...
...
spec/models/members/project_member_spec.rb
View file @
13727686
...
@@ -13,6 +13,10 @@ RSpec.describe ProjectMember do
...
@@ -13,6 +13,10 @@ RSpec.describe ProjectMember do
it
{
is_expected
.
to
validate_inclusion_of
(
:access_level
).
in_array
(
Gitlab
::
Access
.
values
)
}
it
{
is_expected
.
to
validate_inclusion_of
(
:access_level
).
in_array
(
Gitlab
::
Access
.
values
)
}
end
end
describe
'delegations'
do
it
{
is_expected
.
to
delegate_method
(
:namespace_id
).
to
(
:project
)
}
end
describe
'.access_level_roles'
do
describe
'.access_level_roles'
do
it
'returns Gitlab::Access.options'
do
it
'returns Gitlab::Access.options'
do
expect
(
described_class
.
access_level_roles
).
to
eq
(
Gitlab
::
Access
.
options
)
expect
(
described_class
.
access_level_roles
).
to
eq
(
Gitlab
::
Access
.
options
)
...
...
spec/services/members/invite_service_spec.rb
View file @
13727686
...
@@ -2,29 +2,43 @@
...
@@ -2,29 +2,43 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Members
::
InviteService
,
:aggregate_failures
do
RSpec
.
describe
Members
::
InviteService
,
:aggregate_failures
,
:clean_gitlab_redis_shared_state
,
:sidekiq_inline
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:user
)
{
project
.
owner
}
let_it_be
(
:user
)
{
project
.
owner
}
let_it_be
(
:project_user
)
{
create
(
:user
)
}
let_it_be
(
:project_user
)
{
create
(
:user
)
}
let_it_be
(
:namespace
)
{
project
.
namespace
}
let
(
:params
)
{
{}
}
let
(
:params
)
{
{}
}
let
(
:base_params
)
{
{
access_level:
Gitlab
::
Access
::
GUEST
}
}
let
(
:base_params
)
{
{
access_level:
Gitlab
::
Access
::
GUEST
,
source:
project
}
}
subject
(
:result
)
{
described_class
.
new
(
user
,
base_params
.
merge
(
params
)
).
execute
(
project
)
}
subject
(
:result
)
{
described_class
.
new
(
user
,
base_params
.
merge
(
params
)
).
execute
}
context
'when
email is previously unused by current members
'
do
context
'when
there is a valid member invited
'
do
let
(
:params
)
{
{
email:
'email@example.org'
}
}
let
(
:params
)
{
{
email:
'email@example.org'
}
}
it
'successfully creates a member'
do
it
'successfully creates a member'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
end
end
it_behaves_like
'records an onboarding progress action'
,
:user_added
end
context
'when email is not a valid email'
do
let
(
:params
)
{
{
email:
'_bogus_'
}
}
it
'returns an error'
do
expect_not_to_create_members
expect
(
result
[
:message
][
'_bogus_'
]).
to
eq
(
"Invite email is invalid"
)
end
it_behaves_like
'does not record an onboarding progress action'
end
end
context
'when emails are passed as an array'
do
context
'when emails are passed as an array'
do
let
(
:params
)
{
{
email:
%w[email@example.org email2@example.org]
}
}
let
(
:params
)
{
{
email:
%w[email@example.org email2@example.org]
}
}
it
'successfully creates members'
do
it
'successfully creates members'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
2
)
expect
_to_create_members
(
count:
2
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
end
end
end
end
...
@@ -33,33 +47,23 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -33,33 +47,23 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
''
}
}
let
(
:params
)
{
{
email:
''
}
}
it
'returns an error'
do
it
'returns an error'
do
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
_not_to_create_members
expect
(
result
[
:message
]).
to
eq
(
'Email cannot be blank'
)
expect
(
result
[
:message
]).
to
eq
(
'Email cannot be blank'
)
end
end
end
end
context
'when email param is not included'
do
context
'when email param is not included'
do
it
'returns an error'
do
it
'returns an error'
do
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
_not_to_create_members
expect
(
result
[
:message
]).
to
eq
(
'Email cannot be blank'
)
expect
(
result
[
:message
]).
to
eq
(
'Email cannot be blank'
)
end
end
end
end
context
'when email is not a valid email'
do
let
(
:params
)
{
{
email:
'_bogus_'
}
}
it
'returns an error'
do
expect
{
result
}.
not_to
change
(
ProjectMember
,
:count
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
][
'_bogus_'
]).
to
eq
(
"Invite email is invalid"
)
end
end
context
'when duplicate email addresses are passed'
do
context
'when duplicate email addresses are passed'
do
let
(
:params
)
{
{
email:
'email@example.org,email@example.org'
}
}
let
(
:params
)
{
{
email:
'email@example.org,email@example.org'
}
}
it
'only creates one member per unique address'
do
it
'only creates one member per unique address'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
end
end
end
end
...
@@ -71,8 +75,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -71,8 +75,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
emails
}
}
let
(
:params
)
{
{
email:
emails
}
}
it
'limits the number of emails to 100'
do
it
'limits the number of emails to 100'
do
expect
{
result
}.
not_to
change
(
ProjectMember
,
:count
)
expect_not_to_create_members
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
]).
to
eq
(
'Too many users specified (limit is 100)'
)
expect
(
result
[
:message
]).
to
eq
(
'Too many users specified (limit is 100)'
)
end
end
end
end
...
@@ -81,8 +84,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -81,8 +84,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
'email@example.org,email2@example.org'
,
limit:
1
}
}
let
(
:params
)
{
{
email:
'email@example.org,email2@example.org'
,
limit:
1
}
}
it
'limits the number of emails to the limit supplied'
do
it
'limits the number of emails to the limit supplied'
do
expect
{
result
}.
not_to
change
(
ProjectMember
,
:count
)
expect_not_to_create_members
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
]).
to
eq
(
'Too many users specified (limit is 1)'
)
expect
(
result
[
:message
]).
to
eq
(
'Too many users specified (limit is 1)'
)
end
end
end
end
...
@@ -91,7 +93,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -91,7 +93,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
emails
,
limit:
-
1
}
}
let
(
:params
)
{
{
email:
emails
,
limit:
-
1
}
}
it
'does not limit number of emails'
do
it
'does not limit number of emails'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
101
)
expect
_to_create_members
(
count:
101
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
result
[
:status
]).
to
eq
(
:success
)
end
end
end
end
...
@@ -101,7 +103,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -101,7 +103,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
project_user
.
email
}
}
let
(
:params
)
{
{
email:
project_user
.
email
}
}
it
'adds an existing user to members'
do
it
'adds an existing user to members'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
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
end
end
...
@@ -111,8 +113,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -111,8 +113,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
project_user
.
email
,
access_level:
-
1
}
}
let
(
:params
)
{
{
email:
project_user
.
email
,
access_level:
-
1
}
}
it
'returns an error'
do
it
'returns an error'
do
expect
{
result
}.
not_to
change
(
ProjectMember
,
:count
)
expect_not_to_create_members
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
][
project_user
.
email
]).
to
eq
(
"Access level is not included in the list"
)
expect
(
result
[
:message
][
project_user
.
email
]).
to
eq
(
"Access level is not included in the list"
)
end
end
end
end
...
@@ -122,7 +123,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -122,7 +123,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
"
#{
invited_member
.
invite_email
}
,
#{
project_user
.
email
}
"
}
}
let
(
:params
)
{
{
email:
"
#{
invited_member
.
invite_email
}
,
#{
project_user
.
email
}
"
}
}
it
'adds new email and returns an error for the already invited email'
do
it
'adds new email and returns an error for the already invited email'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
][
invited_member
.
invite_email
]).
to
eq
(
"Member already invited to
#{
project
.
name
}
"
)
expect
(
result
[
:message
][
invited_member
.
invite_email
]).
to
eq
(
"Member already invited to
#{
project
.
name
}
"
)
expect
(
project
.
users
).
to
include
project_user
expect
(
project
.
users
).
to
include
project_user
...
@@ -134,7 +135,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -134,7 +135,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
"
#{
requested_member
.
user
.
email
}
,
#{
project_user
.
email
}
"
}
}
let
(
:params
)
{
{
email:
"
#{
requested_member
.
user
.
email
}
,
#{
project_user
.
email
}
"
}
}
it
'adds new email and returns an error for the already invited email'
do
it
'adds new email and returns an error for the already invited email'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
][
requested_member
.
user
.
email
])
expect
(
result
[
:message
][
requested_member
.
user
.
email
])
.
to
eq
(
"Member cannot be invited because they already requested to join
#{
project
.
name
}
"
)
.
to
eq
(
"Member cannot be invited because they already requested to join
#{
project
.
name
}
"
)
...
@@ -147,10 +148,19 @@ RSpec.describe Members::InviteService, :aggregate_failures do
...
@@ -147,10 +148,19 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let
(
:params
)
{
{
email:
"
#{
existing_member
.
user
.
email
}
,
#{
project_user
.
email
}
"
}
}
let
(
:params
)
{
{
email:
"
#{
existing_member
.
user
.
email
}
,
#{
project_user
.
email
}
"
}
}
it
'adds new email and returns an error for the already invited email'
do
it
'adds new email and returns an error for the already invited email'
do
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
1
)
expect
_to_create_members
(
count:
1
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
expect
(
result
[
:message
][
existing_member
.
user
.
email
]).
to
eq
(
"Already a member of
#{
project
.
name
}
"
)
expect
(
result
[
:message
][
existing_member
.
user
.
email
]).
to
eq
(
"Already a member of
#{
project
.
name
}
"
)
expect
(
project
.
users
).
to
include
project_user
expect
(
project
.
users
).
to
include
project_user
end
end
end
end
def
expect_to_create_members
(
count
:)
expect
{
result
}.
to
change
(
ProjectMember
,
:count
).
by
(
count
)
end
def
expect_not_to_create_members
expect
{
result
}.
not_to
change
(
ProjectMember
,
:count
)
expect
(
result
[
:status
]).
to
eq
(
:error
)
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