Commit bc401d36 authored by Fabio Pitino's avatar Fabio Pitino Committed by Stan Hu

Make Ci::Minutes::Notification user agnostic

By removing current_user in Notification we can
reuse it as a ValueObject in other contexts and
make it also a SSOT for notification levels.
parent e7895851
......@@ -21,7 +21,7 @@ module EE
strong_memoize(:show_out_of_ci_minutes_notification) do
next unless project&.persisted? || namespace&.persisted?
::Ci::Minutes::Notification.new(current_user, project, namespace).show?
::Ci::Minutes::Notification.new(project, namespace).show?(current_user)
end
end
end
......
......@@ -10,22 +10,17 @@ module Ci
delegate :last_ci_minutes_usage_notification_level,
:shared_runners_remaining_minutes_percent, to: :namespace
def initialize(user, project, namespace)
@user = user
attr_reader :level
def initialize(project, namespace)
@project = project
@namespace = project&.shared_runners_limit_namespace || namespace
@level = project || namespace
end
def can_see_status?
return false unless level
Ability.allowed?(user, :read_ci_minutes_quota, level)
end
private
attr_reader :project, :user, :level, :namespace
attr_reader :project, :namespace
end
end
end
......@@ -9,32 +9,35 @@ module Ci
exceeded: 0
}.freeze
def initialize(user, project, namespace)
@context = Ci::Minutes::Context.new(user, project, namespace)
@level = calculate_level if eligible_for_notifications?
def initialize(project, namespace)
@context = Ci::Minutes::Context.new(project, namespace)
@stage = calculate_notification_stage if eligible_for_notifications?
end
def show?
level.present?
def show?(current_user)
return false unless @stage
return false unless @context.level
Ability.allowed?(current_user, :read_ci_minutes_quota, @context.level)
end
def text
contextual_map.dig(level, :text)
contextual_map.dig(stage, :text)
end
def style
contextual_map.dig(level, :style)
contextual_map.dig(stage, :style)
end
private
attr_reader :context, :level
attr_reader :context, :stage
def eligible_for_notifications?
context.shared_runners_minutes_limit_enabled? && context.can_see_status?
context.shared_runners_minutes_limit_enabled?
end
def calculate_level
def calculate_notification_stage
percentage = context.shared_runners_remaining_minutes_percent.to_i
if percentage <= PERCENTAGES[:exceeded]
......@@ -74,7 +77,7 @@ module Ci
" minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run.") %
{
namespace_name: context.namespace_name,
percentage: PERCENTAGES[level]
percentage: PERCENTAGES[stage]
}
end
end
......
- notification = ::Ci::Minutes::Notification.new(current_user, local_assigns.dig(:project), local_assigns.dig(:namespace))
- return unless notification.show?
- notification = ::Ci::Minutes::Notification.new(local_assigns.dig(:project), local_assigns.dig(:namespace))
- return unless notification.show?(current_user)
%div{ class: [(classes if defined? classes)] }
.shared-runner-quota-message.gl-pt-5.gl-pb-3
......
......@@ -3,12 +3,11 @@
require 'spec_helper'
describe Ci::Minutes::Context do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:project) { build(:project, namespace: group) }
describe 'delegation' do
subject { described_class.new(user, project, group) }
subject { described_class.new(project, group) }
it { is_expected.to delegate_method(:shared_runners_remaining_minutes_below_threshold?).to(:level) }
it { is_expected.to delegate_method(:shared_runners_minutes_used?).to(:level) }
......@@ -16,64 +15,4 @@ describe Ci::Minutes::Context do
it { is_expected.to delegate_method(:name).to(:namespace).with_prefix }
it { is_expected.to delegate_method(:last_ci_minutes_usage_notification_level).to(:namespace) }
end
context 'when at project level' do
subject { described_class.new(user, project, nil) }
describe '#can_see_status' do
context 'when eligible to see status' do
before do
project.add_developer(user)
end
it 'can see status' do
expect(subject.can_see_status?).to be_truthy
end
end
context 'when not eligible to see status' do
it 'cannot see status' do
expect(subject.can_see_status?).to be_falsey
end
end
context 'when user is not authenticated' do
let(:user) { nil }
it 'cannot see status' do
expect(subject.can_see_status?).to be_falsey
end
end
end
end
context 'when at namespace level' do
subject { described_class.new(user, nil, group) }
describe '#can_see_status' do
context 'when eligible to see status' do
before do
group.add_developer(user)
end
it 'can see status' do
expect(subject.can_see_status?).to be_truthy
end
end
context 'when not eligible to see status' do
it 'cannot see status' do
expect(subject.can_see_status?).to be_falsey
end
end
context 'when user is not authenticated' do
let(:user) { nil }
it 'cannot see status' do
expect(subject.can_see_status?).to be_falsey
end
end
end
end
end
......@@ -42,7 +42,7 @@ describe Ci::Minutes::Notification do
end
it 'has warning notification' do
expect(subject.show?).to be_truthy
expect(subject.show?(user)).to be_truthy
expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :warning
end
......@@ -54,7 +54,7 @@ describe Ci::Minutes::Notification do
end
it 'has danger notification' do
expect(subject.show?).to be_truthy
expect(subject.show?(user)).to be_truthy
expect(subject.text).to match(/.*\shas 5% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :danger
end
......@@ -66,7 +66,7 @@ describe Ci::Minutes::Notification do
end
it 'has warning notification' do
expect(subject.show?).to be_truthy
expect(subject.show?(user)).to be_truthy
expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :warning
end
......@@ -76,7 +76,7 @@ describe Ci::Minutes::Notification do
let(:group) { create(:group, :with_used_build_minutes_limit) }
it 'has exceeded notification' do
expect(subject.show?).to be_truthy
expect(subject.show?(user)).to be_truthy
expect(subject.text).to match(/.*\shas exceeded its pipeline minutes quota/)
expect(subject.style).to eq :danger
end
......@@ -92,9 +92,7 @@ describe Ci::Minutes::Notification do
context 'when not permitted to see notifications' do
it 'has no notifications set' do
expect(subject.show?).to be_falsey
expect(subject.text).to be_nil
expect(subject.style).to be_nil
expect(subject.show?(user)).to be_falsey
end
end
end
......@@ -108,18 +106,26 @@ describe Ci::Minutes::Notification do
it_behaves_like 'queries for notifications' do
subject do
threshold = described_class.new(user, injected_project, nil)
threshold.show?
threshold = described_class.new(injected_project, nil)
threshold.show?(user)
end
end
it_behaves_like 'has notifications' do
subject { described_class.new(user, injected_project, nil) }
subject { described_class.new(injected_project, nil) }
end
end
it_behaves_like 'not eligible to see notifications' do
subject { described_class.new(user, injected_project, nil) }
subject { described_class.new(injected_project, nil) }
end
context 'when user is not authenticated' do
let(:user) { nil }
it_behaves_like 'not eligible to see notifications' do
subject { described_class.new(injected_project, nil) }
end
end
end
end
......@@ -134,26 +140,34 @@ describe Ci::Minutes::Notification do
context 'with a project that has runners enabled inside namespace' do
it_behaves_like 'queries for notifications' do
subject do
threshold = described_class.new(user, nil, injected_group)
threshold.show?
threshold = described_class.new(nil, injected_group)
threshold.show?(user)
end
end
it_behaves_like 'has notifications' do
subject { described_class.new(user, nil, injected_group) }
subject { described_class.new(nil, injected_group) }
end
end
context 'with no projects that have runners enabled inside namespace' do
it_behaves_like 'not eligible to see notifications' do
let(:shared_runners_enabled) { false }
subject { described_class.new(user, nil, injected_group) }
subject { described_class.new(nil, injected_group) }
end
end
end
it_behaves_like 'not eligible to see notifications' do
subject { described_class.new(user, nil, injected_group) }
subject { described_class.new(nil, injected_group) }
end
context 'when user is not authenticated' do
let(:user) { nil }
it_behaves_like 'not eligible to see notifications' do
subject { described_class.new(injected_project, nil) }
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