Commit c0f7c071 authored by Mark Chao's avatar Mark Chao

Merge branch 'vs-add-new-user-signups-cap-alert' into 'master'

Add alert for exceeding new user signups cap

See merge request gitlab-org/gitlab!46673
parents 7ed55907 9f93fd4d
......@@ -7,6 +7,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-buy-pipeline-minutes-notification-callout',
'.js-token-expiry-callout',
'.js-registration-enabled-callout',
'.js-new-user-signups-cap-reached',
];
const initCallouts = () => {
......
......@@ -26,7 +26,8 @@ class UserCallout < ApplicationRecord
suggest_pipeline: 22,
customize_homepage: 23,
feature_flags_new_version: 24,
registration_enabled_callout: 25
registration_enabled_callout: 25,
new_user_signups_cap_reached: 26 # EE-only
}
validates :user, presence: true
......
......@@ -17,6 +17,7 @@
= render_account_recovery_regular_check
= render_if_exists "layouts/header/ee_subscribable_banner"
= render_if_exists "shared/namespace_storage_limit_alert"
= render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :customize_homepage_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
......
......@@ -4,15 +4,16 @@ module EE
module UserCalloutsHelper
extend ::Gitlab::Utils::Override
GEO_ENABLE_HASHED_STORAGE = 'geo_enable_hashed_storage'
GEO_MIGRATE_HASHED_STORAGE = 'geo_migrate_hashed_storage'
CANARY_DEPLOYMENT = 'canary_deployment'
GOLD_TRIAL = 'gold_trial'
GOLD_TRIAL_BILLINGS = 'gold_trial_billings'
THREAT_MONITORING_INFO = 'threat_monitoring_info'
ACCOUNT_RECOVERY_REGULAR_CHECK = 'account_recovery_regular_check'
ACTIVE_USER_COUNT_THRESHOLD = 'active_user_count_threshold'
PERSONAL_ACCESS_TOKEN_EXPIRY = 'personal_access_token_expiry'
ACTIVE_USER_COUNT_THRESHOLD = 'active_user_count_threshold'
CANARY_DEPLOYMENT = 'canary_deployment'
GEO_ENABLE_HASHED_STORAGE = 'geo_enable_hashed_storage'
GEO_MIGRATE_HASHED_STORAGE = 'geo_migrate_hashed_storage'
GOLD_TRIAL = 'gold_trial'
GOLD_TRIAL_BILLINGS = 'gold_trial_billings'
NEW_USER_SIGNUPS_CAP_REACHED = 'new_user_signups_cap_reached'
PERSONAL_ACCESS_TOKEN_EXPIRY = 'personal_access_token_expiry'
THREAT_MONITORING_INFO = 'threat_monitoring_info'
def show_canary_deployment_callout?(project)
!user_dismissed?(CANARY_DEPLOYMENT) &&
......@@ -89,6 +90,17 @@ module EE
!user_dismissed?(PERSONAL_ACCESS_TOKEN_EXPIRY, 1.week.ago)
end
def show_new_user_signups_cap_reached?
return false unless ::Feature.enabled?(:admin_new_user_signups_cap)
return false unless current_user&.admin?
return false if user_dismissed?(NEW_USER_SIGNUPS_CAP_REACHED)
new_user_signups_cap = ::Gitlab::CurrentSettings.current_application_settings.new_user_signups_cap
return false if new_user_signups_cap.nil?
new_user_signups_cap.to_i <= ::User.billable.count
end
private
def hashed_storage_enabled?
......@@ -132,5 +144,8 @@ module EE
def token_expiration_enforced?
::PersonalAccessToken.expiration_enforced?
end
def current_settings
end
end
end
- return unless show_new_user_signups_cap_reached?
- user_cap_help_url = help_page_path('user/admin_area/settings/sign_up_restrictions.md')
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: user_cap_help_url }
- help_link_end = '</a>'.html_safe
%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
.gl-alert.gl-alert-warning.js-new-user-signups-cap-reached{ role: 'alert', data: { feature_id: ::EE::UserCalloutsHelper::NEW_USER_SIGNUPS_CAP_REACHED, dismiss_endpoint: user_callouts_path, defer_links: "true" } }
= sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%button.js-close.gl-alert-dismiss.gl-cursor-pointer{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
%h4.gl-alert-title= s_('Admin|Your instance has reached its user cap')
= s_('Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}.').html_safe % { help_link_start: help_link_start, help_link_end: help_link_end }
- if User.blocked_pending_approval.count > 0
.gl-alert-actions
= link_to s_('Admin|View pending user approvals'), admin_users_path({ filter: 'blocked_pending_approval' }), class: 'btn gl-alert-action btn-info gl-button'
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'displays new user signups cap alert', :js do
let_it_be(:admin) { create(:admin) }
let(:help_page_href) { help_page_path('user/admin_area/settings/sign_up_restrictions.md') }
let(:expected_content) { 'Your instance has reached its user cap' }
context 'when reached active users cap' do
before do
allow(User).to receive(:billable).and_return((0..9))
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:new_user_signups_cap).and_return(9)
gitlab_sign_in(admin)
end
it 'displays and dismiss alert' do
expect(page).to have_content(expected_content)
expect(page).to have_link('usage caps', href: help_page_href)
visit root_dashboard_path
find('.js-new-user-signups-cap-reached .gl-alert-dismiss').click
expect(page).not_to have_content(expected_content)
expect(page).not_to have_link('usage caps', href: help_page_href)
end
end
end
......@@ -368,4 +368,56 @@ RSpec.describe EE::UserCalloutsHelper do
end
end
end
describe '.show_new_user_signups_cap_reached?' do
subject { helper.show_new_user_signups_cap_reached? }
let(:user) { create(:user) }
let(:admin) { create(:user, admin: true) }
context 'when user is anonymous' do
before do
allow(helper).to receive(:current_user).and_return(nil)
end
it { is_expected.to eq(false) }
end
context 'when user is not an admin' do
before do
allow(helper).to receive(:current_user).and_return(user)
end
it { is_expected.to eq(false) }
end
context 'when feature flag is disabled' do
before do
allow(helper).to receive(:current_user).and_return(admin)
stub_feature_flags(admin_new_user_signups_cap: false)
end
it { is_expected.to eq(false) }
end
context 'when feature flag is enabled' do
where(:new_user_signups_cap, :active_user_count, :result) do
nil | 10 | false
10 | 9 | false
0 | 10 | true
1 | 1 | true
end
with_them do
before do
allow(helper).to receive(:current_user).and_return(admin)
allow(User.billable).to receive(:count).and_return(active_user_count)
allow(Gitlab::CurrentSettings.current_application_settings)
.to receive(:new_user_signups_cap).and_return(new_user_signups_cap)
end
it { is_expected.to eq(result) }
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'callout alerts' do
include Capybara::RSpecMatchers
describe 'new_user_signups_cap_reached' do
let_it_be(:user) { create(:admin) }
let(:enabled) { true }
let(:billable_users) { [double(:billable_user)] }
let(:help_page_href) { help_page_path('user/admin_area/settings/sign_up_restrictions.md') }
let(:expected_content) { 'Your instance has reached its user cap' }
shared_examples_for 'a visible alert' do
it 'shows the alert' do
get root_dashboard_path
expect(response.body).to include(expected_content)
expect(response.body).to have_link('usage caps', href: help_page_href)
end
end
shared_examples_for 'a hidden alert' do
it 'does not show the alert' do
get root_dashboard_path
expect(response.body).not_to include(expected_content)
end
end
before do
stub_feature_flags(admin_new_user_signups_cap: enabled)
stub_application_setting(new_user_signups_cap: 1)
allow(User).to receive(:billable).and_return(billable_users)
login_as(user)
end
context 'when cap reached' do
it_behaves_like 'a visible alert'
end
context 'when cap not reached' do
let(:billable_users) { [] }
it_behaves_like 'a hidden alert'
end
context 'when feature disabled' do
let(:enabled) { false }
it_behaves_like 'a hidden alert'
end
context 'when user is not admin' do
let_it_be(:user) { create(:user) }
it_behaves_like 'a hidden alert'
end
end
end
......@@ -2269,6 +2269,15 @@ msgstr ""
msgid "Administration"
msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
msgid "Admin|View pending user approvals"
msgstr ""
msgid "Admin|Your instance has reached its user cap"
msgstr ""
msgid "Advanced"
msgstr ""
......
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