feature(api): setup autorizations
This commit is contained in:
parent
1d7b6a6a54
commit
8a9e5754a1
6 changed files with 198 additions and 2 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
101
app/javascript/controllers/api_token_autorisation_controller.ts
Normal file
101
app/javascript/controllers/api_token_autorisation_controller.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
70
app/views/api_tokens/autorisations.html.haml
Normal file
70
app/views/api_tokens/autorisations.html.haml
Normal 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"
|
12
config/locales/views/api_tokens.en.yml
Normal file
12
config/locales/views/api_tokens.en.yml
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue