mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/master' into rector/rules-up-to-php74
This commit is contained in:
@@ -274,7 +274,7 @@ class ApiController extends AbstractCRUDController
|
||||
$postedData = $this->getSerializer()->deserialize($request->getContent(), $postedDataType, $_format, $postedDataContext);
|
||||
} catch (\Symfony\Component\Serializer\Exception\UnexpectedValueException $e) {
|
||||
throw new BadRequestHttpException(sprintf('Unable to deserialize posted ' .
|
||||
'data: %s', $e->getMessage()), 0, $e);
|
||||
'data: %s', $e->getMessage()), $e, 0);
|
||||
}
|
||||
|
||||
switch ($request->getMethod()) {
|
||||
|
@@ -107,5 +107,4 @@ class AddressToReferenceMatcherController
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class GroupCenter
|
||||
* )
|
||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE")
|
||||
*/
|
||||
private $center;
|
||||
private ?Center $center = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
@@ -40,83 +40,64 @@ class GroupCenter
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var PermissionsGroup
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\MainBundle\Entity\PermissionsGroup",
|
||||
* inversedBy="groupCenters")
|
||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE")
|
||||
*/
|
||||
private $permissionsGroup;
|
||||
private ?PermissionsGroup $permissionsGroup = null;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="Chill\MainBundle\Entity\User",
|
||||
* mappedBy="groupCenters"
|
||||
* )
|
||||
* @var Collection<User::class>
|
||||
*/
|
||||
private $users;
|
||||
private Collection $users;
|
||||
|
||||
/**
|
||||
* GroupCenter constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->permissionsGroup = new ArrayCollection();
|
||||
$this->users = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Center
|
||||
*/
|
||||
public function getCenter()
|
||||
public function getCenter(): ?Center
|
||||
{
|
||||
return $this->center;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PermissionGroup
|
||||
*/
|
||||
public function getPermissionsGroup()
|
||||
public function getPermissionsGroup(): ?PermissionsGroup
|
||||
{
|
||||
return $this->permissionsGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection|Collection
|
||||
* @return Collection<User::class>
|
||||
*/
|
||||
public function getUsers()
|
||||
public function getUsers(): Collection
|
||||
{
|
||||
return $this->users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Chill\MainBundle\Entity\GroupCenter
|
||||
*/
|
||||
public function setCenter(Center $center)
|
||||
public function setCenter(Center $center): self
|
||||
{
|
||||
$this->center = $center;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Chill\MainBundle\Entity\GroupCenter
|
||||
*/
|
||||
public function setPermissionsGroup(PermissionsGroup $permissionsGroup)
|
||||
public function setPermissionsGroup(PermissionsGroup $permissionsGroup): self
|
||||
{
|
||||
$this->permissionsGroup = $permissionsGroup;
|
||||
|
||||
|
@@ -87,6 +87,7 @@ class ComposedRoleScopeType extends AbstractType
|
||||
->add('scope', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choice_label' => static fn (Scope $scope) => $translatableStringHelper->localize($scope->getName()),
|
||||
'placeholder' => 'Choose amongst scopes',
|
||||
'required' => false,
|
||||
'data' => null,
|
||||
]);
|
||||
|
@@ -60,13 +60,15 @@ class ScopePickerType extends AbstractType
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$items = array_filter(
|
||||
$this->authorizationHelper->getReachableScopes(
|
||||
$this->security->getUser(),
|
||||
$options['role'] instanceof Role ? $options['role']->getRole() : $options['role'],
|
||||
$options['center']
|
||||
),
|
||||
static fn (Scope $s) => $s->isActive()
|
||||
$items = array_values(
|
||||
array_filter(
|
||||
$this->authorizationHelper->getReachableScopes(
|
||||
$this->security->getUser(),
|
||||
$options['role'] instanceof Role ? $options['role']->getRole() : $options['role'],
|
||||
$options['center']
|
||||
),
|
||||
static fn (Scope $s) => $s->isActive()
|
||||
)
|
||||
);
|
||||
|
||||
if (0 === count($items)) {
|
||||
|
@@ -241,7 +241,7 @@ class WorkflowStepType extends AbstractType
|
||||
function ($step, ExecutionContextInterface $context, $payload) {
|
||||
$form = $context->getObject();
|
||||
|
||||
foreach($form->get('future_dest_users')->getData() as $u) {
|
||||
foreach ($form->get('future_dest_users')->getData() as $u) {
|
||||
if (in_array($u, $form->get('future_cc_users')->getData(), true)) {
|
||||
$context
|
||||
->buildViolation('workflow.The user in cc cannot be a dest user in the same workflow step')
|
||||
|
@@ -15,7 +15,10 @@ use Chill\MainBundle\Entity\User;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Swift_Mailer;
|
||||
use Swift_Message;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
@@ -26,43 +29,34 @@ use function call_user_func;
|
||||
* Classe d'aide pour l'envoi de notification.
|
||||
*
|
||||
* Héberge toutes les méthodes pour ré-écrire les URL en fonction de la langue de l'utilisateur.
|
||||
*
|
||||
* @deprecated use the MailerInterface
|
||||
*/
|
||||
class Mailer
|
||||
{
|
||||
/**
|
||||
* @var Swift_Mailer
|
||||
*/
|
||||
protected $forcedMailer;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var Swift_Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $routeParameters;
|
||||
private $routeParameters;
|
||||
|
||||
/**
|
||||
* @var RouterInterface
|
||||
*/
|
||||
protected $router;
|
||||
private $router;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* @var \Twig\Environment
|
||||
*/
|
||||
protected $twig;
|
||||
private EngineInterface $twig;
|
||||
|
||||
private MailerInterface $mailer;
|
||||
|
||||
/**
|
||||
* Mailer constructor.
|
||||
@@ -70,11 +64,9 @@ class Mailer
|
||||
* @param $routeParameters
|
||||
*/
|
||||
public function __construct(
|
||||
MailerInterface $mailer,
|
||||
LoggerInterface $logger,
|
||||
Environment $twig,
|
||||
Swift_Mailer $mailer,
|
||||
// due to bug https://github.com/symfony/swiftmailer-bundle/issues/127
|
||||
// \Swift_Transport $mailerTransporter,
|
||||
EngineInterface $twig,
|
||||
RouterInterface $router,
|
||||
TranslatorInterface $translator,
|
||||
$routeParameters
|
||||
@@ -82,7 +74,6 @@ class Mailer
|
||||
$this->logger = $logger;
|
||||
$this->twig = $twig;
|
||||
$this->mailer = $mailer;
|
||||
//$this->forcedMailer = new \Swift_Mailer($mailerTransporter);
|
||||
$this->router = $router;
|
||||
$this->translator = $translator;
|
||||
$this->routeParameters = $routeParameters;
|
||||
@@ -115,20 +106,6 @@ class Mailer
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $force
|
||||
*
|
||||
* @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
|
||||
*/
|
||||
public function sendMessage(Swift_Message $message, $force)
|
||||
{
|
||||
if ($force) {
|
||||
$this->forcedMailer->send($message);
|
||||
} else {
|
||||
$this->mailer->send($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie une notification à un utilisateur.
|
||||
*
|
||||
@@ -155,23 +132,25 @@ class Mailer
|
||||
$subject[2] ?? null
|
||||
);
|
||||
|
||||
$message = (new Swift_Message($subjectI18n))
|
||||
->setFrom($fromEmail, $fromName)
|
||||
->setTo($to);
|
||||
$email = new Email();
|
||||
$email->addTo($to)->subject($subjectI18n);
|
||||
|
||||
foreach ($bodies as $contentType => $content) {
|
||||
$message->setBody($content, $contentType);
|
||||
match ($contentType) {
|
||||
'text/plain' => $email->text($content),
|
||||
default => $email->text($content),
|
||||
};
|
||||
}
|
||||
|
||||
if (null !== $callback) {
|
||||
call_user_func($callback, $message);
|
||||
call_user_func($callback, $email);
|
||||
}
|
||||
|
||||
$this->logger->info('[notification] Sending notification', [
|
||||
'to' => $message->getTo(),
|
||||
'subject' => $message->getSubject(),
|
||||
'to' => $email->getTo(),
|
||||
'subject' => $email->getSubject()
|
||||
]);
|
||||
|
||||
$this->sendMessage($message, $force);
|
||||
$this->mailer->send($email);
|
||||
}
|
||||
}
|
||||
|
@@ -375,6 +375,12 @@ span.dt {
|
||||
font-weight: bolder;
|
||||
background-color: var(--bs-chill-light-gray);
|
||||
}
|
||||
/// help text
|
||||
.help-text {
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-gray);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@@ -1,3 +1,11 @@
|
||||
/// mixin to set sticky area on bottom when scrolling
|
||||
@mixin sticky-bottom {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
margin-top: 4em;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
ul.record_actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -53,16 +61,30 @@ ul.record_actions {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sticky-form {
|
||||
background-color: $white;
|
||||
padding-top: 1.25em;
|
||||
margin: -1em;
|
||||
box-shadow: 0 -20px 20px -20px rgba($chill-gray, .5);
|
||||
@include sticky-bottom;
|
||||
|
||||
.sticky-form-buttons {
|
||||
position: initial;
|
||||
bottom: unset;
|
||||
margin-top: unset;
|
||||
z-index: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.sticky-form-buttons {
|
||||
margin-top: 4em;
|
||||
background-color: $beige;
|
||||
position: sticky;
|
||||
bottom: 0.3em;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
padding: 0.8em 1.6em;
|
||||
border-radius: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
background-color: $beige;
|
||||
text-align: center;
|
||||
padding: 0.8em 1.6em;
|
||||
border-radius: 0;
|
||||
@include sticky-bottom;
|
||||
bottom: 0.3em;
|
||||
}
|
||||
|
||||
/// EXCEPTIONS
|
||||
|
@@ -64,6 +64,7 @@ section.chill-entity {
|
||||
margin: 0.7em 0;
|
||||
p {
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
&.delimiter {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<span v-if="data.working_ref_status === 'to_review'" class="badge bg-danger address-details-button-warning">L'adresse de référence a été modifiée</span>
|
||||
<a v-if="data.loading === false" @click.prevent="clickOrOpen" class="btn btn-sm btn-misc">
|
||||
<span class="fa fa-map address-details-button"></span>
|
||||
<a v-if="data.loading === false" @click.prevent="clickOrOpen" class="btn btn-misc address-details-button">
|
||||
<span class="fa fa-map"></span> <!-- button -->
|
||||
</a>
|
||||
<span v-if="data.loading" class="fa fa-spin fa-spinner "></span>
|
||||
<AddressModal :address="data.working_address" @update-address="onUpdateAddress" ref="address_modal"></AddressModal>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{% set formId = crudMainFormId|default('crud_main_form') %}
|
||||
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.'~crud_name~'.title_edit')|trans }}</h1>
|
||||
<h1 class="mb-5">{{ ('crud.'~crud_name~'.title_edit')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
{% block crud_content_form %}
|
||||
|
@@ -14,7 +14,7 @@
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
{% block table_entities %}
|
||||
<table class="table table-bordered border-dark">
|
||||
<table class="table table-bordered border-dark align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
{% block table_entities_thead_tr %}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
* has_no_address bool
|
||||
* multiline bool multiline display
|
||||
* extended_infos bool add extra informations (step, floor, etc.) DEPRECATED
|
||||
* details_button bool add an address details button
|
||||
|
||||
#}
|
||||
|
||||
@@ -79,7 +80,12 @@
|
||||
<i class="fa fa-fw fa-map-marker"></i>
|
||||
{% endif %}
|
||||
{{ _self.inline(address, options, streetLine, lines) }}
|
||||
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span>
|
||||
{% if options['details_button'] is defined and options['details_button'] == true %}
|
||||
<span data-address-details="1"
|
||||
data-address-id="{{ address.id|escape('html_attr') }}"
|
||||
data-address-ref-status="{{ address.refStatus|escape('html_attr') }}">
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
|
||||
@@ -112,7 +118,12 @@
|
||||
<i class="fa fa-fw fa-map-marker"></i>
|
||||
{% endif %}
|
||||
{{ _self.raw(lines) }}
|
||||
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span></p>
|
||||
{% if options['details_button'] is defined and options['details_button'] == true %}<p class="mt-3">
|
||||
<span data-address-details="1"
|
||||
data-address-id="{{ address.id|escape('html_attr') }}"
|
||||
data-address-ref-status="{{ address.refStatus|escape('html_attr') }}">
|
||||
</span></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ _self.validity(address, options) }}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<footer class="footer">
|
||||
<p>
|
||||
{{ 'This program is free software: you can redistribute it and/or modify it under the terms of the <strong>GNU Affero General Public License</strong>'|trans|raw }}
|
||||
<br/>
|
||||
<a name="bottom" class="btn text-white" href="https://{{ app.request.locale }}.wikibooks.org/wiki/Chill" target="_blank">
|
||||
<br/>
|
||||
<a name="bottom" class="btn text-white" href="https://gitea.champs-libres.be/Chill-project/manuals/releases" target="_blank">
|
||||
{{ 'User manual'|trans }}
|
||||
</a>
|
||||
</p>
|
||||
|
@@ -3,93 +3,130 @@
|
||||
{% block title %}{{ 'PermissionsGroup "%name%" edit'|trans( { '%name%': entity.name } ) }}{% endblock %}
|
||||
|
||||
{% block admin_content -%}
|
||||
<h1>{{ 'PermissionsGroup "%name%" edit'|trans( { '%name%': entity.name } ) }}</h1>
|
||||
<div class="container-xxl">
|
||||
<div class="row">
|
||||
|
||||
<h2>{{ 'Details'|trans }}</h2>
|
||||
<h1 class="mb-4">{{ 'PermissionsGroup "%name%" edit'|trans( { '%name%': entity.name } ) }}</h1>
|
||||
|
||||
{{ form_start(edit_form) }}
|
||||
{{ form_row(edit_form.name) }}
|
||||
{% if edit_form.flags is defined %}
|
||||
{{ form_row(edit_form.flags) }}
|
||||
{% endif %}
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class': 'btn btn-chill-green' } } ) }}
|
||||
{{ form_end(edit_form) }}
|
||||
<h2>{{ 'Details'|trans }}</h2>
|
||||
|
||||
<h2>{{ 'Grant those permissions'|trans }} :</h2>
|
||||
{{ form_start(edit_form) }}
|
||||
{{ form_row(edit_form.name) }}
|
||||
{% if edit_form.flags is defined %}
|
||||
{{ form_row(edit_form.flags) }}
|
||||
{% endif %}
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class': 'btn btn-save float-end' } } ) }}
|
||||
{{ form_end(edit_form) }}
|
||||
|
||||
{%- if entity.getRoleScopes|length > 0 -%}
|
||||
{% for title, role_scopes in role_scopes_sorted %}
|
||||
<h2 class="mb-5">{{ 'Grant those permissions'|trans }} :</h2>
|
||||
|
||||
<h3>{{ title|default("Unclassified")|trans }}</h3>
|
||||
{%- if entity.getRoleScopes|length > 0 -%}
|
||||
{% for title, role_scopes in role_scopes_sorted %}
|
||||
|
||||
<table class="striped rounded">
|
||||
<thead>
|
||||
<h3>{{ title|default("Unclassified")|trans }}</h3>
|
||||
|
||||
<table class="table table-bordered border-dark align-middle mb-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Circle'|trans }}</th>
|
||||
<th class="w-75">{{ 'Role'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for role_scope in role_scopes %}
|
||||
<tr>
|
||||
<th>{{ 'Role'|trans }}</th>
|
||||
<th>{{ 'Circle'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for role_scope in role_scopes %}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="role_scope role">{{ role_scope.role|trans }}</span>
|
||||
{% if expanded_roles[role_scope.role]|length > 1 %}
|
||||
<br/>
|
||||
<small>{{ 'Which implies'|trans }} : {% for role in expanded_roles[role_scope.role] %}{{ role|trans }}{% if not loop.last %}, {% endif %}{% endfor %}</small>
|
||||
<td style="width: 7em">
|
||||
{%- if role_scope.scope is not null -%}
|
||||
<span class="role_scope scope">
|
||||
{{ role_scope.scope.name|localize_translatable_string }}
|
||||
</span>
|
||||
{%- else -%}
|
||||
<small><i>N/A</i></small>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<span class="role_scope role">{{ role_scope.role|trans }}</span>
|
||||
{% if expanded_roles[role_scope.role]|length > 1 %}
|
||||
<div class="help-text">
|
||||
<span style="text-decoration: underline dotted;">{{ 'Which implies'|trans }} :</span>
|
||||
{% for role in expanded_roles[role_scope.role] %}
|
||||
{% if role != role_scope.role %}
|
||||
{{ role|trans }}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{%- if role_scope.scope is not null -%}
|
||||
<span class="role_scope scope">
|
||||
{{ role_scope.scope.name|localize_translatable_string }}
|
||||
</span>
|
||||
{%- else -%}
|
||||
<em>N/A</em>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
{{ form_start(delete_role_scopes_form[role_scope.id]) }}
|
||||
{{ form_widget(delete_role_scopes_form[role_scope.id].submit, { 'attr': { 'class': 'btn btn-chill-red' } } ) }}
|
||||
{{ form_end(delete_role_scopes_form[role_scope.id]) }}
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
<td style="width: 7em">
|
||||
{{ form_start(delete_role_scopes_form[role_scope.id]) }}
|
||||
{{ form_widget(delete_role_scopes_form[role_scope.id].submit, { 'attr': { 'class': 'btn btn-remove' } } ) }}
|
||||
{{ form_end(delete_role_scopes_form[role_scope.id]) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
|
||||
{%- else -%}
|
||||
<p>{{ 'This group does not provide any permission'|trans }}</p>
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
<p>{{ 'This group does not provide any permission'|trans }}</p>
|
||||
{%- endif -%}
|
||||
|
||||
</div>
|
||||
<div class="row sticky-form">
|
||||
|
||||
<div class="mt-5">
|
||||
<h2>{{ 'Grant new permissions'|trans }}</h2>
|
||||
|
||||
{{ form_start(add_role_scopes_form) }}
|
||||
{{ form_errors(add_role_scopes_form) }}
|
||||
{{ form_row(add_role_scopes_form.composed_role_scope.role) }}
|
||||
{{ form_row(add_role_scopes_form.composed_role_scope.scope) }}
|
||||
|
||||
<div class="input-group">
|
||||
{{ form_widget(add_role_scopes_form.composed_role_scope.role, { 'attr': { 'class': 'w-50' }}) }}
|
||||
{{ form_widget(add_role_scopes_form.composed_role_scope.scope) }}
|
||||
</div>
|
||||
<div id="role_scope_legend" class="help-text mb-3">{{ 'Help to pick role and scope'|trans }}</div>
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
{{ form_row(add_role_scopes_form.submit, { 'attr' : { 'class': 'btn btn-create' } } ) }}
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('admin_permissionsgroup_show', { 'id': entity.id }) }}" class="btn btn-cancel">{{ 'Cancel'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<li class="cancel">
|
||||
<a href="{{ path('admin_permissionsgroup') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('admin_permissionsgroup_show', { 'id': entity.id }) }}" class="btn btn-misc">{{ 'Cancel'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_widget(add_role_scopes_form.submit, { 'attr' : { 'class': 'btn btn-create' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(add_role_scopes_form) }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
|
||||
// An event listener give contextual legend when choosing an option.
|
||||
const select = document.getElementById('form_composed_role_scope_role');
|
||||
const legend = document.getElementById('role_scope_legend');
|
||||
|
||||
select.addEventListener('change', function() {
|
||||
const option = this.options[this.selectedIndex];
|
||||
const hasScope = option.getAttribute('data-has-scope');
|
||||
legend.style.display = 'block';
|
||||
if (hasScope === '0') {
|
||||
legend.innerText = '{{ 'The role does not need scope'|trans }}';
|
||||
} else if (hasScope === '1') {
|
||||
legend.innerText = '{{ 'The role need scope'|trans }}';
|
||||
} else {
|
||||
legend.innerText = '{{ 'Help to pick role and scope'|trans }}';
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
{% block admin_content -%}
|
||||
<h1>{{ 'Permissions group list'|trans }}</h1>
|
||||
|
||||
<table class="records_list">
|
||||
<table class="table table-bordered border-dark align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
|
@@ -10,8 +10,6 @@
|
||||
{% if form.flags is defined %}
|
||||
{{ form_row(form.flags) }}
|
||||
{% endif %}
|
||||
{{ form_row(form.submit, { 'attr': { 'class': 'btn btn-chill-green' } } ) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class='cancel'>
|
||||
@@ -19,5 +17,10 @@
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_widget(form.submit, { 'attr': { 'class': 'btn btn-create' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
|
@@ -3,44 +3,52 @@
|
||||
{% block title %}{{ 'Permission group "%name%"'|trans({ '%name%': entity.name }) }}{% endblock %}
|
||||
|
||||
{% block admin_content -%}
|
||||
<h1>{{ 'Permission group "%name%"'|trans({ '%name%': entity.name }) }}</h1>
|
||||
<h1 class="mb-4">{{ 'Permission group "%name%"'|trans({ '%name%': entity.name }) }}</h1>
|
||||
|
||||
<table class="record_properties">
|
||||
<table class="table table-bordered border-dark align-middle">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<td>{{ entity.name }}</td>
|
||||
<td class="w-25">{{ entity.name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if role_scopes_sorted|length > 0 %}
|
||||
<h2>{{ 'Grant those permissions'|trans }} :</h2>
|
||||
<h2 class="mb-5">{{ 'Grant those permissions'|trans }} :</h2>
|
||||
|
||||
{% for title, role_scopes in role_scopes_sorted %}
|
||||
<h3>{{ title|default('Unclassified')|trans }}</h3>
|
||||
<table class="striped rounded">
|
||||
<table class="table table-bordered border-dark align-middle mb-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-25">{{ 'Circle'|trans }}</th>
|
||||
<th>{{ 'Role'|trans }}</th>
|
||||
<th>{{ 'Circle'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for role_scope in role_scopes %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ role_scope.role|trans }}
|
||||
{% if expanded_roles[role_scope.role]|length > 1 %}
|
||||
<br/>
|
||||
<small>{{ 'Which implies'|trans }} : {% for role in expanded_roles[role_scope.role] %}{{ role|trans }}{% if not loop.last %}, {% endif %}{% endfor %}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{%- if role_scope.scope is not null -%}
|
||||
{{ role_scope.scope.name|localize_translatable_string }}
|
||||
<td style="width: 7em">{%- if role_scope.scope is not null -%}
|
||||
{{ role_scope.scope.name|localize_translatable_string }}
|
||||
{%- else -%}
|
||||
<em>N/A</em>
|
||||
{%- endif -%}
|
||||
<small><i>N/A</i></small>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<span class="role_scope role">{{ role_scope.role|trans }}</span>
|
||||
{% if expanded_roles[role_scope.role]|length > 1 %}
|
||||
<div class="help-text">
|
||||
<span style="text-decoration: underline dotted;">{{ 'Which implies'|trans }} :</span>
|
||||
{% for role in expanded_roles[role_scope.role] %}
|
||||
{% if role != role_scope.role %}
|
||||
{{ role|trans }}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -57,17 +65,15 @@
|
||||
{% endif %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
|
||||
<li class="cancel">
|
||||
<a href="{{ path('admin_permissionsgroup') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('admin_permissionsgroup_edit', { 'id': entity.id }) }}" class="btn btn-edit">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('admin_permissionsgroup') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
@@ -4,10 +4,10 @@
|
||||
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||
{% block crud_content_after_form %}
|
||||
{% if access_permissions_group_list %}
|
||||
<h2>{{ 'Permissions granted'|trans }}</h2>
|
||||
<h2 class="mt-5">{{ 'Permissions granted'|trans }}</h2>
|
||||
|
||||
{% if entity.groupcenters|length > 0 %}
|
||||
<table>
|
||||
<table class="table table-bordered border-dark align-middle mb-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Permission group'|trans }}</th>
|
||||
@@ -19,18 +19,18 @@
|
||||
{% for groupcenter in entity.groupcenters %}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="user_group permissionsgroup">
|
||||
{{ groupcenter.permissionsgroup.name }}
|
||||
</span>
|
||||
<span class="user_group permissionsgroup">
|
||||
{{ groupcenter.permissionsgroup.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="user_group center">
|
||||
{{ groupcenter.center.name }}
|
||||
</span>
|
||||
<span class="user_group center">
|
||||
{{ groupcenter.center.name }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<td class="w-25 text-end">
|
||||
{{ form_start(delete_groupcenter_form[groupcenter.id]) }}
|
||||
{{ form_row(delete_groupcenter_form[groupcenter.id].submit, { 'attr': { 'class': 'btn btn-chill-red' } } ) }}
|
||||
{{ form_widget(delete_groupcenter_form[groupcenter.id].submit, { 'attr': { 'class': 'btn btn-remove' } } ) }}
|
||||
{{ form_rest(delete_groupcenter_form[groupcenter.id]) }}
|
||||
{{ form_end(delete_groupcenter_form[groupcenter.id]) }}
|
||||
</td>
|
||||
@@ -47,7 +47,7 @@
|
||||
{{ form_start(add_groupcenter_form) }}
|
||||
{{ form_row(add_groupcenter_form.composed_groupcenter.center) }}
|
||||
{{ form_row(add_groupcenter_form.composed_groupcenter.permissionsgroup) }}
|
||||
{{ form_row(add_groupcenter_form.submit, { 'attr' : { 'class': 'btn btn-chill-green' } } ) }}
|
||||
{{ form_row(add_groupcenter_form.submit, { 'attr' : { 'class': 'btn btn-create' } } ) }}
|
||||
|
||||
{{ form_end(add_groupcenter_form) }}
|
||||
{% endif %}
|
||||
|
@@ -69,19 +69,20 @@
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
|
||||
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
|
||||
<li>
|
||||
<a class="btn btn-chill-blue" href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}" title="{{ "Impersonate"|trans|e('html_attr') }}"><i class="fa fa-user-secret"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}" href="{{ path('chill_crud_admin_user_edit', { 'id': entity.id }) }}"></a>
|
||||
</li>
|
||||
|
||||
{% if allow_change_password is same as(true) %}
|
||||
<li>
|
||||
<a class="btn btn-chill-red" href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" title="{{ 'Edit password'|trans|e('html_attr') }}"><i class="fa fa-ellipsis-h"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
|
||||
<li>
|
||||
<a class="btn btn-chill-blue" href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}" title="{{ "Impersonate"|trans|e('html_attr') }}"><i class="fa fa-user-secret"></i></a>
|
||||
<a class="btn btn-reset" href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" title="{{ 'Edit password'|trans|e('html_attr') }}"><i class="fa fa-key-modern"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
{% block admin_content %}
|
||||
{% embed '@ChillMain/CRUD/_index.html.twig' %}
|
||||
|
||||
|
||||
{% block table_entities_thead_tr %}
|
||||
<th>id</th>
|
||||
<th>{{ 'Label'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block table_entities_tbody %}
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
@@ -25,19 +25,19 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_admin_user_job_edit', { 'id': entity.id}) }}" class="btn btn-sm btn-edit btn-mini"></a>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_admin_user_job_edit', { 'id': entity.id}) }}" class="btn btn-edit"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block actions_before %}
|
||||
<li class='cancel'>
|
||||
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans}}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
@@ -120,6 +120,11 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
||||
if ($role instanceof Role) {
|
||||
$role = $role->getRole();
|
||||
}
|
||||
|
||||
if (!$user instanceof User) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var array<string, Center> $centers */
|
||||
$centers = [];
|
||||
|
||||
|
@@ -14,6 +14,8 @@ namespace Chill\MainBundle\Security\PasswordRecover;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Notification\Mailer;
|
||||
use DateTimeInterface;
|
||||
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
use function array_merge;
|
||||
@@ -22,33 +24,26 @@ class RecoverPasswordHelper
|
||||
{
|
||||
public const RECOVER_PASSWORD_ROUTE = 'password_recover';
|
||||
|
||||
/**
|
||||
* @var Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
protected $routeParameters;
|
||||
private MailerInterface $mailer;
|
||||
|
||||
/**
|
||||
* @var TokenManager
|
||||
*/
|
||||
protected $tokenManager;
|
||||
private $tokenManager;
|
||||
|
||||
/**
|
||||
* @var UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(
|
||||
TokenManager $tokenManager,
|
||||
UrlGeneratorInterface $urlGenerator,
|
||||
Mailer $mailer,
|
||||
array $routeParameters
|
||||
MailerInterface $mailer,
|
||||
) {
|
||||
$this->tokenManager = $tokenManager;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->mailer = $mailer;
|
||||
$this->routeParameters = $routeParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,27 +54,14 @@ class RecoverPasswordHelper
|
||||
*/
|
||||
public function generateUrl(User $user, DateTimeInterface $expiration, $absolute = true, array $parameters = [])
|
||||
{
|
||||
$context = $this->urlGenerator->getContext();
|
||||
$previousHost = $context->getHost();
|
||||
$previousScheme = $context->getScheme();
|
||||
|
||||
$context->setHost($this->routeParameters['host']);
|
||||
$context->setScheme($this->routeParameters['scheme']);
|
||||
|
||||
$url = $this->urlGenerator->generate(
|
||||
return $this->urlGenerator->generate(
|
||||
self::RECOVER_PASSWORD_ROUTE,
|
||||
array_merge(
|
||||
$this->tokenManager->generate($user, $expiration),
|
||||
$parameters
|
||||
),
|
||||
$absolute ? UrlGeneratorInterface::ABSOLUTE_URL : UrlGeneratorInterface::ABSOLUTE_PATH
|
||||
UrlGeneratorInterface::ABSOLUTE_URL
|
||||
);
|
||||
|
||||
// reset the host
|
||||
$context->setHost($previousHost);
|
||||
$context->setScheme($previousScheme);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function sendRecoverEmail(
|
||||
@@ -91,26 +73,20 @@ class RecoverPasswordHelper
|
||||
array $additionalUrlParameters = [],
|
||||
$emailSubject = 'Recover your password'
|
||||
) {
|
||||
$content = $this->mailer->renderContentToUser(
|
||||
$user,
|
||||
$template,
|
||||
array_merge(
|
||||
[
|
||||
'user' => $user,
|
||||
'url' => $this->generateUrl($user, $expiration, true, $additionalUrlParameters),
|
||||
],
|
||||
$templateParameters
|
||||
)
|
||||
);
|
||||
if (null === $user->getEmail() || '' === trim($user->getEmail())) {
|
||||
throw new \UnexpectedValueException("No emaail associated to the user");
|
||||
}
|
||||
|
||||
$this->mailer->sendNotification(
|
||||
$user,
|
||||
[$emailSubject],
|
||||
[
|
||||
'text/plain' => $content,
|
||||
],
|
||||
null,
|
||||
$force
|
||||
);
|
||||
$email = (new TemplatedEmail())
|
||||
->subject($emailSubject)
|
||||
->to($user->getEmail())
|
||||
->textTemplate($template)
|
||||
->context([
|
||||
'user' => $user,
|
||||
'url' => $this->generateUrl($user, $expiration, true, $additionalUrlParameters),
|
||||
...$templateParameters
|
||||
]);
|
||||
|
||||
$this->mailer->send($email);
|
||||
}
|
||||
}
|
||||
|
@@ -207,7 +207,7 @@ final class GeographicalUnitBaseImporter
|
||||
(id, geom, unitname, layer_id, unitrefid)
|
||||
SELECT
|
||||
nextval('chill_main_geographical_unit_id_seq'),
|
||||
geom,
|
||||
st_makevalid(geom),
|
||||
unitName,
|
||||
layer.id,
|
||||
unitKey
|
||||
|
@@ -78,8 +78,8 @@ class PostalCodeFRFromOpenData
|
||||
|
||||
private function handleRecord(array $record): void
|
||||
{
|
||||
if ('' !== trim($record['coordonnees_gps'])) {
|
||||
[$lat, $lon] = array_map(static fn ($el) => (float) trim($el), explode(',', $record['coordonnees_gps']));
|
||||
if ('' !== trim($record['coordonnees_geographiques'] ?? $record['coordonnees_gps'])) {
|
||||
[$lat, $lon] = array_map(static fn ($el) => (float) trim($el), explode(',', $record['coordonnees_geographiques'] ?? $record['coordonnees_gps']));
|
||||
} else {
|
||||
$lat = $lon = 0.0;
|
||||
}
|
||||
|
@@ -10,12 +10,6 @@ services:
|
||||
|
||||
Chill\MainBundle\Notification\Mailer:
|
||||
arguments:
|
||||
$logger: '@Psr\Log\LoggerInterface'
|
||||
$twig: '@Twig\Environment'
|
||||
$mailer: '@swiftmailer.mailer.default'
|
||||
# $mailerTransporter: '@swiftmailer.transport'
|
||||
$router: '@Symfony\Component\Routing\RouterInterface'
|
||||
$translator: '@Symfony\Contracts\Translation\TranslatorInterface'
|
||||
$routeParameters: '%chill_main.notifications%'
|
||||
|
||||
Chill\MainBundle\Notification\NotificationHandlerManager:
|
||||
|
@@ -61,11 +61,7 @@ services:
|
||||
arguments:
|
||||
$secret: '%kernel.secret%'
|
||||
|
||||
Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper:
|
||||
arguments:
|
||||
$tokenManager: '@Chill\MainBundle\Security\PasswordRecover\TokenManager'
|
||||
$mailer: '@Chill\MainBundle\Notification\Mailer'
|
||||
$routeParameters: "%chill_main.notifications%"
|
||||
Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper: ~
|
||||
|
||||
Chill\MainBundle\Security\PasswordRecover\PasswordRecoverEventSubscriber:
|
||||
arguments:
|
||||
|
@@ -69,7 +69,6 @@ final class Version20230306145728 extends AbstractMigration
|
||||
$this->addSql('CREATE INDEX IDX_165051F63174800F ON chill_main_address (createdBy_id)');
|
||||
$this->addSql('CREATE INDEX IDX_165051F665FF1AEC ON chill_main_address (updatedBy_id)');
|
||||
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.point IS \'(DC2Type:point)\'');
|
||||
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
|
@@ -167,12 +167,16 @@ Permissionsgroup: Groupe de permissions
|
||||
New permission group: Nouveau groupe de permissions
|
||||
PermissionsGroup "%name%" edit: Modification du groupe de permission '%name%'
|
||||
Role: Rôle
|
||||
Choose amongst roles: Choisir parmi les rôles
|
||||
Choose amongst roles: Choisir un rôle
|
||||
Choose amongst scopes: Choisir un cercle
|
||||
Add permission: Ajouter les permissions
|
||||
This group does not provide any permission: Ce groupe n'attribue aucune permission
|
||||
The role '%role%' has been removed: Le rôle "%role%" a été enlevé de ce groupe de permission
|
||||
The role '%role%' on circle '%scope%' has been removed: Le rôle "%role%" sur le cercle "%scope%" a été enlevé de ce groupe de permission
|
||||
Unclassified: Non classifié
|
||||
Help to pick role and scope: Certains rôles ne nécessitent pas de cercle.
|
||||
The role need scope: Ce rôle nécessite un cercle.
|
||||
The role does not need scope: Ce rôle ne nécessite pas de cercle !
|
||||
|
||||
#admin section for users
|
||||
User configuration: Gestion des utilisateurs
|
||||
@@ -423,6 +427,7 @@ No entities: Aucun élément
|
||||
|
||||
CHILL_FOO_SEE: Voir un élément
|
||||
CHILL_FOO_EDIT: Modifier un élément
|
||||
chill_export: Exports (statistiques)
|
||||
|
||||
#Show templates
|
||||
Date: Date
|
||||
|
Reference in New Issue
Block a user