Commit c120336d authored by Rubén Dávila's avatar Rubén Dávila

Add new endpoint to do a manual sync of seat link

`should_sync_seats?` was moved because we want to use that method
outside of the worker.
parent 5f64a44d
......@@ -62,6 +62,18 @@ class Admin::LicensesController < Admin::ApplicationController
redirect_to admin_license_path, status: :found
end
def sync_seat_link
sync_result = Gitlab::SeatLinkData.new.sync
if sync_result
flash[:notice] = _('Your license was successfully synced.')
else
flash[:error] = _('There was an error when trying to sync your license. Please verify that your instance is using an active license key.')
end
redirect_to admin_license_path
end
private
def build_license
......
......@@ -19,9 +19,20 @@ module Gitlab
@active_users = active_users || default_active_count
end
# Returns true if historical data exists between license start and the given date.
def historical_data_exists?
historical_data.present?
def sync
return unless should_sync_seats?
SyncSeatLinkWorker.perform_async
end
# Only sync paid licenses from start date until 14 days after expiration
# when seat link feature is enabled.
def should_sync_seats?
Gitlab::CurrentSettings.seat_link_enabled? &&
!license&.trial? &&
license&.expires_at && # Skip sync if license has no expiration
historical_data.present? && # Skip sync if there is no historical data
timestamp.between?(license.starts_at.beginning_of_day, license.expires_at.end_of_day + 14.days)
end
private
......@@ -36,19 +47,23 @@ module Gitlab
}
end
def license
::License.current
end
def default_key
::License.current.data
license&.data
end
def default_max_count
::License.current.historical_max(to: timestamp)
license&.historical_max(to: timestamp)
end
def historical_data
strong_memoize(:historical_data) do
to_timestamp = timestamp || Time.current
::License.current.historical_data(to: to_timestamp).order(:recorded_at).last
license&.historical_data(to: to_timestamp)&.order(:recorded_at)&.last
end
end
......
......@@ -13,7 +13,7 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 12, dead: false
def perform
return unless should_sync_seats?
return unless seat_link_data.should_sync_seats?
SyncSeatLinkRequestWorker.perform_async(
seat_link_data.timestamp.iso8601,
......@@ -28,15 +28,4 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker
def seat_link_data
@seat_link_data ||= Gitlab::SeatLinkData.new
end
# Only sync paid licenses from start date until 14 days after expiration
# when seat link feature is enabled.
def should_sync_seats?
Gitlab::CurrentSettings.seat_link_enabled? &&
License.current &&
!License.current.trial? &&
License.current.expires_at && # Skip sync if license has no expiration
seat_link_data.historical_data_exists? && # Skip sync if there is no historical data
seat_link_data.timestamp.between?(License.current.starts_at.beginning_of_day, License.current.expires_at.end_of_day + 14.days)
end
end
......@@ -28,6 +28,7 @@ namespace :admin do
resource :license, only: [:show, :new, :create, :destroy] do
get :download, on: :member
post :sync_seat_link, on: :collection
resource :usage_export, controller: 'licenses/usage_exports', only: [:show]
end
......
......@@ -83,4 +83,35 @@ RSpec.describe Admin::LicensesController do
end
end
end
describe 'POST sync_seat_link' do
let_it_be(:historical_data) { create(:historical_data, recorded_at: Time.current) }
before do
allow(License).to receive(:current).and_return(create(:license))
allow(Settings.gitlab).to receive(:seat_link_enabled).and_return(seat_link_enabled)
end
context 'with seat link enabled' do
let(:seat_link_enabled) { true }
it 'redirects with a successful message' do
post :sync_seat_link
expect(response).to redirect_to(admin_license_path)
expect(flash[:notice]).to eq('Your license was successfully synced.')
end
end
context 'with seat link disabled' do
let(:seat_link_enabled) { false }
it 'redirects with an error message' do
post :sync_seat_link
expect(response).to redirect_to(admin_license_path)
expect(flash[:error]).to match('There was an error when trying to sync your license.')
end
end
end
end
......@@ -91,24 +91,69 @@ RSpec.describe Gitlab::SeatLinkData do
end
end
describe '#historical_data_exists?' do
let_it_be(:license) { create_current_license(starts_at: Date.current - 7.days) }
describe '#sync' do
before do
allow(subject).to receive(:should_sync_seats?).and_return(sync_seats)
end
context 'when ready to sync seats' do
let(:sync_seats) { true }
it 'performs the sync' do
expect(SyncSeatLinkWorker).to receive(:perform_async)
subject.sync
end
end
it 'returns false if no historical data exists' do
expect(described_class.new.historical_data_exists?).to be(false)
context 'when not ready to sync seats' do
let(:sync_seats) { false }
it 'does not perform the sync' do
expect(SyncSeatLinkWorker).not_to receive(:perform_async)
subject.sync
end
end
end
describe '#should_sync_seats?' do
let_it_be(:historical_data) { create(:historical_data, recorded_at: timestamp) }
subject { super().should_sync_seats? }
it 'returns false if no historical data exists within [license start date, seat_link_data.date]' do
create(:historical_data, recorded_at: Time.current - 8.days)
create(:historical_data, recorded_at: Time.current)
context 'when all the pre conditions are valid' do
it { is_expected.to eq(true) }
end
context 'when seat link is disabled' do
before do
allow(Settings.gitlab).to receive(:seat_link_enabled).and_return(false)
end
it { is_expected.to be_falsey }
end
context 'when license key is missing' do
before do
allow(License).to receive(:current).and_return(nil)
end
it { is_expected.to be_falsey }
end
context 'when license is trial' do
before do
allow(License).to receive(:current).and_return(create(:license, trial: true))
end
expect(described_class.new(timestamp: Time.current - 1.day).historical_data_exists?).to be(false)
it { is_expected.to be_falsey }
end
it 'returns true if historical data exists within [license start date, seat_link_data.date]' do
create(:historical_data, recorded_at: Time.current - 2.days)
context 'when timestamp is out of the range' do
let(:timestamp) { Time.iso8601('2015-03-22T06:09:18Z') }
expect(described_class.new(timestamp: Time.current - 1.day).historical_data_exists?).to be(true)
it { is_expected.to be_falsey }
end
end
end
......@@ -30876,6 +30876,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
......@@ -35397,6 +35400,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
msgid "Your license was successfully synced."
msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
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