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. ...@@ -94,7 +94,7 @@ a license, upload the license in the **Admin Area** in the web user interface.
## What happens when your license expires ## 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. date displays to GitLab administrators.
When your license expires, GitLab locks features, like Git pushes When your license expires, GitLab locks features, like Git pushes
......
...@@ -11,6 +11,9 @@ class License < ApplicationRecord ...@@ -11,6 +11,9 @@ class License < ApplicationRecord
LICENSE_FILE_TYPE = 'license_file' LICENSE_FILE_TYPE = 'license_file'
ALLOWED_PERCENTAGE_OF_USERS_OVERAGE = (10 / 100.0) 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 EE_ALL_PLANS = [STARTER_PLAN, PREMIUM_PLAN, ULTIMATE_PLAN].freeze
EES_FEATURES_WITH_USAGE_PING = %i[ EES_FEATURES_WITH_USAGE_PING = %i[
...@@ -623,6 +626,25 @@ class License < ApplicationRecord ...@@ -623,6 +626,25 @@ class License < ApplicationRecord
super || created_at super || created_at
end 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 private
def restricted_attr(name, default = nil) 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 ...@@ -1623,4 +1623,151 @@ RSpec.describe License do
it { is_expected.to eq(license.created_at) } it { is_expected.to eq(license.created_at) }
end end
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 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