feature(api): setup autorizations

This commit is contained in:
simon lehericey 2024-01-17 11:07:48 +01:00
parent 1d7b6a6a54
commit 8a9e5754a1
6 changed files with 198 additions and 2 deletions

View file

@ -6,6 +6,15 @@ class APITokensController < ApplicationController
@name = params[:name] @name = params[:name]
end end
def autorisations
@name = params[:name]
@libelle_id_procedures = current_administrateur
.procedures
.order(:libelle)
.pluck(:libelle, :id)
.map { |libelle, id| ["#{id} - #{libelle}", id] }
end
def create def create
@api_token, @packed_token = APIToken.generate(current_administrateur) @api_token, @packed_token = APIToken.generate(current_administrateur)

View file

@ -0,0 +1,101 @@
import { ApplicationController } from './application_controller';
export class ApiTokenAutorisationController extends ApplicationController {
static targets = [
'procedures',
'procedureSelect',
'procedureSelectGroup',
'continueButton'
];
declare readonly continueButtonTarget: HTMLButtonElement;
declare readonly procedureSelectTarget: HTMLSelectElement;
declare readonly procedureSelectGroupTarget: HTMLElement;
declare readonly proceduresTarget: HTMLElement;
connect() {
const urlSearchParams = new URLSearchParams(window.location.search);
const targetIds = urlSearchParams.getAll('targets[]');
const customTargets = urlSearchParams.get('target') == 'custom';
this.setupProceduresTarget(targetIds);
if (customTargets && targetIds.length > 0) {
this.showProcedureSelectGroup();
}
this.setContinueButtonState();
}
setupProceduresTarget(targetIds: string[]) {
const options = Array.from(this.procedureSelectTarget.options);
targetIds
.map((id) => options.find((x) => x.value == id))
.forEach((option) => option && this.addProcedureToSelect(option));
}
addProcedure(e: Event) {
e.preventDefault();
const selectedOption = this.procedureSelectTarget.selectedOptions[0];
this.addProcedureToSelect(selectedOption);
this.setContinueButtonState();
}
addProcedureToSelect(option: HTMLOptionElement) {
const template = [
`<li class='flex align-center'>`,
option.text,
"<button class='fr-btn fr-icon-delete-line fr-btn--tertiary-no-outline fr-ml-1w' data-action='click->api-token-autorisation#deleteProcedure'></button>",
`<input type='hidden' name='[targets][]' value='${option.value}' />`,
`</li>`
].join('');
this.proceduresTarget.insertAdjacentHTML('beforeend', template);
}
deleteProcedure(e: Event) {
e.preventDefault();
const target = e.target as HTMLElement;
target.closest('li')?.remove();
this.setContinueButtonState();
}
showProcedureSelectGroup() {
this.procedureSelectGroupTarget.classList.remove('hidden');
this.setContinueButtonState();
}
hideProcedureSelectGroup() {
this.procedureSelectGroupTarget.classList.add('hidden');
this.setContinueButtonState();
}
setContinueButtonState() {
if (this.targetDefined() && this.accessDefined()) {
this.continueButtonTarget.disabled = false;
} else {
this.continueButtonTarget.disabled = true;
}
}
targetDefined() {
if (this.element.querySelectorAll("[value='all']:checked").length > 0) {
return true;
}
if (
this.element.querySelectorAll("[value='custom']:checked").length > 0 &&
this.proceduresTarget.children.length > 0
) {
return true;
}
return false;
}
accessDefined() {
return this.element.querySelectorAll("[name='access']:checked").length == 1;
}
}

View file

@ -0,0 +1,70 @@
- content_for :title, "Privilèges du jeton « #{@name} »"
= render partial: 'administrateurs/breadcrumbs',
locals: { steps: [['Tableau de bord', tableau_de_bord_helper_path],
[t('users.profil.show.profile'), profil_path],
[t('api_tokens.nom.new_token')]] }
.fr-container.fr-mt-2w
%h1 Privilèges du jeton « #{@name} »
= form_with url: securite_api_tokens_path,
method: :get,
data: { controller: 'api-token-autorisation' } do |f|
= render Dsfr::RadioButtonListComponent.new(form: f,
target: :target,
buttons: [ { label: 'certaines de mes démarches',
value: :custom,
checked: params[:target] == 'custom',
data: { 'action': 'click->api-token-autorisation#showProcedureSelectGroup' } },
{ label: 'toutes mes démarches',
value: :all,
hint: 'présentes et futures',
checked: params[:target] == 'all',
data: { 'action': 'click->api-token-autorisation#hideProcedureSelectGroup' } }]) do
Ce jeton accède à
.fr-mb-4w.hidden{ 'data-api-token-autorisation-target': 'procedureSelectGroup' }
.fr-select-group
%label.fr-label{ for: 'procedureSelect' } Sélectionner les démarches autorisées
.flex
= f.select :value,
options_for_select(@libelle_id_procedures),
{ include_blank: true },
{ id: 'procedureSelect',
class: 'fr-select width-33',
name: 'procedureSelect',
data: { 'api-token-autorisation-target': 'procedureSelect' } }
%button.fr-btn.fr-btn--secondary.fr-ml-1w{
'data-action': 'click->api-token-autorisation#addProcedure' } Ajouter
%style
ul:empty { padding: 0; }
ul:empty:before { content: "aucune démarche sélectionnée"; }
%ul{ 'data-api-token-autorisation-target': 'procedures' }
%div{ 'data-action': 'click->api-token-autorisation#setContinueButtonState' }
= render Dsfr::RadioButtonListComponent.new(form: f,
target: :access,
buttons: [ { label: 'de lire uniquement',
value: :read,
checked: params[:access] == 'read',
hint: 'récupérer des dossiers, des pièces-jointes' },
{ label: 'de lire et dʼécrire',
value: :read_write,
checked: params[:access] == 'read_write',
hint: 'changer le statut de dossier, écrire des messages' }]) do
Ce jeton permet
= f.hidden_field :name, value: @name
%ul.fr-btns-group.fr-btns-group--inline
%li
= f.button type: :submit,
class: "fr-btn fr-btn--primary",
disabled: true,
'data-api-token-autorisation-target': 'continueButton' do
= t('.continue')
%li
= link_to t('.cancel'), nom_api_tokens_path(name: @name), class: "fr-btn fr-btn--secondary"

View file

@ -0,0 +1,12 @@
---
en:
api_tokens:
nom:
new_token: New token creation
name: name of the token
name-hint: 'examples: orus prod, presta'
continue: continue
cancel: back
autorisations:
cancel: back
continue: continue

View file

@ -5,5 +5,8 @@ fr:
new_token: Création d'un nouveau jeton new_token: Création d'un nouveau jeton
name: Nom du jeton name: Nom du jeton
name-hint: 'exemples: prod orus, test presta' name-hint: 'exemples: prod orus, test presta'
continue: continuer continue: Continuer
cancel: retour cancel: Retour
autorisations:
cancel: Retour
continue: Continuer

View file

@ -211,6 +211,7 @@ Rails.application.routes.draw do
resources :api_tokens, only: [:create, :destroy] do resources :api_tokens, only: [:create, :destroy] do
collection do collection do
get :nom get :nom
get :autorisations
end end
end end