Commit 8b7111eb authored by Etienne Baqué's avatar Etienne Baqué Committed by Phil Hughes

Added GroupDeployToken model

Added model and rspecs.
Updated DeployToken model associations.
parent c42cbbcf
...@@ -374,6 +374,7 @@ linters: ...@@ -374,6 +374,7 @@ linters:
- 'app/views/shared/boards/components/sidebar/_due_date.html.haml' - 'app/views/shared/boards/components/sidebar/_due_date.html.haml'
- 'app/views/shared/boards/components/sidebar/_labels.html.haml' - 'app/views/shared/boards/components/sidebar/_labels.html.haml'
- 'app/views/shared/boards/components/sidebar/_milestone.html.haml' - 'app/views/shared/boards/components/sidebar/_milestone.html.haml'
- 'app/views/shared/deploy_tokens/_revoke_modal.html.haml'
- 'app/views/shared/empty_states/_priority_labels.html.haml' - 'app/views/shared/empty_states/_priority_labels.html.haml'
- 'app/views/shared/hook_logs/_content.html.haml' - 'app/views/shared/hook_logs/_content.html.haml'
- 'app/views/shared/issuable/_assignees.html.haml' - 'app/views/shared/issuable/_assignees.html.haml'
......
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();
......
...@@ -3,6 +3,7 @@ import SecretValues from '~/behaviors/secret_values'; ...@@ -3,6 +3,7 @@ import SecretValues from '~/behaviors/secret_values';
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list'; import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
import registrySettingsApp from '~/registry/settings/registry_settings_bundle'; import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
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
...@@ -39,5 +40,8 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -39,5 +40,8 @@ document.addEventListener('DOMContentLoaded', () => {
autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked); autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);
}); });
// eslint-disable-next-line no-new
new DueDateSelectors();
registrySettingsApp(); registrySettingsApp();
}); });
# frozen_string_literal: true
class Groups::DeployTokensController < Groups::ApplicationController
before_action :authorize_admin_group!
def revoke
@token = @group.deploy_tokens.find(params[:id])
@token.revoke!
redirect_to group_settings_ci_cd_path(@group, anchor: 'js-deploy-tokens')
end
end
...@@ -9,9 +9,9 @@ module Groups ...@@ -9,9 +9,9 @@ module Groups
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)
end end
before_action :define_variables, only: [:show, :create_deploy_token]
def show def show
define_ci_variables
end end
def update def update
...@@ -41,8 +41,23 @@ module Groups ...@@ -41,8 +41,23 @@ module Groups
redirect_to group_settings_ci_cd_path redirect_to group_settings_ci_cd_path
end end
def create_deploy_token
@new_deploy_token = Groups::DeployTokens::CreateService.new(@group, current_user, deploy_token_params).execute
if @new_deploy_token.persisted?
flash.now[:notice] = s_('DeployTokens|Your new group deploy token has been created.')
end
render 'show'
end
private private
def define_variables
define_ci_variables
define_deploy_token_variables
end
def define_ci_variables def define_ci_variables
@variable = Ci::GroupVariable.new(group: group) @variable = Ci::GroupVariable.new(group: group)
.present(current_user: current_user) .present(current_user: current_user)
...@@ -50,6 +65,12 @@ module Groups ...@@ -50,6 +65,12 @@ 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
...@@ -73,6 +94,10 @@ module Groups ...@@ -73,6 +94,10 @@ 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, :username)
end
end end
end end
end end
...@@ -7,6 +7,6 @@ class Projects::DeployTokensController < Projects::ApplicationController ...@@ -7,6 +7,6 @@ class Projects::DeployTokensController < Projects::ApplicationController
@token = @project.deploy_tokens.find(params[:id]) @token = @project.deploy_tokens.find(params[:id])
@token.revoke! @token.revoke!
redirect_to project_settings_repository_path(project, anchor: 'js-deploy-tokens') redirect_to project_settings_ci_cd_path(project, anchor: 'js-deploy-tokens')
end end
end end
...@@ -46,6 +46,16 @@ module Projects ...@@ -46,6 +46,16 @@ module Projects
redirect_to namespace_project_settings_ci_cd_path redirect_to namespace_project_settings_ci_cd_path
end end
def create_deploy_token
@new_deploy_token = Projects::DeployTokens::CreateService.new(@project, current_user, deploy_token_params).execute
if @new_deploy_token.persisted?
flash.now[:notice] = s_('DeployTokens|Your new project deploy token has been created.')
end
render 'show'
end
private private
def update_params def update_params
...@@ -64,6 +74,10 @@ module Projects ...@@ -64,6 +74,10 @@ module Projects
end end
end end
def deploy_token_params
params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :username)
end
def run_autodevops_pipeline(service) def run_autodevops_pipeline(service)
return unless service.run_auto_devops_pipeline? return unless service.run_auto_devops_pipeline?
...@@ -83,6 +97,7 @@ module Projects ...@@ -83,6 +97,7 @@ module Projects
def define_variables def define_variables
define_runners_variables define_runners_variables
define_ci_variables define_ci_variables
define_deploy_token_variables
define_triggers_variables define_triggers_variables
define_badges_variables define_badges_variables
define_auto_devops_variables define_auto_devops_variables
...@@ -132,6 +147,12 @@ module Projects ...@@ -132,6 +147,12 @@ module Projects
def define_auto_devops_variables def define_auto_devops_variables
@auto_devops = @project.auto_devops || ProjectAutoDevops.new @auto_devops = @project.auto_devops || ProjectAutoDevops.new
end end
def define_deploy_token_variables
@deploy_tokens = @project.deploy_tokens.active
@new_deploy_token = DeployToken.new
end
end end
end end
end end
......
...@@ -10,16 +10,6 @@ module Projects ...@@ -10,16 +10,6 @@ module Projects
render_show render_show
end end
def create_deploy_token
@new_deploy_token = DeployTokens::CreateService.new(@project, current_user, deploy_token_params).execute
if @new_deploy_token.persisted?
flash.now[:notice] = s_('DeployTokens|Your new project deploy token has been created.')
end
render_show
end
def cleanup def cleanup
cleanup_params = params.require(:project).permit(:bfg_object_map) cleanup_params = params.require(:project).permit(:bfg_object_map)
result = Projects::UpdateService.new(project, current_user, cleanup_params).execute result = Projects::UpdateService.new(project, current_user, cleanup_params).execute
...@@ -38,9 +28,7 @@ module Projects ...@@ -38,9 +28,7 @@ module Projects
def render_show def render_show
@deploy_keys = DeployKeysPresenter.new(@project, current_user: current_user) @deploy_keys = DeployKeysPresenter.new(@project, current_user: current_user)
@deploy_tokens = @project.deploy_tokens.active
define_deploy_token
define_protected_refs define_protected_refs
remote_mirror remote_mirror
...@@ -93,14 +81,6 @@ module Projects ...@@ -93,14 +81,6 @@ module Projects
gon.push(protectable_branches_for_dropdown) gon.push(protectable_branches_for_dropdown)
gon.push(access_levels_options) gon.push(access_levels_options)
end end
def define_deploy_token
@new_deploy_token ||= DeployToken.new
end
def deploy_token_params
params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :username)
end
end end
end end
end end
......
...@@ -5,6 +5,22 @@ module CiVariablesHelper ...@@ -5,6 +5,22 @@ module CiVariablesHelper
Gitlab::CurrentSettings.current_application_settings.protected_ci_variables Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
end end
def create_deploy_token_path(entity, opts = {})
if entity.is_a?(Group)
create_deploy_token_group_settings_ci_cd_path(entity, opts)
else
create_deploy_token_project_settings_repository_path(entity, opts)
end
end
def revoke_deploy_token_path(entity, token)
if entity.is_a?(Group)
revoke_group_deploy_token_path(entity, token)
else
revoke_project_deploy_token_path(entity, token)
end
end
def ci_variable_protected?(variable, only_key_value) def ci_variable_protected?(variable, only_key_value)
if variable && !only_key_value if variable && !only_key_value
variable.protected variable.protected
......
...@@ -59,6 +59,9 @@ class Group < Namespace ...@@ -59,6 +59,9 @@ class Group < Namespace
has_many :import_failures, inverse_of: :group has_many :import_failures, inverse_of: :group
has_many :group_deploy_tokens
has_many :deploy_tokens, through: :group_deploy_tokens
accepts_nested_attributes_for :variables, allow_destroy: true accepts_nested_attributes_for :variables, allow_destroy: true
validate :visibility_level_allowed_by_projects validate :visibility_level_allowed_by_projects
......
...@@ -9,7 +9,7 @@ class GroupDeployToken < ApplicationRecord ...@@ -9,7 +9,7 @@ class GroupDeployToken < ApplicationRecord
validates :deploy_token_id, uniqueness: { scope: [:group_id] } validates :deploy_token_id, uniqueness: { scope: [:group_id] }
def has_access_to?(requested_project) def has_access_to?(requested_project)
return false unless Feature.enabled?(:allow_group_deploy_token, default: true) return false unless Feature.enabled?(:allow_group_deploy_token, default_enabled: true)
requested_project_group = requested_project&.group requested_project_group = requested_project&.group
return false unless requested_project_group return false unless requested_project_group
......
...@@ -2343,6 +2343,14 @@ class Project < ApplicationRecord ...@@ -2343,6 +2343,14 @@ class Project < ApplicationRecord
Gitlab::CurrentSettings.self_monitoring_project_id == id Gitlab::CurrentSettings.self_monitoring_project_id == id
end end
def deploy_token_create_url(opts = {})
Gitlab::Routing.url_helpers.create_deploy_token_project_settings_ci_cd_path(self, opts)
end
def deploy_token_revoke_url_for(token)
Gitlab::Routing.url_helpers.revoke_project_deploy_token_path(self, token)
end
private private
def closest_namespace_setting(name) def closest_namespace_setting(name)
......
# frozen_string_literal: true
module DeployTokenMethods
def create_deploy_token_for(entity, params)
params[:deploy_token_type] = DeployToken.deploy_token_types["#{entity.class.name.downcase}_type".to_sym]
entity.deploy_tokens.create(params) do |deploy_token|
deploy_token.username = params[:username].presence
end
end
end
# frozen_string_literal: true
module DeployTokens
class CreateService < BaseService
def execute
@project.deploy_tokens.create(params) do |deploy_token|
deploy_token.username = params[:username].presence
end
end
end
end
# frozen_string_literal: true
module Groups
module DeployTokens
class CreateService < BaseService
include DeployTokenMethods
def execute
create_deploy_token_for(@group, params)
end
end
end
end
# frozen_string_literal: true
module Projects
module DeployTokens
class CreateService < BaseService
include DeployTokenMethods
def execute
create_deploy_token_for(@project, params)
end
end
end
end
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
- 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,
...@@ -24,6 +25,8 @@ ...@@ -24,6 +25,8 @@
.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
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
- expanded = expanded_by_default? - expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true - general_expanded = @project.errors.empty? ? expanded : true
- deploy_token_description = s_('DeployTokens|Deploy tokens allow read-only access to your repository and registry images.')
%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) } %section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) }
.settings-header .settings-header
...@@ -51,6 +52,8 @@ ...@@ -51,6 +52,8 @@
.settings-content .settings-content
= render 'ci/variables/index', save_endpoint: project_variables_path(@project) = render 'ci/variables/index', save_endpoint: project_variables_path(@project)
= render "shared/deploy_tokens/index", group_or_project: @project, description: deploy_token_description
%section.settings.no-animate#js-pipeline-triggers{ class: ('expanded' if expanded) } %section.settings.no-animate#js-pipeline-triggers{ class: ('expanded' if expanded) }
.settings-header .settings-header
%h4 %h4
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
= render "projects/settings/repository/protected_branches" = render "projects/settings/repository/protected_branches"
= render @deploy_keys = render @deploy_keys
= render "projects/deploy_tokens/index"
= render "projects/cleanup/show" = render "projects/cleanup/show"
= render_if_exists 'shared/promotions/promote_repository_features' = render_if_exists 'shared/promotions/promote_repository_features'
%p.profile-settings-content %p.profile-settings-content
= s_("DeployTokens|Pick a name for the application, and we'll give you a unique deploy token.") = s_("DeployTokens|Pick a name for the application, and we'll give you a unique deploy token.")
= form_for token, url: create_deploy_token_namespace_project_settings_repository_path(project.namespace, project, anchor: 'js-deploy-tokens'), method: :post do |f| = form_for token, url: create_deploy_token_path(group_or_project, anchor: 'js-deploy-tokens'), method: :post do |f|
= form_errors(token) = form_errors(token)
.form-group .form-group
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
= label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label' = label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the repository') .text-secondary= s_('DeployTokens|Allows read-only access to the repository')
- if container_registry_enabled?(project) - if container_registry_enabled?(group_or_project)
%fieldset.form-group.form-check %fieldset.form-group.form-check
= f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry' = f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry'
= label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label' = label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
......
- expanded = expand_deploy_tokens_section?(@new_deploy_token) - expanded = expand_deploy_tokens_section?(@new_deploy_token)
%section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded) } %section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded), data: { qa_selector: 'deploy_tokens_settings' } }
.settings-header .settings-header
%h4= s_('DeployTokens|Deploy Tokens') %h4= s_('DeployTokens|Deploy Tokens')
%button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' } %button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
= expanded ? 'Collapse' : 'Expand' = expanded ? 'Collapse' : 'Expand'
%p %p
= s_('DeployTokens|Deploy tokens allow read-only access to your repository and registry images.') = description
.settings-content .settings-content
- if @new_deploy_token.persisted? - if @new_deploy_token.persisted?
= render 'projects/deploy_tokens/new_deploy_token', deploy_token: @new_deploy_token = render 'shared/deploy_tokens/new_deploy_token', deploy_token: @new_deploy_token
%h5.prepend-top-0 %h5.prepend-top-0
= s_('DeployTokens|Add a deploy token') = s_('DeployTokens|Add a deploy token')
= render 'projects/deploy_tokens/form', project: @project, token: @new_deploy_token, presenter: @deploy_tokens = render 'shared/deploy_tokens/form', group_or_project: group_or_project, token: @new_deploy_token, presenter: @deploy_tokens
%hr %hr
= render 'projects/deploy_tokens/table', project: @project, active_tokens: @deploy_tokens = render 'shared/deploy_tokens/table', group_or_project: group_or_project, active_tokens: @deploy_tokens
...@@ -3,15 +3,13 @@ ...@@ -3,15 +3,13 @@
.modal-content .modal-content
.modal-header .modal-header
%h4.modal-title %h4.modal-title
= s_('DeployTokens|Revoke') = s_('DeployTokens|Revoke %{b_start}%{name}%{b_end}?').html_safe % { b_start: '<b>'.html_safe, name: token.name, b_end: '</b>'.html_safe }
%b #{token.name}?
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') } %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": true } &times; %span{ "aria-hidden": true } &times;
.modal-body .modal-body
%p %p
= s_('DeployTokens|You are about to revoke') = s_('DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}.').html_safe % { b_start: '<b>'.html_safe, name: token.name, b_end: '</b>'.html_safe }
%b #{token.name}.
= s_('DeployTokens|This action cannot be undone.') = s_('DeployTokens|This action cannot be undone.')
.modal-footer .modal-footer
%a{ href: '#', data: { dismiss: 'modal' }, class: 'btn btn-default' }= _('Cancel') %a{ href: '#', data: { dismiss: 'modal' }, class: 'btn btn-default' }= _('Cancel')
= link_to s_('DeployTokens|Revoke %{name}') % { name: token.name }, revoke_project_deploy_token_path(project, token), method: :put, class: 'btn btn-danger' = link_to s_('DeployTokens|Revoke %{name}') % { name: token.name }, revoke_deploy_token_path(group_or_project, token), method: :put, class: 'btn btn-danger'
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
%span{ class: ('text-warning' if token.expires_soon?) } %span{ class: ('text-warning' if token.expires_soon?) }
In #{distance_of_time_in_words_to_now(token.expires_at)} In #{distance_of_time_in_words_to_now(token.expires_at)}
- else - else
%span.token-never-expires-label Never %span.token-never-expires-label= _('Never')
%td= token.scopes.present? ? token.scopes.join(", ") : "<no scopes selected>" %td= token.scopes.present? ? token.scopes.join(", ") : _('<no scopes selected>')
%td= link_to s_('DeployTokens|Revoke'), "#", class: "btn btn-danger float-right", data: { toggle: "modal", target: "#revoke-modal-#{token.id}"} %td= link_to s_('DeployTokens|Revoke'), "#", class: "btn btn-danger float-right", data: { toggle: "modal", target: "#revoke-modal-#{token.id}"}
= render 'projects/deploy_tokens/revoke_modal', token: token, project: project = render 'shared/deploy_tokens/revoke_modal', token: token, group_or_project: group_or_project
- else - else
.settings-message.text-center .settings-message.text-center
= s_('DeployTokens|This project has no active Deploy Tokens.') = s_('DeployTokens|This %{entity_type} has no active Deploy Tokens.') % { entity_type: group_or_project.class.name.downcase }
---
title: Addition of the Group Deploy Token interface
merge_request: 24102
author:
type: added
...@@ -29,6 +29,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -29,6 +29,7 @@ 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'
end end
end end
...@@ -49,6 +50,12 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -49,6 +50,12 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end end
end end
resources :deploy_tokens, constraints: { id: /\d+/ }, only: [] do
member do
put :revoke
end
end
resource :avatar, only: [:destroy] resource :avatar, only: [:destroy]
concerns :clusterable concerns :clusterable
......
...@@ -79,7 +79,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -79,7 +79,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resource :integrations, only: [:show] resource :integrations, only: [:show]
resource :repository, only: [:show], controller: :repository do resource :repository, only: [:show], controller: :repository do
post :create_deploy_token, path: 'deploy_token/create' # TODO: Move 'create_deploy_token' here to the ':ci_cd' resource above during 12.9.
# More details here: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24102#note_287572556
post :create_deploy_token, path: 'deploy_token/create', to: 'ci_cd#create_deploy_token'
post :cleanup post :cleanup
end end
end end
......
...@@ -8,8 +8,8 @@ module EE ...@@ -8,8 +8,8 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
before_action :assign_variables_to_gon, only: :show before_action :assign_variables_to_gon, only: [:show, :create_deploy_token]
before_action :define_protected_env_variables, only: :show before_action :define_protected_env_variables, only: [:show, :create_deploy_token]
end end
# rubocop:disable Gitlab/ModuleWithInstanceVariables # rubocop:disable Gitlab/ModuleWithInstanceVariables
......
...@@ -42,7 +42,6 @@ module EE ...@@ -42,7 +42,6 @@ module EE
@deploy_keys = ::Projects::Settings::DeployKeysPresenter.new(@project, current_user: current_user) @deploy_keys = ::Projects::Settings::DeployKeysPresenter.new(@project, current_user: current_user)
@deploy_tokens = @project.deploy_tokens.active @deploy_tokens = @project.deploy_tokens.active
define_deploy_token
define_protected_refs define_protected_refs
push_rule push_rule
remote_mirror remote_mirror
......
...@@ -6501,6 +6501,9 @@ msgstr "" ...@@ -6501,6 +6501,9 @@ msgstr ""
msgid "DeployTokens|Expires" msgid "DeployTokens|Expires"
msgstr "" msgstr ""
msgid "DeployTokens|Group deploy tokens allow read-only access to the repositories and registry images within the group."
msgstr ""
msgid "DeployTokens|Name" msgid "DeployTokens|Name"
msgstr "" msgstr ""
...@@ -6510,16 +6513,19 @@ msgstr "" ...@@ -6510,16 +6513,19 @@ msgstr ""
msgid "DeployTokens|Revoke" msgid "DeployTokens|Revoke"
msgstr "" msgstr ""
msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
msgstr ""
msgid "DeployTokens|Revoke %{name}" msgid "DeployTokens|Revoke %{name}"
msgstr "" msgstr ""
msgid "DeployTokens|Scopes" msgid "DeployTokens|Scopes"
msgstr "" msgstr ""
msgid "DeployTokens|This action cannot be undone." msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
msgstr "" msgstr ""
msgid "DeployTokens|This project has no active Deploy Tokens." msgid "DeployTokens|This action cannot be undone."
msgstr "" msgstr ""
msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again." msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
...@@ -6531,12 +6537,15 @@ msgstr "" ...@@ -6531,12 +6537,15 @@ msgstr ""
msgid "DeployTokens|Username" msgid "DeployTokens|Username"
msgstr "" msgstr ""
msgid "DeployTokens|You are about to revoke" msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
msgstr "" msgstr ""
msgid "DeployTokens|Your New Deploy Token" msgid "DeployTokens|Your New Deploy Token"
msgstr "" msgstr ""
msgid "DeployTokens|Your new group deploy token has been created."
msgstr ""
msgid "DeployTokens|Your new project deploy token has been created." msgid "DeployTokens|Your new project deploy token has been created."
msgstr "" msgstr ""
......
...@@ -13,6 +13,16 @@ module QA ...@@ -13,6 +13,16 @@ module QA
element :variables_settings_content element :variables_settings_content
end end
view 'app/views/shared/deploy_tokens/_index.html.haml' do
element :deploy_tokens_settings
end
def expand_deploy_tokens(&block)
expand_section(:deploy_tokens_settings) do
Settings::DeployTokens.perform(&block)
end
end
def expand_runners_settings(&block) def expand_runners_settings(&block)
expand_section(:runners_settings_content) do expand_section(:runners_settings_content) do
Settings::Runners.perform(&block) Settings::Runners.perform(&block)
......
...@@ -5,7 +5,7 @@ module QA ...@@ -5,7 +5,7 @@ module QA
module Project module Project
module Settings module Settings
class DeployTokens < Page::Base class DeployTokens < Page::Base
view 'app/views/projects/deploy_tokens/_form.html.haml' do view 'app/views/shared/deploy_tokens/_form.html.haml' do
element :deploy_token_name element :deploy_token_name
element :deploy_token_expires_at element :deploy_token_expires_at
element :deploy_token_read_repository element :deploy_token_read_repository
...@@ -13,7 +13,7 @@ module QA ...@@ -13,7 +13,7 @@ module QA
element :create_deploy_token element :create_deploy_token
end end
view 'app/views/projects/deploy_tokens/_new_deploy_token.html.haml' do view 'app/views/shared/deploy_tokens/_new_deploy_token.html.haml' do
element :created_deploy_token_section element :created_deploy_token_section
element :deploy_token_user element :deploy_token_user
element :deploy_token element :deploy_token
......
...@@ -31,12 +31,6 @@ module QA ...@@ -31,12 +31,6 @@ module QA
end end
end end
def expand_deploy_tokens(&block)
expand_section(:deploy_tokens_settings) do
DeployTokens.perform(&block)
end
end
def expand_mirroring_repositories(&block) def expand_mirroring_repositories(&block)
expand_section(:mirroring_repositories_settings_section) do expand_section(:mirroring_repositories_settings_section) do
MirroringRepositories.perform(&block) MirroringRepositories.perform(&block)
......
...@@ -6,16 +6,16 @@ module QA ...@@ -6,16 +6,16 @@ module QA
attr_accessor :name, :expires_at attr_accessor :name, :expires_at
attribute :username do attribute :username do
Page::Project::Settings::Repository.perform do |repository_page| Page::Project::Settings::CICD.perform do |cicd_page|
repository_page.expand_deploy_tokens do |token| cicd_page.expand_deploy_tokens do |token|
token.token_username token.token_username
end end
end end
end end
attribute :password do attribute :password do
Page::Project::Settings::Repository.perform do |repository_page| Page::Project::Settings::CICD.perform do |cicd_page|
repository_page.expand_deploy_tokens do |token| cicd_page.expand_deploy_tokens do |token|
token.token_password token.token_password
end end
end end
...@@ -31,12 +31,10 @@ module QA ...@@ -31,12 +31,10 @@ module QA
def fabricate! def fabricate!
project.visit! project.visit!
Page::Project::Menu.act do Page::Project::Menu.perform(&:go_to_ci_cd_settings)
go_to_repository_settings
end
Page::Project::Settings::Repository.perform do |setting| Page::Project::Settings::CICD.perform do |cicd|
setting.expand_deploy_tokens do |page| cicd.expand_deploy_tokens do |page|
page.fill_token_name(name) page.fill_token_name(name)
page.fill_token_expires_at(expires_at) page.fill_token_expires_at(expires_at)
page.fill_scopes(read_repository: true, read_registry: false) page.fill_scopes(read_repository: true, read_registry: false)
......
...@@ -210,4 +210,16 @@ describe Groups::Settings::CiCdController do ...@@ -210,4 +210,16 @@ describe Groups::Settings::CiCdController do
end end
end end
end end
describe 'POST create_deploy_token' do
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] }
before do
entity.add_owner(user)
end
end
end
end end
...@@ -247,4 +247,12 @@ describe Projects::Settings::CiCdController do ...@@ -247,4 +247,12 @@ describe Projects::Settings::CiCdController do
end end
end end
end end
describe 'POST create_deploy_token' do
it_behaves_like 'a created deploy token' do
let(:entity) { project }
let(:create_entity_params) { { namespace_id: project.namespace, project_id: project } }
let(:deploy_token_type) { DeployToken.deploy_token_types[:project_type] }
end
end
end end
...@@ -32,24 +32,4 @@ describe Projects::Settings::RepositoryController do ...@@ -32,24 +32,4 @@ describe Projects::Settings::RepositoryController do
expect(RepositoryCleanupWorker).to have_received(:perform_async).once expect(RepositoryCleanupWorker).to have_received(:perform_async).once
end end
end end
describe 'POST create_deploy_token' do
let(:deploy_token_params) do
{
name: 'deployer_token',
expires_at: 1.month.from_now.to_date.to_s,
username: 'deployer',
read_repository: '1'
}
end
subject(:create_deploy_token) { post :create_deploy_token, params: { namespace_id: project.namespace, project_id: project, deploy_token: deploy_token_params } }
it 'creates deploy token' do
expect { create_deploy_token }.to change { DeployToken.active.count }.by(1)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
end
end
end end
...@@ -37,6 +37,19 @@ describe 'Group CI/CD settings' do ...@@ -37,6 +37,19 @@ 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 'Projects > Settings > CI/CD settings' do
let(:project) { create(:project_empty_repo) }
let(:user) { create(:user) }
let(:role) { :maintainer }
context 'Deploy tokens' do
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
before do
project.add_role(user, role)
sign_in(user)
stub_container_registry_config(enabled: true)
visit project_settings_ci_cd_path(project)
end
it_behaves_like 'a deploy token in ci/cd settings' do
let(:entity_type) { 'project' }
end
end
end
...@@ -108,39 +108,6 @@ describe 'Projects > Settings > Repository settings' do ...@@ -108,39 +108,6 @@ describe 'Projects > Settings > Repository settings' do
end end
end end
context 'Deploy tokens' do
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
before do
stub_container_registry_config(enabled: true)
visit project_settings_repository_path(project)
end
it 'view deploy tokens' do
within('.deploy-tokens') do
expect(page).to have_content(deploy_token.name)
expect(page).to have_content('read_repository')
expect(page).to have_content('read_registry')
end
end
it 'add a new deploy token' do
fill_in 'deploy_token_name', with: 'new_deploy_key'
fill_in 'deploy_token_expires_at', with: (Date.today + 1.month).to_s
fill_in 'deploy_token_username', with: 'deployer'
check 'deploy_token_read_repository'
check 'deploy_token_read_registry'
click_button 'Create deploy token'
expect(page).to have_content('Your new project deploy token has been created')
within('.created-deploy-token-container') do
expect(page).to have_selector("input[name='deploy-token-user'][value='deployer']")
expect(page).to have_selector("input[name='deploy-token'][readonly='readonly']")
end
end
end
context 'remote mirror settings' do context 'remote mirror settings' do
let(:user2) { create(:user) } let(:user2) { create(:user) }
......
...@@ -11,7 +11,7 @@ describe 'Repository Settings > User sees revoke deploy token modal', :js do ...@@ -11,7 +11,7 @@ describe 'Repository Settings > User sees revoke deploy token modal', :js do
before do before do
project.add_role(user, role) project.add_role(user, role)
sign_in(user) sign_in(user)
visit(project_settings_repository_path(project)) visit(project_settings_ci_cd_path(project))
click_link('Revoke') click_link('Revoke')
end end
......
...@@ -798,6 +798,11 @@ describe 'project routing' do ...@@ -798,6 +798,11 @@ describe 'project routing' do
end end
it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/settings/repository", "/gitlab/gitlabhq/-/settings/repository" it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/settings/repository", "/gitlab/gitlabhq/-/settings/repository"
# TODO: remove this test as part of https://gitlab.com/gitlab-org/gitlab/issues/207079 (12.9)
it 'to ci_cd#create_deploy_token' do
expect(post('gitlab/gitlabhq/-/settings/repository/deploy_token/create')).to route_to('projects/settings/ci_cd#create_deploy_token', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
end end
describe Projects::TemplatesController, 'routing' do describe Projects::TemplatesController, 'routing' do
......
# frozen_string_literal: true
require 'spec_helper'
describe Groups::DeployTokens::CreateService do
it_behaves_like 'a deploy token creation service' do
let(:entity) { create(:group) }
let(:deploy_token_class) { GroupDeployToken }
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Projects::DeployTokens::CreateService do
it_behaves_like 'a deploy token creation service' do
let(:entity) { create(:project) }
let(:deploy_token_class) { ProjectDeployToken }
end
end
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' RSpec.shared_examples 'a deploy token creation service' do
describe DeployTokens::CreateService do
let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:deploy_token_params) { attributes_for(:deploy_token) } let(:deploy_token_params) { attributes_for(:deploy_token) }
describe '#execute' do describe '#execute' do
subject { described_class.new(project, user, deploy_token_params).execute } subject { described_class.new(entity, user, deploy_token_params).execute }
context 'when the deploy token is valid' do context 'when the deploy token is valid' do
it 'creates a new DeployToken' do it 'creates a new DeployToken' do
...@@ -16,7 +13,7 @@ describe DeployTokens::CreateService do ...@@ -16,7 +13,7 @@ describe DeployTokens::CreateService do
end end
it 'creates a new ProjectDeployToken' do it 'creates a new ProjectDeployToken' do
expect { subject }.to change { ProjectDeployToken.count }.by(1) expect { subject }.to change { deploy_token_class.count }.by(1)
end end
it 'returns a DeployToken' do it 'returns a DeployToken' do
...@@ -56,7 +53,7 @@ describe DeployTokens::CreateService do ...@@ -56,7 +53,7 @@ describe DeployTokens::CreateService do
end end
it 'does not create a new ProjectDeployToken' do it 'does not create a new ProjectDeployToken' do
expect { subject }.not_to change { ProjectDeployToken.count } expect { subject }.not_to change { deploy_token_class.count }
end end
end end
end end
......
# frozen_string_literal: true
RSpec.shared_examples 'a created deploy token' do
let(:deploy_token_params) do
{
name: 'deployer_token',
expires_at: 1.month.from_now.to_date.to_s,
username: 'deployer',
read_repository: '1',
deploy_token_type: deploy_token_type
}
end
subject(:create_deploy_token) { post :create_deploy_token, params: create_entity_params.merge({ deploy_token: deploy_token_params }) }
it 'creates deploy token' do
expect { create_deploy_token }.to change { DeployToken.active.count }.by(1)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
end
end
# frozen_string_literal: true
RSpec.shared_examples 'a deploy token in ci/cd settings' do
it 'view deploy tokens' do
within('.deploy-tokens') do
expect(page).to have_content(deploy_token.name)
expect(page).to have_content('read_repository')
expect(page).to have_content('read_registry')
end
end
it 'add a new deploy token' do
fill_in 'deploy_token_name', with: 'new_deploy_key'
fill_in 'deploy_token_expires_at', with: (Date.today + 1.month).to_s
fill_in 'deploy_token_username', with: 'deployer'
check 'deploy_token_read_repository'
check 'deploy_token_read_registry'
click_button 'Create deploy token'
expect(page).to have_content("Your new #{entity_type} deploy token has been created")
within('.created-deploy-token-container') do
expect(page).to have_selector("input[name='deploy-token-user'][value='deployer']")
expect(page).to have_selector("input[name='deploy-token'][readonly='readonly']")
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