Commit f6bda794 authored by Doug Stull's avatar Doug Stull Committed by Alper Akgun

Add free user cap feature flag and availability check

- foundation work for free user cap project
parent b50ade79
......@@ -15,7 +15,7 @@ class Groups::UsageQuotasController < Groups::ApplicationController
end
def pending_members
render_404 unless @group.user_cap_available?
render_404 unless @group.apply_user_cap?
@hide_search_settings = true
end
......
......@@ -301,6 +301,18 @@ module EE
end
end
def on_existing_free_subscription?
# this is a side-effect free version of checking if a namespace
# is on a free plan - see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80839#note_851566461
strong_memoize(:on_existing_free_subscription) do
::Plan
.joins(:hosted_subscriptions)
.where(name: ::Plan::FREE)
.where(gitlab_subscriptions: { namespace_id: id })
.exists?
end
end
# When a purchasing a GL.com plan for a User namespace
# we only charge for a single user.
# This method is overwritten in Group where we made the calculation
......@@ -458,6 +470,17 @@ module EE
::Feature.enabled?(:saas_user_caps, root_ancestor, default_enabled: :yaml)
end
def apply_free_user_cap?
return false unless ::Gitlab.com?
return false unless root_ancestor.on_existing_free_subscription?
::Feature.enabled?(:free_user_cap, root_ancestor, default_enabled: :yaml)
end
def apply_user_cap?
user_cap_available? || apply_free_user_cap?
end
private
def any_project_with_shared_runners_enabled_with_cte?
......
......@@ -6,7 +6,7 @@
- page_title s_("UsageQuota|Usage")
- url_to_purchase_storage = buy_storage_path(@group) if purchase_storage_link_enabled?(@group)
- buy_addon_target_attr = buy_addon_target_attr(@group) if purchase_storage_link_enabled?(@group)
- pending_members_page_path = pending_members_group_usage_quotas_path(@group) if @group.user_cap_available?
- pending_members_page_path = pending_members_group_usage_quotas_path(@group) if @group.apply_user_cap?
- pending_members_count = Member.in_hierarchy(@group).with_state("awaiting").count
- if show_product_purchase_success_alert?
......
---
name: free_user_cap
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80839
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352633
milestone: '14.9'
type: development
group: group::conversion
default_enabled: false
......@@ -43,7 +43,7 @@ RSpec.describe Groups::UsageQuotasController do
before do
allow_next_found_instance_of(Group) do |group|
allow(group).to receive(:user_cap_available?).and_return(feature_available)
allow(group).to receive(:apply_user_cap?).and_return(feature_available)
end
end
......
......@@ -2207,6 +2207,101 @@ RSpec.describe Namespace do
end
end
describe '#apply_free_user_cap?', :saas do
let_it_be(:namespace) { create(:group_with_plan, plan: :free_plan) }
let_it_be(:subgroup) { create(:group, parent: namespace) }
subject(:apply_free_user_cap?) { namespace.apply_free_user_cap? }
context 'when not on Gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(false)
end
it { is_expected.to be false }
end
context 'when :free_user_cap is disabled' do
before do
stub_feature_flags(free_user_cap: false)
end
it { is_expected.to be false }
end
context 'when :free_user_cap is enabled' do
before do
stub_feature_flags(free_user_cap: true)
end
it { is_expected.to be true }
context 'when the namespace is not a group' do
let_it_be(:namespace) do
namespace = create(:user).namespace
create(:gitlab_subscription, hosted_plan: create(:free_plan), namespace: namespace)
namespace
end
it { is_expected.to be true }
end
context 'when it is a non free plan' do
let_it_be(:namespace) { create(:group_with_plan, plan: :ultimate_plan) }
it { is_expected.to be false }
end
context 'when no plan exists' do
let_it_be(:namespace) { create(:group) }
it { is_expected.to be false }
end
end
end
describe '#apply_user_cap?' do
let(:namespace) { build(:namespace) }
where(:user_cap_available, :apply_free_user_cap, :result) do
false | false | false
false | true | true
true | false | true
true | true | true
end
subject { namespace.apply_user_cap? }
with_them do
before do
allow(namespace).to receive(:user_cap_available?).and_return(user_cap_available)
allow(namespace).to receive(:apply_free_user_cap?).and_return(apply_free_user_cap)
end
it { is_expected.to eq(result) }
end
end
describe '#on_existing_free_subscription?', :saas do
it 'returns true with a free plan' do
namespace = create(:group_with_plan, plan: :free_plan)
expect(namespace.on_existing_free_subscription?).to be(true)
end
it 'returns false when the plan is not free' do
namespace = create(:group_with_plan, plan: :ultimate_plan)
expect(namespace.on_existing_free_subscription?).to be(false)
end
it 'returns false when there is no plan' do
namespace = create(:namespace)
expect(namespace.on_existing_free_subscription?).to be(false)
end
end
def create_project(repository_size:, lfs_objects_size:, repository_size_limit:)
create(:project, namespace: namespace, repository_size_limit: repository_size_limit).tap do |project|
create(:project_statistics, project: project, repository_size: repository_size, lfs_objects_size: lfs_objects_size)
......
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