Commit c58f99d5 authored by Tyler Amos's avatar Tyler Amos Committed by Aleksei Lipniagov

Notify admins 15 days prior to license expiration

Overriding notification methods from Gitlab::License so that admins
are notified only 15 days prior to license expiration.  Previously,
admins were notified 1 month prior to expiration when the
Gitlab::License method was used, but this is inconsistent when
customers are able renew.  Notifying admins early lead to confusion.

Changelog: fixed
EE: true
parent d74b5255
......@@ -94,7 +94,7 @@ a license, upload the license in the **Admin Area** in the web user interface.
## What happens when your license expires
One month before the license expires, a message with the upcoming expiration
Fifteen days before the license expires, a notification banner with the upcoming expiration
date displays to GitLab administrators.
When your license expires, GitLab locks features, like Git pushes
......
......@@ -11,6 +11,9 @@ class License < ApplicationRecord
LICENSE_FILE_TYPE = 'license_file'
ALLOWED_PERCENTAGE_OF_USERS_OVERAGE = (10 / 100.0)
NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY = 1.week
ADMIN_NOTIFICATION_DAYS_BEFORE_EXPIRY = 15.days
EE_ALL_PLANS = [STARTER_PLAN, PREMIUM_PLAN, ULTIMATE_PLAN].freeze
EES_FEATURES_WITH_USAGE_PING = %i[
......@@ -623,6 +626,25 @@ class License < ApplicationRecord
super || created_at
end
# Overrides method from Gitlab::License which will be removed in a future version
def notify_admins?
return false if expires_at.blank?
return true if expired?
notification_days = trial? ? NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY : ADMIN_NOTIFICATION_DAYS_BEFORE_EXPIRY
Date.current >= (expires_at - notification_days)
end
# Overrides method from Gitlab::License which will be removed in a future version
def notify_users?
return false if expires_at.blank?
notification_start_date = trial? ? expires_at - NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY : block_changes_at
Date.current >= notification_start_date
end
private
def restricted_attr(name, default = nil)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Expiring Subscription Message', :js, :freeze_time do
shared_examples 'no expiration notification' do
it 'loads the page without any subscription expiration notifications' do
expect(page).not_to have_content('Your subscription expired!')
expect(page).not_to have_content('Your subscription will expire')
end
end
context 'for self-managed subscriptions' do
context 'when signed in user is an admin' do
let_it_be(:admin) { create(:admin) }
before do
create_current_license(plan: License::ULTIMATE_PLAN, expires_at: expires_at)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
end
context 'with a license with no expiration' do
let(:expires_at) { nil }
include_examples 'no expiration notification'
end
context 'with an expired license' do
let(:expires_at) { Date.current - 1.day }
it 'notifies the admin of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
context 'with a license expiring in 15 days' do
let(:expires_at) { Date.current + 15.days }
it 'notifies the admin of a soon expiring subscription' do
expect(page).to have_content('Your subscription will expire in 15 days')
end
end
context 'with a license expiring in more than 15 days' do
let(:expires_at) { Date.current + 16.days }
include_examples 'no expiration notification'
end
end
context 'when signed in user is not an admin' do
let_it_be(:user) { create(:user) }
before do
create_current_license(plan: License::ULTIMATE_PLAN, expires_at: expires_at, block_changes_at: block_changes_at)
sign_in(user)
visit root_path
end
context 'with a license with no expiration' do
let(:expires_at) { nil }
let(:block_changes_at) { nil }
include_examples 'no expiration notification'
end
context 'with an expired license in the grace period' do
let(:expires_at) { Date.current - 1.day }
let(:block_changes_at) { Date.current + 13.days }
include_examples 'no expiration notification'
end
context 'with an expired license beyond the grace period' do
let(:expires_at) { Date.current - 15.days }
let(:block_changes_at) { Date.current - 1.day }
it 'notifies the admin of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
end
end
context 'for namespace subscriptions', :saas do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
before do
enable_namespace_license_check!
create(:gitlab_subscription, namespace: group, end_date: end_date, auto_renew: false)
allow_next_instance_of(GitlabSubscriptions::CheckFutureRenewalService, namespace: group) do |service|
allow(service).to receive(:execute).and_return(false)
end
end
context 'when signed in user is a group owner' do
before do
group.add_owner(user)
sign_in(user)
visit group_path(group)
end
context 'with an expired license' do
let(:end_date) { Date.current - 1.day }
it 'notifies the group owner of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
context 'with a license expiring in less than 30 days' do
let(:end_date) { Date.current + 29.days }
it 'notifies the group owner of a soon expiring subscription' do
expect(page).to have_content('Your subscription will expire in 29 days')
end
end
context 'with a license expiring in 30 or more days' do
let(:end_date) { Date.current + 30.days }
include_examples 'no expiration notification'
end
end
context 'when signed in user is not a group owner' do
before do
group.add_developer(user)
sign_in(user)
visit group_path(group)
end
context 'with an expired license' do
let(:end_date) { Date.current - 1.day }
include_examples 'no expiration notification'
end
context 'with a license expiring in less than 30 days' do
let(:end_date) { Date.current + 29.days }
include_examples 'no expiration notification'
end
end
end
end
......@@ -1623,4 +1623,151 @@ RSpec.describe License do
it { is_expected.to eq(license.created_at) }
end
end
describe '#notify_admins?', :freeze_time do
subject(:notify_admins?) { license.notify_admins? }
context 'when license has expired' do
before do
gl_license.expires_at = Date.yesterday
end
it { is_expected.to eq(true) }
end
context 'when license has no expiration' do
before do
gl_license.expires_at = nil
end
it { is_expected.to eq(false) }
end
context 'when license has not expired' do
context 'when license is a trial' do
before do
gl_license.restrictions = { trial: true }
end
context 'when license expiration is more than a week from today' do
before do
gl_license.expires_at = Date.current + 8.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is a week from today' do
before do
gl_license.expires_at = Date.current + 7.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than a week from today' do
before do
gl_license.expires_at = Date.current + 6.days
end
it { is_expected.to eq(true) }
end
end
context 'when license is not a trial' do
context 'when license expiration is more than 15 days from today' do
before do
gl_license.expires_at = Date.current + 16.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is 15 days from today' do
before do
gl_license.expires_at = Date.current + 15.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than 15 days from today' do
before do
gl_license.expires_at = Date.current + 14.days
end
it { is_expected.to eq(true) }
end
end
end
end
describe '#notify_users?', :freeze_time do
subject(:notify_users?) { license.notify_users? }
context 'when license has no expiration' do
before do
gl_license.expires_at = nil
gl_license.block_changes_at = nil
end
it { is_expected.to eq(false) }
end
context 'when license is a trial' do
before do
gl_license.restrictions = { trial: true }
end
context 'when license expiration is more than a week from today' do
before do
gl_license.expires_at = Date.current + 8.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is a week from today' do
before do
gl_license.expires_at = Date.current + 7.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than a week from today' do
before do
gl_license.expires_at = Date.current + 6.days
end
it { is_expected.to eq(true) }
end
end
context 'when license is not a trial' do
context 'when license block changes date is before today' do
before do
gl_license.block_changes_at = Date.current - 1.day
end
it { is_expected.to eq(true) }
end
context 'when license block changes date is today' do
before do
gl_license.block_changes_at = Date.current
end
it { is_expected.to eq(true) }
end
context 'when license block changes date is after today' do
before do
gl_license.block_changes_at = Date.current + 1.day
end
it { is_expected.to eq(false) }
end
end
end
end
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