Refactor authentication system (#2602)

Make auth configuration available via UI, remove FOSUserBundle and SAML-Bundle dependency
This commit is contained in:
Kevin Papst
2021-06-10 15:34:13 +02:00
committed by GitHub
parent 286b63e2c8
commit 7f20cb045c
155 changed files with 5590 additions and 1802 deletions

View File

@@ -20,7 +20,6 @@ use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseAbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\DataCollectorTranslator;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
@@ -35,18 +34,12 @@ abstract class AbstractController extends BaseAbstractController implements Serv
*/
public const ROLE_ADMIN = User::ROLE_ADMIN;
/**
* @return DataCollectorTranslator
*/
private function getTranslator()
protected function getTranslator(): TranslatorInterface
{
return $this->container->get('translator');
}
/**
* @return LoggerInterface $logger
*/
private function getLogger()
private function getLogger(): LoggerInterface
{
return $this->container->get('logger');
}
@@ -57,7 +50,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
* @param string $translationKey
* @param array $parameter
*/
protected function flashSuccess($translationKey, $parameter = [])
protected function flashSuccess(string $translationKey, array $parameter = []): void
{
$this->addFlashTranslated('success', $translationKey, $parameter);
}
@@ -68,7 +61,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
* @param string $translationKey
* @param array $parameter
*/
protected function flashWarning($translationKey, $parameter = [])
protected function flashWarning(string $translationKey, array $parameter = []): void
{
$this->addFlashTranslated('warning', $translationKey, $parameter);
}
@@ -79,7 +72,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
* @param string $translationKey
* @param array $parameter
*/
protected function flashError($translationKey, $parameter = [])
protected function flashError(string $translationKey, array $parameter = []): void
{
$this->addFlashTranslated('error', $translationKey, $parameter);
}
@@ -89,7 +82,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
*
* @param \Exception $exception
*/
protected function flashUpdateException(\Exception $exception)
protected function flashUpdateException(\Exception $exception): void
{
$this->flashException($exception, 'action.update.error');
}
@@ -99,7 +92,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
*
* @param \Exception $exception
*/
protected function flashDeleteException(\Exception $exception)
protected function flashDeleteException(\Exception $exception): void
{
$this->flashException($exception, 'action.delete.error');
}
@@ -111,7 +104,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
* @param string $translationKey
* @param array $parameter
*/
protected function flashException(\Exception $exception, string $translationKey, array $parameter = [])
protected function flashException(\Exception $exception, string $translationKey, array $parameter = []): void
{
$this->logException($exception);
@@ -129,7 +122,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
* @param string $message
* @param array $parameter
*/
protected function addFlashTranslated(string $type, string $message, array $parameter = [])
protected function addFlashTranslated(string $type, string $message, array $parameter = []): void
{
if (!empty($parameter)) {
foreach ($parameter as $key => $value) {
@@ -145,7 +138,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv
$this->addFlash($type, $message);
}
protected function logException(\Exception $ex)
protected function logException(\Exception $ex): void
{
$this->getLogger()->critical($ex->getMessage());
}

View File

@@ -10,7 +10,7 @@
namespace App\Controller\Auth;
use App\Configuration\SystemConfiguration;
use App\Saml\SamlAuth;
use App\Saml\SamlAuthFactory;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -22,12 +22,12 @@ use Symfony\Component\Security\Core\Security;
*/
final class SamlController extends AbstractController
{
private $oneLoginAuth;
private $authFactory;
private $systemConfiguration;
public function __construct(SamlAuth $oneLoginAuth, SystemConfiguration $systemConfiguration)
public function __construct(SamlAuthFactory $authFactory, SystemConfiguration $systemConfiguration)
{
$this->oneLoginAuth = $oneLoginAuth;
$this->authFactory = $authFactory;
$this->systemConfiguration = $systemConfiguration;
}
@@ -59,7 +59,7 @@ final class SamlController extends AbstractController
throw new \RuntimeException($error);
}
$this->oneLoginAuth->login($session->get('_security.main.target_path'));
$this->authFactory->create()->login($session->get('_security.main.target_path'));
}
/**
@@ -71,7 +71,7 @@ final class SamlController extends AbstractController
throw $this->createNotFoundException('SAML deactivated');
}
$metadata = $this->oneLoginAuth->getSettings()->getSPMetadata();
$metadata = $this->authFactory->create()->getSettings()->getSPMetadata();
$response = new Response($metadata);
$response->headers->set('Content-Type', 'xml');

View File

@@ -18,15 +18,15 @@ use App\Form\UserPasswordType;
use App\Form\UserPreferencesForm;
use App\Form\UserRolesType;
use App\Form\UserTeamsType;
use App\Repository\TeamRepository;
use App\Repository\TimesheetRepository;
use App\User\UserService;
use App\Utils\LocaleSettings;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
/**
* User profile controller
@@ -36,29 +36,10 @@ use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
*/
final class ProfileController extends AbstractController
{
/**
* @var EventDispatcherInterface
*/
private $dispatcher;
/**
* @var UserPasswordEncoderInterface
*/
private $encoder;
/**
* @var TeamRepository
*/
private $teams;
public function __construct(UserPasswordEncoderInterface $encoder, EventDispatcherInterface $dispatcher)
{
$this->encoder = $encoder;
$this->dispatcher = $dispatcher;
}
/**
* @Route(path="/", name="my_profile", methods={"GET"})
*/
public function profileAction()
public function profileAction(): Response
{
return $this->redirectToRoute('user_profile', ['username' => $this->getUser()->getUsername()]);
}
@@ -67,7 +48,7 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}", name="user_profile", methods={"GET"})
* @Security("is_granted('view', profile)")
*/
public function indexAction(User $profile, TimesheetRepository $repository, LocaleSettings $localeSettings)
public function indexAction(User $profile, TimesheetRepository $repository, LocaleSettings $localeSettings): Response
{
$userStats = $repository->getUserStatistics($profile);
@@ -91,7 +72,7 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/edit", name="user_profile_edit", methods={"GET", "POST"})
* @Security("is_granted('edit', profile)")
*/
public function editAction(User $profile, Request $request)
public function editAction(User $profile, Request $request): Response
{
$form = $this->createEditForm($profile);
$form->handleRequest($request);
@@ -117,18 +98,13 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/password", name="user_profile_password", methods={"GET", "POST"})
* @Security("is_granted('password', profile)")
*/
public function passwordAction(User $profile, Request $request)
public function passwordAction(User $profile, Request $request, UserService $userService): Response
{
$form = $this->createPasswordForm($profile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$password = $this->encoder->encodePassword($profile, $profile->getPlainPassword());
$profile->setPassword($password);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($profile);
$entityManager->flush();
$userService->updateUser($profile);
$this->flashSuccess('action.update.success');
@@ -146,18 +122,13 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/api-token", name="user_profile_api_token", methods={"GET", "POST"})
* @Security("is_granted('api-token', profile)")
*/
public function apiTokenAction(User $profile, Request $request)
public function apiTokenAction(User $profile, Request $request, UserService $userService): Response
{
$form = $this->createApiTokenForm($profile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$password = $this->encoder->encodePassword($profile, $profile->getPlainApiToken());
$profile->setApiToken($password);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($profile);
$entityManager->flush();
$userService->updateUser($profile);
$this->flashSuccess('action.update.success');
@@ -175,7 +146,7 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/roles", name="user_profile_roles", methods={"GET", "POST"})
* @Security("is_granted('roles', profile)")
*/
public function rolesAction(User $profile, Request $request)
public function rolesAction(User $profile, Request $request): Response
{
$isSuperAdmin = $profile->isSuperAdmin();
@@ -209,7 +180,7 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/teams", name="user_profile_teams", methods={"GET", "POST"})
* @Security("is_granted('teams', profile)")
*/
public function teamsAction(User $profile, Request $request)
public function teamsAction(User $profile, Request $request): Response
{
$form = $this->createTeamsForm($profile);
$form->handleRequest($request);
@@ -235,11 +206,11 @@ final class ProfileController extends AbstractController
* @Route(path="/{username}/prefs", name="user_profile_preferences", methods={"GET", "POST"})
* @Security("is_granted('preferences', profile)")
*/
public function preferencesAction(User $profile, Request $request)
public function preferencesAction(User $profile, Request $request, EventDispatcherInterface $dispatcher): Response
{
// we need to prepare the user preferences, which is done via an EventSubscriber
$event = new PrepareUserEvent($profile);
$this->dispatcher->dispatch($event);
$dispatcher->dispatch($event);
$original = [];
foreach ($profile->getPreferences() as $preference) {

View File

@@ -0,0 +1,195 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Controller\Security;
use App\Configuration\SystemConfiguration;
use App\Controller\AbstractController;
use App\Entity\User;
use App\Event\EmailEvent;
use App\Event\EmailPasswordResetEvent;
use App\Form\PasswordResetForm;
use App\User\LoginManager;
use App\User\UserService;
use DateTime;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* @Route(path="/resetting")
*/
final class PasswordResetController extends AbstractController
{
private $eventDispatcher;
private $userService;
private $configuration;
public function __construct(EventDispatcherInterface $eventDispatcher, UserService $userService, SystemConfiguration $configuration)
{
$this->eventDispatcher = $eventDispatcher;
$this->userService = $userService;
$this->configuration = $configuration;
}
/**
* Request reset user password: show form.
*
* @Route(path="/request", name="fos_user_resetting_request", methods={"GET"})
*/
public function requestAction(): Response
{
if (!$this->configuration->isPasswordResetActive()) {
throw $this->createNotFoundException();
}
return $this->render('security/password-reset/request.html.twig');
}
/**
* Request reset user password: submit form and send email.
*
* @Route(path="/send-email", name="fos_user_resetting_send_email", methods={"POST"})
*/
public function sendEmailAction(Request $request): Response
{
if (!$this->configuration->isPasswordResetActive()) {
throw $this->createNotFoundException();
}
$username = $request->request->get('username');
$user = $this->userService->findUserByUsernameOrEmail($username);
if (null !== $user && !$user->isPasswordRequestNonExpired($this->configuration->getPasswordResetRetryLifetime())) {
if (!$user->isInternalUser()) {
throw $this->createAccessDeniedException(
sprintf('The user "%s" tried to reset the password, but it is registered as "%s" auth-type.', $user->getUsername(), $user->getAuth())
);
}
if (null === $user->getConfirmationToken()) {
$user->setConfirmationToken($this->userService->generateSecurityToken());
}
$mail = $this->generateResettingEmailMessage($user);
$event = new EmailPasswordResetEvent($user, $mail);
$this->eventDispatcher->dispatch($event);
// this will finally send the email
$this->eventDispatcher->dispatch(new EmailEvent($event->getEmail()));
$user->setPasswordRequestedAt(new DateTime());
$this->userService->updateUser($user);
}
return $this->redirectToRoute('fos_user_resetting_check_email', ['username' => $username]);
}
/**
* Tell the user to check his email provider.
*
* @Route(path="/check-email", name="fos_user_resetting_check_email", methods={"GET"})
*/
public function checkEmailAction(Request $request): Response
{
if (!$this->configuration->isPasswordResetActive()) {
throw $this->createNotFoundException();
}
$username = $request->query->get('username');
if (empty($username)) {
// the user does not come from the sendEmail action
return $this->redirectToRoute('fos_user_resetting_request');
}
return $this->render('security/password-reset/check_email.html.twig', [
'tokenLifetime' => ceil($this->configuration->getPasswordResetRetryLifetime() / 3600),
]);
}
/**
* Reset user password.
*
* @Route(path="/reset/{token}", name="fos_user_resetting_reset", methods={"GET", "POST"})
*/
public function resetAction(Request $request, LoginManager $loginManager, ?string $token): Response
{
if (!$this->configuration->isPasswordResetActive()) {
throw $this->createNotFoundException();
}
$user = $this->userService->findUserByConfirmationToken($token);
if (null === $user) {
return $this->redirectToRoute('fos_user_security_login');
}
if (!$user->isPasswordRequestNonExpired($this->configuration->getPasswordResetTokenLifetime())) {
return $this->redirectToRoute('fos_user_resetting_request');
}
$form = $this->createResetForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setConfirmationToken(null);
$user->setPasswordRequestedAt(null);
$user->setEnabled(true);
$this->userService->updateUser($user);
$response = $this->redirectToRoute('my_profile');
$loginManager->logInUser($user, $response);
return $response;
}
return $this->render('security/password-reset/reset.html.twig', [
'token' => $token,
'form' => $form->createView(),
]);
}
private function createResetForm(): FormInterface
{
$options = ['validation_groups' => ['ResetPassword', 'Default']];
return $this->createFormBuilder()->create('fos_user_resetting_form', PasswordResetForm::class, $options)->getForm();
}
private function generateResettingEmailMessage(User $user): Email
{
$username = $user->getDisplayName();
$language = $user->getLanguage();
$url = $this->generateUrl('fos_user_resetting_reset', ['token' => $user->getConfirmationToken()], UrlGeneratorInterface::ABSOLUTE_URL);
return (new TemplatedEmail())
->to(new Address($user->getEmail()))
->subject(
$this->getTranslator()->trans('reset.subject', ['%username%' => $username], 'email', $language)
)
->htmlTemplate('emails/password-reset.html.twig')
->context([
'user' => $user,
'username' => $username,
'confirmationUrl' => $url,
])
;
}
}

View File

@@ -0,0 +1,84 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Controller\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
final class SecurityController extends AbstractController
{
private $tokenManager;
public function __construct(CsrfTokenManagerInterface $tokenManager)
{
$this->tokenManager = $tokenManager;
}
/**
* @Route(path="/login", name="fos_user_security_login", methods={"GET", "POST"})
*/
public function loginAction(Request $request): Response
{
/** @var SessionInterface $session */
$session = $request->getSession();
$authErrorKey = Security::AUTHENTICATION_ERROR;
$lastUsernameKey = Security::LAST_USERNAME;
// get the error if any (works with forward and redirect -- see below)
if ($request->attributes->has($authErrorKey)) {
$error = $request->attributes->get($authErrorKey);
} elseif (null !== $session && $session->has($authErrorKey)) {
$error = $session->get($authErrorKey);
$session->remove($authErrorKey);
} else {
$error = null;
}
if (!$error instanceof AuthenticationException) {
$error = null; // The value does not come from the security component.
}
$lastUsername = '';
if ($request->hasSession()) {
$lastUsername = $session->get($lastUsernameKey);
}
$csrfToken = $this->tokenManager->getToken('authenticate')->getValue();
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => $csrfToken,
]);
}
/**
* @Route(path="/login_check", name="fos_user_security_check", methods={"POST"})
*/
public function checkAction()
{
throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
}
/**
* @Route(path="/logout", name="fos_user_security_logout", methods={"GET", "POST"})
*/
public function logoutAction()
{
throw new \RuntimeException('You must activate the logout in your security firewall configuration.');
}
}

View File

@@ -0,0 +1,212 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Controller\Security;
use App\Configuration\SystemConfiguration;
use App\Controller\AbstractController;
use App\Entity\User;
use App\Event\EmailEvent;
use App\Event\EmailSelfRegistrationEvent;
use App\Form\SelfRegistrationForm;
use App\User\LoginManager;
use App\User\UserService;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* @Route(path="/register")
*/
class SelfRegistrationController extends AbstractController
{
private $eventDispatcher;
private $userService;
private $tokenStorage;
private $configuration;
public function __construct(EventDispatcherInterface $eventDispatcher, UserService $userService, TokenStorageInterface $tokenStorage, SystemConfiguration $configuration)
{
$this->eventDispatcher = $eventDispatcher;
$this->userService = $userService;
$this->tokenStorage = $tokenStorage;
$this->configuration = $configuration;
}
/**
* @Route(path="/", name="fos_user_registration_register", methods={"GET", "POST"})
*/
public function registerAction(Request $request): Response
{
if (!$this->configuration->isSelfRegistrationActive()) {
throw $this->createNotFoundException();
}
$user = $this->userService->createNewUser();
$user->setLanguage($request->getLocale());
$form = $this->createSelfRegistrationForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setEnabled(false);
$user->setConfirmationToken($this->userService->generateSecurityToken());
$mail = $this->generateConfirmationEmail($user);
$event = new EmailSelfRegistrationEvent($user, $mail);
$this->eventDispatcher->dispatch($event);
// this will finally send the email
$this->eventDispatcher->dispatch(new EmailEvent($event->getEmail()));
$request->getSession()->set('fos_user_send_confirmation_email/email', $user->getEmail());
$this->userService->saveNewUser($user);
return $this->redirectToRoute('fos_user_registration_check_email');
}
return $this->render('security/self-registration/register.html.twig', [
'form' => $form->createView(),
]);
}
/**
* Tell the user to check their email provider.
*
* @Route(path="/check-email", name="fos_user_registration_check_email", methods={"GET"})
*/
public function checkEmailAction(Request $request): Response
{
if (!$this->configuration->isSelfRegistrationActive()) {
throw $this->createNotFoundException();
}
$email = $request->getSession()->get('fos_user_send_confirmation_email/email');
if (empty($email)) {
return $this->redirectToRoute('fos_user_registration_register');
}
$request->getSession()->remove('fos_user_send_confirmation_email/email');
$user = $this->userService->findUserByEmail($email);
if (null === $user) {
return $this->redirectToRoute('fos_user_security_login');
}
return $this->render('security/self-registration/check_email.html.twig', [
'user' => $user,
]);
}
/**
* Receive the confirmation token from user email provider, login the user.
*
* @Route(path="/confirm/{token}", name="fos_user_registration_confirm", methods={"GET"})
*/
public function confirmAction(LoginManager $loginManager, ?string $token): Response
{
if (!$this->configuration->isSelfRegistrationActive()) {
throw $this->createNotFoundException();
}
$user = $this->userService->findUserByConfirmationToken($token);
if (null === $user) {
return $this->redirectToRoute('fos_user_security_login');
}
$user->setConfirmationToken(null);
$user->setEnabled(true);
$this->userService->updateUser($user);
$response = $this->redirectToRoute('fos_user_registration_confirmed');
$loginManager->logInUser($user, $response);
return $response;
}
/**
* Tell the user his account is now confirmed.
*
* @Route(path="/confirmed", name="fos_user_registration_confirmed", methods={"GET"})
*/
public function confirmedAction(Request $request): Response
{
if (!$this->configuration->isSelfRegistrationActive()) {
throw $this->createNotFoundException();
}
$user = $this->getUser();
if ($user === null) {
throw $this->createAccessDeniedException('This user does not have access to this section.');
}
return $this->render('security/self-registration/confirmed.html.twig', [
'user' => $user,
'targetUrl' => $this->getTargetUrlFromSession($request->getSession()),
]);
}
private function createSelfRegistrationForm(): FormInterface
{
$options = ['validation_groups' => ['Registration', 'Default']];
return $this->createFormBuilder()->create('fos_user_registration_form', SelfRegistrationForm::class, $options)->getForm();
}
private function getTargetUrlFromSession(SessionInterface $session): ?string
{
$token = $this->tokenStorage->getToken();
if (!method_exists($token, 'getProviderKey')) {
return null;
}
$key = sprintf('_security.%s.target_path', $token->getProviderKey());
if ($session->has($key)) {
return $session->get($key);
}
return null;
}
private function generateConfirmationEmail(User $user): Email
{
$username = $user->getDisplayName();
$language = $user->getLanguage();
$url = $this->generateUrl('fos_user_registration_confirm', ['token' => $user->getConfirmationToken()], UrlGeneratorInterface::ABSOLUTE_URL);
return (new TemplatedEmail())
->to(new Address($user->getEmail()))
->subject(
$this->getTranslator()->trans('registration.subject', ['%username%' => $username], 'email', $language)
)
->htmlTemplate('emails/confirmation.html.twig')
->context([
'user' => $user,
'username' => $username,
'confirmationUrl' => $url,
])
;
}
}

View File

@@ -265,7 +265,60 @@ final class SystemConfigurationController extends AbstractController
}
}
return [
$authentication = (new SystemConfigurationModel())
->setSection(SystemConfigurationModel::SECTION_AUTHENTICATION)
->setConfiguration([
(new Configuration())
->setName('user.login')
->setLabel('user_auth_login')
->setTranslationDomain('system-configuration')
->setType(YesNoType::class),
(new Configuration())
->setName('user.registration')
->setLabel('user_auth_registration')
->setTranslationDomain('system-configuration')
->setType(YesNoType::class),
(new Configuration())
->setName('user.password_reset')
->setTranslationDomain('system-configuration')
->setLabel('user_auth_password_reset')
->setType(YesNoType::class),
(new Configuration())
->setName('user.password_reset_retry_ttl')
->setTranslationDomain('system-configuration')
->setLabel('user_auth_password_reset_retry_ttl')
->setConstraints([new NotNull(), new GreaterThanOrEqual(['value' => 60])])
->setType(IntegerType::class),
(new Configuration())
->setName('user.password_reset_token_ttl')
->setTranslationDomain('system-configuration')
->setLabel('user_auth_password_reset_token_ttl')
->setConstraints([new NotNull(), new GreaterThanOrEqual(['value' => 60])])
->setType(IntegerType::class),
/*
(new Configuration())
->setName('ldap.activate')
->setLabel('ldap_activate')
->setTranslationDomain('system-configuration')
->setType(YesNoType::class),
(new Configuration())
->setName('saml.activate')
->setLabel('saml_activate')
->setTranslationDomain('system-configuration')
->setType(YesNoType::class),
*/
]);
if (!$this->configurations->isSamlActive()) {
$authentication->getConfigurationByName('user.login')->setEnabled(false);
}
if (!$this->configurations->isPasswordResetActive()) {
$authentication->getConfigurationByName('user.password_reset_retry_ttl')->setEnabled(false);
$authentication->getConfigurationByName('user.password_reset_token_ttl')->setEnabled(false);
}
$configurationModels = [
(new SystemConfigurationModel())
->setSection(SystemConfigurationModel::SECTION_TIMESHEET)
->setConfiguration([
@@ -399,6 +452,7 @@ final class SystemConfigurationController extends AbstractController
->setType(YesNoType::class)
->setTranslationDomain('system-configuration'),
]),
$authentication,
(new SystemConfigurationModel())
->setSection(SystemConfigurationModel::SECTION_FORM_CUSTOMER)
->setConfiguration([
@@ -539,5 +593,7 @@ final class SystemConfigurationController extends AbstractController
->setOptions(['input' => 'string']),
]),
];
return $configurationModels;
}
}