diff --git a/Gemfile b/Gemfile index 0fd082ee2a43c44306aa25a41f1866bcdae85d34..7b9c1a77ce47ba8645b9adfcdec64fcb069cbaa7 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 88348e790f12a56ab00fc5f9c5f4494cfbb4ccee..e16cc0192235dfcae395d969568c5ca60758cb3b 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 f0230b2996c9d81db261d221e686726281d87ee8..369c2f4b1cda19db7e2c3bcef8320d5cf965abe1 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 bb1ef2d4856b81f560d870f7e846238d302490f3..964a93139d7377f9010a5a1cbfe3a0bc6dc13ba0 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 3a812f5e8146931f7d3c42cf658118799f80bc74..d969d913d881f8eeabc179b8a3e49f8d27342e51 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 ""