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
enable :destroy_design
enable :read_terraform_state
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
rule { can?(:developer_access) & user_confirmed? }.policy do
......@@ -371,6 +377,7 @@ class ProjectPolicy < BasePolicy
enable :read_freeze_period
enable :update_freeze_period
enable :destroy_freeze_period
enable :admin_feature_flags_client
end
rule { public_project & metrics_dashboard_allowed }.policy do
......@@ -447,6 +454,8 @@ class ProjectPolicy < BasePolicy
prevent :read_pipeline
prevent :read_pipeline_schedule
prevent(*create_read_update_admin_destroy(:release))
prevent(*create_read_update_admin_destroy(:feature_flag))
prevent(:admin_feature_flags_user_lists)
end
rule { container_registry_disabled }.policy do
......
......@@ -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
---
# 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.
You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery.
......@@ -349,7 +350,7 @@ else
end
```
## Feature Flag Related Issues
## Feature Flag Related Issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default.
......
......@@ -5,7 +5,7 @@ module Projects
include IssuableLinks
before_action :ensure_feature_enabled!
before_action :authorize_admin_feature_flag!
before_action :authorize_admin_feature_flags_issue_links!
private
......
......@@ -30,7 +30,7 @@ module EE
override :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) }]
end
......
......@@ -12,7 +12,7 @@ module FeatureFlagsHelper
end
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)
end
......
......@@ -72,7 +72,7 @@ class License < ApplicationRecord
epics
extended_audit_events
external_authorization_service_api_management
feature_flags
feature_flags_related_issues
file_locks
geo
generic_alert_fingerprinting
......
......@@ -120,11 +120,6 @@ module EE
@subject.feature_available?(:threat_monitoring)
end
with_scope :subject
condition(:feature_flags_disabled) do
!@subject.feature_available?(:feature_flags)
end
with_scope :subject
condition(:code_review_analytics_enabled) do
@subject.feature_available?(:code_review_analytics, @user)
......@@ -142,6 +137,11 @@ module EE
@subject.root_namespace.over_storage_limit?
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
prevent :read_note
enable :create_note
......@@ -154,6 +154,10 @@ module EE
prevent :push_code
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 { can?(:guest_access) & iterations_available }.enable :read_iteration
......@@ -171,13 +175,8 @@ module EE
enable :create_vulnerability_feedback
enable :destroy_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 :admin_feature_flags_issue_links
end
rule { can?(:developer_access) & iterations_available }.policy do
......@@ -223,16 +222,10 @@ module EE
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
enable :push_code_to_protected_branches
enable :admin_path_locks
enable :update_approvers
enable :admin_feature_flags_client
enable :modify_approvers_rules
enable :modify_auto_fix_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
end
def authorize_feature_flags_feature!
forbidden! unless project.feature_available?(:feature_flags)
forbidden! unless project.feature_available?(:repository)
end
def feature_flags
......
......@@ -13,7 +13,7 @@ RSpec.describe Projects::FeatureFlagIssuesController do
end
before do
stub_licensed_features(feature_flags: true)
stub_licensed_features(feature_flags_related_issues: true)
end
describe 'GET #index' do
......@@ -172,19 +172,9 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns not found when related issues feature is unavailable' 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
context 'when feature flag related issues feature is unlicensed' do
before do
stub_licensed_features(feature_flags: false)
stub_licensed_features(feature_flags_related_issues: false)
end
it 'does not return linked issues' do
......@@ -332,23 +322,12 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(::FeatureFlagIssue.count).to eq(0)
end
it 'does not create a link when the related issues feature is unavailable' 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
context 'when feature flag related issues feature is unlicensed' do
before do
stub_licensed_features(feature_flags: false)
stub_licensed_features(feature_flags_related_issues: false)
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
sign_in(developer)
......@@ -400,15 +379,20 @@ RSpec.describe Projects::FeatureFlagIssuesController do
expect(feature_flag.reload.issues).to eq([issue])
end
it 'does not unlink the issue when the related issues feature is unavailable' do
stub_licensed_features(blocked_issues: false)
feature_flag, issue, link = setup
sign_in(developer)
context 'when feature flag related issues feature is unlicensed' do
before do
stub_licensed_features(feature_flags_related_issues: false)
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)
expect(feature_flag.reload.issues).to eq([issue])
delete_request(project, feature_flag, link)
expect(response).to have_gitlab_http_status(:not_found)
expect(feature_flag.reload.issues).to eq([issue])
end
end
end
end
......@@ -16,7 +16,6 @@ RSpec.describe Projects::FeatureFlagsClientsController do
end
before do
stub_licensed_features(feature_flags: true)
sign_in(user)
end
......
......@@ -10,7 +10,6 @@ RSpec.describe Projects::FeatureFlagsController do
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let(:user) { developer }
let(:feature_enabled) { true }
before_all do
project.add_developer(developer)
......@@ -19,7 +18,6 @@ RSpec.describe Projects::FeatureFlagsController do
before do
sign_in(user)
stub_licensed_features(feature_flags: feature_enabled)
end
describe 'GET index' do
......@@ -41,14 +39,6 @@ RSpec.describe Projects::FeatureFlagsController do
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
let(:user) { reporter }
......
......@@ -12,10 +12,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do
project.add_developer(developer)
end
before do
stub_licensed_features(feature_flags: true)
end
def request_params(extra_params = {})
{ namespace_id: project.namespace, project_id: project }.merge(extra_params)
end
......@@ -44,15 +40,6 @@ RSpec.describe Projects::FeatureFlagsUserListsController do
expect(response).to have_gitlab_http_status(:not_found)
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
sign_in(developer)
......
......@@ -8,7 +8,6 @@ RSpec.describe 'User deletes feature flag user list', :js do
before do
project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer)
end
......
......@@ -8,7 +8,6 @@ RSpec.describe 'User edits feature flag user list', :js do
before do
project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer)
end
......
......@@ -8,7 +8,6 @@ RSpec.describe 'User sees feature flag user list details', :js do
before do
project.add_developer(developer)
stub_licensed_features(feature_flags: true)
sign_in(developer)
end
......
......@@ -13,7 +13,7 @@ RSpec.describe 'Feature flag issue links', :js do
end
before do
stub_licensed_features(feature_flags: true)
stub_licensed_features(feature_flags_related_issues: true)
sign_in(developer)
end
......@@ -72,6 +72,19 @@ RSpec.describe 'Feature flag issue links', :js do
expect(page).not_to have_selector '#related-issues'
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
describe 'unlinking a feature flag from an issue' do
......
......@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do
before do
project.add_developer(user)
stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user)
end
......
......@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do
before do
project.add_developer(user)
stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user)
......
......@@ -13,7 +13,6 @@ RSpec.describe 'User sees feature flag list', :js do
end
before do
stub_licensed_features(feature_flags: true)
sign_in(user)
end
......
......@@ -13,7 +13,6 @@ RSpec.describe 'User updates feature flag', :js do
end
before do
stub_licensed_features(feature_flags: true)
stub_feature_flags(
feature_flag_permissions: false,
feature_flags_legacy_read_only_override: false
......
......@@ -14,6 +14,11 @@ RSpec.describe 'Project navbar' do
stub_feature_flags(project_iterations: false)
insert_package_nav(_('Operations'))
insert_after_sub_nav_item(
_('Kubernetes'),
within: _('Operations'),
new_sub_nav_item_name: _('Feature Flags')
)
project.add_maintainer(user)
sign_in(user)
......
......@@ -29,13 +29,13 @@ RSpec.describe FeatureFlagsHelper do
end
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
end
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")
end
......
......@@ -60,16 +60,6 @@ RSpec.describe SearchHelper do
end
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
expect(project_autocomplete.find { |i| i[:label] == 'Feature Flags' }).to be_present
end
......
......@@ -22,14 +22,14 @@ RSpec.describe ProjectPolicy do
let(:additional_developer_permissions) do
%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
admin_vulnerability_issue_link read_merge_train
]
end
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
let(:auditor_permissions) do
......@@ -622,35 +622,48 @@ RSpec.describe ProjectPolicy do
end
end
describe 'read_feature_flag' do
context 'with admin' do
let(:current_user) { admin }
describe 'admin_feature_flags_issue_links' do
before do
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
before do
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,
builds_access_level: ProjectFeature::DISABLED,
repository_access_level: ProjectFeature::DISABLED)
repository_access_level: ProjectFeature::DISABLED
)
end
it { is_expected.to be_disallowed(:read_feature_flag) }
it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end
end
context 'with developer' do
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
stub_licensed_features(feature_flags: false)
stub_licensed_features(feature_flags_related_issues: false)
end
it { is_expected.to be_disallowed(:read_feature_flag) }
it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end
end
context 'with reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:admin_feature_flags_issue_links) }
end
end
describe 'admin_software_license_policy' do
......@@ -1336,7 +1349,7 @@ RSpec.describe ProjectPolicy do
before do
allow(project.root_namespace).to receive(:over_storage_limit?).and_return(over_storage_limit)
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
context 'when the group has exceeded its storage limit' do
......
......@@ -10,8 +10,6 @@ RSpec.describe API::FeatureFlagScopes do
let(:user) { developer }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer)
project.add_reporter(reporter)
end
......@@ -26,18 +24,6 @@ RSpec.describe API::FeatureFlagScopes do
expect(response).to have_gitlab_http_status(:forbidden)
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
shared_examples_for 'not found' do
......
......@@ -15,10 +15,6 @@ RSpec.describe API::FeatureFlags do
project.add_reporter(reporter)
end
before do
stub_licensed_features(feature_flags: true)
end
shared_examples_for 'check user permission' do
context 'when user is reporter' do
let(:user) { reporter }
......
......@@ -3,7 +3,7 @@
require 'spec_helper'
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(:reporter) { create(:user) }
......@@ -12,14 +12,18 @@ RSpec.describe API::FeatureFlagsUserLists do
project.add_reporter(reporter)
end
before do
stub_licensed_features(feature_flags: true)
end
def create_list(name: 'mylist', user_xids: 'user1')
create(:operations_feature_flag_user_list, project: project, name: name, user_xids: user_xids)
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
it 'forbids the request for a reporter' do
get api("/projects/#{project.id}/feature_flags_user_lists", reporter)
......@@ -28,7 +32,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end
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)
......@@ -103,7 +107,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end
it 'returns forbidden if the feature is unavailable' do
stub_licensed_features(feature_flags: false)
disable_repository(project)
list = create_list
get api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer)
......@@ -171,7 +175,7 @@ RSpec.describe API::FeatureFlagsUserLists do
end
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: {
name: 'mylist', user_xids: 'user1'
......@@ -254,7 +258,7 @@ RSpec.describe API::FeatureFlagsUserLists do
it 'returns forbidden if the feature is unavailable' do
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: {
name: 'mylist', user_xids: '456,789'
......@@ -328,7 +332,7 @@ RSpec.describe API::FeatureFlagsUserLists do
it 'returns forbidden if the feature is unavailable' do
list = create_list
stub_licensed_features(feature_flags: false)
disable_repository(project)
delete api("/projects/#{project.id}/feature_flags_user_lists/#{list.iid}", developer)
......
......@@ -5,16 +5,11 @@ require 'spec_helper'
RSpec.describe API::Unleash do
include FeatureFlagHelpers
let_it_be(:project) { create(:project) }
let_it_be(:project, refind: true) { create(:project) }
let(:project_id) { project.id }
let(:feature_enabled) { true }
let(:params) { }
let(:headers) { }
before do
stub_licensed_features(feature_flags: feature_enabled)
end
shared_examples 'authenticated request' do
context 'when using instance id' do
let(:client) { create(:operations_feature_flags_client, project: project) }
......@@ -27,7 +22,13 @@ RSpec.describe API::Unleash do
end
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
subject
......
......@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagEntity do
before do
project.add_developer(user)
stub_licensed_features(feature_flags: true)
end
subject { entity.as_json }
......
......@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSerializer do
let(:feature_flags) { create_list(:operations_feature_flag, 3) }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(user)
end
......
......@@ -11,8 +11,6 @@ RSpec.describe FeatureFlagSummaryEntity do
before do
project.add_developer(user)
stub_licensed_features(feature_flags: true)
end
subject { entity.as_json }
......
......@@ -9,7 +9,6 @@ RSpec.describe FeatureFlagSummarySerializer do
let!(:feature_flags) { create(:operations_feature_flag, project: project) }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(user)
end
......
......@@ -7,10 +7,6 @@ RSpec.describe FeatureFlagsClientSerializer do
let(:feature_flags_client) { project.create_operations_feature_flags_client! }
let(:serializer) { described_class.new }
before do
stub_licensed_features(feature_flags: true)
end
describe '#represent_token' do
subject { serializer.represent_token(feature_flags_client).to_json }
......
......@@ -13,7 +13,7 @@ RSpec.describe FeatureFlagIssues::DestroyService do
end
before do
stub_licensed_features(feature_flags: true)
stub_licensed_features(feature_flags_related_issues: true)
end
def setup
......
......@@ -9,7 +9,6 @@ RSpec.describe FeatureFlags::CreateService do
let(:user) { developer }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer)
project.add_reporter(reporter)
end
......
......@@ -12,7 +12,6 @@ RSpec.describe FeatureFlags::DestroyService do
let!(:feature_flag) { create(:operations_feature_flag, project: project) }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer)
project.add_reporter(reporter)
end
......
......@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::DisableService do
let(:params) { {} }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(user)
end
......
......@@ -11,7 +11,6 @@ RSpec.describe FeatureFlags::EnableService do
let(:params) { {} }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(user)
end
......
......@@ -10,7 +10,6 @@ RSpec.describe FeatureFlags::UpdateService do
let(:feature_flag) { create(:operations_feature_flag, project: project, active: true) }
before do
stub_licensed_features(feature_flags: true)
project.add_developer(developer)
project.add_reporter(reporter)
end
......
......@@ -28,8 +28,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:user) { create(:user) }
before do
stub_licensed_features(feature_flags: true)
project.project_feature.update!(builds_access_level: feature)
project.team.add_developer(user)
......
......@@ -18,6 +18,14 @@ RSpec.describe 'Project navbar' do
project.add_maintainer(user)
sign_in(user)
if Gitlab.ee?
insert_after_sub_nav_item(
_('Kubernetes'),
within: _('Operations'),
new_sub_nav_item_name: _('Feature Flags')
)
end
end
it_behaves_like 'verified navigation bar' do
......
......@@ -15,8 +15,6 @@ RSpec.describe FeatureFlagsFinder do
before do
project.add_developer(developer)
project.add_reporter(reporter)
stub_licensed_features(feature_flags: true)
end
describe '#execute' do
......
......@@ -901,4 +901,44 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:read_package) }
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
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