From eb9ac6e66e76b5a9422c3780f0106300ad265bab Mon Sep 17 00:00:00 2001 From: Aishwarya Subramanian <asubramanian@gitlab.com> Date: Wed, 12 Jun 2024 13:03:30 +0000 Subject: [PATCH] Display temporary extension expiration banner Display temporary extension banner when the license is about to expire soon or has already expired. Changelog: added MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/155634 EE: true --- Gemfile | 2 +- Gemfile.lock | 2 +- .../gitlab/expiring_subscription_message.rb | 31 ++++++++++++ .../expiring_subscription_message_spec.rb | 48 ++++++++++++++++++- locale/gitlab.pot | 6 +++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 0fd082ee2a43c..7b9c1a77ce47b 100644 --- a/Gemfile +++ b/Gemfile @@ -349,7 +349,7 @@ gem 'gon', '~> 6.4.0' # rubocop:todo Gemfile/MissingFeatureCategory gem 'request_store', '~> 1.5.1' # rubocop:todo Gemfile/MissingFeatureCategory gem 'base32', '~> 0.3.0' # rubocop:todo Gemfile/MissingFeatureCategory -gem 'gitlab-license', '~> 2.4', feature_category: :shared +gem 'gitlab-license', '~> 2.5', feature_category: :shared # Protect against bruteforcing gem 'rack-attack', '~> 6.7.0' # rubocop:todo Gemfile/MissingFeatureCategory diff --git a/Gemfile.lock b/Gemfile.lock index 88348e790f12a..e16cc0192235d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2004,7 +2004,7 @@ DEPENDENCIES gitlab-housekeeper! gitlab-http! gitlab-labkit (~> 0.36.0) - gitlab-license (~> 2.4) + gitlab-license (~> 2.5) gitlab-mail_room (~> 0.0.24) gitlab-markup (~> 1.9.0) gitlab-net-dns (~> 0.9.2) diff --git a/ee/lib/gitlab/expiring_subscription_message.rb b/ee/lib/gitlab/expiring_subscription_message.rb index f0230b2996c9d..369c2f4b1cda1 100644 --- a/ee/lib/gitlab/expiring_subscription_message.rb +++ b/ee/lib/gitlab/expiring_subscription_message.rb @@ -3,6 +3,7 @@ module Gitlab class ExpiringSubscriptionMessage GRACE_PERIOD_EXTENSION_DAYS = 30.days + TEMP_EXTENSION_EXPIRING_SOON_NOTIFY_WITHIN = 7.days include Gitlab::Utils::StrongMemoize include Gitlab::Routing @@ -46,6 +47,8 @@ def license_message_subject end def expired_subject + return temporary_extension_expired_subject if display_temporary_extension_notification? + if namespace && auto_renew _('Something went wrong with your automatic subscription renewal.') else @@ -54,6 +57,8 @@ def expired_subject end def expiring_subject + return temporary_extension_expiring_subject if display_temporary_extension_notification? + _('Your %{plan_name} subscription will expire on %{expires_on}') % { expires_on: subscribable.expires_at.iso8601, @@ -61,6 +66,18 @@ def expiring_subject } end + def temporary_extension_expired_subject + _('Your subscription with temporary extension expired!') + end + + def temporary_extension_expiring_subject + _("Your %{plan_name} subscription with a temporary extension will expire on %{expires_on}") % + { + expires_on: subscribable.expires_at.iso8601, + plan_name: plan_name + } + end + def expiration_blocking_message return '' unless subscribable.will_block_changes? @@ -168,6 +185,7 @@ def self_managed_subscription_future_renewal? def require_notification? return false if expiring_auto_renew? || ::License.future_dated.present? return true if force_notification && subscribable.block_changes? + return display_temporary_extension_notification? if temporary_extension? auto_renew_choice_exists? && expired_subscribable_within_notification_window? && !subscription_future_renewal? end @@ -214,6 +232,19 @@ def self_managed? subscribable.is_a?(::License) end + def display_temporary_extension_notification? + strong_memoize(:display_temporary_extension_notification) do + next false unless temporary_extension? + + expiring_soon = Date.current >= (subscribable.expires_at - TEMP_EXTENSION_EXPIRING_SOON_NOTIFY_WITHIN) + subscribable.expired? || expiring_soon ? true : false + end + end + + def temporary_extension? + self_managed? && subscribable.temporary_extension? + end + def remaining_days strong_memoize(:remaining_days) do days = if subscribable.expired? diff --git a/ee/spec/lib/gitlab/expiring_subscription_message_spec.rb b/ee/spec/lib/gitlab/expiring_subscription_message_spec.rb index bb1ef2d4856b8..964a93139d737 100644 --- a/ee/spec/lib/gitlab/expiring_subscription_message_spec.rb +++ b/ee/spec/lib/gitlab/expiring_subscription_message_spec.rb @@ -11,7 +11,7 @@ subject(:message) { strip_tags(raw_message) } let(:subject) { strip_tags(raw_subject) } - let(:subscribable) { double(:license) } + let(:subscribable) { double(:license, temporary_extension?: false) } let(:namespace) { nil } let(:force_notification) { false } let(:raw_message) do @@ -320,6 +320,52 @@ end end end + + context 'subscribable is a temporary extension license' do + let(:subscribable) { double(:license, temporary_extension?: true) } + + before do + allow(subscribable).to receive(:is_a?).with(::License).and_return(true) + allow(subscribable).to receive_messages( + will_block_changes?: true, + block_changes_at: block_changes_date, + expired?: expired? + ) + end + + context 'when expiring soon' do + let(:expired?) { false } + + it 'has a subject and message indicating the temporary extension is expiring soon' do + expect(subject).to include("Your #{plan_name.capitalize} subscription with a temporary extension will expire on #{expired_date.iso8601}") + expect(message).to include("If you don\'t renew by #{block_changes_date.iso8601} your instance will become read-only, and you won't be able to create issues or merge requests. You will also lose access to your paid features and support entitlement. How do I renew my subscription?") + end + end + + context 'when already expired' do + let(:expired?) { true } + + before do + allow(subscribable).to receive(:block_changes?).and_return(true) + end + + it 'has a subject and message indicating the temporary extension has expired' do + expect(subject).to include("Your subscription with temporary extension expired!") + expect(message).to include("This instance is now read-only. Don't worry, your data is safe. To change to GitLab Free and restore write access to this instance, delete your expired license") + end + end + + context 'when not in notification window' do + let(:expired?) { false } + let(:expired_date) { (today + 20.days).to_date } + let(:block_changes_date) { expired_date } + + it 'does not return a subject and message' do + expect(subject).to be_nil + expect(message).to be_nil + end + end + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3a812f5e81469..d969d913d881f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -61053,6 +61053,9 @@ msgstr "" msgid "Your %{plan_name} subscription will expire on %{expires_on}" msgstr "" +msgid "Your %{plan_name} subscription with a temporary extension will expire on %{expires_on}" +msgstr "" + msgid "Your %{plan} plan will be applied to your group." msgstr "" @@ -61393,6 +61396,9 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_ msgstr[0] "" msgstr[1] "" +msgid "Your subscription with temporary extension expired!" +msgstr "" + msgid "Your top-level group %{namespace_name} has reached the %{free_limit} user limit" msgstr "" -- GitLab