gestion droit d'access au application pour les compagnies

This commit is contained in:
Charles 2025-10-22 11:27:44 +02:00
parent 2b9b030d9a
commit 016c415c11
3 changed files with 172 additions and 36 deletions

View File

@ -1,40 +1,110 @@
import { Controller } from '@hotwired/stimulus'
import {Controller} from '@hotwired/stimulus'
import Quill from 'quill'
// controllers/application_controller.js
export default class extends Controller {
static targets = ['hidden']
static values = {
application: String,
organization: String,
}
static targets = ['hidden', 'submitBtn']
connect() {
// Map each editor to its toolbar and hidden field
this.editors = [
{
editorSelector: '#editor-description',
toolbarSelector: '#toolbar-description',
hiddenTarget: this.hiddenTargets[0],
},
{
editorSelector: '#editor-descriptionSmall',
toolbarSelector: '#toolbar-descriptionSmall',
hiddenTarget: this.hiddenTargets[1],
},
]
this.editors.forEach(({ editorSelector, toolbarSelector, hiddenTarget }) => {
const quill = new Quill(editorSelector, {
modules: {
toolbar: toolbarSelector, // HTML toolbar container
if (document.querySelector('#editor-description')) {
this.editors = [
{
editorSelector: '#editor-description',
toolbarSelector: '#toolbar-description',
hiddenTarget: this.hiddenTargets[0],
},
theme: 'snow', // include quill.snow.css
placeholder: 'Écrivez votre texte...',
})
{
editorSelector: '#editor-descriptionSmall',
toolbarSelector: '#toolbar-descriptionSmall',
hiddenTarget: this.hiddenTargets[1],
},
]
this.editors.forEach(({editorSelector, toolbarSelector, hiddenTarget}) => {
const quill = new Quill(editorSelector, {
modules: {
toolbar: toolbarSelector,
},
theme: 'snow',
placeholder: 'Écrivez votre texte...',
})
quill.on('text-change', () => {
hiddenTarget.value = quill.root.innerHTML
})
// Keep hidden field in sync with editor HTML
quill.on('text-change', () => {
hiddenTarget.value = quill.root.innerHTML
})
}
}
// Ensure initial value sync in case user submits without changes
hiddenTarget.value = quill.root.innerHTML
handleAuthorizeSubmit(event) {
event.preventDefault();
const originalText = this.submitBtnTarget.textContent;
if (!confirm(`Vous vous apprêtez à donner l'accès à ${this.organizationValue} pour ${this.applicationValue}. Êtesvous sûr(e) ?`)) {
return;
}
this.submitBtnTarget.textContent = 'En cours...';
this.submitBtnTarget.disabled = true;
fetch(event.target.action, {
method: 'POST',
body: new FormData(event.target)
})
.then(response => {
if (response.ok) {
this.submitBtnTarget.textContent = 'Autorisé ✓';
this.submitBtnTarget.classList.replace('btn-secondary', 'btn-success');
} else {
this.submitBtnTarget.textContent = originalText;
this.submitBtnTarget.disabled = false;
alert('Erreur lors de l\'action');
}
})
.catch(error => {
this.submitBtnTarget.textContent = originalText;
this.submitBtnTarget.disabled = false;
alert('Erreur lors de l\'action');
});
}
handleRemoveSubmit(event) {
event.preventDefault();
const originalText = this.submitBtnTarget.textContent;
if (!confirm(`Vous vous apprêtez à retirer l'accès à ${this.applicationValue} pour ${this.organizationValue}. Êtesvous sûr(e) ?`)) {
return;
}
this.submitBtnTarget.textContent = 'En cours...';
this.submitBtnTarget.disabled = true;
fetch(event.target.action, {
method: 'POST',
body: new FormData(event.target)
})
.then(response => {
if (response.ok) {
this.submitBtnTarget.textContent = 'Retiré ✓';
this.submitBtnTarget.classList.replace('btn-secondary', 'btn-danger');
} else {
this.submitBtnTarget.textContent = originalText;
this.submitBtnTarget.disabled = false;
alert('Erreur lors de l\'action');
}
})
.catch(error => {
this.submitBtnTarget.textContent = originalText;
this.submitBtnTarget.disabled = false;
alert('Erreur lors de l\'action');
});
}
}

View File

@ -3,6 +3,7 @@
namespace App\Controller;
use App\Entity\Apps;
use App\Entity\Organizations;
use App\Service\ActionService;
use App\Service\UserService;
use Doctrine\ORM\EntityManagerInterface;
@ -64,4 +65,39 @@ class ApplicationController extends AbstractController
}
#[Route(path: '/authorize/{id}', name: 'authorize', methods: ['POST'])]
public function authorize(int $id, Request $request)
{
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$application = $this->entityManager->getRepository(Apps::class)->find($id);
if (!$application) {
throw $this->createNotFoundException("L'application n'existe pas.");
}
$orgId = $request->get('organizationId');
$organization = $this->entityManager->getRepository(Organizations::Class)->find($orgId);
$application->addOrganization($organization);
$this->actionService->createAction("Authorization d'accès", $actingUser, $organization, $application->getName());
return new Response('', Response::HTTP_OK);
}
#[Route(path: '/remove/{id}', name: 'remove', methods: ['POST'])]
public function remove(int $id, Request $request)
{
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$application = $this->entityManager->getRepository(Apps::class)->find($id);
if (!$application) {
throw $this->createNotFoundException("L'application n'existe pas.");
}
$orgId = $request->get('organizationId');
$organization = $this->entityManager->getRepository(Organizations::Class)->find($orgId);
$application->removeOrganization($organization);
$this->actionService->createAction("Authorization retirer", $actingUser, $organization, $application->getName());
return new Response('', Response::HTTP_OK);
}
}

View File

@ -2,23 +2,53 @@
<div class="card ">
<div class="card-header d-flex gap-2">
<img class="rounded-circle " style="width:50px; height:50px;" src="{{ asset(application.entity.logoUrl) }}" alt="Logo application">
<img class="rounded-circle " style="width:50px; height:50px;" src="{{ asset(application.entity.logoUrl) }}"
alt="Logo application">
<div class="card-title">
<h1>{{ application.entity.name }}</h1>
</div>
</div>
<div class="card-body d-flex flex-column align-items-center">
<p class="card-text">{{ application.entity.descriptionSmall|raw }}</p>
{% if application.hasAccess %}
<div >
<a href="http://{{ application.entity.subDomain }}.solutions-easy.moi" class="btn btn-primary me-2">Y
accéder</a>
<a href="#" class="btn btn-secondary">Gérer l'application</a>
</div>
{% if application.hasAccess %}
{% if is_granted("ROLE_SUPER_ADMIN") %}
<form method="POST"
action="{{ path('application_remove', {'id': application.entity.id}) }}"
data-controller="application"
data-application-application-value="{{ application.entity.name }}"
data-application-organization-value="{{ organization.name|capitalize }}"
data-action="submit->application#handleRemoveSubmit"
style="display: inline-block;">
<input type="hidden" name="organizationId" value="{{ organization.id }}">
<button class="btn btn-secondary" type="submit" data-application-target="submitBtn">
Retirer l'accès
</button>
</form>
{% else %}
<div>
<a href="http://{{ application.entity.subDomain }}.solutions-easy.moi"
class="btn btn-primary me-2">Y accéder</a>
<a href="#" class="btn btn-secondary">Gérer l'application</a>
</div>
{% endif %}
{% else %}
<a href="#" class="btn btn-primary">Demander l'accès</a>
{#TODO: page d'accès#}
{% if is_granted("ROLE_SUPER_ADMIN") %}
<form method="POST"
action="{{ path('application_authorize', {'id': application.entity.id}) }}"
data-controller="application"
data-application-application-value="{{ application.entity.name }}"
data-application-organization-value="{{ organization.name|capitalize }}"
data-action="submit->application#handleAuthorizeSubmit"
style="display: inline-block;">
<input type="hidden" name="organizationId" value="{{ organization.id }}">
<button class="btn btn-secondary" type="submit" data-application-target="submitBtn">
Autoriser l'accès
</button>
</form>
{% else %}
<a href="#" class="btn btn-primary">Demander l'accès</a>
{% endif %}
{% endif %}
</div>
</div>