Commit 594683e0 authored by Reuben Pereira's avatar Reuben Pereira

Refactor UpcomingReconciliationHelper

Helpers are all included into views, which makes methods defined
in helpers globally available.
To reduce the number of methods in UpcomingReconciliationHelper,
introduce a separate entity class and use that class in the helper.
The entity class is used as a PORO.
parent 3cb81609
......@@ -2,71 +2,29 @@
module GitlabSubscriptions
module UpcomingReconciliationHelper
include Gitlab::Utils::StrongMemoize
COOKIE_KEY_PREFIX = 'hide_upcoming_reconciliation_alert'
def upcoming_reconciliation_hash(namespace = nil)
return {} unless display_upcoming_reconciliation_alert?(namespace)
reconciliation = upcoming_reconciliation(namespace&.id)
entity = reconciliation_entity(namespace)
{
reconciliation_date: reconciliation.next_reconciliation_date.to_s,
cookie_key: cookie_key(reconciliation, namespace&.id)
reconciliation_date: entity.next_reconciliation_date.to_s,
cookie_key: entity.cookie_key
}
end
def display_upcoming_reconciliation_alert?(namespace = nil)
return false unless has_permissions?(namespace)
entity = reconciliation_entity(namespace)
reconciliation = upcoming_reconciliation(namespace&.id)
return false unless reconciliation&.display_alert?
return false if alert_dismissed?(reconciliation, namespace&.id)
return false unless entity.has_permissions?
return false unless entity.display_alert?
return false if cookies[entity.cookie_key] == 'true'
true
end
private
def upcoming_reconciliation(namespace_id)
strong_memoize(:upcoming_reconciliation) do
UpcomingReconciliation.next(namespace_id)
end
end
def alert_dismissed?(reconciliation, namespace_id)
key = cookie_key(reconciliation, namespace_id)
cookies[key] == 'true'
end
def cookie_key(reconciliation, namespace_id)
if saas?
"#{COOKIE_KEY_PREFIX}_#{current_user.id}_#{namespace_id}_#{reconciliation.next_reconciliation_date}"
else
"#{COOKIE_KEY_PREFIX}_#{current_user.id}_#{reconciliation.next_reconciliation_date}"
end
end
def has_permissions?(namespace)
if saas?
user_can_admin?(namespace)
else
user_is_admin?
end
end
def user_is_admin?
current_user.can_admin_all_resources?
end
def user_can_admin?(namespace)
Ability.allowed?(current_user, :admin_namespace, namespace)
end
def saas?
::Gitlab.com?
def reconciliation_entity(namespace)
@reconciliation_entity ||= GitlabSubscriptions::UpcomingReconciliationEntity.new(current_user: current_user, namespace: namespace)
end
end
end
# frozen_string_literal: true
module GitlabSubscriptions
class UpcomingReconciliationEntity
include Gitlab::Utils::StrongMemoize
COOKIE_KEY_PREFIX = 'hide_upcoming_reconciliation_alert'
delegate :next_reconciliation_date, to: :upcoming_reconciliation, allow_nil: true
def initialize(current_user:, namespace: nil)
@current_user = current_user
@namespace = namespace
end
def cookie_key
namespace_string = namespace ? "#{namespace.id}_" : ''
"#{COOKIE_KEY_PREFIX}_#{current_user.id}_#{namespace_string}#{upcoming_reconciliation.next_reconciliation_date}"
end
def has_permissions?
if namespace
user_can_admin_namespace?
else
!!user_is_admin?
end
end
def display_alert?
!!upcoming_reconciliation&.display_alert?
end
private
attr_reader :current_user, :namespace
def upcoming_reconciliation
strong_memoize(:upcoming_reconciliation) do
UpcomingReconciliation.next(namespace&.id)
end
end
def user_is_admin?
current_user&.can_admin_all_resources?
end
def user_can_admin_namespace?
Ability.allowed?(current_user, :admin_namespace, namespace)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSubscriptions::UpcomingReconciliationEntity do
subject { described_class.new(current_user: user, namespace: namespace) }
let(:upcoming_reconciliation) { build(:upcoming_reconciliation, :self_managed) }
let(:user) { build(:user) }
let(:namespace) { nil }
before do
allow(GitlabSubscriptions::UpcomingReconciliation).to receive(:next).with(nil).and_return(upcoming_reconciliation)
end
it { is_expected.to delegate_method(:next_reconciliation_date).to(:upcoming_reconciliation) }
it { is_expected.to delegate_method(:display_alert?).to(:upcoming_reconciliation) }
describe '#has_permissions?' do
context 'with namespace' do
let(:namespace) { build(:namespace, owner: user) }
it 'checks if user can admin_namespace' do
expect(Ability).to receive(:allowed?).with(user, :admin_namespace, namespace).and_return(true)
expect(subject.has_permissions?).to eq(true)
end
end
context 'without namespace' do
it 'checks if user is admin' do
expect(user).to receive(:can_admin_all_resources?).and_return(true)
expect(subject.has_permissions?).to eq(true)
end
context 'when current_user is nil' do
let(:current_user) { nil }
it 'returns false' do
expect(subject.has_permissions?).to eq(false)
end
end
end
end
describe '#cookie_key' do
let(:upcoming_reconciliation) { build(:upcoming_reconciliation, :saas, namespace: namespace) }
before do
allow(user).to receive(:id).and_return(1)
end
context 'with namespace' do
let(:namespace) { build(:namespace, owner: user) }
before do
allow(::Gitlab).to receive(:com?).and_return(true)
allow(namespace).to receive(:id).and_return(2)
allow(GitlabSubscriptions::UpcomingReconciliation).to receive(:next).with(namespace.id).and_return(upcoming_reconciliation)
end
it 'includes namespace id in key' do
expected_key = "#{described_class::COOKIE_KEY_PREFIX}_#{user.id}_#{namespace.id}_#{upcoming_reconciliation.next_reconciliation_date}"
expect(subject.cookie_key).to eq(expected_key)
end
end
context 'without namespace' do
it 'does not include namespace id in cookie key' do
expected_key = "#{described_class::COOKIE_KEY_PREFIX}_#{user.id}_#{upcoming_reconciliation.next_reconciliation_date}"
expect(subject.cookie_key).to eq(expected_key)
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