Compare commits
No commits in common. "307e615fb37ed604e68c01fa764663dc0a497170" and "1008d636a654f14ae2433df4ac3ea49e3b9dfe00" have entirely different histories.
307e615fb3
...
1008d636a6
|
|
@ -9,7 +9,6 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import './styles/app.css';
|
import './styles/app.css';
|
||||||
import './styles/navbar.css';
|
import './styles/navbar.css';
|
||||||
import './styles/sidebar.css';
|
import './styles/sidebar.css';
|
||||||
import './styles/choices.css'
|
|
||||||
|
|
||||||
import 'bootstrap';
|
import 'bootstrap';
|
||||||
import './js/template.js';
|
import './js/template.js';
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,77 @@
|
||||||
import { Controller } from '@hotwired/stimulus';
|
import {Controller} from '@hotwired/stimulus';
|
||||||
import Choices from 'choices.js';
|
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 {
|
export default class extends Controller {
|
||||||
static values = {
|
static values = {
|
||||||
rolesArray: Array,
|
rolesArray: Array,
|
||||||
selectedRoleIds: Array,
|
selectedRoleIds: Array,
|
||||||
|
applicationsArray: Array,
|
||||||
|
selectedApplicationIds: Array
|
||||||
}
|
}
|
||||||
|
// {value: 'choice1', label: 'Choice 1'},
|
||||||
static targets = ["select"];
|
// {value: 'choice2', label: 'Choice 2'},
|
||||||
|
// {value: 'choice3', label: 'Choice 3'},
|
||||||
connect() {
|
|
||||||
this.roleSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
roleSelect() {
|
roleSelect() {
|
||||||
if (this.hasSelectTarget) {
|
const element = document.getElementById('roles');
|
||||||
|
if (element) {
|
||||||
const choicesData = this.rolesArrayValue.map(role => ({
|
const choicesData = this.rolesArrayValue.map(role => ({
|
||||||
value: role.id,
|
value: role.id,
|
||||||
label: role.name,
|
label: role.name,
|
||||||
selected: this.selectedRoleIdsValue.includes(role.id)
|
selected: this.selectedRoleIdsValue.includes(role.id)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
new Choices(this.selectTarget, {
|
const choices = new Choices(element, {
|
||||||
choices: choicesData,
|
choices: choicesData,
|
||||||
removeItemButton: true,
|
removeItemButton: true,
|
||||||
placeholder: true,
|
placeholder: true,
|
||||||
placeholderValue: 'Ajouter un ou plusieurs rôles',
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M11 17h2l.3-1.5q.3-.125.563-.262t.537-.338l1.45.45l1-1.7l-1.15-1q.05-.35.05-.65t-.05-.65l1.15-1l-1-1.7l-1.45.45q-.275-.2-.537-.338T13.3 8.5L13 7h-2l-.3 1.5q-.3.125-.562.263T9.6 9.1l-1.45-.45l-1 1.7l1.15 1q-.05.35-.05.65t.05.65l-1.15 1l1 1.7l1.45-.45q.275.2.538.338t.562.262zm1-3q-.825 0-1.412-.587T10 12t.588-1.412T12 10t1.413.588T14 12t-.587 1.413T12 14m-7 7q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h14q.825 0 1.413.588T21 5v14q0 .825-.587 1.413T19 21zm0-2h14V5H5zM5 5v14z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 577 B |
|
|
@ -128,8 +128,4 @@ body {
|
||||||
background: var(--secondary-dark);
|
background: var(--secondary-dark);
|
||||||
color : #FFFFFF;
|
color : #FFFFFF;
|
||||||
border: var(--secondary);
|
border: var(--secondary);
|
||||||
}
|
|
||||||
|
|
||||||
.btn-warning{
|
|
||||||
border-radius: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
.choices {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input style */
|
|
||||||
.choices__inner {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid var(--primary-blue-light);
|
|
||||||
border-radius: 0.375rem; /* same as Bootstrap `.form-control` */
|
|
||||||
padding: 0.5rem;
|
|
||||||
min-height: 2.5rem;
|
|
||||||
box-shadow: none;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Placeholder */
|
|
||||||
.choices__placeholder {
|
|
||||||
color: #6c757d; /* Bootstrap muted */
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Selected items (tags) */
|
|
||||||
.choices__list--multiple .choices__item {
|
|
||||||
background-color: var(--primary-blue-light) !important;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
margin: 0.15rem;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove "x" button */
|
|
||||||
.choices__list--multiple .choices__item .choices__button {
|
|
||||||
border-left: 1px solid rgba(255,255,255,0.3);
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
color: #fff;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.choices__list--multiple .choices__item .choices__button:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown list */
|
|
||||||
.choices__list--dropdown {
|
|
||||||
border: 1px solid var(--primary-blue-light);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
box-shadow: 0 3px 6px rgba(0,0,0,0.1);
|
|
||||||
margin-top: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown options */
|
|
||||||
.choices__list--dropdown .choices__item {
|
|
||||||
padding: 0.5rem;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hover/active in dropdown */
|
|
||||||
.choices__list--dropdown .choices__item--highlighted {
|
|
||||||
background-color: var(--primary-blue-light);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controller;
|
|
||||||
|
|
||||||
use App\Entity\Apps;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
|
||||||
|
|
||||||
#[Route(path: '/application', name: 'application_')]
|
|
||||||
|
|
||||||
class ApplicationController extends AbstractController
|
|
||||||
{
|
|
||||||
public function __construct(private readonly EntityManagerInterface $entityManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route(path: '/', name: 'index', methods: ['GET'])]
|
|
||||||
public function index(): Response
|
|
||||||
{
|
|
||||||
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
|
|
||||||
$applications = $this->entityManager->getRepository(Apps::class)->findAll();
|
|
||||||
|
|
||||||
return $this->render('application/index.html.twig', [
|
|
||||||
'applications' => $applications,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -12,15 +12,8 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||||
final class IndexController extends AbstractController
|
final class IndexController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/', name: 'app_index')]
|
#[Route('/', name: 'app_index')]
|
||||||
public function index(): Response
|
public function index(Request $request, LoggerInterface $logger): Response
|
||||||
{
|
{
|
||||||
if ($this->isGranted('ROLE_ADMIN')) {
|
|
||||||
return $this->redirectToRoute('organization_index');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->isGranted('ROLE_USER')) {
|
|
||||||
return $this->redirectToRoute('application_index');
|
|
||||||
}
|
|
||||||
return $this->render('index/index.html.twig', [
|
return $this->render('index/index.html.twig', [
|
||||||
'controller_name' => 'IndexController',
|
'controller_name' => 'IndexController',
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,6 @@ class OrganizationController extends AbstractController
|
||||||
$organizations[] = $uo->getOrganization();
|
$organizations[] = $uo->getOrganization();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(count($organizations) === 1 && $organizations[0]->isActive() === true){
|
|
||||||
return $this->redirectToRoute('organization_show', ['id' => $organizations[0]->getId()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,8 +177,6 @@ class OrganizationController extends AbstractController
|
||||||
|
|
||||||
$actions = $this->entityManager->getRepository(Actions::class)->findBy(['Organization' => $organization]);
|
$actions = $this->entityManager->getRepository(Actions::class)->findBy(['Organization' => $organization]);
|
||||||
$activities = $this->actionService->formatActivities($actions);
|
$activities = $this->actionService->formatActivities($actions);
|
||||||
|
|
||||||
$this->actionService->createAction("View Organization", $actingUser, $organization, $organization->getName());
|
|
||||||
return $this->render('organization/show.html.twig', [
|
return $this->render('organization/show.html.twig', [
|
||||||
'organization' => $organization,
|
'organization' => $organization,
|
||||||
'newUsers' => $newUsers,
|
'newUsers' => $newUsers,
|
||||||
|
|
@ -211,34 +206,5 @@ class OrganizationController extends AbstractController
|
||||||
return $this->redirectToRoute('organization_index');
|
return $this->redirectToRoute('organization_index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(path: '/deactivate/{id}', name: 'deactivate', methods: ['POST'])]
|
|
||||||
public function deactivate($id){
|
|
||||||
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
|
|
||||||
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
||||||
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
||||||
if (!$organization) {
|
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
||||||
}
|
|
||||||
$organization->setIsActive(false);
|
|
||||||
$this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, null, $organization);
|
|
||||||
$this->entityManager->persist($organization);
|
|
||||||
$this->actionService->createAction("Deactivate Organization", $actingUser, $organization, $organization->getName());
|
|
||||||
return $this->redirectToRoute('organization_index');
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route(path: '/activate/{id}', name: 'activate', methods: ['POST'])]
|
|
||||||
public function activate($id){
|
|
||||||
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
|
|
||||||
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
||||||
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
||||||
if (!$organization) {
|
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
||||||
}
|
|
||||||
$organization->setIsActive(true);
|
|
||||||
$this->entityManager->persist($organization);
|
|
||||||
$this->actionService->createAction("Activate Organization", $actingUser, $organization, $organization->getName());
|
|
||||||
return $this->redirectToRoute('organization_index');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\Apps;
|
|
||||||
use App\Entity\Organizations;
|
use App\Entity\Organizations;
|
||||||
use App\Entity\Roles;
|
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Entity\UserOrganizatonApp;
|
use App\Entity\UserOrganizatonApp;
|
||||||
use App\Entity\UsersOrganizations;
|
use App\Entity\UsersOrganizations;
|
||||||
|
|
@ -93,7 +91,7 @@ class UserController extends AbstractController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$uoa = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $uo, 'isActive' => true]);
|
$uoa = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $uo, 'isActive' => true]);
|
||||||
$uoas = $this->userOrganizationAppService->groupUserOrganizationAppsByApplication($uoa);
|
$uoa = $this->userOrganizationAppService->groupUserOrganizationAppsByApplication($uoa);
|
||||||
$this->actionService->createAction("View user information", $actingUser, null, $user->getUserIdentifier());
|
$this->actionService->createAction("View user information", $actingUser, null, $user->getUserIdentifier());
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
//ignore
|
//ignore
|
||||||
|
|
@ -101,9 +99,10 @@ class UserController extends AbstractController
|
||||||
} else {
|
} else {
|
||||||
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('user/show.html.twig', [
|
return $this->render('user/show.html.twig', [
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'uoas' => $uoas ?? null,
|
'uoas' => $uoa ?? null,
|
||||||
'orgs' => $orgs ?? null,
|
'orgs' => $orgs ?? null,
|
||||||
'organizationId' => $orgId ?? null,
|
'organizationId' => $orgId ?? null,
|
||||||
'uoActive' => $uoActive ?? null// specific for single organization context and deactivate user from said org
|
'uoActive' => $uoActive ?? null// specific for single organization context and deactivate user from said org
|
||||||
|
|
@ -333,46 +332,4 @@ class UserController extends AbstractController
|
||||||
$this->actionService->createAction("Delete user", $actingUser, null, $user->getUserIdentifier());
|
$this->actionService->createAction("Delete user", $actingUser, null, $user->getUserIdentifier());
|
||||||
return $this->redirectToRoute('user_index');
|
return $this->redirectToRoute('user_index');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(path: '/application/roles/{id}', name: 'application_role', methods: ['GET', 'POST'])]
|
|
||||||
public function applicationRole(int $id, Request $request): Response
|
|
||||||
{
|
|
||||||
$this->denyAccessUnlessGranted("ROLE_ADMIN");
|
|
||||||
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
||||||
|
|
||||||
if ($this->userService->hasAccessTo($actingUser, true)) {
|
|
||||||
$uo = $this->userOrganizationService->getByIdOrFail($id);
|
|
||||||
|
|
||||||
$application = $this->entityManager->getRepository(Apps::class)->find($request->get('applicationId'));
|
|
||||||
if (!$application) {
|
|
||||||
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
$selectedRolesIds = $request->get('roles', []);
|
|
||||||
$roleUser = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'USER']);
|
|
||||||
if (!$roleUser) {
|
|
||||||
throw $this->createNotFoundException('Default role not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($roleUser->getId(), $selectedRolesIds)) {
|
|
||||||
$this->userOrganizationAppService->syncRolesForUserOrganizationApp(
|
|
||||||
$uo,
|
|
||||||
$application,
|
|
||||||
$selectedRolesIds,
|
|
||||||
$actingUser
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->userOrganizationAppService->deactivateAllUserOrganizationsAppLinks($uo, $application);
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = $uo->getUsers();
|
|
||||||
return $this->redirectToRoute('user_show', [
|
|
||||||
'user' => $user,
|
|
||||||
'id' => $user->getId(),
|
|
||||||
'organizationId'=> $uo->getOrganization()->getId()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use App\Entity\Apps;
|
|
||||||
use App\Entity\Roles;
|
|
||||||
use App\Entity\User;
|
|
||||||
use App\Entity\UserOrganizatonApp;
|
use App\Entity\UserOrganizatonApp;
|
||||||
use App\Entity\UsersOrganizations;
|
use App\Entity\UsersOrganizations;
|
||||||
use App\Service\ActionService;
|
use App\Service\ActionService;
|
||||||
|
|
@ -17,8 +14,7 @@ class UserOrganizationAppService
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups UserOrganizationApp entities by Application
|
* Groups UserOrganizationApp entities by their associated Application.
|
||||||
* and prepares data for Twig.
|
|
||||||
*
|
*
|
||||||
* @param UserOrganizatonApp[] $userOrgApps
|
* @param UserOrganizatonApp[] $userOrgApps
|
||||||
* @return array
|
* @return array
|
||||||
|
|
@ -34,33 +30,19 @@ class UserOrganizationAppService
|
||||||
|
|
||||||
if (!isset($grouped[$appId])) {
|
if (!isset($grouped[$appId])) {
|
||||||
$grouped[$appId] = [
|
$grouped[$appId] = [
|
||||||
'uoId' => $uoa->getUserOrganization()->getId(),
|
'userOrganization'=> $uoa->getUserOrganization(),
|
||||||
'application' => $app, // you can still pass entity here
|
'application' => $app,
|
||||||
'roles' => [], // selected roles for display
|
'roles' => [],
|
||||||
'rolesArray' => [], // all possible roles
|
|
||||||
'selectedRoleIds' => [],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$grouped[$appId]['roles'][] = [
|
$grouped[$appId]['roles'][] = [
|
||||||
'id' => $roleEntity->getId(),
|
'id' => $roleEntity->getId(),
|
||||||
'name' => $roleEntity->getName(),
|
'name' => $roleEntity->getName(), // adjust to your Role entity fields
|
||||||
];
|
];
|
||||||
$grouped[$appId]['selectedRoleIds'][] = $roleEntity->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
// roles are the same for all apps → load once, inject into each appGroup
|
|
||||||
$allRoles = $this->entityManager->getRepository(Roles::class)->findAll();
|
|
||||||
|
|
||||||
foreach ($grouped as &$appGroup) {
|
|
||||||
foreach ($allRoles as $role) {
|
|
||||||
$appGroup['rolesArray'][] = [
|
|
||||||
'id' => $role->getId(),
|
|
||||||
'name' => $role->getName(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if you want a simple indexed array instead of associative keyed by appId
|
||||||
return array_values($grouped);
|
return array_values($grouped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,13 +52,9 @@ class UserOrganizationAppService
|
||||||
* @param UsersOrganizations $userOrganization
|
* @param UsersOrganizations $userOrganization
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function deactivateAllUserOrganizationsAppLinks(UsersOrganizations $userOrganization, Apps $app = null): void
|
public function deactivateAllUserOrganizationsAppLinks(UsersOrganizations $userOrganization): void
|
||||||
{
|
{
|
||||||
if($app) {
|
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $userOrganization, 'isActive' => true]);
|
||||||
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $userOrganization, 'application' => $app, 'isActive' => true]);
|
|
||||||
} else {
|
|
||||||
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $userOrganization, 'isActive' => true]);
|
|
||||||
}
|
|
||||||
foreach ($uoas as $uoa) {
|
foreach ($uoas as $uoa) {
|
||||||
$uoa->setIsActive(false);
|
$uoa->setIsActive(false);
|
||||||
$this->actionService->createAction("Deactivate UOA link", $userOrganization->getUsers(),
|
$this->actionService->createAction("Deactivate UOA link", $userOrganization->getUsers(),
|
||||||
|
|
@ -84,71 +62,4 @@ class UserOrganizationAppService
|
||||||
$this->entityManager->persist($uoa);
|
$this->entityManager->persist($uoa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncRolesForUserOrganizationApp(
|
|
||||||
UsersOrganizations $uo,
|
|
||||||
Apps $application,
|
|
||||||
array $selectedRoleIds,
|
|
||||||
User $actingUser
|
|
||||||
): void {
|
|
||||||
$repo = $this->entityManager->getRepository(UserOrganizatonApp::class);
|
|
||||||
$currentLinks = $repo->findBy([
|
|
||||||
'userOrganization' => $uo,
|
|
||||||
'application' => $application,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$currentRoleIds = [];
|
|
||||||
foreach ($currentLinks as $uoa) {
|
|
||||||
$roleId = $uoa->getRole()->getId();
|
|
||||||
$currentRoleIds[] = $roleId;
|
|
||||||
|
|
||||||
if (in_array($roleId, $selectedRoleIds)) {
|
|
||||||
if (!$uoa->isActive()) {
|
|
||||||
$uoa->setIsActive(true);
|
|
||||||
$this->entityManager->persist($uoa);
|
|
||||||
$this->actionService->createAction(
|
|
||||||
"Re-activate user role for application",
|
|
||||||
$actingUser,
|
|
||||||
$uo->getOrganization(),
|
|
||||||
"App: {$application->getName()}, Role: {$uoa->getRole()->getName()} for user {$uo->getUsers()->getUserIdentifier()}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($uoa->isActive()) {
|
|
||||||
$uoa->setIsActive(false);
|
|
||||||
$this->entityManager->persist($uoa);
|
|
||||||
|
|
||||||
$this->actionService->createAction(
|
|
||||||
"Deactivate user role for application",
|
|
||||||
$actingUser,
|
|
||||||
$uo->getOrganization(),
|
|
||||||
"App: {$application->getName()}, Role: {$uoa->getRole()->getName()} for user {$uo->getUsers()->getUserIdentifier()}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add missing roles
|
|
||||||
foreach ($selectedRoleIds as $roleId) {
|
|
||||||
if (!in_array($roleId, $currentRoleIds)) {
|
|
||||||
$role = $this->entityManager->getRepository(Roles::class)->find($roleId);
|
|
||||||
if ($role) {
|
|
||||||
$newUoa = new UserOrganizatonApp();
|
|
||||||
$newUoa->setUserOrganization($uo);
|
|
||||||
$newUoa->setApplication($application);
|
|
||||||
$newUoa->setRole($role);
|
|
||||||
$newUoa->setIsActive(true);
|
|
||||||
|
|
||||||
$this->entityManager->persist($newUoa);
|
|
||||||
$this->actionService->createAction("New user role for application",
|
|
||||||
$actingUser,
|
|
||||||
$uo->getOrganization(),
|
|
||||||
"App: {$application->getName()}, Role: {$role->getName()} for user {$uo->getUsers()->getUserIdentifier()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->entityManager->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use App\Entity\UsersOrganizations;
|
||||||
use App\Service\ActionService;
|
use App\Service\ActionService;
|
||||||
use \App\Service\UserOrganizationAppService;
|
use \App\Service\UserOrganizationAppService;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service pour la gestion des organisations d'utilisateurs.
|
* Service pour la gestion des organisations d'utilisateurs.
|
||||||
|
|
@ -44,14 +43,5 @@ readonly class UserOrganizationService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getByIdOrFail(int $id): UsersOrganizations
|
|
||||||
{
|
|
||||||
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->find($id);
|
|
||||||
if (!$uo) {
|
|
||||||
throw new NotFoundHttpException("UserOrganization not found");
|
|
||||||
}
|
|
||||||
return $uo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{% block body %}
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="card-title">
|
|
||||||
<h3><img width=10% src="{{ asset(application.logoUrl) }}" alt="Logo {{ application.title }}">
|
|
||||||
{{ application.name }}</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body d-flex flex-column align-items-center">
|
|
||||||
<p class="card-text">{{ application.description }}</p>
|
|
||||||
<div>
|
|
||||||
<a href="http://{{ application.subDomain }}.solutions-easy.moi" class="btn btn-primary me-2">Accéder à l'application</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
Suite Easy
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<div class="row m-5">
|
|
||||||
<div class="container mt-5">
|
|
||||||
<h1 class="mb-4">Bienvenue sur la suite Easy</h1>
|
|
||||||
<p class="lead">Ici, vous pouvez trouver toutes nos applications à un seul endroit !</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% for application in applications %}
|
|
||||||
<div class="col-6 mb-3">
|
|
||||||
{% include 'application/InformationCard.html.twig' with {
|
|
||||||
application: application
|
|
||||||
} %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -16,8 +16,7 @@
|
||||||
<a href="#" class="btn btn-secondary">Gérer l'application</a>
|
<a href="#" class="btn btn-secondary">Gérer l'application</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% else %}
|
{% else %}<a href="#" class="btn btn-primary">Demander l'accès</a>
|
||||||
<a href="#" class="btn btn-primary">Demander l'accès</a>
|
|
||||||
{#TODO: page d'accès#}
|
{#TODO: page d'accès#}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -28,31 +28,24 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{{ path('application_index') }}">
|
|
||||||
<i class="icon-grid menu-icon">{{ ux_icon('material-symbols:settings-applications-outline', {height: '15px', width: '15px'}) }}</i>
|
|
||||||
<span class="menu-title">Applications</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{# if user is Super Admin #}
|
{# if user is Super Admin #}
|
||||||
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
{% if is_granted('ROLE_ADMIN') %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ path('user_index') }}">
|
<a class="nav-link" href="{{ path('user_index') }}">
|
||||||
<i class="icon-grid menu-icon">{{ ux_icon('fa6-regular:circle-user', {height: '15px', width: '15px'}) }}</i>
|
<i class="icon-grid menu-icon">{{ ux_icon('fa6-regular:circle-user', {height: '15px', width: '15px'}) }}</i>
|
||||||
<span class="menu-title">Users</span>
|
<span class="menu-title">Users</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
<li class="nav-item">
|
||||||
<li class="nav-item">
|
{% if is_granted('ROLE_ADMIN') %}
|
||||||
{% if is_granted('ROLE_ADMIN') %}
|
<a class="nav-link" href="{{ path('organization_index') }}">
|
||||||
<a class="nav-link" href="{{ path('organization_index') }}">
|
<i class="icon-grid menu-icon"> {{ ux_icon('bi:buildings', {height: '15px', width: '15px'}) }}
|
||||||
<i class="icon-grid menu-icon"> {{ ux_icon('bi:buildings', {height: '15px', width: '15px'}) }}
|
</i>
|
||||||
</i>
|
<span class="menu-title">
|
||||||
<span class="menu-title">
|
|
||||||
Organizations</span>
|
Organizations</span>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
<th>Nom</th>
|
<th>Nom</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th>Visualiser</th>
|
<th>Visualiser</th>
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -39,13 +38,6 @@
|
||||||
</td>
|
</td>
|
||||||
<td>{{ organization.name }}</td>
|
<td>{{ organization.name }}</td>
|
||||||
<td>{{ organization.email }}</td>
|
<td>{{ organization.email }}</td>
|
||||||
<td>
|
|
||||||
{% if organization.active %}
|
|
||||||
<span class="badge bg-success">Active</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="badge bg-danger">Inactive</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ path('organization_show', {'id': organization.id}) }}"
|
<a href="{{ path('organization_show', {'id': organization.id}) }}"
|
||||||
class="p-3 align-middle color-primary">
|
class="p-3 align-middle color-primary">
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,13 @@
|
||||||
onsubmit="return confirm('Vous allez supprimer cette organisation, êtes vous sûre?');"
|
onsubmit="return confirm('Vous allez supprimer cette organisation, êtes vous sûre?');"
|
||||||
style="display: inline-block;">
|
style="display: inline-block;">
|
||||||
<button class="btn btn-danger" type="submit">Supprimer l'organisation</button>
|
<button class="btn btn-danger" type="submit">Supprimer l'organisation</button>
|
||||||
</form>
|
{# {% if organization.active %}#}
|
||||||
{% if organization.active %}
|
{# <a href="{{ path('organization_deactivate', {'id': organization.id}) }}"#}
|
||||||
<form method="POST" action="{{ path('organization_deactivate', {'id': organization.id}) }}"
|
{# class="btn btn-danger">Désactiver l'organisation</a>#}
|
||||||
onsubmit="return confirm('Vous allez désactiver cette organisation, êtes vous sûre?');"
|
{# {% else %}#}
|
||||||
style="display: inline-block;">
|
{# <a href="{{ path('organization_activate', {'id': organization.id}) }}"#}
|
||||||
<button class="btn btn-warning" type="submit">Désactiver l'organisation</button>
|
{# class="btn btn-success">Activer l'organisation</a>#}
|
||||||
</form>
|
{# {% endif %}#}
|
||||||
{% else %}
|
|
||||||
<form method="POST" action="{{ path('organization_activate', {'id': organization.id}) }}"
|
|
||||||
onsubmit="return confirm('Vous allez re-activer cette organisation, êtes vous sûre?');"
|
|
||||||
style="display: inline-block;">
|
|
||||||
<button class="btn btn-primary" type="submit">Activer l'organisation</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
{% elseif is_granted("ROLE_ADMIN") %}
|
{% elseif is_granted("ROLE_ADMIN") %}
|
||||||
<a href="{{ path('organization_edit', {'id': organization.id}) }}" class="btn btn-primary">Gérer mon
|
<a href="{{ path('organization_edit', {'id': organization.id}) }}" class="btn btn-primary">Gérer mon
|
||||||
organisation</a>
|
organisation</a>
|
||||||
|
|
@ -59,18 +52,18 @@
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{# <div class="m-auto"> #}
|
{# <div class="m-auto">#}
|
||||||
{% include 'user/userList.html.twig' with {
|
{% include 'user/userList.html.twig' with {
|
||||||
title: 'Mes utilisateurs',
|
title: 'Mes utilisateurs',
|
||||||
organizationId: organization.id,
|
organizationId: organization.id,
|
||||||
empty_message: 'Aucun utilisateurs trouvé.'
|
empty_message: 'Aucun utilisateurs trouvé.'
|
||||||
} %}
|
} %}
|
||||||
{# </div> #}
|
{# </div>#}
|
||||||
{# APPLICATION ROW #}
|
{# APPLICATION ROW #}
|
||||||
<div class="row ">
|
<div class="row ">
|
||||||
{% for application in applications %}
|
{% for application in applications %}
|
||||||
<div class="col-6 mb-3">
|
<div class="col-6 mb-3">
|
||||||
{% include 'application/appSmall.html.twig' with {
|
{% include 'applications/appSmall.html.twig' with {
|
||||||
application: application
|
application: application
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,42 +14,41 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<p><b> Description : </b>{{ uoa.application.description|default('Aucune description disponible.') }}</p>
|
<p><b> Description : </b>{{ uoa.application.description|default('Aucune description disponible.') }}</p>
|
||||||
</div>
|
{% if roles|length is not null %}
|
||||||
{% if is_granted('ROLE_ADMIN') %}
|
<div class="col">
|
||||||
<form method="POST"
|
<p><b>Rôles :</b>
|
||||||
action="{{ path('user_application_role', { id : uoa.uoId }) }}"
|
|
||||||
onsubmit="return confirm('Attention, si le role utilisateur ' +
|
{% for role in roles %}
|
||||||
'n\'est pas attribué, l\'utilisateur ne pourra plus accéder à l\'application. Êtes-vous sûr ?');"
|
{% if role.name == "SUPER ADMIN" %}
|
||||||
data-controller="user"
|
<span class="badge bg-danger">{{ role.name|capitalize }}</span>
|
||||||
data-user-roles-array-value="{{ uoa.rolesArray|json_encode }}"
|
{% elseif role.name == "ADMIN" %}
|
||||||
data-user-selected-role-ids-value="{{ uoa.selectedRoleIds|json_encode }}">
|
<span class="badge bg-danger">{{ role.name|capitalize }}</span>
|
||||||
<div class="form-group mb-3">
|
{% else %}
|
||||||
<label for="roles-{{ uoa.application.id }}"><b>Rôles :</b></label>
|
<span class="badge bg-primary">{{ role.name|capitalize }}</span>
|
||||||
<select data-user-target="select"
|
{% endif %}
|
||||||
class="choices"
|
{% if not loop.last %} - {% endif %}
|
||||||
id="roles-{{ uoa.application.id }}"
|
{% else %}
|
||||||
name="roles[]"
|
<p>Aucun rôle attribué.</p>
|
||||||
multiple>
|
{% endfor %}
|
||||||
</select>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<input hidden type="text" value="{{ uoa.application.id }}" name="applicationId">
|
|
||||||
<button type="submit" class="btn btn-primary">Sauvegarder</button>
|
{% endif %}
|
||||||
</form>
|
</div>
|
||||||
{% else %}
|
{# {% if is_granted('ROLE_ADMIN') %} #}
|
||||||
<label for="roles-{{ uoa.application.id }}"><b>Rôles :</b></label>
|
{# <form method="POST" action="{{ path('user_organization_edit', {'id' : uo.uoId}) }}" #}
|
||||||
<select data-user-target="select"
|
{# data-controller="user" #}
|
||||||
class="choices"
|
{# data-user-roles-array-value="{{ rolesArray|json_encode }}" #}
|
||||||
id="roles-{{ uoa.application.id }}"
|
{# data-user-selected-role-ids-value="{{ selectedRoleIds|json_encode }}"> #}
|
||||||
name="roles[]"
|
{# <div class="form-group mb-3"> #}
|
||||||
data-controller="user"
|
{# <label for="roles">Roles</label> #}
|
||||||
data-user-roles-array-value="{{ uoa.rolesArray|json_encode }}"
|
{# <select class="choices" data-type="select-multiple" id="roles" name="roles[]" multiple> #}
|
||||||
data-user-selected-role-ids-value="{{ uoa.selectedRoleIds|json_encode }}"
|
{# </select> #}
|
||||||
multiple
|
{# </div> #}
|
||||||
disabled>
|
{# <button type="submit" class="btn btn-primary">Sauvegarder</button> #}
|
||||||
</select>
|
{# </form> #}
|
||||||
{% endif %}
|
{# {% endif %} #}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
{% if user.active %}
|
{% if user.active %}
|
||||||
<a href="{{ path('user_deactivate', {'id': user.id}) }}"
|
<a href="{{ path('user_deactivate', {'id': user.id}) }}"
|
||||||
class="btn btn-danger">Désactiver l'utilisateur</a>
|
class="btn btn-danger">Désactiver</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ path('user_activate', {'id': user.id}) }}" class="btn btn-success">Activer l'utilisateur</a>
|
<a href="{{ path('user_activate', {'id': user.id}) }}" class="btn btn-success">Activer</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -24,10 +24,13 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% include 'user/userInformation.html.twig' %}
|
{% include 'user/userInformation.html.twig' %}
|
||||||
{% if orgs|length >0 %}
|
{% if orgs|length >1 %}
|
||||||
|
|
||||||
<h1 class="mt-5 mb-4">Vos applications</h1>
|
<h1 class="mt-5 mb-4">Vos applications</h1>
|
||||||
|
{% elseif orgs|length == 1 %}
|
||||||
|
{% for org in orgs %}
|
||||||
|
<h1 class="mt-5 mb-4">{{ org.name }}</h1>
|
||||||
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1 class="mt-5 mb-4">Aucune application</h1>
|
<h1 class="mt-5 mb-4">Aucune application</h1>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@
|
||||||
<form method="post" action="{{ path('user_deactivate_organization', {'id': user.id}) }}"
|
<form method="post" action="{{ path('user_deactivate_organization', {'id': user.id}) }}"
|
||||||
onsubmit="return confirm('Vous allez retirer l\'utilisateur de cette organisation, êtes vous sûre?');">
|
onsubmit="return confirm('Vous allez retirer l\'utilisateur de cette organisation, êtes vous sûre?');">
|
||||||
<input type="hidden" name="organizationId" value="{{ organizationId }}">
|
<input type="hidden" name="organizationId" value="{{ organizationId }}">
|
||||||
<button class="btn btn-danger" type="submit">Désactiver l'utilisateur de l'organisation</button>
|
<button class="btn btn-danger" type="submit">Désactiver</button>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<form method="post" action="{{ path('user_activate_organization', {'id': user.id}) }}"
|
<form method="post" action="{{ path('user_activate_organization', {'id': user.id}) }}"
|
||||||
onsubmit="return confirm('Vous allez activer cette utilisateur dans votre organisation, êtes vous sûre?');">
|
onsubmit="return confirm('Vous allez activer cette utilisateur dans votre organisation, êtes vous sûre?');">
|
||||||
<input type="hidden" name="organizationId" value="{{ organizationId }}">
|
<input type="hidden" name="organizationId" value="{{ organizationId }}">
|
||||||
<button class="btn btn-primary" type="submit">Activer l'utilisateur de l'organisation</button>
|
<button class="btn btn-primary" type="submit">Activer</button>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue