Commit 2aebdde6 authored by Jason Goodman's avatar Jason Goodman Committed by Shinya Maeda

Remove feature flag license check

This makes feature flags available in all tiers of EE
Require a premium or ultimate license for feature flag related issues
Move feature flag policy and related permissions to core
Move feature flags finder to core
Part of moving feature flags to core
parent 99a7757c
...@@ -325,6 +325,12 @@ class ProjectPolicy < BasePolicy ...@@ -325,6 +325,12 @@ class ProjectPolicy < BasePolicy
enable :destroy_design enable :destroy_design
enable :read_terraform_state enable :read_terraform_state
enable :read_pod_logs enable :read_pod_logs
enable :read_feature_flag
enable :create_feature_flag
enable :update_feature_flag
enable :destroy_feature_flag
enable :admin_feature_flag
enable :admin_feature_flags_user_lists
end end
rule { can?(:developer_access) & user_confirmed? }.policy do rule { can?(:developer_access) & user_confirmed? }.policy do
...@@ -371,6 +377,7 @@ class ProjectPolicy < BasePolicy ...@@ -371,6 +377,7 @@ class ProjectPolicy < BasePolicy
enable :read_freeze_period enable :read_freeze_period
enable :update_freeze_period enable :update_freeze_period
enable :destroy_freeze_period enable :destroy_freeze_period
enable :admin_feature_flags_client
end end
rule { public_project & metrics_dashboard_allowed }.policy do rule { public_project & metrics_dashboard_allowed }.policy do
...@@ -447,6 +454,8 @@ class ProjectPolicy < BasePolicy ...@@ -447,6 +454,8 @@ class ProjectPolicy < BasePolicy
prevent :read_pipeline prevent :read_pipeline
prevent :read_pipeline_schedule prevent :read_pipeline_schedule
prevent(*create_read_update_admin_destroy(:release)) prevent(*create_read_update_admin_destroy(:release))
prevent(*create_read_update_admin_destroy(:feature_flag))
prevent(:admin_feature_flags_user_lists)
end end
rule { container_registry_disabled }.policy do rule { container_registry_disabled }.policy do
......
...@@ -4,9 +4,10 @@ group: Progressive Delivery ...@@ -4,9 +4,10 @@ group: Progressive Delivery
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
--- ---
# Feature Flags **(PREMIUM)** # Feature Flags **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) in GitLab 11.4. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) in GitLab 11.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4
With Feature Flags, you can deploy your application's new features to production in smaller batches. With Feature Flags, you can deploy your application's new features to production in smaller batches.
You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery. You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery.
...@@ -349,7 +350,7 @@ else ...@@ -349,7 +350,7 @@ else
end end
``` ```
## Feature Flag Related Issues ## Feature Flag Related Issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default. > - It's deployed behind a feature flag, enabled by default.
......
...@@ -5,7 +5,7 @@ module Projects ...@@ -5,7 +5,7 @@ module Projects
include IssuableLinks include IssuableLinks
before_action :ensure_feature_enabled! before_action :ensure_feature_enabled!
before_action :authorize_admin_feature_flag! before_action :authorize_admin_feature_flags_issue_links!
private private
......
...@@ -30,7 +30,7 @@ module EE ...@@ -30,7 +30,7 @@ module EE
override :project_autocomplete override :project_autocomplete
def project_autocomplete def project_autocomplete
return super unless @project && @project.feature_available?(:feature_flags) return super unless @project && @project.feature_available?(:repository)
super + [{ category: "In this project", label: _("Feature Flags"), url: project_feature_flags_path(@project) }] super + [{ category: "In this project", label: _("Feature Flags"), url: project_feature_flags_path(@project) }]
end end
......
...@@ -12,7 +12,7 @@ module FeatureFlagsHelper ...@@ -12,7 +12,7 @@ module FeatureFlagsHelper
end end
def feature_flag_issues_links_endpoint(project, feature_flag, user) def feature_flag_issues_links_endpoint(project, feature_flag, user)
return '' unless Feature.enabled?(:feature_flags_issue_links, project, default_enabled: true) && can?(user, :read_issue_link, project) return '' unless Feature.enabled?(:feature_flags_issue_links, project, default_enabled: true) && can?(user, :admin_feature_flags_issue_links, project)
project_feature_flag_issues_path(project, feature_flag) project_feature_flag_issues_path(project, feature_flag)
end end
......
...@@ -72,7 +72,7 @@ class License < ApplicationRecord ...@@ -72,7 +72,7 @@ class License < ApplicationRecord
epics epics
extended_audit_events extended_audit_events
external_authorization_service_api_management external_authorization_service_api_management
feature_flags feature_flags_related_issues
file_locks file_locks
geo geo
generic_alert_fingerprinting generic_alert_fingerprinting
......
...@@ -120,11 +120,6 @@ module EE ...@@ -120,11 +120,6 @@ module EE
@subject.feature_available?(:threat_monitoring) @subject.feature_available?(:threat_monitoring)
end end
with_scope :subject
condition(:feature_flags_disabled) do
!@subject.feature_available?(:feature_flags)
end
with_scope :subject with_scope :subject
condition(:code_review_analytics_enabled) do condition(:code_review_analytics_enabled) do
@subject.feature_available?(:code_review_analytics, @user) @subject.feature_available?(:code_review_analytics, @user)
...@@ -142,6 +137,11 @@ module EE ...@@ -142,6 +137,11 @@ module EE
@subject.root_namespace.over_storage_limit? @subject.root_namespace.over_storage_limit?
end end
with_scope :subject
condition(:feature_flags_related_issues_disabled) do
!@subject.feature_available?(:feature_flags_related_issues)
end
rule { visual_review_bot }.policy do rule { visual_review_bot }.policy do
prevent :read_note prevent :read_note
enable :create_note enable :create_note
...@@ -154,6 +154,10 @@ module EE ...@@ -154,6 +154,10 @@ module EE
prevent :push_code prevent :push_code
end end
rule { feature_flags_related_issues_disabled | repository_disabled }.policy do
prevent :admin_feature_flags_issue_links
end
rule { ~group_timelogs_available }.prevent :read_group_timelogs rule { ~group_timelogs_available }.prevent :read_group_timelogs
rule { can?(:guest_access) & iterations_available }.enable :read_iteration rule { can?(:guest_access) & iterations_available }.enable :read_iteration
...@@ -171,13 +175,8 @@ module EE ...@@ -171,13 +175,8 @@ module EE
enable :create_vulnerability_feedback enable :create_vulnerability_feedback
enable :destroy_vulnerability_feedback enable :destroy_vulnerability_feedback
enable :update_vulnerability_feedback enable :update_vulnerability_feedback
enable :read_feature_flag
enable :create_feature_flag
enable :update_feature_flag
enable :destroy_feature_flag
enable :admin_feature_flag
enable :admin_feature_flags_user_lists
enable :read_ci_minutes_quota enable :read_ci_minutes_quota
enable :admin_feature_flags_issue_links
end end
rule { can?(:developer_access) & iterations_available }.policy do rule { can?(:developer_access) & iterations_available }.policy do
...@@ -223,16 +222,10 @@ module EE ...@@ -223,16 +222,10 @@ module EE
rule { deploy_board_disabled & ~is_development }.prevent :read_deploy_board rule { deploy_board_disabled & ~is_development }.prevent :read_deploy_board
rule { feature_flags_disabled | repository_disabled }.policy do
prevent(*create_read_update_admin_destroy(:feature_flag))
prevent(:admin_feature_flags_user_lists)
end
rule { can?(:maintainer_access) }.policy do rule { can?(:maintainer_access) }.policy do
enable :push_code_to_protected_branches enable :push_code_to_protected_branches
enable :admin_path_locks enable :admin_path_locks
enable :update_approvers enable :update_approvers
enable :admin_feature_flags_client
enable :modify_approvers_rules enable :modify_approvers_rules
enable :modify_auto_fix_setting enable :modify_auto_fix_setting
enable :modify_merge_request_author_setting enable :modify_merge_request_author_setting
......
---
title: Remove license check for feature flags
merge_request: 42023
author:
type: changed
---
name: feature_flags_related_issues
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42023
rollout_issue_url:
group: group::progressive delivery
type: licensed
default_enabled: true
...@@ -66,7 +66,7 @@ module API ...@@ -66,7 +66,7 @@ module API
end end
def authorize_feature_flags_feature! def authorize_feature_flags_feature!
forbidden! unless project.feature_available?(:feature_flags) forbidden! unless project.feature_available?(:repository)
end end
def feature_flags def feature_flags
......
...@@ -13,7 +13,7 @@ RSpec.describe Projects::FeatureFlagIssuesController do ...@@ -13,7 +13,7 @@ RSpec.describe Projects::FeatureFlagIssuesController do
end end
before do before do
stub_licensed_features(feature_flags: true) stub_licensed_features(feature_flags_related_issues: true)
end end
describe 'GET #index' do describe 'GET #index' do
...@@ -172,19 +172,9 @@ RSpec.describe Projects::FeatureFlagIssuesController do ...@@ -172,19 +172,9 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
it 'returns not found when related issues feature is unavailable' do context 'when feature flag related issues feature is unlicensed' do
stub_licensed_features(blocked_issues: false)
feature_flag, _issue = setup
sign_in(developer)
get_request(project, feature_flag)
expect(response).to have_gitlab_http_status(:not_found)
end
context 'when feature flags are unlicensed' do
before do before do
stub_licensed_features(feature_flags: false) stub_licensed_features(feature_flags_related_issues: false)
end end
it 'does not return linked issues' do it 'does not return linked issues' do
...@@ -332,23 +322,12 @@ RSpec.describe Projects::FeatureFlagIssuesController do ...@@ -332,23 +322,12 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(::FeatureFlagIssue.count).to eq(0) expect(::FeatureFlagIssue.count).to eq(0)
end end
it 'does not create a link when the related issues feature is unavailable' do context 'when feature flag related issues feature is unlicensed' do
stub_licensed_features(blocked_issues: false)
feature_flag, issue = setup
sign_in(developer)
post_request(project, feature_flag, issue)
expect(response).to have_gitlab_http_status(:not_found)
expect(::FeatureFlagIssue.count).to eq(0)
end
context 'when feature flags are unlicensed' do
before do before do
stub_licensed_features(feature_flags: false) stub_licensed_features(feature_flags_related_issues: false)
end end
it 'does not create a link between the feature flag and the issue when feature flags are unlicensed' do it 'does not create a link between the feature flag and the issue' do
feature_flag, issue = setup feature_flag, issue = setup
sign_in(developer) sign_in(developer)
...@@ -400,15 +379,20 @@ RSpec.describe Projects::FeatureFlagIssuesController do ...@@ -400,15 +379,20 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(feature_flag.reload.issues).to eq([issue]) expect(feature_flag.reload.issues).to eq([issue])
end end
it 'does not unlink the issue when the related issues feature is unavailable' do context 'when feature flag related issues feature is unlicensed' do
stub_licensed_features(blocked_issues: false) before do
feature_flag, issue, link = setup stub_licensed_features(feature_flags_related_issues: false)
sign_in(developer) end
delete_request(project, feature_flag, link) it 'does not unlink the issue' do
feature_flag, issue, link = setup
sign_in(developer)
expect(response).to have_gitlab_http_status(:not_found) delete_request(project, feature_flag, link)
expect(feature_flag.reload.issues).to eq([issue])
expect(response).to have_gitlab_http_status(:not_found)
expect(feature_flag.reload.issues).to eq([issue])
end
end end
end end
end end
...@@ -16,7 +16,6 @@ RSpec.describe Projects::FeatureFlagsClientsController do ...@@ -16,7 +16,6 @@ RSpec.describe Projects::FeatureFlagsClientsController do
end end
before do before do
stub_licensed_features(feature_flags: true)
sign_in(user) sign_in(user)
end end
......
...@@ -10,7 +10,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -10,7 +10,6 @@ RSpec.describe Projects::FeatureFlagsController do
let_it_be(:developer) { create(:user) } let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) } let_it_be(:reporter) { create(:user) }
let(:user) { developer } let(:user) { developer }
let(:feature_enabled) { true }
before_all do before_all do
project.add_developer(developer) project.add_developer(developer)
...@@ -19,7 +18,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -19,7 +18,6 @@ RSpec.describe Projects::FeatureFlagsController do
before do before do
sign_in(user) sign_in(user)
stub_licensed_features(feature_flags: feature_enabled)
end end
describe 'GET index' do describe 'GET index' do
...@@ -41,14 +39,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -41,14 +39,6 @@ RSpec.describe Projects::FeatureFlagsController do
end end
end end
context 'when feature is not available' do
let(:feature_enabled) { false }
it 'responds with not found' do
is_expected.to have_gitlab_http_status(:not_found)
end
end
context 'when the user is a reporter' do context 'when the user is a reporter' do
let(:user) { reporter } let(:user) { reporter }
......
...@@ -12,10 +12,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do ...@@ -12,10 +12,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do
project.add_developer(developer) project.add_developer(developer)
end end
before do
stub_licensed_features(feature_flags: true)
end
def request_params(extra_params = {}) def request_params(extra_params = {})
{ namespace_id: project.namespace, project_id: project }.merge(extra_params) { namespace_id: project.namespace, project_id: project }.merge(extra_params)
end end
...@@ -44,15 +40,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do ...@@ -44,15 +40,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
it 'returns not found when feature flags are not licensed' do
stub_licensed_features(feature_flags: false)
sign_in(developer)
get(:new, params: request_params)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'renders the new page for a developer' do it 'renders the new page for a developer' do
sign_in(developer) sign_in(developer)
......
...@@ -8,7 +8,6 @@ RSpec.describe 'User deletes feature flag user list', :js do ...@@ -8,7 +8,6 @@ RSpec.describe 'User deletes feature flag user list', :js do
before do before do
project.add_developer(developer) project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer) sign_in(developer)
end end
......
...@@ -8,7 +8,6 @@ RSpec.describe 'User edits feature flag user list', :js do ...@@ -8,7 +8,6 @@ RSpec.describe 'User edits feature flag user list', :js do
before do before do
project.add_developer(developer) project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer) sign_in(developer)
end end
......
...@@ -8,7 +8,6 @@ RSpec.describe 'User sees feature flag user list details', :js do ...@@ -8,7 +8,6 @@ RSpec.describe 'User sees feature flag user list details', :js do
before do before do
project.add_developer(developer) project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer) sign_in(developer)
end end
......
...@@ -13,7 +13,7 @@ RSpec.describe 'Feature flag issue links', :js do ...@@ -13,7 +13,7 @@ RSpec.describe 'Feature flag issue links', :js do
end end
before do before do
stub_licensed_features(feature_flags: true) stub_licensed_features(feature_flags_related_issues: true)
sign_in(developer) sign_in(developer)
end end
...@@ -72,6 +72,19 @@ RSpec.describe 'Feature flag issue links', :js do ...@@ -72,6 +72,19 @@ RSpec.describe 'Feature flag issue links', :js do
expect(page).not_to have_selector '#related-issues' expect(page).not_to have_selector '#related-issues'
end end
end end
context 'when the feature is unlicensed' do
before do
stub_licensed_features(feature_flags_related_issues: false)
end
it 'does not show the related issues widget' do
visit(edit_project_feature_flag_path(project, feature_flag))
expect(page).to have_text 'Strategies'
expect(page).not_to have_selector '#related-issues'
end
end
end end
describe 'unlinking a feature flag from an issue' do describe 'unlinking a feature flag from an issue' do
......
...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flag_permissions: false) stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
end end
......
...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do ...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flag_permissions: false) stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
......
...@@ -13,7 +13,6 @@ RSpec.describe 'User sees feature flag list', :js do ...@@ -13,7 +13,6 @@ RSpec.describe 'User sees feature flag list', :js do
end end
before do before do
stub_licensed_features(feature_flags: true)
sign_in(user) sign_in(user)
end end
......
...@@ -13,7 +13,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -13,7 +13,6 @@ RSpec.describe 'User updates feature flag', :js do
end end
before do before do
stub_licensed_features(feature_flags: true)
stub_feature_flags( stub_feature_flags(
feature_flag_permissions: false, feature_flag_permissions: false,
feature_flags_legacy_read_only_override: false feature_flags_legacy_read_only_override: false
......
...@@ -14,6 +14,11 @@ RSpec.describe 'Project navbar' do ...@@ -14,6 +14,11 @@ RSpec.describe 'Project navbar' do
stub_feature_flags(project_iterations: false) stub_feature_flags(project_iterations: false)
insert_package_nav(_('Operations')) insert_package_nav(_('Operations'))
insert_after_sub_nav_item(
_('Kubernetes'),
within: _('Operations'),
new_sub_nav_item_name: _('Feature Flags')
)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
......
...@@ -29,13 +29,13 @@ RSpec.describe FeatureFlagsHelper do ...@@ -29,13 +29,13 @@ RSpec.describe FeatureFlagsHelper do
end end
it 'returns an empty string when the user is not allowed' do it 'returns an empty string when the user is not allowed' do
allow(helper).to receive(:can?).with(user, :read_issue_link, project).and_return(false) allow(helper).to receive(:can?).with(user, :admin_feature_flags_issue_links, project).and_return(false)
is_expected.to be_empty is_expected.to be_empty
end end
it 'returns the issue endpoint when the user is allowed' do it 'returns the issue endpoint when the user is allowed' do
allow(helper).to receive(:can?).with(user, :read_issue_link, project).and_return(true) allow(helper).to receive(:can?).with(user, :admin_feature_flags_issue_links, project).and_return(true)
is_expected.to eq("/#{project.full_path}/-/feature_flags/#{feature_flag.iid}/issues") is_expected.to eq("/#{project.full_path}/-/feature_flags/#{feature_flag.iid}/issues")
end end
......
...@@ -60,16 +60,6 @@ RSpec.describe SearchHelper do ...@@ -60,16 +60,6 @@ RSpec.describe SearchHelper do
end end
context 'with a licensed user' do context 'with a licensed user' do
it "does not include feature flags" do
expect(project_autocomplete.find { |i| i[:label] == 'Feature Flags'} ).to be_nil
end
end
context 'with a licensed user' do
before do
stub_licensed_features(feature_flags: true)
end
it "does include feature flags" do it "does include feature flags" do
expect(project_autocomplete.find { |i| i[:label] == 'Feature Flags' }).to be_present expect(project_autocomplete.find { |i| i[:label] == 'Feature Flags' }).to be_present
end end
......
...@@ -22,14 +22,14 @@ RSpec.describe ProjectPolicy do ...@@ -22,14 +22,14 @@ RSpec.describe ProjectPolicy do
let(:additional_developer_permissions) do let(:additional_developer_permissions) do
%i[ %i[
admin_vulnerability_feedback read_project_security_dashboard read_feature_flag admin_vulnerability_feedback read_project_security_dashboard
read_vulnerability read_vulnerability_scanner create_vulnerability create_vulnerability_export admin_vulnerability read_vulnerability read_vulnerability_scanner create_vulnerability create_vulnerability_export admin_vulnerability
admin_vulnerability_issue_link read_merge_train admin_vulnerability_issue_link read_merge_train
] ]
end end
let(:additional_maintainer_permissions) do let(:additional_maintainer_permissions) do
%i[push_code_to_protected_branches admin_feature_flags_client modify_auto_fix_setting] %i[push_code_to_protected_branches modify_auto_fix_setting]
end end
let(:auditor_permissions) do let(:auditor_permissions) do
...@@ -622,35 +622,48 @@ RSpec.describe ProjectPolicy do ...@@ -622,35 +622,48 @@ RSpec.describe ProjectPolicy do
end end
end end
describe 'read_feature_flag' do describe 'admin_feature_flags_issue_links' do
context 'with admin' do before do
let(:current_user) { admin } stub_licensed_features(feature_flags_related_issues: true)
end
context 'with maintainer' do
let(:current_user) { maintainer }
it { is_expected.to be_allowed(:admin_feature_flags_issue_links) }
context 'when repository is disabled' do context 'when repository is disabled' do
before do before do
project.project_feature.update!( project.project_feature.update!(
# Disable merge_requests and builds as well, since merge_requests and
# builds cannot have higher visibility than repository.
merge_requests_access_level: ProjectFeature::DISABLED, merge_requests_access_level: ProjectFeature::DISABLED,
builds_access_level: ProjectFeature::DISABLED, builds_access_level: ProjectFeature::DISABLED,
repository_access_level: ProjectFeature::DISABLED) repository_access_level: ProjectFeature::DISABLED
)
end end
it { is_expected.to be_disallowed(:read_feature_flag) } it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end end
end end
context 'with developer' do context 'with developer' do
let(:current_user) { developer } let(:current_user) { developer }
context 'when feature flags features is not available' do it { is_expected.to be_allowed(:admin_feature_flags_issue_links) }
context 'when feature is unlicensed' do
before do before do
stub_licensed_features(feature_flags: false) stub_licensed_features(feature_flags_related_issues: false)
end end
it { is_expected.to be_disallowed(:read_feature_flag) } it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end end
end end
context 'with reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end
end end
describe 'admin_software_license_policy' do describe 'admin_software_license_policy' do
...@@ -1336,7 +1349,7 @@ RSpec.describe ProjectPolicy do ...@@ -1336,7 +1349,7 @@ RSpec.describe ProjectPolicy do
before do before do
allow(project.root_namespace).to receive(:over_storage_limit?).and_return(over_storage_limit) allow(project.root_namespace).to receive(:over_storage_limit?).and_return(over_storage_limit)
allow(project).to receive(:design_management_enabled?).and_return(true) allow(project).to receive(:design_management_enabled?).and_return(true)
stub_licensed_features(security_dashboard: true, license_scanning: true, feature_flags: true) stub_licensed_features(security_dashboard: true, license_scanning: true)
end end
context 'when the group has exceeded its storage limit' do context 'when the group has exceeded its storage limit' do
......
...@@ -10,8 +10,6 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -10,8 +10,6 @@ RSpec.describe API::FeatureFlagScopes do
let(:user) { developer } let(:user) { developer }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
end end
...@@ -26,18 +24,6 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -26,18 +24,6 @@ RSpec.describe API::FeatureFlagScopes do
expect(response).to have_gitlab_http_status(:forbidden) expect(response).to have_gitlab_http_status(:forbidden)
end end
end end
context 'when license is not sufficient' do
before do
stub_licensed_features(feature_flags: false)
end
it 'forbids the request' do
subject
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end end
shared_examples_for 'not found' do shared_examples_for 'not found' do
......
...@@ -15,10 +15,6 @@ RSpec.describe API::FeatureFlags do ...@@ -15,10 +15,6 @@ RSpec.describe API::FeatureFlags do
project.add_reporter(reporter) project.add_reporter(reporter)
end end
before do
stub_licensed_features(feature_flags: true)
end
shared_examples_for 'check user permission' do shared_examples_for 'check user permission' do
context 'when user is reporter' do context 'when user is reporter' do
let(:user) { reporter } let(:user) { reporter }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe API::FeatureFlagsUserLists do RSpec.describe API::FeatureFlagsUserLists do
let_it_be(:project) { create(:project) } let_it_be(:project, refind: true) { create(:project) }
let_it_be(:developer) { create(:user) } let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) } let_it_be(:reporter) { create(:user) }
...@@ -12,14 +12,18 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -12,14 +12,18 @@ RSpec.describe API::FeatureFlagsUserLists do
project.add_reporter(reporter) project.add_reporter(reporter)
end end
before do
stub_licensed_features(feature_flags: true)
end
def create_list(name: 'mylist', user_xids: 'user1') def create_list(name: 'mylist', user_xids: 'user1')
create(:operations_feature_flag_user_list, project: project, name: name, user_xids: user_xids) create(:operations_feature_flag_user_list, project: project, name: name, user_xids: user_xids)
end end
def disable_repository(project)
project.project_feature.update!(
repository_access_level: ::ProjectFeature::DISABLED,
merge_requests_access_level: ::ProjectFeature::DISABLED,
builds_access_level: ::ProjectFeature::DISABLED
)
end
describe 'GET /projects/:id/feature_flags_user_lists' do describe 'GET /projects/:id/feature_flags_user_lists' do
it 'forbids the request for a reporter' do it 'forbids the request for a reporter' do
get api("/projects/#{project.id}/feature_flags_user_lists", reporter) get api("/projects/#{project.id}/feature_flags_user_lists", reporter)
...@@ -28,7 +32,7 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -28,7 +32,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end end
it 'returns forbidden if the feature is unavailable' do it 'returns forbidden if the feature is unavailable' do
stub_licensed_features(feature_flags: false) disable_repository(project)
get api("/projects/#{project.id}/feature_flags_user_lists", developer) get api("/projects/#{project.id}/feature_flags_user_lists", developer)
...@@ -103,7 +107,7 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -103,7 +107,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end end
it 'returns forbidden if the feature is unavailable' do it 'returns forbidden if the feature is unavailable' do
stub_licensed_features(feature_flags: false) disable_repository(project)
list = create_list list = create_list
get api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer) get api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer)
...@@ -171,7 +175,7 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -171,7 +175,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end end
it 'returns forbidden if the feature is unavailable' do it 'returns forbidden if the feature is unavailable' do
stub_licensed_features(feature_flags: false) disable_repository(project)
post api("/projects/#{project.id}/feature_flags_user_lists", developer), params: { post api("/projects/#{project.id}/feature_flags_user_lists", developer), params: {
name: 'mylist', user_xids: 'user1' name: 'mylist', user_xids: 'user1'
...@@ -254,7 +258,7 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -254,7 +258,7 @@ RSpec.describe API::FeatureFlagsUserLists do
it 'returns forbidden if the feature is unavailable' do it 'returns forbidden if the feature is unavailable' do
list = create_list(name: 'original_name') list = create_list(name: 'original_name')
stub_licensed_features(feature_flags: false) disable_repository(project)
put api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer), params: { put api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer), params: {
name: 'mylist', user_xids: '456,789' name: 'mylist', user_xids: '456,789'
...@@ -328,7 +332,7 @@ RSpec.describe API::FeatureFlagsUserLists do ...@@ -328,7 +332,7 @@ RSpec.describe API::FeatureFlagsUserLists do
it 'returns forbidden if the feature is unavailable' do it 'returns forbidden if the feature is unavailable' do
list = create_list list = create_list
stub_licensed_features(feature_flags: false) disable_repository(project)
delete api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer) delete api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer)
......
...@@ -5,16 +5,11 @@ require 'spec_helper' ...@@ -5,16 +5,11 @@ require 'spec_helper'
RSpec.describe API::Unleash do RSpec.describe API::Unleash do
include FeatureFlagHelpers include FeatureFlagHelpers
let_it_be(:project) { create(:project) } let_it_be(:project, refind: true) { create(:project) }
let(:project_id) { project.id } let(:project_id) { project.id }
let(:feature_enabled) { true }
let(:params) { } let(:params) { }
let(:headers) { } let(:headers) { }
before do
stub_licensed_features(feature_flags: feature_enabled)
end
shared_examples 'authenticated request' do shared_examples 'authenticated request' do
context 'when using instance id' do context 'when using instance id' do
let(:client) { create(:operations_feature_flags_client, project: project) } let(:client) { create(:operations_feature_flags_client, project: project) }
...@@ -27,7 +22,13 @@ RSpec.describe API::Unleash do ...@@ -27,7 +22,13 @@ RSpec.describe API::Unleash do
end end
context 'when feature is not available' do context 'when feature is not available' do
let(:feature_enabled) { false } before do
project.project_feature.update!(
repository_access_level: ::ProjectFeature::DISABLED,
merge_requests_access_level: ::ProjectFeature::DISABLED,
builds_access_level: ::ProjectFeature::DISABLED
)
end
it 'responds with forbidden' do it 'responds with forbidden' do
subject subject
......
...@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagEntity do ...@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagEntity do
before do before do
project.add_developer(user) project.add_developer(user)
stub_licensed_features(feature_flags: true)
end end
subject { entity.as_json } subject { entity.as_json }
......
...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSerializer do ...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSerializer do
let(:feature_flags) { create_list(:operations_feature_flag, 3) } let(:feature_flags) { create_list(:operations_feature_flag, 3) }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(user) project.add_developer(user)
end end
......
...@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagSummaryEntity do ...@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagSummaryEntity do
before do before do
project.add_developer(user) project.add_developer(user)
stub_licensed_features(feature_flags: true)
end end
subject { entity.as_json } subject { entity.as_json }
......
...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSummarySerializer do ...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSummarySerializer do
let!(:feature_flags) { create(:operations_feature_flag, project: project) } let!(:feature_flags) { create(:operations_feature_flag, project: project) }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(user) project.add_developer(user)
end end
......
...@@ -7,10 +7,6 @@ RSpec.describe FeatureFlagsClientSerializer do ...@@ -7,10 +7,6 @@ RSpec.describe FeatureFlagsClientSerializer do
let(:feature_flags_client) { project.create_operations_feature_flags_client! } let(:feature_flags_client) { project.create_operations_feature_flags_client! }
let(:serializer) { described_class.new } let(:serializer) { described_class.new }
before do
stub_licensed_features(feature_flags: true)
end
describe '#represent_token' do describe '#represent_token' do
subject { serializer.represent_token(feature_flags_client).to_json } subject { serializer.represent_token(feature_flags_client).to_json }
......
...@@ -13,7 +13,7 @@ RSpec.describe FeatureFlagIssues::DestroyService do ...@@ -13,7 +13,7 @@ RSpec.describe FeatureFlagIssues::DestroyService do
end end
before do before do
stub_licensed_features(feature_flags: true) stub_licensed_features(feature_flags_related_issues: true)
end end
def setup def setup
......
...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlags::CreateService do ...@@ -9,7 +9,6 @@ RSpec.describe FeatureFlags::CreateService do
let(:user) { developer } let(:user) { developer }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
end end
......
...@@ -12,7 +12,6 @@ RSpec.describe FeatureFlags::DestroyService do ...@@ -12,7 +12,6 @@ RSpec.describe FeatureFlags::DestroyService do
let!(:feature_flag) { create(:operations_feature_flag, project: project) } let!(:feature_flag) { create(:operations_feature_flag, project: project) }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
end end
......
...@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::DisableService do ...@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::DisableService do
let(:params) { {} } let(:params) { {} }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(user) project.add_developer(user)
end end
......
...@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::EnableService do ...@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::EnableService do
let(:params) { {} } let(:params) { {} }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(user) project.add_developer(user)
end end
......
...@@ -10,7 +10,6 @@ RSpec.describe FeatureFlags::UpdateService do ...@@ -10,7 +10,6 @@ RSpec.describe FeatureFlags::UpdateService do
let(:feature_flag) { create(:operations_feature_flag, project: project, active: true) } let(:feature_flag) { create(:operations_feature_flag, project: project, active: true) }
before do before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
end end
......
...@@ -28,8 +28,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -28,8 +28,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
stub_licensed_features(feature_flags: true)
project.project_feature.update!(builds_access_level: feature) project.project_feature.update!(builds_access_level: feature)
project.team.add_developer(user) project.team.add_developer(user)
......
...@@ -18,6 +18,14 @@ RSpec.describe 'Project navbar' do ...@@ -18,6 +18,14 @@ RSpec.describe 'Project navbar' do
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
if Gitlab.ee?
insert_after_sub_nav_item(
_('Kubernetes'),
within: _('Operations'),
new_sub_nav_item_name: _('Feature Flags')
)
end
end end
it_behaves_like 'verified navigation bar' do it_behaves_like 'verified navigation bar' do
......
...@@ -15,8 +15,6 @@ RSpec.describe FeatureFlagsFinder do ...@@ -15,8 +15,6 @@ RSpec.describe FeatureFlagsFinder do
before do before do
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
stub_licensed_features(feature_flags: true)
end end
describe '#execute' do describe '#execute' do
......
...@@ -901,4 +901,44 @@ RSpec.describe ProjectPolicy do ...@@ -901,4 +901,44 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:read_package) } it { is_expected.to be_allowed(:read_package) }
end end
end end
describe 'read_feature_flag' do
subject { described_class.new(current_user, project) }
context 'with maintainer' do
let(:current_user) { maintainer }
context 'when repository is available' do
it { is_expected.to be_allowed(:read_feature_flag) }
end
context 'when repository is disabled' do
before do
project.project_feature.update!(
merge_requests_access_level: ProjectFeature::DISABLED,
builds_access_level: ProjectFeature::DISABLED,
repository_access_level: ProjectFeature::DISABLED
)
end
it { is_expected.to be_disallowed(:read_feature_flag) }
end
end
context 'with developer' do
let(:current_user) { developer }
context 'when repository is available' do
it { is_expected.to be_allowed(:read_feature_flag) }
end
end
context 'with reporter' do
let(:current_user) { reporter }
context 'when repository is available' do
it { is_expected.to be_disallowed(:read_feature_flag) }
end
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