Commit 0bab2291 authored by Serena Fang's avatar Serena Fang

Render create token form if can create token

Modify project policy

Add a policy to check if token creation allowed

Remove project helper

Update group policy

Add group policy specs

Update group policy and revoke service

Fix sidebar permission

Change check can destroy token name

Address MR review comments

Add comment, condense policies

Rename resource access token available

To resource access token feature available

Revert "Address MR review comments"

This reverts commit e4d52ad855b9d3f672994bb5d3224293a5aecd1a.

Revert "Rename resource access token available"

This reverts commit 402b1a1e23713c1c4d1f3aa55c822230c5c40701.

Add before checks to controller

Need to check if can read, destroy, create
parent 8e4db7c6
...@@ -6,7 +6,9 @@ module Projects ...@@ -6,7 +6,9 @@ module Projects
include ProjectsHelper include ProjectsHelper
layout 'project_settings' layout 'project_settings'
before_action :check_feature_availability before_action :check_read, only: [:index]
before_action :check_destroy, only: [:revoke]
before_action :check_create, only: [:create]
feature_category :authentication_and_authorization feature_category :authentication_and_authorization
...@@ -43,8 +45,16 @@ module Projects ...@@ -43,8 +45,16 @@ module Projects
private private
def check_feature_availability def check_read
render_404 unless project_access_token_available?(@project) render_404 unless can?(current_user, :read_resource_access_tokens, @project)
end
def check_destroy
render_404 unless can?(current_user, :destroy_resource_access_tokens, @project)
end
def check_create
render_404 unless can?(current_user, :create_resource_access_tokens, @project)
end end
def create_params def create_params
......
...@@ -809,10 +809,6 @@ module ProjectsHelper ...@@ -809,10 +809,6 @@ module ProjectsHelper
can?(current_user, :destroy_container_image, project) can?(current_user, :destroy_container_image, project)
end end
def project_access_token_available?(project)
can?(current_user, :create_resource_access_tokens, project)
end
def build_project_breadcrumb_link(project) def build_project_breadcrumb_link(project)
project_name = simple_sanitize(project.name) project_name = simple_sanitize(project.name)
......
...@@ -61,7 +61,8 @@ class GroupPolicy < BasePolicy ...@@ -61,7 +61,8 @@ class GroupPolicy < BasePolicy
end end
with_scope :subject with_scope :subject
condition(:resource_access_token_available) { resource_access_token_available? } condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
with_scope :subject with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? } condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
...@@ -213,15 +214,12 @@ class GroupPolicy < BasePolicy ...@@ -213,15 +214,12 @@ class GroupPolicy < BasePolicy
rule { developer & dependency_proxy_available } rule { developer & dependency_proxy_available }
.enable :admin_dependency_proxy .enable :admin_dependency_proxy
rule { can?(:admin_group) }.policy do rule { can?(:admin_group) & resource_access_token_feature_available }.policy do
enable :read_resource_access_tokens enable :read_resource_access_tokens
end
rule { can?(:admin_group) }.policy do
enable :destroy_resource_access_tokens enable :destroy_resource_access_tokens
end end
rule { resource_access_token_available & can?(:read_resource_access_tokens) }.policy do rule { resource_access_token_creation_allowed & can?(:read_resource_access_tokens) }.policy do
enable :create_resource_access_tokens enable :create_resource_access_tokens
end end
...@@ -250,8 +248,12 @@ class GroupPolicy < BasePolicy ...@@ -250,8 +248,12 @@ class GroupPolicy < BasePolicy
@subject @subject
end end
def resource_access_token_available? def resource_access_token_feature_available?
group.root_ancestor.resource_access_token_creation_allowed? true
end
def resource_access_token_creation_allowed?
group.resource_access_token_creation_allowed?
end end
end end
......
...@@ -108,7 +108,8 @@ class ProjectPolicy < BasePolicy ...@@ -108,7 +108,8 @@ class ProjectPolicy < BasePolicy
condition(:service_desk_enabled) { @subject.service_desk_enabled? } condition(:service_desk_enabled) { @subject.service_desk_enabled? }
with_scope :subject with_scope :subject
condition(:resource_access_token_available) { resource_access_token_available? } condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
# We aren't checking `:read_issue` or `:read_merge_request` in this case # We aren't checking `:read_issue` or `:read_merge_request` in this case
# because it could be possible for a user to see an issuable-iid # because it could be possible for a user to see an issuable-iid
...@@ -632,15 +633,12 @@ class ProjectPolicy < BasePolicy ...@@ -632,15 +633,12 @@ class ProjectPolicy < BasePolicy
rule { project_bot }.enable :project_bot_access rule { project_bot }.enable :project_bot_access
rule { can?(:admin_project) }.policy do rule { can?(:admin_project) & resource_access_token_feature_available }.policy do
enable :read_resource_access_tokens enable :read_resource_access_tokens
end
rule { can?(:admin_project) }.policy do
enable :destroy_resource_access_tokens enable :destroy_resource_access_tokens
end end
rule { resource_access_token_available & can?(:read_resource_access_tokens) }.policy do rule { can?(:read_resource_access_tokens) & resource_access_token_creation_allowed }.policy do
enable :create_resource_access_tokens enable :create_resource_access_tokens
end end
...@@ -730,12 +728,16 @@ class ProjectPolicy < BasePolicy ...@@ -730,12 +728,16 @@ class ProjectPolicy < BasePolicy
end end
end end
def resource_access_token_available? def resource_access_token_feature_available?
true
end
def resource_access_token_creation_allowed?
group = project.group group = project.group
return true unless group # always enable for projects in personal namespaces return true unless group # always enable for projects in personal namespaces
group.root_ancestor.resource_access_token_creation_allowed? group.resource_access_token_creation_allowed
end end
def project def project
......
...@@ -14,7 +14,7 @@ module ResourceAccessTokens ...@@ -14,7 +14,7 @@ module ResourceAccessTokens
end end
def execute def execute
return error("#{current_user.name} cannot delete #{bot_user.name}") unless can_destroy_bot_member? return error("#{current_user.name} cannot delete #{bot_user.name}") unless can_destroy_token?
return error("Failed to find bot user") unless find_member return error("Failed to find bot user") unless find_member
access_token.revoke! access_token.revoke!
...@@ -37,14 +37,8 @@ module ResourceAccessTokens ...@@ -37,14 +37,8 @@ module ResourceAccessTokens
DeleteUserWorker.perform_async(current_user.id, bot_user.id, skip_authorization: true) DeleteUserWorker.perform_async(current_user.id, bot_user.id, skip_authorization: true)
end end
def can_destroy_bot_member? def can_destroy_token?
if resource.is_a?(Project) %w(project group).include?(resource.class.name.downcase) && can?(current_user, :destroy_resource_access_tokens, resource)
can?(current_user, :destroy_resource_access_tokens, @resource)
elsif resource.is_a?(Group)
can?(current_user, :destroy_resource_access_tokens, @resource)
else
false
end
end end
def find_member def find_member
......
...@@ -407,7 +407,7 @@ ...@@ -407,7 +407,7 @@
= link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do = link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do
%span %span
= _('Webhooks') = _('Webhooks')
- if project_access_token_available?(@project) - if can?(current_user, :read_resource_access_tokens, @project)
= nav_link(controller: [:access_tokens]) do = nav_link(controller: [:access_tokens]) do
= link_to project_settings_access_tokens_path(@project), title: _('Access Tokens'), data: { qa_selector: 'access_tokens_settings_link' } do = link_to project_settings_access_tokens_path(@project), title: _('Access Tokens'), data: { qa_selector: 'access_tokens_settings_link' } do
%span %span
......
...@@ -20,12 +20,13 @@ ...@@ -20,12 +20,13 @@
type: type, type: type,
new_token_value: @new_project_access_token new_token_value: @new_project_access_token
= render 'shared/access_tokens/form', - if current_user.can?(:create_resource_access_tokens, @project)
type: type, = render 'shared/access_tokens/form',
path: project_settings_access_tokens_path(@project), type: type,
token: @project_access_token, path: project_settings_access_tokens_path(@project),
scopes: @scopes, token: @project_access_token,
prefix: :project_access_token scopes: @scopes,
prefix: :project_access_token
= render 'shared/access_tokens/table', = render 'shared/access_tokens/table',
active_tokens: @active_project_access_tokens, active_tokens: @active_project_access_tokens,
......
...@@ -391,8 +391,8 @@ module EE ...@@ -391,8 +391,8 @@ module EE
end end
# Available in Core for self-managed but only paid, non-trial for .com to prevent abuse # Available in Core for self-managed but only paid, non-trial for .com to prevent abuse
override :resource_access_token_available? override :resource_access_token_feature_available?
def resource_access_token_available? def resource_access_token_feature_available?
value_from_super = super value_from_super = super
return value_from_super unless ::Gitlab.com? return value_from_super unless ::Gitlab.com?
......
...@@ -423,17 +423,14 @@ module EE ...@@ -423,17 +423,14 @@ module EE
end end
# Available in Core for self-managed but only paid, non-trial for .com to prevent abuse # Available in Core for self-managed but only paid, non-trial for .com to prevent abuse
override :resource_access_token_available? override :resource_access_token_feature_available?
def resource_access_token_available? def resource_access_token_feature_available?
value_from_super = super return true unless ::Gitlab.com?
return value_from_super unless ::Gitlab.com? group = project.namespace
if project.group ::Feature.enabled?(:resource_access_token_feature, group, default_enabled: true) &&
return value_from_super && project.group.feature_available_non_trial?(:resource_access_token) group.feature_available_non_trial?(:resource_access_token)
end
project.namespace.feature_available_non_trial?(:resource_access_token)
end end
end end
end end
...@@ -1385,7 +1385,25 @@ RSpec.describe GroupPolicy do ...@@ -1385,7 +1385,25 @@ RSpec.describe GroupPolicy do
group.add_owner(owner) group.add_owner(owner)
end end
it { is_expected.to be_allowed(:create_resource_access_tokens) } context 'create resource access tokens' do
it { is_expected.to be_allowed(:create_resource_access_tokens) }
context 'when resource access token creation is not allowed' do
before do
group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
end
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
end
context 'read resource access tokens' do
it { is_expected.to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.to be_allowed(:destroy_resource_access_tokens) }
end
end end
context 'with developer' do context 'with developer' do
...@@ -1395,7 +1413,17 @@ RSpec.describe GroupPolicy do ...@@ -1395,7 +1413,17 @@ RSpec.describe GroupPolicy do
group.add_developer(developer) group.add_developer(developer)
end end
it { is_expected.not_to be_allowed(:create_resource_access_tokens)} context 'create resource access tokens' do
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
context 'read resource access tokens' do
it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
end
end end
end end
end end
......
...@@ -1577,24 +1577,55 @@ RSpec.describe ProjectPolicy do ...@@ -1577,24 +1577,55 @@ RSpec.describe ProjectPolicy do
allow(::Gitlab).to receive(:com?).and_return(true) allow(::Gitlab).to receive(:com?).and_return(true)
end end
context 'with maintainer' do context 'with maintainer access' do
let(:current_user) { maintainer } let(:current_user) { maintainer }
before do before do
project.add_maintainer(maintainer) project.add_maintainer(maintainer)
end end
it { is_expected.to be_allowed(:create_resource_access_tokens) } context 'create resource access tokens' do
it { is_expected.to be_allowed(:create_resource_access_tokens) }
context 'when resource access token creation is not allowed' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
before do
group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
end
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
end
context 'read resource access tokens' do
it { is_expected.to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.to be_allowed(:destroy_resource_access_tokens) }
end
end end
context 'with developer' do context 'with developer access' do
let(:current_user) { developer } let(:current_user) { developer }
before do before do
project.add_developer(developer) project.add_developer(developer)
end end
it { is_expected.not_to be_allowed(:create_resource_access_tokens)} context 'create resource access tokens' do
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
context 'read resource access tokens' do
it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
end
end end
end end
end end
......
...@@ -5,7 +5,8 @@ require 'spec_helper' ...@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe 'Project > Settings > Access Tokens', :js do RSpec.describe 'Project > Settings > Access Tokens', :js do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:bot_user) { create(:user, :project_bot) } let_it_be(:bot_user) { create(:user, :project_bot) }
let_it_be(:project) { create(:project) } let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
before_all do before_all do
project.add_maintainer(user) project.add_maintainer(user)
...@@ -57,6 +58,18 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do ...@@ -57,6 +58,18 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
expect(active_project_access_tokens).to have_text('read_api') expect(active_project_access_tokens).to have_text('read_api')
expect(created_project_access_token).not_to be_empty expect(created_project_access_token).not_to be_empty
end end
context 'when token creation is not allowed' do
before do
group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
end
it 'does not show project access token creation form' do
visit project_settings_access_tokens_path(project)
expect(page).not_to have_selector('.new_project_access_token')
end
end
end end
describe 'active tokens' do describe 'active tokens' do
......
...@@ -5,56 +5,45 @@ RSpec.shared_examples 'Self-managed Core resource access tokens' do ...@@ -5,56 +5,45 @@ RSpec.shared_examples 'Self-managed Core resource access tokens' do
allow(::Gitlab).to receive(:com?).and_return(false) allow(::Gitlab).to receive(:com?).and_return(false)
end end
context 'create resource access tokens' do context 'with owner access' do
context 'with owner' do let(:current_user) { owner }
let(:current_user) { owner }
context 'create resource access tokens' do
it { is_expected.to be_allowed(:create_resource_access_tokens) } it { is_expected.to be_allowed(:create_resource_access_tokens) }
end
context 'with developer' do
let(:current_user) { developer }
it { is_expected.not_to be_allowed(:create_resource_access_tokens) } context 'when resource access token creation is not allowed' do
end let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
context 'when resource access tokens are not available' do before do
let(:current_user) { owner } group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
let(:group) { create(:group) } end
let(:project) { create(:project, group: group) }
before do it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
end end
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end end
end
context 'read resource access tokens' do
context 'with owner' do
let(:current_user) { owner }
context 'read resource access tokens' do
it { is_expected.to be_allowed(:read_resource_access_tokens) } it { is_expected.to be_allowed(:read_resource_access_tokens) }
end end
context 'with developer' do context 'destroy resource access tokens' do
let(:current_user) { developer } it { is_expected.to be_allowed(:destroy_resource_access_tokens) }
it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
end end
end end
context 'destroy resource access tokens' do context 'with developer access' do
context 'with owner' do let(:current_user) { developer }
let(:current_user) { owner }
it { is_expected.to be_allowed(:destroy_resource_access_tokens) } context 'create resource access tokens' do
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end end
context 'with developer' do context 'read resource access tokens' do
let(:current_user) { developer } it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) } it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
end end
end end
...@@ -66,9 +55,19 @@ RSpec.shared_examples 'GitLab.com Core resource access tokens' do ...@@ -66,9 +55,19 @@ RSpec.shared_examples 'GitLab.com Core resource access tokens' do
stub_ee_application_setting(should_check_namespace_plan: true) stub_ee_application_setting(should_check_namespace_plan: true)
end end
context 'with owner' do context 'with owner access' do
let(:current_user) { owner } let(:current_user) { owner }
it { is_expected.not_to be_allowed(:create_resource_access_tokens) } context 'create resource access tokens' do
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
context 'read resource access tokens' do
it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
end
context 'destroy resource access tokens' do
it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
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