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
54f976e4
Commit
54f976e4
authored
Feb 17, 2020
by
Shreyas Agarwal
Committed by
Bob Van Landuyt
Feb 17, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Count users in nested projects on Gitlab.com
parent
6d9099bf
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
186 additions
and
8 deletions
+186
-8
app/models/member.rb
app/models/member.rb
+1
-0
ee/app/models/ee/group.rb
ee/app/models/ee/group.rb
+43
-2
ee/app/models/ee/user.rb
ee/app/models/ee/user.rb
+1
-1
ee/changelogs/unreleased/33142-count-users-in-nested-projects-on-gitlab-com.yml
...ed/33142-count-users-in-nested-projects-on-gitlab-com.yml
+5
-0
ee/spec/models/namespace_spec.rb
ee/spec/models/namespace_spec.rb
+136
-5
No files found.
app/models/member.rb
View file @
54f976e4
...
@@ -75,6 +75,7 @@ class Member < ApplicationRecord
...
@@ -75,6 +75,7 @@ class Member < ApplicationRecord
scope
:reporters
,
->
{
active
.
where
(
access_level:
REPORTER
)
}
scope
:reporters
,
->
{
active
.
where
(
access_level:
REPORTER
)
}
scope
:developers
,
->
{
active
.
where
(
access_level:
DEVELOPER
)
}
scope
:developers
,
->
{
active
.
where
(
access_level:
DEVELOPER
)
}
scope
:maintainers
,
->
{
active
.
where
(
access_level:
MAINTAINER
)
}
scope
:maintainers
,
->
{
active
.
where
(
access_level:
MAINTAINER
)
}
scope
:non_guests
,
->
{
where
(
'members.access_level > ?'
,
GUEST
)
}
scope
:masters
,
->
{
maintainers
}
# @deprecated
scope
:masters
,
->
{
maintainers
}
# @deprecated
scope
:owners
,
->
{
active
.
where
(
access_level:
OWNER
)
}
scope
:owners
,
->
{
active
.
where
(
access_level:
OWNER
)
}
scope
:owners_and_maintainers
,
->
{
active
.
where
(
access_level:
[
OWNER
,
MAINTAINER
])
}
scope
:owners_and_maintainers
,
->
{
active
.
where
(
access_level:
[
OWNER
,
MAINTAINER
])
}
...
...
ee/app/models/ee/group.rb
View file @
54f976e4
...
@@ -248,12 +248,22 @@ module EE
...
@@ -248,12 +248,22 @@ module EE
# For now, we are not billing for members with a Guest role for subscriptions
# For now, we are not billing for members with a Guest role for subscriptions
# with a Gold plan. The other plans will treat Guest members as a regular member
# with a Gold plan. The other plans will treat Guest members as a regular member
# for billing purposes.
# for billing purposes.
#
# We are plucking the user_ids from the "Members" table in an array and
# concatenating the array of user_ids with ruby "|" (pipe) method to generate
# one single array of unique user_ids.
override
:billable_members_count
override
:billable_members_count
def
billable_members_count
(
requested_hosted_plan
=
nil
)
def
billable_members_count
(
requested_hosted_plan
=
nil
)
if
[
actual_plan_name
,
requested_hosted_plan
].
include?
(
Plan
::
GOLD
)
if
[
actual_plan_name
,
requested_hosted_plan
].
include?
(
Plan
::
GOLD
)
users_with_descendants
.
excluding_guests
.
count
(
billed_group_members
.
non_guests
.
distinct
.
pluck
(
:user_id
)
|
billed_project_members
.
non_guests
.
distinct
.
pluck
(
:user_id
)
|
billed_shared_group_members
.
non_guests
.
distinct
.
pluck
(
:user_id
)
|
billed_invited_group_members
.
non_guests
.
distinct
.
pluck
(
:user_id
)).
count
else
else
users_with_descendants
.
count
(
billed_group_members
.
distinct
.
pluck
(
:user_id
)
|
billed_project_members
.
distinct
.
pluck
(
:user_id
)
|
billed_shared_group_members
.
distinct
.
pluck
(
:user_id
)
|
billed_invited_group_members
.
distinct
.
pluck
(
:user_id
)).
count
end
end
end
end
...
@@ -296,5 +306,36 @@ module EE
...
@@ -296,5 +306,36 @@ module EE
errors
.
add
(
:custom_project_templates_group_id
,
"has to be a subgroup of the group"
)
errors
.
add
(
:custom_project_templates_group_id
,
"has to be a subgroup of the group"
)
end
end
def
billed_group_members
::
GroupMember
.
active_without_invites_and_requests
.
where
(
source_id:
self_and_descendants
)
end
def
billed_project_members
::
ProjectMember
.
active_without_invites_and_requests
.
where
(
source_id:
::
Project
.
joins
(
:group
).
where
(
namespace:
self_and_descendants
)
)
end
def
billed_invited_group_members
invited_or_shared_group_members
(
invited_groups_in_projects
)
end
def
billed_shared_group_members
return
::
GroupMember
.
none
unless
::
Feature
.
enabled?
(
:share_group_with_group
)
invited_or_shared_group_members
(
shared_groups
)
end
def
invited_or_shared_group_members
(
groups
)
::
GroupMember
.
active_without_invites_and_requests
.
where
(
source_id:
::
Gitlab
::
ObjectHierarchy
.
new
(
groups
).
base_and_ancestors
)
end
def
invited_groups_in_projects
::
Group
.
joins
(
:project_group_links
)
.
where
(
project_group_links:
{
project_id:
all_projects
})
end
end
end
end
end
ee/app/models/ee/user.rb
View file @
54f976e4
...
@@ -62,7 +62,7 @@ module EE
...
@@ -62,7 +62,7 @@ module EE
scope
scope
}
}
scope
:excluding_guests
,
->
{
joins
(
:members
).
where
(
'members.access_level > ?'
,
::
Gitlab
::
Access
::
GUEST
).
distinct
}
scope
:excluding_guests
,
->
{
joins
(
:members
).
merge
(
::
Member
.
non_guests
).
distinct
}
scope
:subscribed_for_admin_email
,
->
{
where
(
admin_email_unsubscribed_at:
nil
)
}
scope
:subscribed_for_admin_email
,
->
{
where
(
admin_email_unsubscribed_at:
nil
)
}
scope
:ldap
,
->
{
joins
(
:identities
).
where
(
'identities.provider LIKE ?'
,
'ldap%'
)
}
scope
:ldap
,
->
{
joins
(
:identities
).
where
(
'identities.provider LIKE ?'
,
'ldap%'
)
}
...
...
ee/changelogs/unreleased/33142-count-users-in-nested-projects-on-gitlab-com.yml
0 → 100644
View file @
54f976e4
---
title
:
Include users from all sub-projects and shared groups when counting billing seats currently in use
merge_request
:
22967
author
:
type
:
fixed
ee/spec/models/namespace_spec.rb
View file @
54f976e4
...
@@ -843,28 +843,159 @@ describe Namespace do
...
@@ -843,28 +843,159 @@ describe Namespace do
context
'with a group namespace'
do
context
'with a group namespace'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:developer
)
{
create
(
:user
)
}
let
(
:developer
)
{
create
(
:user
)
}
let
(
:guest
)
{
create
(
:user
)
}
before
do
before
do
group
.
add_developer
(
developer
)
group
.
add_developer
(
developer
)
group
.
add_guest
(
guest
)
group
.
add_developer
(
create
(
:user
,
:blocked
))
group
.
add_guest
(
create
(
:user
))
end
end
context
'with a gold plan'
do
context
'with a gold plan'
do
it
'does not count guest users'
do
before
do
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
gold_plan
)
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
gold_plan
)
end
it
'does not count guest users and counts only active users'
do
expect
(
group
.
billable_members_count
).
to
eq
(
1
)
expect
(
group
.
billable_members_count
).
to
eq
(
1
)
end
end
context
'when group has a project and users invited to it'
do
let
(
:project
)
{
create
(
:project
,
namespace:
group
)
}
before
do
project
.
add_developer
(
create
(
:user
))
project
.
add_guest
(
create
(
:user
))
project
.
add_developer
(
developer
)
project
.
add_developer
(
create
(
:user
,
:blocked
))
end
it
'includes invited active users except guests to the group'
do
expect
(
group
.
billable_members_count
).
to
eq
(
2
)
end
context
'when group is invited to the project'
do
let
(
:invited_group
)
{
create
(
:group
)
}
before
do
invited_group
.
add_developer
(
create
(
:user
))
invited_group
.
add_guest
(
create
(
:user
))
invited_group
.
add_developer
(
create
(
:user
,
:blocked
))
invited_group
.
add_developer
(
developer
)
create
(
:project_group_link
,
project:
project
,
group:
invited_group
)
end
it
'counts the only active users except guests of the invited groups'
do
expect
(
group
.
billable_members_count
).
to
eq
(
3
)
end
end
end
context
'when group has been shared with another group'
do
let
(
:shared_group
)
{
create
(
:group
)
}
before
do
shared_group
.
add_developer
(
create
(
:user
))
shared_group
.
add_guest
(
create
(
:user
))
shared_group
.
add_developer
(
create
(
:user
,
:blocked
))
create
(
:group_group_link
,
{
shared_with_group:
group
,
shared_group:
shared_group
})
end
context
'when feature is not enabled'
do
before
do
stub_feature_flags
(
share_group_with_group:
false
)
end
it
'does not include users coming from the shared groups'
do
expect
(
group
.
billable_members_count
).
to
eq
(
1
)
end
end
context
'when feature is enabled'
do
before
do
stub_feature_flags
(
share_group_with_group:
true
)
end
it
'includes active users from the shared group to the billed members count'
do
expect
(
group
.
billable_members_count
).
to
eq
(
2
)
end
end
end
end
end
context
'with other plans'
do
context
'with other plans'
do
%i[bronze_plan silver_plan]
.
each
do
|
plan
|
%i[bronze_plan silver_plan]
.
each
do
|
plan
|
it
'counts guest users'
do
it
'counts
active
guest users'
do
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
send
(
plan
))
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
send
(
plan
))
expect
(
group
.
billable_members_count
).
to
eq
(
2
)
expect
(
group
.
billable_members_count
).
to
eq
(
2
)
end
end
context
'when group has a project and users invited to it'
do
let
(
:project
)
{
create
(
:project
,
namespace:
group
)
}
before
do
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
send
(
plan
))
project
.
add_developer
(
create
(
:user
))
project
.
add_guest
(
create
(
:user
))
project
.
add_developer
(
create
(
:user
,
:blocked
))
project
.
add_developer
(
developer
)
end
it
'includes invited active users to the group'
do
expect
(
group
.
billable_members_count
).
to
eq
(
4
)
end
context
'when group is invited to the project'
do
let
(
:invited_group
)
{
create
(
:group
)
}
before
do
invited_group
.
add_developer
(
create
(
:user
))
invited_group
.
add_developer
(
developer
)
invited_group
.
add_guest
(
create
(
:user
))
invited_group
.
add_developer
(
create
(
:user
,
:blocked
))
create
(
:project_group_link
,
project:
project
,
group:
invited_group
)
end
it
'counts the unique active users including guests of the invited groups'
do
expect
(
group
.
billable_members_count
).
to
eq
(
6
)
end
end
end
context
'when group has been shared with another group'
do
let
(
:shared_group
)
{
create
(
:group
)
}
before
do
create
(
:gitlab_subscription
,
namespace:
group
,
hosted_plan:
send
(
plan
))
shared_group
.
add_developer
(
create
(
:user
))
shared_group
.
add_guest
(
create
(
:user
))
shared_group
.
add_developer
(
create
(
:user
,
:blocked
))
create
(
:group_group_link
,
{
shared_with_group:
group
,
shared_group:
shared_group
})
end
context
'when feature is not enabled'
do
before
do
stub_feature_flags
(
share_group_with_group:
false
)
end
it
'does not include users coming from the shared groups'
do
expect
(
group
.
billable_members_count
).
to
eq
(
2
)
end
end
context
'when feature is enabled'
do
before
do
stub_feature_flags
(
share_group_with_group:
true
)
end
it
'includes active users from the shared group including guests to the billed members count'
do
expect
(
group
.
billable_members_count
).
to
eq
(
4
)
end
end
end
end
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