Compare commits
13 Commits
c3d3218bff
...
00e3003257
| Author | SHA1 | Date |
|---|---|---|
|
|
00e3003257 | |
|
|
f1b953d005 | |
|
|
4aadaa351a | |
|
|
fcb69f987f | |
|
|
d7677db885 | |
|
|
8eb5cf433d | |
|
|
fed351b433 | |
|
|
0a602fb52e | |
|
|
e87fdd32e4 | |
|
|
cfe89f58db | |
|
|
1d2debf364 | |
|
|
3271da59fa | |
|
|
d8df0bc1f4 |
|
|
@ -23,3 +23,7 @@
|
|||
/public/assets/
|
||||
/assets/vendor/
|
||||
###< symfony/asset-mapper ###
|
||||
|
||||
###> IntelliJ IDEA ###
|
||||
.idea/
|
||||
*.iml
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
- Les icones sont gérées via symfony UX (https://ux.symfony.com/icons)
|
||||
- Les icones sont prises en prioritées dans la bibliothèque bootstrap
|
||||
- Les icones n'éxistants pas dans cette bibliothèques seront prises en priorité dans fontawesome regular (pour une cohérence visuelle)
|
||||
- Sinon privilégier la bibliothèque ayant le visuel le plus proche
|
||||
- Sinon privilégier la bibliothèque ayant le visuel le plus proche
|
||||
|
||||
### Version 0.1 : (17/03/2025)
|
||||
- Contient la logique de login mot de passe avec une entité user (email et password seuelement)
|
||||
|
|
@ -19,5 +19,12 @@
|
|||
- Une base de template est gérée pour toutes les pages de l'application aya,t besoin de l'entête et du menu général
|
||||
- Une ébauche de page d'accueil est en cours
|
||||
|
||||
### Installation
|
||||
#### Choices.js
|
||||
```bash
|
||||
php bin/console importmap:require choices.js
|
||||
php bin/console importmap:require choices.js/public/assets/styles/choices.min.css
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ import './js/template.js';
|
|||
import './js/off_canvas.js';
|
||||
import './js/hoverable-collapse.js';
|
||||
import './js/cookies.js';
|
||||
|
||||
import 'choices.js';
|
||||
import 'choices.js/public/assets/styles/choices.min.css';
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"@symfony/ux-turbo": {
|
||||
"turbo-core": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"fetch": "eager"
|
||||
},
|
||||
"mercure-turbo-stream": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import {Controller} from '@hotwired/stimulus';
|
||||
import Choices from 'choices.js';
|
||||
/*
|
||||
* The following line makes this controller "lazy": it won't be downloaded until needed
|
||||
* See https://symfony.com/bundles/StimulusBundle/current/index.html#lazy-stimulus-controllers
|
||||
*/
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
rolesArray: Array,
|
||||
selectedRoleIds: Array,
|
||||
applicationsArray: Array,
|
||||
selectedApplicationIds: Array
|
||||
}
|
||||
// {value: 'choice1', label: 'Choice 1'},
|
||||
// {value: 'choice2', label: 'Choice 2'},
|
||||
// {value: 'choice3', label: 'Choice 3'},
|
||||
|
||||
roleSelect() {
|
||||
const element = document.getElementById('roles');
|
||||
if (element) {
|
||||
const choicesData = this.rolesArrayValue.map(role => ({
|
||||
value: role.id,
|
||||
label: role.name,
|
||||
selected: this.selectedRoleIdsValue.includes(role.id)
|
||||
}));
|
||||
|
||||
const choices = new Choices(element, {
|
||||
choices: choicesData,
|
||||
removeItemButton: true,
|
||||
placeholder: true,
|
||||
placeholderValue: 'Ajouter un ou plusieurs rôles'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
appSelect() {
|
||||
const element = document.getElementById('applications');
|
||||
if (element) {
|
||||
|
||||
const choicesData = this.applicationsArrayValue.map(app => ({
|
||||
value: app.id,
|
||||
label: app.name,
|
||||
customProperties: {icon: app.icon},
|
||||
selected: this.selectedApplicationIdsValue.includes(app.id)
|
||||
}));
|
||||
|
||||
const choices = new Choices(element, {
|
||||
choices: choicesData,
|
||||
removeItemButton: true,
|
||||
placeholder: true,
|
||||
placeholderValue: 'Ajouter une ou plusieurs applications',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.roleSelect();
|
||||
this.appSelect();
|
||||
|
||||
// Set choices after initialization
|
||||
// choices.setValue(choicesData);
|
||||
}
|
||||
|
||||
|
||||
// Add custom controller actions here
|
||||
// fooBar() { this.fooTarget.classList.toggle(this.bazClass) }
|
||||
|
||||
disconnect() {
|
||||
// Called anytime its element is disconnected from the DOM
|
||||
// (on page change, when it's removed from or moved in the DOM, etc.)
|
||||
|
||||
// Here you should remove all event listeners added in "connect()"
|
||||
// this.fooTarget.removeEventListener('click', this._fooBar)
|
||||
}
|
||||
}
|
||||
|
|
@ -2423,16 +2423,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpdoc-parser.git",
|
||||
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68"
|
||||
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
|
||||
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
|
||||
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2464,9 +2464,9 @@
|
|||
"description": "PHPDoc parser with support for nullable, intersection and generic types",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0"
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0"
|
||||
},
|
||||
"time": "2025-02-19T13:28:12+00:00"
|
||||
"time": "2025-07-13T07:04:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ security:
|
|||
property: email
|
||||
|
||||
role_hierarchy:
|
||||
ROLE_SUDALYS: ROLE_USER
|
||||
ROLE_ADMIN: ROLE_USER
|
||||
ROLE_SUDALYS_ADMIN: [ROLE_SUDALYS, ROLE_ALLOWED_TO_SWITCH, ROLE_ADMIN]
|
||||
ROLE_SUPER_ADMIN: [ROLE_ALLOWED_TO_SWITCH, ROLE_ADMIN]
|
||||
|
||||
|
||||
firewalls:
|
||||
|
|
|
|||
|
|
@ -35,4 +35,11 @@ return [
|
|||
'version' => '5.3.5',
|
||||
'type' => 'css',
|
||||
],
|
||||
'choices.js' => [
|
||||
'version' => '11.1.0',
|
||||
],
|
||||
'choices.js/public/assets/styles/choices.min.css' => [
|
||||
'version' => '11.1.0',
|
||||
'type' => 'css',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250724133531 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE user_organization_app (id SERIAL NOT NULL, applications_id INT DEFAULT NULL, organization_id INT DEFAULT NULL, users_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_BEF66DF129A0022 ON user_organization_app (applications_id)');
|
||||
$this->addSql('CREATE INDEX IDX_BEF66DF132C8A3DE ON user_organization_app (organization_id)');
|
||||
$this->addSql('CREATE INDEX IDX_BEF66DF167B3B43D ON user_organization_app (users_id)');
|
||||
$this->addSql('CREATE TABLE user_organization_roles (id SERIAL NOT NULL, role_id INT DEFAULT NULL, users_id INT DEFAULT NULL, organization_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_94FD2EFBD60322AC ON user_organization_roles (role_id)');
|
||||
$this->addSql('CREATE INDEX IDX_94FD2EFB67B3B43D ON user_organization_roles (users_id)');
|
||||
$this->addSql('CREATE INDEX IDX_94FD2EFB32C8A3DE ON user_organization_roles (organization_id)');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT FK_BEF66DF129A0022 FOREIGN KEY (applications_id) REFERENCES apps (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT FK_BEF66DF132C8A3DE FOREIGN KEY (organization_id) REFERENCES organizations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT FK_BEF66DF167B3B43D FOREIGN KEY (users_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT FK_94FD2EFBD60322AC FOREIGN KEY (role_id) REFERENCES roles (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT FK_94FD2EFB67B3B43D FOREIGN KEY (users_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT FK_94FD2EFB32C8A3DE FOREIGN KEY (organization_id) REFERENCES organizations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT FK_BEF66DF129A0022');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT FK_BEF66DF132C8A3DE');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT FK_BEF66DF167B3B43D');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT FK_94FD2EFBD60322AC');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT FK_94FD2EFB67B3B43D');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT FK_94FD2EFB32C8A3DE');
|
||||
$this->addSql('DROP TABLE user_organization_app');
|
||||
$this->addSql('DROP TABLE user_organization_roles');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250725065027 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP SEQUENCE user_organization_roles_id_seq CASCADE');
|
||||
$this->addSql('DROP SEQUENCE user_organization_app_id_seq CASCADE');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT fk_bef66df129a0022');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT fk_bef66df132c8a3de');
|
||||
$this->addSql('ALTER TABLE user_organization_app DROP CONSTRAINT fk_bef66df167b3b43d');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT fk_94fd2efb32c8a3de');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT fk_94fd2efb67b3b43d');
|
||||
$this->addSql('ALTER TABLE user_organization_roles DROP CONSTRAINT fk_94fd2efbd60322ac');
|
||||
$this->addSql('DROP TABLE user_organization_app');
|
||||
$this->addSql('DROP TABLE user_organization_roles');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('CREATE SEQUENCE user_organization_roles_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE SEQUENCE user_organization_app_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE user_organization_app (id SERIAL NOT NULL, applications_id INT DEFAULT NULL, organization_id INT DEFAULT NULL, users_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX idx_bef66df129a0022 ON user_organization_app (applications_id)');
|
||||
$this->addSql('CREATE INDEX idx_bef66df132c8a3de ON user_organization_app (organization_id)');
|
||||
$this->addSql('CREATE INDEX idx_bef66df167b3b43d ON user_organization_app (users_id)');
|
||||
$this->addSql('CREATE TABLE user_organization_roles (id SERIAL NOT NULL, role_id INT DEFAULT NULL, users_id INT DEFAULT NULL, organization_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX idx_94fd2efb32c8a3de ON user_organization_roles (organization_id)');
|
||||
$this->addSql('CREATE INDEX idx_94fd2efb67b3b43d ON user_organization_roles (users_id)');
|
||||
$this->addSql('CREATE INDEX idx_94fd2efbd60322ac ON user_organization_roles (role_id)');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT fk_bef66df129a0022 FOREIGN KEY (applications_id) REFERENCES apps (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT fk_bef66df132c8a3de FOREIGN KEY (organization_id) REFERENCES organizations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_app ADD CONSTRAINT fk_bef66df167b3b43d FOREIGN KEY (users_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT fk_94fd2efb32c8a3de FOREIGN KEY (organization_id) REFERENCES organizations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT fk_94fd2efb67b3b43d FOREIGN KEY (users_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_organization_roles ADD CONSTRAINT fk_94fd2efbd60322ac FOREIGN KEY (role_id) REFERENCES roles (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route(path: '/organization', name: 'organization_')]
|
||||
|
||||
class OrganizationController extends AbstractController
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Apps;
|
||||
use App\Entity\Roles;
|
||||
use App\Entity\User;
|
||||
use App\Form\UserForm;
|
||||
use App\Entity\UsersOrganizations;
|
||||
use App\Service\UserOrganizationService;
|
||||
use App\Service\UserService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Asset\Packages;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
|
@ -15,11 +19,13 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||
#[Route(path: '/user', name: 'user_')]
|
||||
class UserController extends AbstractController
|
||||
{
|
||||
private const NOT_FOUND = 'User not found';
|
||||
private const NOT_FOUND = 'Entity not found';
|
||||
private const ACCESS_DENIED = 'Access denied';
|
||||
|
||||
public function __construct(
|
||||
private readonly UserOrganizationService $userOrganizationService,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly UserService $userService)
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly UserService $userService)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -29,13 +35,17 @@ class UserController extends AbstractController
|
|||
#[Route('/', name: 'index', methods: ['GET'])]
|
||||
public function index(EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isGranted('ROLE_SUDALYS_ADMIN')) {
|
||||
$users = $entityManager->getRepository(User::class)->getAllActiveUsers();
|
||||
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
$usersByOrganization = $entityManager->getRepository(UsersOrganizations::class)->getActiveUsersGroupedByOrganization();
|
||||
|
||||
} else {
|
||||
$users = 'Not Super Admin';
|
||||
$userIdentifier = $this->getUser()->getUserIdentifier();
|
||||
$organizations = $this->entityManager->getRepository(UsersOrganizations::class)->findOrganizationsByUserEmailAndRoleName($userIdentifier, 'ADMIN');
|
||||
$usersByOrganization = $this->entityManager->getRepository(UsersOrganizations::class)
|
||||
->findActiveUsersByOrganizations($organizations);
|
||||
}
|
||||
return $this->render('user/index.html.twig', [
|
||||
'users' => $users,
|
||||
'usersByOrganization' => $usersByOrganization,
|
||||
'controller_name' => 'IndexController',
|
||||
]);
|
||||
}
|
||||
|
|
@ -43,11 +53,11 @@ class UserController extends AbstractController
|
|||
/**
|
||||
* GET /user/{id} - Show specific user (show/member)
|
||||
*/
|
||||
#[Route('/{id}', name: 'show', methods: ['GET'], requirements: ['id' => '\d+'])]
|
||||
#[Route('/{id}', name: 'show', requirements: ['id' => '\d+'], methods: ['GET'])]
|
||||
public function show(int $id, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if (!$this->isGranted('ROLE_SUDALYS_ADMIN')) {
|
||||
throw $this->createAccessDeniedException('Access denied');
|
||||
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
$user = $entityManager->getRepository(User::class)->find($id);
|
||||
|
|
@ -102,8 +112,8 @@ class UserController extends AbstractController
|
|||
public function edit(int $id, EntityManagerInterface $entityManager, Request $request): Response
|
||||
{
|
||||
//Handle access control
|
||||
if (!$this->isGranted('ROLE_SUDALYS_ADMIN')) {
|
||||
throw $this->createAccessDeniedException('Access denied');
|
||||
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
//Fetch user by ID and handle not found case
|
||||
|
|
@ -132,34 +142,65 @@ class UserController extends AbstractController
|
|||
]);
|
||||
}
|
||||
|
||||
//
|
||||
// /**
|
||||
// * DELETE /user/{id} - Delete user
|
||||
// */
|
||||
// #[Route('/{id}', name: 'delete', methods: ['DELETE'], requirements: ['id' => '\d+'])]
|
||||
// public function delete(int $id, EntityManagerInterface $entityManager): Response
|
||||
// {
|
||||
// if (!$this->isGranted('ROLE_SUDALYS_ADMIN')) {
|
||||
// throw $this->createAccessDeniedException('Access denied');
|
||||
// }
|
||||
//
|
||||
// $user = $entityManager->getRepository(User::class)->find($id);
|
||||
// if (!$user) {
|
||||
// throw $this->createNotFoundException(self::NOT_FOUND));
|
||||
// }
|
||||
//
|
||||
// // Handle user deletion logic
|
||||
// $entityManager->remove($user);
|
||||
// $entityManager->flush();
|
||||
//
|
||||
// return $this->redirectToRoute('user_index');
|
||||
// }
|
||||
|
||||
|
||||
#[Route('/deactivate/{id}', name: 'deactivate', methods: ['GET'])]
|
||||
public function userDeactivate(Request $request, EntityManagerInterface $entityManager): Response
|
||||
/**
|
||||
* DELETE /user/{id} - Delete user
|
||||
*/
|
||||
#[Route('/{id}', name: 'setDelete', requirements: ['id' => '\d+'], methods: ['POST'])]
|
||||
public function setDelete(int $id, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isGranted('ROLE_SUDALYS_ADMIN')) {
|
||||
//This method is used to set a user as deleted without actually removing them from the database.
|
||||
|
||||
//Handle access control
|
||||
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
||||
}
|
||||
//Fetch user by ID and handle not found case
|
||||
$user = $entityManager->getRepository(User::class)->find($id);
|
||||
if (!$user) {
|
||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
}
|
||||
|
||||
// Handle user deletion logic
|
||||
$user->setIsDeleted(true);
|
||||
$entityManager->persist($user);
|
||||
$entityManager->flush();
|
||||
|
||||
return $this->redirectToRoute('user_index');
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /user/{id} - Delete user
|
||||
*/
|
||||
#[Route('/{id}', name: 'delete', requirements: ['id' => '\d+'], methods: ['DELETE'])]
|
||||
public function delete(int $id, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
$user = $entityManager->getRepository(User::class)->find($id);
|
||||
if (!$user) {
|
||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
}
|
||||
|
||||
// Handle user deletion logic
|
||||
$entityManager->remove($user);
|
||||
$entityManager->flush();
|
||||
|
||||
return $this->redirectToRoute('user_index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GET /user/deactivate/{id} - Deactivate user
|
||||
* This method is used to deactivate a user without deleting them.
|
||||
* The user will still exist in the database but will not be active.
|
||||
*/
|
||||
#[Route('/deactivate/{id}', name: 'deactivate', methods: ['GET'])]
|
||||
public function deactivate(Request $request, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
|
||||
$userId = $request->attributes->get('id');
|
||||
$user = $entityManager->getRepository(User::class)->find($userId);
|
||||
if (!$user) {
|
||||
|
|
@ -173,6 +214,102 @@ class UserController extends AbstractController
|
|||
return new Response('Unauthorized', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update organization user /userOrganizationEdit/{id} - Update organization user
|
||||
* The id parameter is the ID of the UsersOrganizations entity.
|
||||
*/
|
||||
#[Route('/userOrganizationEdit/{id}', name: 'organization_edit', requirements: ['id' => '\d+'], methods: ['GET', 'POST'])]
|
||||
public function userOrganizationEdit(int $id, Request $request, EntityManagerInterface $entityManager, Packages $packages): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
||||
|
||||
// get the UsersOrganizations entity by ID and handle not found case same for user
|
||||
$userOrganization = $entityManager->getRepository(UsersOrganizations::class)->find($id);
|
||||
if (!$userOrganization) {
|
||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
}
|
||||
$user = $userOrganization->getUsers() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
$organization = $userOrganization->getOrganization() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
|
||||
//Handle the POST
|
||||
if ($request->isMethod('POST')) {
|
||||
// Get the selected roles and apps from the request
|
||||
$selectedRoles = $request->request->all('roles');
|
||||
$selectedApps = $request->request->all('applications');
|
||||
|
||||
// order in important here. apps MUST be before roles
|
||||
$this->userOrganizationService->setUserOrganizationsApps($user, $organization,$selectedApps);
|
||||
$this->userOrganizationService->setUserOrganizations($user, $organization, $selectedRoles);
|
||||
|
||||
|
||||
|
||||
// Redirect to the user profile after successful update
|
||||
return $this->redirectToRoute('user_show', ['id' => $user->getId()]);
|
||||
}
|
||||
|
||||
//Overwrite the userOrganization with the userOrganizationsService for data consistency
|
||||
// NULL pointer won't occur here because a valid UsersOrganizations entity was fetched above
|
||||
$userOrganization = $this->userOrganizationService->getUserOrganizations($userOrganization->getUsers(), $userOrganization->getOrganization()->getId());
|
||||
|
||||
// Fetch all roles and apps
|
||||
$roles = $entityManager->getRepository(Roles::class)->findAll();
|
||||
$apps = $entityManager->getRepository(Apps::class)->findAll();
|
||||
if (!$roles) {
|
||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
}
|
||||
if (!$apps) {
|
||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
}
|
||||
|
||||
// Map roles and apps to arrays for rendering
|
||||
$rolesArray = array_map(static function ($role) {
|
||||
return [
|
||||
'id' => $role->getId(),
|
||||
'name' => $role->getName()
|
||||
];
|
||||
}, $roles);
|
||||
$appsArray = [];
|
||||
foreach ($apps as $app) {
|
||||
$appsArray[] = [
|
||||
'id' => $app->getId(),
|
||||
'name' => $app->getName(),
|
||||
'icon' => $packages->getUrl($app->getLogoUrl()),
|
||||
];
|
||||
}
|
||||
|
||||
// Map selected roles and apps to their IDs for the form
|
||||
$selectedRoles = array_map(static function ($role) {
|
||||
return $role->getId();
|
||||
}, $userOrganization[0]["roles"]);
|
||||
$selectedApps = array_map(static function ($app) {
|
||||
return $app->getId();
|
||||
}, $userOrganization[0]["apps"]);
|
||||
|
||||
return $this->render('user/organization/edit.html.twig', [
|
||||
'userOrganization' => $userOrganization,
|
||||
'user' => $user,
|
||||
'rolesArray' => $rolesArray,
|
||||
'selectedRoleIds' => $selectedRoles,
|
||||
'appsArray' => $appsArray,
|
||||
'selectedAppIds' => $selectedApps,]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /user/deactivateOrganization/{id} - Deactivate user
|
||||
* This method is used to deactivate a user without deleting them in an organization.
|
||||
* The user will still exist in the database but will not be active.
|
||||
*/
|
||||
#[Route('/organizationDeactivate/{id}', name: 'organization_deactivate', requirements: ['id' => '\d+'], methods: ['GET'])]
|
||||
public function deactivateUserOrganization(int $id, Request $request, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
$userOrganization = $entityManager->getRepository(UsersOrganizations::class)->find($id) ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
$user = $userOrganization->getUsers() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
$organization = $userOrganization->getOrganization() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
||||
|
||||
$this->userOrganizationService->deactivateAllUserRoles($user, $organization);
|
||||
|
||||
return $this->redirectToRoute('user_show', ['id' => $user->getId()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ class UsersOrganizations
|
|||
public function __construct()
|
||||
{
|
||||
$this->apps = new ArrayCollection();
|
||||
$this->isActive = true; // Default value for isActive
|
||||
$this->createdAt = new \DateTimeImmutable(); // Set createdAt to current
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
class UserOrganization extends AbstractType
|
||||
{
|
||||
|
||||
public function buildForm($builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('admin' , CheckboxType::class, [
|
||||
'label' => 'Admin',
|
||||
'required' => false])
|
||||
->add('application' , ChoiceType::class, [
|
||||
'label' => 'Application',
|
||||
'choices' => [
|
||||
'Application 1' => 'app1',
|
||||
'Application 2' => 'app2',
|
||||
'Application 3' => 'app3',
|
||||
]]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\UserOrganizationRoles;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<UserOrganizationRoles>
|
||||
*/
|
||||
class UserOrganizationRolesRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, UserOrganizationRoles::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return UserOrganizationRoles[] Returns an array of UserOrganizationRoles objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('u')
|
||||
// ->andWhere('u.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('u.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?UserOrganizationRoles
|
||||
// {
|
||||
// return $this->createQueryBuilder('u')
|
||||
// ->andWhere('u.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
|
|
@ -33,13 +33,14 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
|
|||
$this->getEntityManager()->flush();
|
||||
}
|
||||
|
||||
// Rewrote this function to return less data
|
||||
public function getAllActiveUsers(): array{
|
||||
$queryBuilder = $this->createQueryBuilder('u')
|
||||
->select('u.surname', 'u.email', 'u.id', 'u.isActive', 'u.name', 'u.pictureUrl')
|
||||
// Remove this line: ->from(User::class, 'u')
|
||||
->where('u.isActive = :isActive') // Also fixed the concatenation
|
||||
->where('u.isActive = :isActive')
|
||||
->orderBy('u.surname', 'ASC');
|
||||
$queryBuilder->setParameter('isActive', true);
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,16 @@
|
|||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Entity\UsersOrganizations;
|
||||
use App\Entity\Organizations;
|
||||
use App\Entity\Roles;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<UsersOrganizations>
|
||||
*/
|
||||
class UsersOrganizationsRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
|
|
@ -14,6 +19,12 @@ class UsersOrganizationsRepository extends ServiceEntityRepository
|
|||
parent::__construct($registry, UsersOrganizations::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all distinct active organizations for a given user ID.
|
||||
*
|
||||
* @param int $userId
|
||||
* @return UsersOrganizations[]
|
||||
*/
|
||||
public function findAllDistinctOrganizationsByUserId(int $userId): array
|
||||
{
|
||||
return $this->createQueryBuilder('uo')
|
||||
|
|
@ -28,4 +39,157 @@ class UsersOrganizationsRepository extends ServiceEntityRepository
|
|||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all organizations where a user (by email) has a specific role.
|
||||
*
|
||||
* @param string $userEmail
|
||||
* @param string $roleName
|
||||
* @return Organizations[]
|
||||
*/
|
||||
public function findOrganizationsByUserEmailAndRoleName(string $userEmail, string $roleName): array
|
||||
{
|
||||
$results = $this->createQueryBuilder('uo')
|
||||
->innerJoin('uo.users', 'u')
|
||||
->innerJoin('uo.organization', 'o')
|
||||
->innerJoin('uo.role', 'r')
|
||||
->where('u.email = :email')
|
||||
->andWhere('r.name = :roleName')
|
||||
->andWhere('uo.isActive = :isActive')
|
||||
->setParameter('email', $userEmail)
|
||||
->setParameter('roleName', $roleName)
|
||||
->setParameter('isActive', true)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
return array_map(fn($uo) => $uo->getOrganization(), $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active users grouped by organization.
|
||||
* Users with no organization are grouped under 'autre'.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getActiveUsersGroupedByOrganization(): array
|
||||
{
|
||||
$users = $this->getEntityManager()->getRepository(User::class)->getAllActiveUsers();
|
||||
$userOrgs = $this->getAllActiveUserOrganizationLinks();
|
||||
|
||||
$userToOrgs = $this->mapUserToOrganizations($userOrgs);
|
||||
|
||||
$orgs = [];
|
||||
foreach ($users as $user) {
|
||||
$userId = $user['id'];
|
||||
if (isset($userToOrgs[$userId])) {
|
||||
foreach ($userToOrgs[$userId] as $orgInfo) {
|
||||
$orgId = $orgInfo['organization_id'];
|
||||
if (!isset($orgs[$orgId])) {
|
||||
$orgs[$orgId] = [
|
||||
'organization_id' => $orgId,
|
||||
'organization_name' => $orgInfo['organization_name'],
|
||||
'users' => [],
|
||||
];
|
||||
}
|
||||
$orgs[$orgId]['users'][$userId] = $user;
|
||||
}
|
||||
} else {
|
||||
if (!isset($orgs['autre'])) {
|
||||
$orgs['autre'] = [
|
||||
'organization_id' => null,
|
||||
'organization_name' => 'autre',
|
||||
'users' => [],
|
||||
];
|
||||
}
|
||||
$orgs['autre']['users'][$userId] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert users arrays to indexed arrays
|
||||
foreach ($orgs as &$org) {
|
||||
$org['users'] = array_values($org['users']);
|
||||
}
|
||||
|
||||
return array_values($orgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active users for each organization in the given array.
|
||||
*
|
||||
* @param Organizations[] $organizations
|
||||
* @return array
|
||||
*/
|
||||
public function findActiveUsersByOrganizations(array $organizations): array
|
||||
{
|
||||
if (empty($organizations)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$userOrgs = $this->getAllActiveUserOrganizationLinks($organizations);
|
||||
|
||||
$usersByOrg = [];
|
||||
foreach ($userOrgs as $uo) {
|
||||
$org = $uo->getOrganization();
|
||||
$orgId = $org->getId();
|
||||
if (!isset($usersByOrg[$orgId])) {
|
||||
$usersByOrg[$orgId] = [
|
||||
'organization_id' => $orgId,
|
||||
'organization_name' => $org->getName(),
|
||||
'users' => [],
|
||||
];
|
||||
}
|
||||
$userId = $uo->getUsers()->getId();
|
||||
$usersByOrg[$orgId]['users'][$userId] = $uo->getUsers();
|
||||
}
|
||||
|
||||
// Convert users arrays to indexed arrays
|
||||
foreach ($usersByOrg as &$org) {
|
||||
$org['users'] = array_values($org['users']);
|
||||
}
|
||||
|
||||
return array_values($usersByOrg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Get all active UsersOrganizations links, optionally filtered by organizations.
|
||||
*
|
||||
* @param Organizations[]|null $organizations
|
||||
* @return UsersOrganizations[]
|
||||
*/
|
||||
private function getAllActiveUserOrganizationLinks(array $organizations = null): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('uo')
|
||||
->innerJoin('uo.organization', 'o')
|
||||
->innerJoin('uo.users', 'u')
|
||||
->where('uo.isActive = :isActive')
|
||||
->setParameter('isActive', true);
|
||||
|
||||
if (!empty($organizations)) {
|
||||
$qb->andWhere('o IN (:organizations)')
|
||||
->setParameter('organizations', $organizations);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Map userId to their organizations (id and name), avoiding duplicates.
|
||||
*
|
||||
* @param UsersOrganizations[] $userOrgs
|
||||
* @return array
|
||||
*/
|
||||
private function mapUserToOrganizations(array $userOrgs): array
|
||||
{
|
||||
$userToOrgs = [];
|
||||
foreach ($userOrgs as $uo) {
|
||||
$userId = $uo->getUsers()->getId();
|
||||
$org = $uo->getOrganization();
|
||||
$orgId = $org->getId();
|
||||
$orgName = $org->getName();
|
||||
$userToOrgs[$userId][$orgId] = [
|
||||
'organization_id' => $orgId,
|
||||
'organization_name' => $orgName,
|
||||
];
|
||||
}
|
||||
return $userToOrgs;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,37 @@
|
|||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Apps;
|
||||
use App\Entity\Organizations;
|
||||
use App\Entity\Roles;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UsersOrganizations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* Service pour la gestion des organisations d'utilisateurs.
|
||||
* Fournit des méthodes pour récupérer, modifier et désactiver les rôles et applications d'un utilisateur dans une organisation.
|
||||
*/
|
||||
readonly class UserOrganizationService
|
||||
{
|
||||
public function __construct(private readonly EntityManagerInterface $entityManager) {}
|
||||
/**
|
||||
* Constructeur du service UserOrganizationService.
|
||||
*
|
||||
* @param EntityManagerInterface $entityManager Le gestionnaire d'entités Doctrine
|
||||
*/
|
||||
public function __construct(private readonly EntityManagerInterface $entityManager)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all organizations the given user belongs to,
|
||||
* including the unique roles and apps the user has in each organization.
|
||||
* Récupère toutes les organisations auxquelles appartient l'utilisateur donné,
|
||||
* incluant les rôles et applications uniques de l'utilisateur dans chaque organisation.
|
||||
*
|
||||
* @param User $user The user whose organizations are being fetched
|
||||
* @return array<array{organization:object, roles:Roles[], apps:object[]}>
|
||||
* @param User $user L'utilisateur concerné
|
||||
* @param int|null $organizationsId ID optionnel pour filtrer par organisation
|
||||
* @return array<array{organization:object, roles:Roles[], apps:object[], uoId:int}>
|
||||
*/
|
||||
public function getUserOrganizations(User $user): array
|
||||
public function getUserOrganizations(User $user, int $organizationsId = null): array
|
||||
{
|
||||
$userOrganizations = $this->entityManager
|
||||
->getRepository(UsersOrganizations::class)
|
||||
|
|
@ -28,39 +42,77 @@ readonly class UserOrganizationService
|
|||
foreach ($userOrganizations as $uo) {
|
||||
$orgId = $uo->getOrganization()->getId();
|
||||
|
||||
// Initialize the organization entry if it doesn't exist
|
||||
$organizations[$orgId] = $organizations[$orgId] ?? $this->createEmptyOrganizationBucket($uo);
|
||||
// Si $organizationsId est fourni, ignorer les autres organisations
|
||||
if ($organizationsId !== null && $orgId !== $organizationsId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Aggregate roles & apps
|
||||
// Initialiser l'entrée de l'organisation si elle n'existe pas
|
||||
$organizations[$orgId] = $organizations[$orgId] ?? $this->createEmptyOrganizationBucket($uo);
|
||||
$organizations[$orgId]['uoId'] = $uo->getId();
|
||||
|
||||
// Agréger les rôles et applications
|
||||
$this->addRole($organizations[$orgId]['roles'], $uo->getRole());
|
||||
$this->addApps($organizations[$orgId]['apps'], $uo->getApps());
|
||||
}
|
||||
|
||||
// Ordonner les rôles : Super Admin, Admin, puis les autres
|
||||
foreach ($organizations as &$org) {
|
||||
$org['roles'] = $this->sortRoles($org['roles']);
|
||||
}
|
||||
unset($org);
|
||||
|
||||
$this->normalizeAppsIndexes($organizations);
|
||||
|
||||
return array_values($organizations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the initial array structure for a fresh organization entry.
|
||||
* Trie les rôles pour que Super Admin et Admin soient en premier, puis les autres.
|
||||
*
|
||||
* @param UsersOrganizations $link
|
||||
* @param Roles[] $roles
|
||||
* @return Roles[]
|
||||
*/
|
||||
private function sortRoles(array $roles): array
|
||||
{
|
||||
usort($roles, function ($a, $b) {
|
||||
$priority = [
|
||||
'SUPER_ADMIN' => 0,
|
||||
'ADMIN' => 1
|
||||
];
|
||||
$aName = strtoupper($a->getName());
|
||||
$bName = strtoupper($b->getName());
|
||||
$aPriority = $priority[$aName] ?? 2;
|
||||
$bPriority = $priority[$bName] ?? 2;
|
||||
if ($aPriority === $bPriority) {
|
||||
return strcmp($aName, $bName);
|
||||
}
|
||||
return $aPriority <=> $bPriority;
|
||||
});
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la structure de données pour une organisation.
|
||||
*
|
||||
* @param UsersOrganizations $link Lien utilisateur-organisation
|
||||
* @return array{organization:object, roles:Roles[], apps:array<int,object>}
|
||||
*/
|
||||
private function createEmptyOrganizationBucket(UsersOrganizations $link): array
|
||||
{
|
||||
return [
|
||||
'organization' => $link->getOrganization(),
|
||||
'roles' => [],
|
||||
'apps' => [],
|
||||
'roles' => [],
|
||||
'apps' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Role entity to the roles array only if it is not already present (by ID).
|
||||
* Ajoute un rôle à la liste si non déjà présent (par ID).
|
||||
*
|
||||
* @param Roles[] &$roles
|
||||
* @param Roles|null $role
|
||||
* @param Roles[] &$roles Liste des rôles
|
||||
* @param Roles|null $role Rôle à ajouter
|
||||
* @return void
|
||||
*/
|
||||
private function addRole(array &$roles, ?Roles $role): void
|
||||
{
|
||||
|
|
@ -76,10 +128,11 @@ readonly class UserOrganizationService
|
|||
}
|
||||
|
||||
/**
|
||||
* Merge one or many apps into the apps map, keeping only one entry per id.
|
||||
* Fusionne une ou plusieurs applications dans le tableau associatif, une entrée par ID.
|
||||
*
|
||||
* @param array<int,object> &$apps
|
||||
* @param iterable $appsToAdd Collection returned by $userOrganizations->getApps()
|
||||
* @param array<int,object> &$apps Tableau des applications
|
||||
* @param iterable $appsToAdd Applications à ajouter
|
||||
* @return void
|
||||
*/
|
||||
private function addApps(array &$apps, iterable $appsToAdd): void
|
||||
{
|
||||
|
|
@ -89,10 +142,10 @@ readonly class UserOrganizationService
|
|||
}
|
||||
|
||||
/**
|
||||
* Convert apps from associative maps (keyed by id) to plain indexed arrays,
|
||||
* so the final output is clean JSON-able.
|
||||
* Normalise le tableau des applications pour le rendre indexé (JSON-friendly).
|
||||
*
|
||||
* @param array &$organizations
|
||||
* @param array &$organizations Tableau des organisations
|
||||
* @return void
|
||||
*/
|
||||
private function normalizeAppsIndexes(array &$organizations): void
|
||||
{
|
||||
|
|
@ -100,4 +153,186 @@ readonly class UserOrganizationService
|
|||
$org['apps'] = array_values($org['apps']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit les rôles d'un utilisateur dans une organisation, en s'assurant que le rôle USER est toujours présent.
|
||||
* Désactive tous les rôles si USER n'est pas sélectionné.
|
||||
*
|
||||
* @param User $user L'utilisateur
|
||||
* @param Organizations $organization L'organisation
|
||||
* @param array $selectedRoles Tableau des IDs de rôles sélectionnés
|
||||
* @return void
|
||||
* @throws \RuntimeException Si le rôle USER n'est pas trouvé
|
||||
*/
|
||||
public function setUserOrganizations(User $user, Organizations $organization, array $selectedRoles): void
|
||||
{
|
||||
$repo = $this->entityManager->getRepository(UsersOrganizations::class);
|
||||
$roleRepo = $this->entityManager->getRepository(Roles::class);
|
||||
$userRole = $roleRepo->findOneBy(['name' => 'USER']);
|
||||
if (!$userRole) {
|
||||
throw new \RuntimeException('USER role not found');
|
||||
}
|
||||
if (!in_array($userRole->getId(), $selectedRoles)) {
|
||||
$this->deactivateAllUserRoles($user, $organization);
|
||||
return;
|
||||
}
|
||||
$currentUserOrgs = $repo->findBy([
|
||||
'users' => $user,
|
||||
'organization' => $organization
|
||||
]);
|
||||
$currentRolesMap = $this->mapUserOrgRoles($currentUserOrgs);
|
||||
$selectedRoles = $this->ensureUserRolePresent($selectedRoles, $userRole->getId());
|
||||
$this->addOrUpdateRoles($selectedRoles, $currentRolesMap, $roleRepo, $user, $organization);
|
||||
$this->deactivateUnselectedRoles($currentRolesMap);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les applications associées à l'utilisateur dans une organisation.
|
||||
*
|
||||
* @param User $user L'utilisateur
|
||||
* @param Organizations $organization L'organisation
|
||||
* @param array $selectedApps Tableau des IDs d'applications sélectionnées
|
||||
* @return void
|
||||
*/
|
||||
public function setUserOrganizationsApps(User $user, Organizations $organization, array $selectedApps): void
|
||||
{
|
||||
$roleUser = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'USER']);
|
||||
$uoEntity = $this->entityManager
|
||||
->getRepository(UsersOrganizations::class)
|
||||
->findOneBy(['users' => $user, 'organization' => $organization, 'role' => $roleUser]);
|
||||
if (!$uoEntity) {
|
||||
return;
|
||||
}
|
||||
$this->removeUnselectedApps($uoEntity, $selectedApps);
|
||||
$this->addSelectedApps($uoEntity, $selectedApps);
|
||||
$this->entityManager->persist($uoEntity);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une map des rôles actuels de l'utilisateur dans l'organisation.
|
||||
* @param array $currentUserOrgs
|
||||
* @return array
|
||||
*/
|
||||
private function mapUserOrgRoles(array $currentUserOrgs): array
|
||||
{
|
||||
$map = [];
|
||||
foreach ($currentUserOrgs as $uo) {
|
||||
$map[$uo->getRole()->getId()] = $uo;
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* S'assure que le rôle USER est présent dans la sélection si nécessaire.
|
||||
* @param array $selectedRoles
|
||||
* @param int $userRoleId
|
||||
* @return array
|
||||
*/
|
||||
private function ensureUserRolePresent(array $selectedRoles, int $userRoleId): array
|
||||
{
|
||||
$hasNonUserRole = false;
|
||||
foreach ($selectedRoles as $roleId) {
|
||||
if ($roleId !== $userRoleId) {
|
||||
$hasNonUserRole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hasNonUserRole && !in_array($userRoleId, $selectedRoles)) {
|
||||
$selectedRoles[] = $userRoleId;
|
||||
}
|
||||
return $selectedRoles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute ou réactive les rôles sélectionnés pour l'utilisateur dans l'organisation.
|
||||
* @param array $selectedRoles
|
||||
* @param array $currentRolesMap
|
||||
* @param $roleRepo
|
||||
* @param User $user
|
||||
* @param Organizations $organization
|
||||
*/
|
||||
private function addOrUpdateRoles(array $selectedRoles, array &$currentRolesMap, $roleRepo, User $user, Organizations $organization): void
|
||||
{
|
||||
foreach ($selectedRoles as $roleId) {
|
||||
if (!isset($currentRolesMap[$roleId])) {
|
||||
$roleEntity = $roleRepo->find($roleId);
|
||||
if ($roleEntity) {
|
||||
$newUserOrganization = new UsersOrganizations();
|
||||
$newUserOrganization->setUsers($user);
|
||||
$newUserOrganization->setRole($roleEntity);
|
||||
$newUserOrganization->setOrganization($organization);
|
||||
$newUserOrganization->setIsActive(true);
|
||||
$this->entityManager->persist($newUserOrganization);
|
||||
}
|
||||
} else {
|
||||
$currentRolesMap[$roleId]->setIsActive(true);
|
||||
$this->entityManager->persist($currentRolesMap[$roleId]);
|
||||
}
|
||||
unset($currentRolesMap[$roleId]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Désactive les rôles non sélectionnés pour l'utilisateur dans l'organisation.
|
||||
* @param array $currentRolesMap
|
||||
*/
|
||||
private function deactivateUnselectedRoles(array $currentRolesMap): void
|
||||
{
|
||||
foreach ($currentRolesMap as $uo) {
|
||||
$uo->setIsActive(false);
|
||||
$this->entityManager->persist($uo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retire les applications non sélectionnées de l'utilisateur dans l'organisation.
|
||||
* @param UsersOrganizations $uoEntity
|
||||
* @param array $selectedApps
|
||||
*/
|
||||
private function removeUnselectedApps(UsersOrganizations $uoEntity, array $selectedApps): void
|
||||
{
|
||||
foreach ($uoEntity->getApps()->toArray() as $existingApp) {
|
||||
if (!in_array($existingApp->getId(), $selectedApps)) {
|
||||
$uoEntity->removeApp($existingApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute les applications sélectionnées à l'utilisateur dans l'organisation.
|
||||
* @param UsersOrganizations $uoEntity
|
||||
* @param array $selectedApps
|
||||
*/
|
||||
private function addSelectedApps(UsersOrganizations $uoEntity, array $selectedApps): void
|
||||
{
|
||||
foreach ($selectedApps as $appId) {
|
||||
$appEntity = $this->entityManager->getRepository(Apps::class)->find($appId);
|
||||
if ($appEntity && !$uoEntity->getApps()->contains($appEntity)) {
|
||||
$uoEntity->addApp($appEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Désactive tous les rôles d'un utilisateur dans une organisation.
|
||||
*
|
||||
* @param User $user L'utilisateur
|
||||
* @param Organizations $organization L'organisation
|
||||
* @return void
|
||||
*/
|
||||
public function deactivateAllUserRoles(User $user, Organizations $organization): void
|
||||
{
|
||||
$repo = $this->entityManager->getRepository(UsersOrganizations::class);
|
||||
$userOrganizations = $repo->findBy([
|
||||
'users' => $user,
|
||||
'organization' => $organization
|
||||
]);
|
||||
foreach ($userOrganizations as $uo) {
|
||||
$uo->setIsActive(false);
|
||||
$this->entityManager->persist($uo);
|
||||
}
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,16 @@
|
|||
namespace App\Service;
|
||||
|
||||
|
||||
use App\Entity\Organizations;
|
||||
use App\Entity\Roles;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UsersOrganizations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class UserService
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
public function __construct(private readonly EntityManagerInterface $entityManager)
|
||||
{
|
||||
// Constructor logic if needed
|
||||
}
|
||||
|
|
@ -26,4 +32,31 @@ class UserService
|
|||
|
||||
return $randomPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user is an admin in the given organization.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $organizationId
|
||||
* @return bool
|
||||
*/
|
||||
public function isUserAdminInOrganization(int $userId, int $organizationId): bool
|
||||
{
|
||||
$user = $this->entityManager->getRepository(User::class)->find($userId);
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
$organization = $this->entityManager->getRepository(Organizations::class)->find($organizationId);
|
||||
if (!$organization) {
|
||||
return false;
|
||||
}
|
||||
$roleAdmin = $this->entityManager->getRepository(Roles::class)->findBy(['name'=> 'ADMIN']);
|
||||
|
||||
// Check if the user is an admin in the organization
|
||||
return empty($this->entityManager->getRepository(UsersOrganizations::class)->findBy([
|
||||
'userId' => $userId,
|
||||
'organizationId' => $organizationId,
|
||||
'roleId' => $roleAdmin[0]->getId()]));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,7 +291,8 @@
|
|||
"assets/bootstrap.js",
|
||||
"assets/controllers.json",
|
||||
"assets/controllers/csrf_protection_controller.js",
|
||||
"assets/controllers/hello_controller.js"
|
||||
"assets/controllers/hello_controller.js",
|
||||
"assets/controllers/igg_controller.js"
|
||||
]
|
||||
},
|
||||
"symfony/translation": {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
</li>
|
||||
{# if user is Super Admin#}
|
||||
{% if is_granted('ROLE_SUDALYS_ADMIN') %}
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('user_index') }}">
|
||||
<i class="icon-grid menu-icon">{{ ux_icon('bi:menu-up', {height: '15px', width: '15px'}) }}</i>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="w-100 h-100 p-5 m-auto">
|
||||
<h1>Modifier l'utilisateur</h1>
|
||||
{{ form_start(form, {'action': path('user_edit', {'id': user.id}), 'method': 'PUT'}) }}
|
||||
{{ form_widget(form) }}
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
{{ form_end(form) }}
|
||||
<div class=" col-md-10 m-auto p-5">
|
||||
<div class="card">
|
||||
<div class="card-title shadow-sm p-3 d-flex justify-content-between align-items-center">
|
||||
<h2>Modifier l'utilisateur</h2>
|
||||
<a href="{{ path('user_delete', {'id': user.id}) }}" class="btn btn-danger">Supprimer</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
{{ form_start(form, {'action': path('user_edit', {'id': user.id}), 'method': 'PUT'}) }}
|
||||
{{ form_widget(form) }}
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -3,46 +3,50 @@
|
|||
{% block title %}User Profile{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="w-100 h-100 p-5 m-auto ">
|
||||
<div class="w-100 h-100 p-5 m-auto" data-controller="user">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Gestion Utilisateurs</h1>
|
||||
<a href="{{ path('user_new') }}" class="btn btn-primary">Ajouter un utilisateur</a>
|
||||
</div>
|
||||
|
||||
|
||||
<table class="table align-middle shadow">
|
||||
<thead class="table-light shadow-sm">
|
||||
<tr>
|
||||
<th>Picture</th>
|
||||
<th>Surname</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Visualiser</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ user.surname }}</td>
|
||||
<td>{{ user.name }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<a href="{{ path('user_show', {'id': user.id}) }}" class="p-3 align-middle">
|
||||
<i class="icon-grid menu-icon color-primary">
|
||||
{{ ux_icon('fa6-regular:eye', {height: '30px', width: '30px'}) }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if users|length == 0 %}
|
||||
{% for org in usersByOrganization %}
|
||||
<h2 class="mt-5 mb-3">{{ org.organization_name|title }}</h2>
|
||||
<table class="table align-middle shadow">
|
||||
<thead class="table-light shadow-sm">
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">Aucun utilisateur trouvé.</td>
|
||||
<th>Picture</th>
|
||||
<th>Surname</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Visualiser</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in org.users %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if user.pictureUrl %}
|
||||
<img src="{{ asset(user.pictureUrl) }}" alt="User profile pic" class="rounded-circle" style="width:40px; height:40px;">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.surname }}</td>
|
||||
<td>{{ user.name }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<a href="{{ path('user_show', {'id': user.id}) }}" class="p-3 align-middle">
|
||||
<i class="icon-grid menu-icon color-primary">
|
||||
{{ ux_icon('fa6-regular:eye', {height: '30px', width: '30px'}) }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if org.users|length == 0 %}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">Aucun utilisateur trouvé.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -1,16 +1,22 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Ajouter un utilisateur{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="w-100 h-100 p-5 m-auto">
|
||||
<h1>Ajouter un utilisateur</h1>
|
||||
<form method="post" action="{{ path('user_new') }}" enctype="multipart/form-data">
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
{{ form_end(form) }}
|
||||
</form>
|
||||
<div class=" col-md-10 m-auto p-5">
|
||||
<div class="card">
|
||||
<div class="card-title shadow-sm p-3 d-flex justify-content-between align-items-center">
|
||||
<h1>Ajouter un utilisateur</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="{{ path('user_new') }}" enctype="multipart/form-data">
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
{{ form_end(form) }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="col-md-10 m-auto p-5">
|
||||
<div class="card">
|
||||
{% for uo in userOrganization %}
|
||||
<div class="card-title shadow-sm p-3 d-flex justify-content-between align-items-center">
|
||||
<h3>
|
||||
Modification de : <b>{{ user.name|capitalize }} {{ user.surname|capitalize }} </b> chez
|
||||
<b> {{ uo.organization.name }}</b>
|
||||
</h3>
|
||||
<a href="{{ path('user_organization_deactivate', {'id': uo.uoId}) }}" class="btn btn-danger">Supprimer</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ path('user_organization_edit', {'id' : uo.uoId}) }}"
|
||||
data-controller="user"
|
||||
data-user-roles-array-value="{{ rolesArray|json_encode }}"
|
||||
data-user-selected-role-ids-value="{{ selectedRoleIds|json_encode }}"
|
||||
data-user-applications-array-value="{{ appsArray|json_encode }}"
|
||||
data-user-selected-application-ids-value="{{ selectedAppIds|json_encode }}">
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-group mb-3">
|
||||
<label for="roles">Roles</label>
|
||||
<select class="choices" data-type="select-multiple" id="roles" name="roles[]" multiple>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<label for="applications">Applications</label>
|
||||
<select class="choices" data-type="select-multiple" id="applications" name="applications[]"
|
||||
multiple>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# bouton d'envoie du formulaire#}
|
||||
|
||||
<button type="submit" class="btn btn-primary">Modifier</button>
|
||||
{# <a href="{{ path('user_organization_list') }}" class="btn btn-secondary">Annuler</a>#}
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -1,15 +1,21 @@
|
|||
{% block body %}
|
||||
|
||||
|
||||
<div class="card col-4 mt-3 me-3 user-org-card" style="cursor:pointer;" data-bs-toggle="collapse"
|
||||
data-bs-target="#org-details-{{ organization.id }}" aria-expanded="false"
|
||||
aria-controls="org-details-{{ organization.id }}">
|
||||
|
||||
<div class="card-title shadow-sm p-3 d-flex ">
|
||||
<h2 class=" pe-2">{{ organization.name|capitalize }}</h2>
|
||||
<i class="pt-2" id="arrow-icon-{{ organization.id }}">
|
||||
{{ ux_icon('fa6-regular:circle-down', {height: '25px', width: '25px'}) }}
|
||||
</i>
|
||||
<div class="card col-4 mt-3 me-3" >
|
||||
<div class="card-title shadow-sm p-3 d-flex justify-content-between align-items-center">
|
||||
{# Affichage du nom de l'organisation et de l'icône de flèche #}
|
||||
<div class="d-flex user-org-card"
|
||||
style="cursor:pointer;" data-bs-toggle="collapse"
|
||||
data-bs-target="#org-details-{{ organization.id }}" aria-expanded="false"
|
||||
aria-controls="org-details-{{ organization.id }}">
|
||||
<h2 class=" pe-2">{{ organization.name|capitalize }}</h2>
|
||||
<i class="pt-2" id="arrow-icon-{{ organization.id }}">
|
||||
{{ ux_icon('fa6-regular:circle-down', {height: '25px', width: '25px'}) }}
|
||||
</i>
|
||||
</div>
|
||||
{% if is_granted("ROLE_ADMIN") %}
|
||||
<a href="{{ path('user_organization_edit', {'id': uoId}) }}" class="btn btn-primary" >Modifier</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# Information principale sur l'utilisateur dans l'organisation#}
|
||||
|
|
@ -18,12 +24,12 @@
|
|||
<p><b>Role:</b>
|
||||
{% if roles|length > 0 %}
|
||||
{% set firstRole = roles[0] %}
|
||||
{% if firstRole.name == "ROLE ADMIN SUDALYS" or firstRole.name == "ROLE ADMIN" %}
|
||||
<span class="badge bg-danger">{{ firstRole.name|capitalize }}</span>
|
||||
{% elseif firstRole.name == "ROLE USER" %}
|
||||
{% if firstRole.name == "SUPER ADMIN" %}
|
||||
<span class="badge bg-danger">Super Administrateur</span>
|
||||
{% elseif firstRole.name == "ADMIN" %}
|
||||
<span class="badge bg-danger">Administrateur</span>
|
||||
{% else %}
|
||||
<span class="badge bg-primary">{{ firstRole.name|capitalize }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">{{ firstRole.name|capitalize }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
Aucun rôle
|
||||
|
|
@ -34,10 +40,7 @@
|
|||
<div class="d-flex">
|
||||
{% if apps is not empty %}
|
||||
{% for app in apps %}
|
||||
<div class="col">
|
||||
{{ app.name }}
|
||||
<img src="{{ asset(app.logoUrl) }}" alt="Logo {{ app.name }}" class="img-fluid ms-2" style="height: 20px; width: 20px;">
|
||||
</div>
|
||||
<img src="{{ asset(app.logoUrl) }}" alt="Logo {{ app.name }}" class="img-fluid ms-2" style="height: 30px; width: 30px;">
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
Aucune application associée.
|
||||
|
|
@ -50,12 +53,12 @@
|
|||
{% if roles|length > 1 %}
|
||||
<p><b>Autres rôles:</b>
|
||||
{% for role in roles|slice(1) %}
|
||||
{% if role.name == "ROLE ADMIN SUDALYS" or role.name == "ROLE ADMIN" %}
|
||||
<span class="badge bg-danger">{{ role.name|capitalize }}</span>
|
||||
{% elseif role.name == "ROLE USER" %}
|
||||
<span class="badge bg-primary">{{ role.name|capitalize }}</span>
|
||||
{% if role.name == "SUPER ADMIN"%}
|
||||
<span class="badge bg-danger">Super Administrateur</span>
|
||||
{% elseif role.name == "ADMIN" %}
|
||||
<span class="badge bg-danger">Administrateur</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">{{ role.name|capitalize }}</span>
|
||||
<span class="badge bg-primary">{{ role.name|capitalize }}</span>
|
||||
{% endif %}
|
||||
{% if not loop.last %} - {% endif %}
|
||||
{% endfor %}
|
||||
|
|
@ -80,6 +83,7 @@
|
|||
arrowEl.innerHTML = `{{ ux_icon('fa6-regular:circle-down', {height: '25px', width: '25px'})|e('js') }}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
</div>
|
||||
{% else %}
|
||||
{% for organization in userOrganizations %}
|
||||
{% include 'elements/userOrganizationInformation.html.twig'
|
||||
with {'organization': organization.organization, 'roles': organization.roles, 'apps': organization.apps} %}
|
||||
{% include 'user/organization/userOrganizationInformation.html.twig'
|
||||
with {'organization': organization.organization, 'roles': organization.roles, 'apps': organization.apps, 'uoId': organization.uoId} %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue