Merge pull request #9952 from demarches-simplifiees/better_api_token_edition
Admin: permet d'éditer la liste des démarches accessibles par un jeton d'api
This commit is contained in:
commit
e95e86faae
4 changed files with 157 additions and 56 deletions
|
@ -5,7 +5,7 @@ module Administrateurs
|
||||||
include ActionView::RecordIdentifier
|
include ActionView::RecordIdentifier
|
||||||
|
|
||||||
before_action :authenticate_administrateur!
|
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
|
def nom
|
||||||
@name = name
|
@name = name
|
||||||
|
@ -13,11 +13,7 @@ module Administrateurs
|
||||||
|
|
||||||
def autorisations
|
def autorisations
|
||||||
@name = name
|
@name = name
|
||||||
@libelle_id_procedures = current_administrateur
|
@libelle_id_procedures = libelle_id_procedures
|
||||||
.procedures
|
|
||||||
.order(:libelle)
|
|
||||||
.pluck(:libelle, :id)
|
|
||||||
.map { |libelle, id| ["#{id} - #{libelle}", id] }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def securite
|
def securite
|
||||||
|
@ -37,23 +33,54 @@ module Administrateurs
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@libelle_id_procedures = libelle_id_procedures
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if invalid_network?
|
@libelle_id_procedures = libelle_id_procedures
|
||||||
@invalid_network = true
|
|
||||||
return render :edit
|
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
|
end
|
||||||
|
|
||||||
if @api_token.eternal? && networks.empty?
|
if procedure_to_add.present?
|
||||||
flash[:alert] = "Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent."
|
to_add = current_administrateur
|
||||||
return render :edit
|
.procedure_ids
|
||||||
|
.intersection([procedure_to_add])
|
||||||
|
|
||||||
|
h[:allowed_procedure_ids] =
|
||||||
|
(Array.wrap(@api_token.allowed_procedure_ids) + to_add).uniq
|
||||||
end
|
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."
|
@api_token.update!(h)
|
||||||
redirect_to profil_path
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -74,6 +101,14 @@ module Administrateurs
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def libelle_id_procedures
|
||||||
|
current_administrateur
|
||||||
|
.procedures
|
||||||
|
.order(:libelle)
|
||||||
|
.pluck(:libelle, :id)
|
||||||
|
.map { |libelle, id| ["#{id} - #{libelle}", id] }
|
||||||
|
end
|
||||||
|
|
||||||
def all_params
|
def all_params
|
||||||
[:name, :access, :target, :targets, :networkFiltering, :networks, :lifetime, :customLifetime]
|
[:name, :access, :target, :targets, :networkFiltering, :networks, :lifetime, :customLifetime]
|
||||||
.index_with { |param| params[param] }
|
.index_with { |param| params[param] }
|
||||||
|
@ -115,6 +150,10 @@ module Administrateurs
|
||||||
params[:name]
|
params[:name]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def procedure_to_add
|
||||||
|
params[:procedure_to_add]&.to_i
|
||||||
|
end
|
||||||
|
|
||||||
def write_access
|
def write_access
|
||||||
params[:access] == "read_write"
|
params[:access] == "read_write"
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,41 +6,76 @@
|
||||||
["Jeton d’API : #{@api_token.name}"]] }
|
["Jeton d’API : #{@api_token.name}"]] }
|
||||||
|
|
||||||
.fr-container.fr-mt-2w
|
.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|
|
%turbo-frame#tokenUpdate
|
||||||
.fr-input-group
|
%h1 Modification du jeton d'API « #{@api_token.name} »
|
||||||
= 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
|
|
||||||
|
|
||||||
.fr-input-group.fr-mb-4w{
|
= form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f|
|
||||||
class: class_names('fr-input-group--error': @invalid_network) }
|
.fr-input-group
|
||||||
= f.label :name, class: 'fr-label' do
|
= f.label :name, class: 'fr-label' do
|
||||||
= @api_token.eternal? ? "Entrez au moins 1 réseau autorisé" : "Entrez les adresses ip autorisées"
|
= t('name', scope: [:administrateurs, :api_tokens, :nom])
|
||||||
%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
|
%span.fr-hint-text= t('name-hint', scope: [:administrateurs, :api_tokens, :nom])
|
||||||
= f.text_field :networks,
|
.flex
|
||||||
class: class_names('fr-input': true, 'fr-input--error': @invalid_network),
|
= f.text_field :name,
|
||||||
autocomplete: 'off',
|
class: 'fr-input width-33',
|
||||||
autocapitalize: 'off',
|
autocomplete: 'off',
|
||||||
autocorrect: 'off',
|
autocapitalize: 'off',
|
||||||
spellcheck: false,
|
autocorrect: 'off',
|
||||||
required: @api_token.eternal?,
|
spellcheck: false,
|
||||||
value: @api_token.authorized_networks_for_ui.gsub(/,/, ' ')
|
required: true,
|
||||||
|
value: @api_token.name
|
||||||
|
|
||||||
- if @invalid_network
|
%button.fr-btn.fr-btn--secondary.fr-ml-1w Renommer
|
||||||
%p.fr-error-text vous devez entrer des adresses ipv4 ou ipv6 valides
|
|
||||||
|
|
||||||
%ul.fr-btns-group.fr-btns-group--inline
|
= form_with url: admin_api_token_path(@api_token), method: :patch, html: { class: 'fr-mt-2w' } do |f|
|
||||||
%li
|
.fr-input-group.fr-mb-4w{
|
||||||
= f.button 'Modifier', type: :submit, class: "fr-btn fr-btn--primary"
|
class: class_names('fr-input-group--error': @invalid_network_message.present?) }
|
||||||
%li
|
= f.label :name, class: 'fr-label' do
|
||||||
= link_to 'Revenir', profil_path, class: "fr-btn fr-btn--secondary"
|
= @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"
|
||||||
|
|
|
@ -744,6 +744,9 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :api_tokens, only: [:create, :destroy, :edit, :update] do
|
resources :api_tokens, only: [:create, :destroy, :edit, :update] do
|
||||||
|
member do
|
||||||
|
delete 'remove_procedure'
|
||||||
|
end
|
||||||
collection do
|
collection do
|
||||||
get :nom
|
get :nom
|
||||||
get :autorisations
|
get :autorisations
|
||||||
|
|
|
@ -98,9 +98,10 @@ describe Administrateurs::APITokensController, type: :controller do
|
||||||
|
|
||||||
describe 'update' do
|
describe 'update' do
|
||||||
let(:token) { APIToken.generate(admin).first }
|
let(:token) { APIToken.generate(admin).first }
|
||||||
let(:params) { { name:, networks: } }
|
let(:params) { { name:, networks:, procedure_to_add: } }
|
||||||
let(:name) { 'new name' }
|
let(:name) { 'new name' }
|
||||||
let(:networks) { '118.218.200.200' }
|
let(:networks) { '118.218.200.200' }
|
||||||
|
let(:procedure_to_add) { nil }
|
||||||
|
|
||||||
subject { patch :update, params: params.merge(id: token.id) }
|
subject { patch :update, params: params.merge(id: token.id) }
|
||||||
|
|
||||||
|
@ -119,9 +120,8 @@ describe Administrateurs::APITokensController, type: :controller do
|
||||||
before { subject; token.reload }
|
before { subject; token.reload }
|
||||||
|
|
||||||
it 'does not update a token' do
|
it 'does not update a token' do
|
||||||
expect(token.name).not_to eq('new name')
|
expect(token.authorized_networks).to be_blank
|
||||||
expect(assigns(:invalid_network)).to be true
|
expect(assigns(:invalid_network_message)).to eq('vous devez entrer des adresses ipv4 ou ipv6 valides')
|
||||||
expect(response).to render_template(:edit)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -135,10 +135,34 @@ describe Administrateurs::APITokensController, type: :controller do
|
||||||
let(:networks) { '' }
|
let(:networks) { '' }
|
||||||
|
|
||||||
it 'does not update a token' do
|
it 'does not update a token' do
|
||||||
expect(token.name).not_to eq('new name')
|
expect(token.authorized_networks).to eq([IPAddr.new('118.218.200.200')])
|
||||||
expect(flash[:alert]).to eq("Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent.")
|
expect(assigns(:invalid_network_message)).to eq("Vous ne pouvez pas supprimer les restrictions d'accès à l'API d'un jeton permanent.")
|
||||||
expect(response).to render_template(:edit)
|
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue