Commit 08c5fbee authored by Enrique Alcántara's avatar Enrique Alcántara

Merge branch '342516-add-minimal-access-user-statistics' into 'master'

Add with_highest_role_minimal_access to statistics

See merge request gitlab-org/gitlab!73651
parents 3e554c95 15b863d0
......@@ -3,12 +3,6 @@
class UsersStatistics < ApplicationRecord
scope :order_created_at_desc, -> { order(created_at: :desc) }
class << self
def latest
order_created_at_desc.first
end
end
def active
[
without_groups_and_projects,
......@@ -26,30 +20,26 @@ class UsersStatistics < ApplicationRecord
end
class << self
def create_current_stats!
stats_by_role = highest_role_stats
def latest
order_created_at_desc.first
end
create!(
without_groups_and_projects: without_groups_and_projects_stats,
with_highest_role_guest: stats_by_role[:guest],
with_highest_role_reporter: stats_by_role[:reporter],
with_highest_role_developer: stats_by_role[:developer],
with_highest_role_maintainer: stats_by_role[:maintainer],
with_highest_role_owner: stats_by_role[:owner],
bots: bot_stats,
blocked: blocked_stats
)
def create_current_stats!
create!(highest_role_stats)
end
private
def highest_role_stats
{
owner: batch_count_for_access_level(Gitlab::Access::OWNER),
maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
guest: batch_count_for_access_level(Gitlab::Access::GUEST)
without_groups_and_projects: without_groups_and_projects_stats,
with_highest_role_guest: batch_count_for_access_level(Gitlab::Access::GUEST),
with_highest_role_reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
with_highest_role_developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
with_highest_role_maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
with_highest_role_owner: batch_count_for_access_level(Gitlab::Access::OWNER),
bots: bot_stats,
blocked: blocked_stats
}
end
......
- page_title s_('AdminArea|Users statistics')
%h3.my-4
%h3.gl-my-6
= s_('AdminArea|Users statistics')
%table.table.gl-text-gray-500
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users without a Group and Project')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
%td.p-3.text-right
= @users_statistics&.without_groups_and_projects.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.without_groups_and_projects
= render_if_exists 'admin/dashboard/minimal_access_stats_row', users_statistics: @users_statistics
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Guest')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
%td.p-3.text-right
= @users_statistics&.with_highest_role_guest.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.with_highest_role_guest
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Reporter')
%td.p-3.text-right
= @users_statistics&.with_highest_role_reporter.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.with_highest_role_reporter
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Developer')
%td.p-3.text-right
= @users_statistics&.with_highest_role_developer.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.with_highest_role_developer
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Maintainer')
%td.p-3.text-right
= @users_statistics&.with_highest_role_maintainer.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.with_highest_role_maintainer
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Owner')
%td.p-3.text-right
= @users_statistics&.with_highest_role_owner.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.with_highest_role_owner
%tr
%td.p-3
%td.gl-p-5!
= s_('AdminArea|Bots')
%td.p-3.text-right
= @users_statistics&.bots.to_i
%td.gl-text-right{ class: 'gl-p-5!' }
= @users_statistics&.bots
= render_if_exists 'admin/dashboard/billable_users_row'
%tr.bg-gray-light.gl-text-gray-900
%td.p-3
%td.gl-p-5!
%strong
= s_('AdminArea|Active users')
%td.p-3.text-right
%td.gl-text-right{ class: 'gl-p-5!' }
%strong
= @users_statistics&.active.to_i
= @users_statistics&.active
%tr.bg-gray-light.gl-text-gray-900
%td.p-3
%td.gl-p-5!
%strong
= s_('AdminArea|Blocked users')
%td.p-3.text-right
%td.gl-text-right{ class: 'gl-p-5!' }
%strong
= @users_statistics&.blocked.to_i
= @users_statistics&.blocked
%tr.bg-gray-light.gl-text-gray-900
%td.p-3
%td.gl-p-5!
%strong
= s_('AdminArea|Total users')
%td.p-3.text-right
%td.gl-text-right{ class: 'gl-p-5!' }
%strong
= @users_statistics&.total.to_i
= @users_statistics&.total
# frozen_string_literal: true
class AddWithHighestRoleMinimalAccessToUsersStatistics < Gitlab::Database::Migration[1.0]
def change
add_column :users_statistics, :with_highest_role_minimal_access, :integer, null: false, default: 0
end
end
a22322122144f28306b3b38dbe50b3465ad623c389f8bfe6fa97a0f71b1c7c21
\ No newline at end of file
......@@ -20289,7 +20289,8 @@ CREATE TABLE users_statistics (
with_highest_role_maintainer integer DEFAULT 0 NOT NULL,
with_highest_role_owner integer DEFAULT 0 NOT NULL,
bots integer DEFAULT 0 NOT NULL,
blocked integer DEFAULT 0 NOT NULL
blocked integer DEFAULT 0 NOT NULL,
with_highest_role_minimal_access integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE users_statistics_id_seq
......@@ -2,10 +2,18 @@
module EE
module UsersStatistics
extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override
def billable
(base_billable_users + guest_billable_users).sum
end
override :active
def active
super + with_highest_role_minimal_access
end
private
def base_billable_users
......@@ -21,7 +29,18 @@ module EE
if License.current&.exclude_guests_from_active_count?
[]
else
[without_groups_and_projects, with_highest_role_guest]
[without_groups_and_projects, with_highest_role_guest, with_highest_role_minimal_access]
end
end
class_methods do
extend ::Gitlab::Utils::Override
private
override :highest_role_stats
def highest_role_stats
super.merge(with_highest_role_minimal_access: batch_count_for_access_level(::Gitlab::Access::MINIMAL_ACCESS))
end
end
end
......
- return unless License.feature_available?(:minimal_access_role)
- users_statistics = local_assigns.fetch(:users_statistics)
%tr
%td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Minimal access')
%td.gl-text-right{ class: 'gl-p-5!' }
= users_statistics&.with_highest_role_minimal_access
# frozen_string_literal: true
FactoryBot.modify do
factory :user_highest_role do
trait(:minimal_access) { highest_access_level { GroupMember::MINIMAL_ACCESS } }
end
end
......@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe UsersStatistics do
let(:users_statistics) { build(:users_statistics) }
let(:users_statistics) { build(:users_statistics, with_highest_role_minimal_access: 5) }
describe '#billable' do
it 'sums users statistics values excluding blocked users and bots' do
expect(users_statistics.billable).to eq(69)
expect(users_statistics.billable).to eq(74)
end
context 'when there is an ultimate license' do
......@@ -16,9 +16,29 @@ RSpec.describe UsersStatistics do
allow(License).to receive(:current).and_return(license)
end
it 'excludes blocked users, bots, guest users, and users without a group or project' do
it 'excludes blocked users, bots, guest users, users without a group or project and minimal access users' do
expect(users_statistics.billable).to eq(41)
end
end
end
describe '#active' do
it 'includes minimal access roles' do
expect(users_statistics.active).to eq(76)
end
end
describe '.create_current_stats!' do
before do
create(:user_highest_role, :minimal_access)
allow(ApplicationRecord.connection).to receive(:transaction_open?).and_return(false)
end
it 'includes minimal access in current statistics values' do
expect(described_class.create_current_stats!).to have_attributes(
with_highest_role_minimal_access: 1
)
end
end
end
......@@ -2316,6 +2316,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
msgid "AdminArea|Minimal access"
msgstr ""
msgid "AdminArea|New group"
msgstr ""
......
......@@ -5,10 +5,10 @@ FactoryBot.define do
highest_access_level { nil }
user
trait(:guest) { highest_access_level { GroupMember::GUEST } }
trait(:reporter) { highest_access_level { GroupMember::REPORTER } }
trait(:developer) { highest_access_level { GroupMember::DEVELOPER } }
trait(:maintainer) { highest_access_level { GroupMember::MAINTAINER } }
trait(:owner) { highest_access_level { GroupMember::OWNER } }
trait(:guest) { highest_access_level { GroupMember::GUEST } }
trait(:reporter) { highest_access_level { GroupMember::REPORTER } }
trait(:developer) { highest_access_level { GroupMember::DEVELOPER } }
trait(:maintainer) { highest_access_level { GroupMember::MAINTAINER } }
trait(:owner) { highest_access_level { GroupMember::OWNER } }
end
end
......@@ -39,7 +39,7 @@ export const member = {
Developer: 30,
Maintainer: 40,
Owner: 50,
'Minimal Access': 5,
'Minimal access': 5,
},
};
......
......@@ -34,11 +34,11 @@ RSpec.describe UsersStatistics do
describe '.create_current_stats!' do
before do
create_list(:user_highest_role, 4)
create_list(:user_highest_role, 1)
create_list(:user_highest_role, 2, :guest)
create_list(:user_highest_role, 3, :reporter)
create_list(:user_highest_role, 4, :developer)
create_list(:user_highest_role, 3, :maintainer)
create_list(:user_highest_role, 2, :reporter)
create_list(:user_highest_role, 2, :developer)
create_list(:user_highest_role, 2, :maintainer)
create_list(:user_highest_role, 2, :owner)
create_list(:user, 2, :bot)
create_list(:user, 1, :blocked)
......@@ -49,11 +49,11 @@ RSpec.describe UsersStatistics do
context 'when successful' do
it 'creates an entry with the current statistics values' do
expect(described_class.create_current_stats!).to have_attributes(
without_groups_and_projects: 4,
without_groups_and_projects: 1,
with_highest_role_guest: 2,
with_highest_role_reporter: 3,
with_highest_role_developer: 4,
with_highest_role_maintainer: 3,
with_highest_role_reporter: 2,
with_highest_role_developer: 2,
with_highest_role_maintainer: 2,
with_highest_role_owner: 2,
bots: 2,
blocked: 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment