Commit 1c9a812f authored by Etienne Baqué's avatar Etienne Baqué Committed by Rémy Coutable

Moved group deploy tokens to repository settings

Created new Repository settings at group level.
Moved Group Deploy Tokens to this new section.
Adjusted existing controllers, views, routes and spec accordingly.
parent a9b6ecb3
import initSettingsPanels from '~/settings_panels'; import initSettingsPanels from '~/settings_panels';
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list'; import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
import initVariableList from '~/ci_variable_list'; import initVariableList from '~/ci_variable_list';
import DueDateSelectors from '~/due_date_select';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels // Initialize expandable settings panels
initSettingsPanels(); initSettingsPanels();
// eslint-disable-next-line no-new
new DueDateSelectors();
if (gon.features.newVariablesUi) { if (gon.features.newVariablesUi) {
initVariableList(); initVariableList();
......
import initSettingsPanels from '~/settings_panels';
import DueDateSelectors from '~/due_date_select';
document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
initSettingsPanels();
new DueDateSelectors(); // eslint-disable-line no-new
});
...@@ -7,6 +7,6 @@ class Groups::DeployTokensController < Groups::ApplicationController ...@@ -7,6 +7,6 @@ class Groups::DeployTokensController < Groups::ApplicationController
@token = @group.deploy_tokens.find(params[:id]) @token = @group.deploy_tokens.find(params[:id])
@token.revoke! @token.revoke!
redirect_to group_settings_ci_cd_path(@group, anchor: 'js-deploy-tokens') redirect_to group_settings_repository_path(@group, anchor: 'js-deploy-tokens')
end end
end end
...@@ -8,9 +8,8 @@ module Groups ...@@ -8,9 +8,8 @@ module Groups
before_action :authorize_update_max_artifacts_size!, only: [:update] before_action :authorize_update_max_artifacts_size!, only: [:update]
before_action do before_action do
push_frontend_feature_flag(:new_variables_ui, @group, default_enabled: true) push_frontend_feature_flag(:new_variables_ui, @group, default_enabled: true)
push_frontend_feature_flag(:ajax_new_deploy_token, @group)
end end
before_action :define_variables, only: [:show, :create_deploy_token] before_action :define_variables, only: [:show]
def show def show
end end
...@@ -42,38 +41,10 @@ module Groups ...@@ -42,38 +41,10 @@ module Groups
redirect_to group_settings_ci_cd_path redirect_to group_settings_ci_cd_path
end end
def create_deploy_token
result = Groups::DeployTokens::CreateService.new(@group, current_user, deploy_token_params).execute
@new_deploy_token = result[:deploy_token]
if result[:status] == :success
respond_to do |format|
format.json do
# IMPORTANT: It's a security risk to expose the token value more than just once here!
json = API::Entities::DeployTokenWithToken.represent(@new_deploy_token).as_json
render json: json, status: result[:http_status]
end
format.html do
flash.now[:notice] = s_('DeployTokens|Your new group deploy token has been created.')
render :show
end
end
else
respond_to do |format|
format.json { render json: { message: result[:message] }, status: result[:http_status] }
format.html do
flash.now[:alert] = result[:message]
render :show
end
end
end
end
private private
def define_variables def define_variables
define_ci_variables define_ci_variables
define_deploy_token_variables
end end
def define_ci_variables def define_ci_variables
...@@ -83,12 +54,6 @@ module Groups ...@@ -83,12 +54,6 @@ module Groups
.map { |variable| variable.present(current_user: current_user) } .map { |variable| variable.present(current_user: current_user) }
end end
def define_deploy_token_variables
@deploy_tokens = @group.deploy_tokens.active
@new_deploy_token = DeployToken.new
end
def authorize_admin_group! def authorize_admin_group!
return render_404 unless can?(current_user, :admin_group, group) return render_404 unless can?(current_user, :admin_group, group)
end end
...@@ -112,10 +77,6 @@ module Groups ...@@ -112,10 +77,6 @@ module Groups
def update_group_params def update_group_params
params.require(:group).permit(:max_artifacts_size) params.require(:group).permit(:max_artifacts_size)
end end
def deploy_token_params
params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :username)
end
end end
end end
end end
# frozen_string_literal: true
module Groups
module Settings
class RepositoryController < Groups::ApplicationController
skip_cross_project_access_check :show
before_action :authorize_admin_group!
before_action :define_deploy_token_variables
before_action do
push_frontend_feature_flag(:ajax_new_deploy_token, @group)
end
def create_deploy_token
result = Groups::DeployTokens::CreateService.new(@group, current_user, deploy_token_params).execute
@new_deploy_token = result[:deploy_token]
if result[:status] == :success
respond_to do |format|
format.json do
# IMPORTANT: It's a security risk to expose the token value more than just once here!
json = API::Entities::DeployTokenWithToken.represent(@new_deploy_token).as_json
render json: json, status: result[:http_status]
end
format.html do
flash.now[:notice] = s_('DeployTokens|Your new group deploy token has been created.')
render :show
end
end
else
respond_to do |format|
format.json { render json: { message: result[:message] }, status: result[:http_status] }
format.html do
flash.now[:alert] = result[:message]
render :show
end
end
end
end
private
def define_deploy_token_variables
@deploy_tokens = @group.deploy_tokens.active
@new_deploy_token = DeployToken.new
end
def deploy_token_params
params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :username)
end
end
end
end
...@@ -7,7 +7,7 @@ module CiVariablesHelper ...@@ -7,7 +7,7 @@ module CiVariablesHelper
def create_deploy_token_path(entity, opts = {}) def create_deploy_token_path(entity, opts = {})
if entity.is_a?(Group) if entity.is_a?(Group)
create_deploy_token_group_settings_ci_cd_path(entity, opts) create_deploy_token_group_settings_repository_path(entity, opts)
else else
# TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path' # TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path'
# See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356 # See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
......
...@@ -15,6 +15,7 @@ module GroupsHelper ...@@ -15,6 +15,7 @@ module GroupsHelper
groups#projects groups#projects
groups#edit groups#edit
badges#index badges#index
repository#show
ci_cd#show ci_cd#show
integrations#index integrations#index
integrations#edit integrations#edit
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
- expanded = expanded_by_default? - expanded = expanded_by_default?
- general_expanded = @group.errors.empty? ? expanded : true - general_expanded = @group.errors.empty? ? expanded : true
- deploy_token_description = s_('DeployTokens|Group deploy tokens allow read-only access to the repositories and registry images within the group.')
-# Given we only have one field in this form which is also admin-only, -# Given we only have one field in this form which is also admin-only,
-# we don't want to show an empty section to non-admin users, -# we don't want to show an empty section to non-admin users,
...@@ -25,8 +24,6 @@ ...@@ -25,8 +24,6 @@
.settings-content .settings-content
= render 'ci/variables/index', save_endpoint: group_variables_path = render 'ci/variables/index', save_endpoint: group_variables_path
= render "shared/deploy_tokens/index", group_or_project: @group, description: deploy_token_description
%section.settings#runners-settings.no-animate{ class: ('expanded' if expanded) } %section.settings#runners-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header .settings-header
%h4 %h4
......
- breadcrumb_title _('Repository Settings')
- page_title _('Repository')
- deploy_token_description = s_('DeployTokens|Group deploy tokens allow read-only access to the repositories and registry images within the group.')
= render "shared/deploy_tokens/index", group_or_project: @group, description: deploy_token_description
...@@ -155,6 +155,11 @@ ...@@ -155,6 +155,11 @@
%span %span
= _('Projects') = _('Projects')
= nav_link(controller: :repository) do
= link_to group_settings_repository_path(@group), title: _('Repository') do
%span
= _('Repository')
= nav_link(controller: :ci_cd) do = nav_link(controller: :ci_cd) do
= link_to group_settings_ci_cd_path(@group), title: _('CI / CD') do = link_to group_settings_ci_cd_path(@group), title: _('CI / CD') do
%span %span
......
---
title: Move Group Deploy Tokens to new Group-scoped Repository settings
merge_request: 29290
author:
type: changed
...@@ -32,6 +32,10 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -32,6 +32,10 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resource :ci_cd, only: [:show, :update], controller: 'ci_cd' do resource :ci_cd, only: [:show, :update], controller: 'ci_cd' do
put :reset_registration_token put :reset_registration_token
patch :update_auto_devops patch :update_auto_devops
post :create_deploy_token, path: 'deploy_token/create', to: 'repository#create_deploy_token'
end
resource :repository, only: [:show], controller: 'repository' do
post :create_deploy_token, path: 'deploy_token/create' post :create_deploy_token, path: 'deploy_token/create'
end end
......
...@@ -216,88 +216,4 @@ describe Groups::Settings::CiCdController do ...@@ -216,88 +216,4 @@ describe Groups::Settings::CiCdController do
end end
end end
end end
describe 'POST create_deploy_token' do
context 'when ajax_new_deploy_token feature flag is disabled for the project' do
before do
stub_feature_flags(ajax_new_deploy_token: { enabled: false, thing: group })
entity.add_owner(user)
end
it_behaves_like 'a created deploy token' do
let(:entity) { group }
let(:create_entity_params) { { group_id: group } }
let(:deploy_token_type) { DeployToken.deploy_token_types[:group_type] }
end
end
context 'when ajax_new_deploy_token feature flag is enabled for the project' do
let(:good_deploy_token_params) do
{
name: 'name',
expires_at: 1.day.from_now.to_s,
username: 'deployer',
read_repository: '1',
deploy_token_type: DeployToken.deploy_token_types[:group_type]
}
end
let(:request_params) do
{
group_id: group.to_param,
deploy_token: deploy_token_params
}
end
before do
group.add_owner(user)
end
subject { post :create_deploy_token, params: request_params, format: :json }
context('a good request') do
let(:deploy_token_params) { good_deploy_token_params }
let(:expected_response) do
{
'id' => be_a(Integer),
'name' => deploy_token_params[:name],
'username' => deploy_token_params[:username],
'expires_at' => Time.parse(deploy_token_params[:expires_at]),
'token' => be_a(String),
'scopes' => deploy_token_params.inject([]) do |scopes, kv|
key, value = kv
key.to_s.start_with?('read_') && !value.to_i.zero? ? scopes << key.to_s : scopes
end
}
end
it 'creates the deploy token' do
subject
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/deploy_token')
expect(json_response).to match(expected_response)
end
end
context('a bad request') do
let(:deploy_token_params) { good_deploy_token_params.except(:read_repository) }
let(:expected_response) { { 'message' => "Scopes can't be blank" } }
it 'does not create the deploy token' do
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to match(expected_response)
end
end
context('an invalid request') do
let(:deploy_token_params) { good_deploy_token_params.except(:name) }
it 'raises a validation error' do
expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
describe Groups::Settings::RepositoryController do
include ExternalAuthorizationServiceHelpers
let(:group) { create(:group) }
let(:user) { create(:user) }
before do
sign_in(user)
end
describe 'POST create_deploy_token' do
context 'when ajax_new_deploy_token feature flag is disabled for the project' do
before do
stub_feature_flags(ajax_new_deploy_token: { enabled: false, thing: group })
entity.add_owner(user)
end
it_behaves_like 'a created deploy token' do
let(:entity) { group }
let(:create_entity_params) { { group_id: group } }
let(:deploy_token_type) { DeployToken.deploy_token_types[:group_type] }
end
end
context 'when ajax_new_deploy_token feature flag is enabled for the project' do
let(:good_deploy_token_params) do
{
name: 'name',
expires_at: 1.day.from_now.to_s,
username: 'deployer',
read_repository: '1',
deploy_token_type: DeployToken.deploy_token_types[:group_type]
}
end
let(:request_params) do
{
group_id: group.to_param,
deploy_token: deploy_token_params
}
end
before do
group.add_owner(user)
end
subject { post :create_deploy_token, params: request_params, format: :json }
context('a good request') do
let(:deploy_token_params) { good_deploy_token_params }
let(:expected_response) do
{
'id' => be_a(Integer),
'name' => deploy_token_params[:name],
'username' => deploy_token_params[:username],
'expires_at' => Time.parse(deploy_token_params[:expires_at]),
'token' => be_a(String),
'scopes' => deploy_token_params.inject([]) do |scopes, kv|
key, value = kv
key.to_s.start_with?('read_') && !value.to_i.zero? ? scopes << key.to_s : scopes
end
}
end
it 'creates the deploy token' do
subject
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/deploy_token')
expect(json_response).to match(expected_response)
end
end
context('a bad request') do
let(:deploy_token_params) { good_deploy_token_params.except(:read_repository) }
let(:expected_response) { { 'message' => "Scopes can't be blank" } }
it 'does not create the deploy token' do
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to match(expected_response)
end
end
context('an invalid request') do
let(:deploy_token_params) { good_deploy_token_params.except(:name) }
it 'raises a validation error' do
expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
end
end
end
end
end
...@@ -37,19 +37,6 @@ describe 'Group CI/CD settings' do ...@@ -37,19 +37,6 @@ describe 'Group CI/CD settings' do
end end
end end
context 'Deploy tokens' do
let!(:deploy_token) { create(:deploy_token, :group, groups: [group]) }
before do
stub_container_registry_config(enabled: true)
visit group_settings_ci_cd_path(group)
end
it_behaves_like 'a deploy token in ci/cd settings' do
let(:entity_type) { 'group' }
end
end
describe 'Auto DevOps form' do describe 'Auto DevOps form' do
before do before do
stub_application_setting(auto_devops_enabled: true) stub_application_setting(auto_devops_enabled: true)
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Group Repository settings' do
include WaitForRequests
let(:user) { create(:user) }
let(:group) { create(:group) }
before do
group.add_owner(user)
sign_in(user)
end
context 'Deploy tokens' do
let!(:deploy_token) { create(:deploy_token, :group, groups: [group]) }
before do
stub_container_registry_config(enabled: true)
visit group_settings_repository_path(group)
end
it_behaves_like 'a deploy token in settings' do
let(:entity_type) { 'group' }
end
end
end
...@@ -18,7 +18,7 @@ describe 'Projects > Settings > CI / CD settings' do ...@@ -18,7 +18,7 @@ describe 'Projects > Settings > CI / CD settings' do
visit project_settings_ci_cd_path(project) visit project_settings_ci_cd_path(project)
end end
it_behaves_like 'a deploy token in ci/cd settings' do it_behaves_like 'a deploy token in settings' do
let(:entity_type) { 'project' } let(:entity_type) { 'project' }
end end
end end
......
...@@ -111,6 +111,7 @@ RSpec.shared_context 'group navbar structure' do ...@@ -111,6 +111,7 @@ RSpec.shared_context 'group navbar structure' do
nav_sub_items: [ nav_sub_items: [
_('General'), _('General'),
_('Projects'), _('Projects'),
_('Repository'),
_('CI / CD'), _('CI / CD'),
_('Integrations'), _('Integrations'),
_('Webhooks'), _('Webhooks'),
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'a deploy token in ci/cd settings' do RSpec.shared_examples 'a deploy token in settings' do
it 'view deploy tokens' do it 'view deploy tokens' do
within('.deploy-tokens') do within('.deploy-tokens') do
expect(page).to have_content(deploy_token.name) expect(page).to have_content(deploy_token.name)
......
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