diff --git a/app/controllers/administrateurs/api_tokens_controller.rb b/app/controllers/administrateurs/api_tokens_controller.rb index 9b35d5faa..742f5916c 100644 --- a/app/controllers/administrateurs/api_tokens_controller.rb +++ b/app/controllers/administrateurs/api_tokens_controller.rb @@ -5,7 +5,7 @@ module Administrateurs include ActionView::RecordIdentifier before_action :authenticate_administrateur! - before_action :set_api_token, only: [:edit, :update, :destroy] + before_action :set_api_token, only: [:edit, :update, :destroy, :remove_procedure] def nom @name = name @@ -13,11 +13,7 @@ module Administrateurs def autorisations @name = name - @libelle_id_procedures = current_administrateur - .procedures - .order(:libelle) - .pluck(:libelle, :id) - .map { |libelle, id| ["#{id} - #{libelle}", id] } + @libelle_id_procedures = libelle_id_procedures end def securite @@ -37,23 +33,54 @@ module Administrateurs end def edit + @libelle_id_procedures = libelle_id_procedures end def update - if invalid_network? - @invalid_network = true - return render :edit + @libelle_id_procedures = libelle_id_procedures + + h = {} + + if !params[:networks].nil? + if invalid_network? + @invalid_network_message = "vous devez entrer des adresses ipv4 ou ipv6 valides" + return render :edit + end + + if @api_token.eternal? && networks.empty? + @invalid_network_message = "Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent." + @api_token.reload + return render :edit + end + + h[:authorized_networks] = networks end - if @api_token.eternal? && networks.empty? - flash[:alert] = "Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent." - return render :edit + if procedure_to_add.present? + to_add = current_administrateur + .procedure_ids + .intersection([procedure_to_add]) + + h[:allowed_procedure_ids] = + (Array.wrap(@api_token.allowed_procedure_ids) + to_add).uniq end - @api_token.update!(name:, authorized_networks: networks) + if params[:name].present? + h[:name] = name + end - flash[:notice] = "Le jeton d'API a été mis à jour." - redirect_to profil_path + @api_token.update!(h) + + render :edit + end + + def remove_procedure + procedure_id = params[:procedure_id].to_i + @api_token.allowed_procedure_ids = + @api_token.allowed_procedure_ids - [procedure_id] + @api_token.save! + + render turbo_stream: turbo_stream.remove("authorized_procedure_#{procedure_id}") end def destroy @@ -74,6 +101,14 @@ module Administrateurs EOF end + def libelle_id_procedures + current_administrateur + .procedures + .order(:libelle) + .pluck(:libelle, :id) + .map { |libelle, id| ["#{id} - #{libelle}", id] } + end + def all_params [:name, :access, :target, :targets, :networkFiltering, :networks, :lifetime, :customLifetime] .index_with { |param| params[param] } @@ -115,6 +150,10 @@ module Administrateurs params[:name] end + def procedure_to_add + params[:procedure_to_add]&.to_i + end + def write_access params[:access] == "read_write" end diff --git a/app/views/administrateurs/api_tokens/edit.html.haml b/app/views/administrateurs/api_tokens/edit.html.haml index 6efa775f5..1d4635e43 100644 --- a/app/views/administrateurs/api_tokens/edit.html.haml +++ b/app/views/administrateurs/api_tokens/edit.html.haml @@ -6,41 +6,76 @@ ["Jeton d’API : #{@api_token.name}"]] } .fr-container.fr-mt-2w - %h1 Modification du jeton d'API « #{@api_token.name} » - = form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f| - .fr-input-group - = f.label :name, class: 'fr-label' do - = t('name', scope: [:administrateurs, :api_tokens, :nom]) - %span.fr-hint-text= t('name-hint', scope: [:administrateurs, :api_tokens, :nom]) - = f.text_field :name, - class: 'fr-input width-33', - autocomplete: 'off', - autocapitalize: 'off', - autocorrect: 'off', - spellcheck: false, - required: true, - value: @api_token.name + %turbo-frame#tokenUpdate + %h1 Modification du jeton d'API « #{@api_token.name} » - .fr-input-group.fr-mb-4w{ - class: class_names('fr-input-group--error': @invalid_network) } - = f.label :name, class: 'fr-label' do - = @api_token.eternal? ? "Entrez au moins 1 réseau autorisé" : "Entrez les adresses ip autorisées" - %span.fr-hint-text adresses réseaux séparées par des espaces. ex: 176.31.79.200 192.168.33.0/24 2001:41d0:304:400::52f/128 - = f.text_field :networks, - class: class_names('fr-input': true, 'fr-input--error': @invalid_network), - autocomplete: 'off', - autocapitalize: 'off', - autocorrect: 'off', - spellcheck: false, - required: @api_token.eternal?, - value: @api_token.authorized_networks_for_ui.gsub(/,/, ' ') + = form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f| + .fr-input-group + = f.label :name, class: 'fr-label' do + = t('name', scope: [:administrateurs, :api_tokens, :nom]) + %span.fr-hint-text= t('name-hint', scope: [:administrateurs, :api_tokens, :nom]) + .flex + = f.text_field :name, + class: 'fr-input width-33', + autocomplete: 'off', + autocapitalize: 'off', + autocorrect: 'off', + spellcheck: false, + required: true, + value: @api_token.name - - if @invalid_network - %p.fr-error-text vous devez entrer des adresses ipv4 ou ipv6 valides + %button.fr-btn.fr-btn--secondary.fr-ml-1w Renommer - %ul.fr-btns-group.fr-btns-group--inline - %li - = f.button 'Modifier', type: :submit, class: "fr-btn fr-btn--primary" - %li - = link_to 'Revenir', profil_path, class: "fr-btn fr-btn--secondary" + = form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f| + .fr-input-group.fr-mb-4w{ + class: class_names('fr-input-group--error': @invalid_network_message.present?) } + = f.label :name, class: 'fr-label' do + = @api_token.eternal? ? "Entrez au moins 1 réseau autorisé" : "Entrez les adresses ip autorisées" + %span.fr-hint-text adresses réseaux séparées par des espaces. ex: 176.31.79.200 192.168.33.0/24 2001:41d0:304:400::52f/128 + .flex + = f.text_field :networks, + class: class_names('fr-input': true, 'fr-input--error': @invalid_network_message.present?), + autocomplete: 'off', + autocapitalize: 'off', + autocorrect: 'off', + spellcheck: false, + value: @api_token.authorized_networks_for_ui.gsub(/,/, ' ') + + %button.fr-btn.fr-btn--secondary.fr-ml-1w Modifier + + - if @invalid_network_message.present? + %p.fr-error-text= @invalid_network_message + + = form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f| + .fr-mb-4w + - if @api_token.full_access? + %p Votre jeton d'API a accès à toutes vos démarches. + = hidden_field_tag :procedure_to_add, '[]' + %button.fr-btn.fr-btn--secondary.fr-btn--sm Restreindre l'accès à certaines les démarches + - else + .fr-select-group + %label.fr-label{ for: 'procedure_to_add' } Ajouter des démarches autorisées + .flex + = f.select :value, + options_for_select(@libelle_id_procedures), + { include_blank: true }, + { class: 'fr-select width-33', + name: 'procedure_to_add'} + + %button.fr-btn.fr-btn--secondary.fr-ml-1w Ajouter + + %ul.fr-mb-4w + - @api_token.procedures.each do |procedure| + %li{ id: dom_id(procedure, :authorized) } + = procedure.libelle + = button_to 'Supprimer', + remove_procedure_admin_api_token_path(@api_token, procedure_id: procedure.id), + class: 'fr-btn fr-btn--tertiary-no-outline fr-btn--sm fr-btn--icon-left fr-icon-delete-line', + form_class: 'inline', + method: :delete, + form: { data: { turbo: 'true' } } + + %ul.fr-btns-group.fr-btns-group--inline + %li + = link_to 'Revenir', profil_path, class: "fr-btn fr-btn--secondary" diff --git a/config/routes.rb b/config/routes.rb index e6440634a..4ecc68874 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -744,6 +744,9 @@ Rails.application.routes.draw do end resources :api_tokens, only: [:create, :destroy, :edit, :update] do + member do + delete 'remove_procedure' + end collection do get :nom get :autorisations diff --git a/spec/controllers/administrateurs/api_tokens_controller_spec.rb b/spec/controllers/administrateurs/api_tokens_controller_spec.rb index b16321cc5..ae359aa2f 100644 --- a/spec/controllers/administrateurs/api_tokens_controller_spec.rb +++ b/spec/controllers/administrateurs/api_tokens_controller_spec.rb @@ -98,9 +98,10 @@ describe Administrateurs::APITokensController, type: :controller do describe 'update' do let(:token) { APIToken.generate(admin).first } - let(:params) { { name:, networks: } } + let(:params) { { name:, networks:, procedure_to_add: } } let(:name) { 'new name' } let(:networks) { '118.218.200.200' } + let(:procedure_to_add) { nil } subject { patch :update, params: params.merge(id: token.id) } @@ -119,9 +120,8 @@ describe Administrateurs::APITokensController, type: :controller do before { subject; token.reload } it 'does not update a token' do - expect(token.name).not_to eq('new name') - expect(assigns(:invalid_network)).to be true - expect(response).to render_template(:edit) + expect(token.authorized_networks).to be_blank + expect(assigns(:invalid_network_message)).to eq('vous devez entrer des adresses ipv4 ou ipv6 valides') end end @@ -135,10 +135,34 @@ describe Administrateurs::APITokensController, type: :controller do let(:networks) { '' } it 'does not update a token' do - expect(token.name).not_to eq('new name') - expect(flash[:alert]).to eq("Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent.") - expect(response).to render_template(:edit) + expect(token.authorized_networks).to eq([IPAddr.new('118.218.200.200')]) + expect(assigns(:invalid_network_message)).to eq("Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent.") end end + + context 'with a legitime procedure to add' do + let(:params) { { procedure_to_add: procedure.id } } + + before { subject; token.reload } + + it { expect(token.allowed_procedure_ids).to eq([procedure.id]) } + end + + context 'with a procedure to add not owned by the admin' do + let(:another_procedure) { create(:procedure, administrateurs: [create(:administrateur)]) } + let(:params) { { procedure_to_add: another_procedure.id } } + + before { subject; token.reload } + + it { expect(token.allowed_procedure_ids).to eq([]) } + end + + context 'with an empty procedure to add' do + let(:params) { { procedure_to_add: '' } } + + before { subject; token.reload } + + it { expect(token.allowed_procedure_ids).to eq([]) } + end end end