NEW FEATURE: settings page
This commit is contained in:
parent
dc09ba2275
commit
56bc06e6f0
2
assets/js/settings.js
Normal file
2
assets/js/settings.js
Normal file
@ -0,0 +1,2 @@
|
||||
import 'bootstrap';
|
||||
import '/assets/scss/settings.scss';
|
4
assets/scss/settings.scss
Normal file
4
assets/scss/settings.scss
Normal file
@ -0,0 +1,4 @@
|
||||
@import "assets/scss/base";
|
||||
@import "assets/scss/icons";
|
||||
@import "/node_modules/@eonasdan/tempus-dominus/dist/css/tempus-dominus.css";
|
||||
@import "assets/scss/tempus-dominus-dark";
|
@ -1,6 +1,6 @@
|
||||
default:
|
||||
path: '/'
|
||||
controller: App\Controller\SecurityController::loginAction
|
||||
controller: App\Controller\UserController::loginAction
|
||||
|
||||
login_check:
|
||||
path: '/login_check'
|
||||
@ -16,13 +16,23 @@ favicon:
|
||||
path: '/favicon.ico'
|
||||
controller: App\Controller\SiteController::faviconAction
|
||||
|
||||
settings:
|
||||
path: '/{_locale}/settings'
|
||||
methods: [ 'GET' ]
|
||||
controller: App\Controller\UserController::settingsAction
|
||||
|
||||
settings_save:
|
||||
path: '/{_locale}/settings'
|
||||
methods: [ 'POST' ]
|
||||
controller: App\Controller\UserController::settingsSaveAction
|
||||
|
||||
default_locale:
|
||||
path: '/{_locale}'
|
||||
controller: App\Controller\SecurityController::loginAction
|
||||
controller: App\Controller\UserController::loginAction
|
||||
|
||||
login:
|
||||
path: '/{_locale}/login'
|
||||
controller: App\Controller\SecurityController::loginAction
|
||||
controller: App\Controller\UserController::loginAction
|
||||
|
||||
job_index:
|
||||
path: '/{_locale}/job'
|
||||
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
|
||||
class SecurityController extends AbstractController
|
||||
{
|
||||
public function loginAction(Request $request, AuthenticationUtils $authenticationUtils): Response
|
||||
{
|
||||
if($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
|
||||
$session = $request->getSession();
|
||||
$user = $this->getUser();
|
||||
$session->set('_locale', $user->getLocale());
|
||||
return new RedirectResponse($this->generateUrl('job_index', ['_locale' => $user->getLocale()]));
|
||||
}
|
||||
// get the login error if there is one
|
||||
$error = $authenticationUtils->getLastAuthenticationError();
|
||||
|
||||
// last username entered by the user
|
||||
$lastUsername = $authenticationUtils->getLastUsername();
|
||||
|
||||
return $this->render('security/login.html.twig', [
|
||||
'controller_name' => 'LoginController',
|
||||
'last_username' => $lastUsername,
|
||||
'error' => $error
|
||||
]);
|
||||
}
|
||||
|
||||
public function logoutAction(): void
|
||||
{
|
||||
// controller can be blank: it will never be called!
|
||||
throw new \Exception('Don\'t forget to activate logout in security.yaml');
|
||||
}
|
||||
|
||||
public function loginCheckAction(): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
107
src/Controller/UserController.php
Normal file
107
src/Controller/UserController.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\User;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
|
||||
class UserController extends AbstractController
|
||||
{
|
||||
public function loginAction(Request $request, AuthenticationUtils $authenticationUtils): Response
|
||||
{
|
||||
if($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
|
||||
$session = $request->getSession();
|
||||
$user = $this->getUser();
|
||||
$session->set('_locale', $user->getLocale());
|
||||
return new RedirectResponse($this->generateUrl('job_index', ['_locale' => $user->getLocale()]));
|
||||
}
|
||||
if($request->cookies->has('logout-notice')) {
|
||||
$this->addFlash('success', 'settings.flashes.passwordsaved');
|
||||
$res = new Response();
|
||||
$res->headers->clearCookie('logout-notice');
|
||||
$res->sendHeaders();
|
||||
}
|
||||
// get the login error if there is one
|
||||
$error = $authenticationUtils->getLastAuthenticationError();
|
||||
|
||||
// last username entered by the user
|
||||
$lastUsername = $authenticationUtils->getLastUsername();
|
||||
|
||||
return $this->render('security/login.html.twig', [
|
||||
'controller_name' => 'LoginController',
|
||||
'last_username' => $lastUsername,
|
||||
'error' => $error
|
||||
]);
|
||||
}
|
||||
|
||||
public function settingsAction(Request $request)
|
||||
{
|
||||
$params['locales'] = $this->getParameter('enabled_locales');
|
||||
$params['user'] = $this->getUser();
|
||||
return $this->render('settings.html.twig', $params);
|
||||
}
|
||||
|
||||
public function settingsSaveAction(Request $request, ManagerRegistry $em, UserPasswordHasherInterface $passwordHasher)
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$data = $request->request->all();
|
||||
$locale = $request->getLocale();
|
||||
$userRepo = $em->getRepository(User::class);
|
||||
$route = 'settings';
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
if(!empty($data['locale']) && $user->getLocale() != $data['locale']) {
|
||||
$error = false;
|
||||
if(!array_key_exists($data['locale'], $this->getParameter('enabled_locales'))) {
|
||||
$error = true;
|
||||
$this->addFlash('danger', 'settings.flashes.inexistinglocale');
|
||||
}
|
||||
if(!$error) {
|
||||
$userRepo->setLocale($user, $data['locale']);
|
||||
$locale = $data['locale'];
|
||||
$this->addFlash('success', 'settings.flashes.localesaved');
|
||||
}
|
||||
}
|
||||
if(!empty($data['current']) && !empty($data['password'])) {
|
||||
$error = false;
|
||||
if (empty($data['repeat']) || ($data['password'] != $data['repeat'])) {
|
||||
$error = true;
|
||||
$this->addFlash('danger', 'settings.flashes.repeatpasswordnotok');
|
||||
} elseif(!$passwordHasher->isPasswordValid($user, $data['current'])) {
|
||||
$error = true;
|
||||
$this->addFlash('danger', 'settings.flashes.currentpassnotok');
|
||||
}
|
||||
if(!$error) {
|
||||
$hashedpass = $passwordHasher->hashPassword($user, $data['password']);
|
||||
$userRepo->setPassword($user, $hashedpass);
|
||||
$cookie = new Cookie('logout-notice', true, (time() + 2), secure: $request->isSecure());
|
||||
$res = new Response();
|
||||
$res->headers->setCookie( $cookie );
|
||||
$res->sendHeaders();
|
||||
$route = 'logout';
|
||||
}
|
||||
}
|
||||
|
||||
return $this->redirect($this->generateUrl($route, ['_locale' => $locale]));
|
||||
}
|
||||
|
||||
public function logoutAction(): void
|
||||
{
|
||||
// controller can be blank: it will never be called!
|
||||
throw new \Exception('Don\'t forget to activate logout in security.yaml');
|
||||
}
|
||||
|
||||
public function loginCheckAction(): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -4,18 +4,25 @@
|
||||
namespace App\Repository;
|
||||
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Service\Secret;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class UserRepository extends EntityRepository
|
||||
{
|
||||
public function getMailAddresses() {
|
||||
$users = $this->findBy(['sendmail' => 1]);
|
||||
public function setLocale(User $user, $locale)
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user->setLocale($locale);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
$return = [];
|
||||
foreach($users as $user) {
|
||||
$return[] = $user->getEmail();
|
||||
}
|
||||
return $return;
|
||||
public function setPassword(User $user, $hashedPassword)
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user->setPassword($hashedPassword);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="{{ path('job_index') }}">{{ 'menu.overview' | trans }}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{{ path('job_add') }}">{{ 'menu.add' | trans }}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{{ path('settings') }}">{{ 'menu.settings' | trans }}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{{ path('logout') }}">{{ 'menu.logout' | trans }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
44
templates/settings.html.twig
Normal file
44
templates/settings.html.twig
Normal file
@ -0,0 +1,44 @@
|
||||
{% extends "base.html.twig" %}
|
||||
{% block title %}{{ "settings.title" | trans }}{% endblock %}
|
||||
{% block content %}
|
||||
<h2>{{ "settings.header" | trans }}</h2>
|
||||
<form method="post" class="form-horizontal" enctype="multipart/form-data" action="{{ path('settings_save') }}">
|
||||
|
||||
<h3>{{ "settings.password.header" | trans }}</h3>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="current">{{ "settings.password.current.label" | trans }}</label>
|
||||
<input type="password" name="current" class="form-control" id="current" placeholder="{{ "settings.password.current.placeholder" | trans }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password">{{ "settings.password.password.label" | trans }}</label>
|
||||
<input type="password" name="password" class="form-control" id="password" placeholder="{{ "settings.password.password.placeholder" | trans }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="repeat">{{ "settings.password.repeat.label" | trans }}</label>
|
||||
<input type="password" name="repeat" class="form-control" id="repeat" placeholder="{{ "settings.password.repeat.placeholder" | trans }}">
|
||||
</div>
|
||||
|
||||
<h3>{{ "settings.other.header" | trans }}</h3>
|
||||
<div class="mb-3">
|
||||
<label for="locale">{{ "settings.other.locale.label" | trans }}</label>
|
||||
<select name="locale" class="form-select">
|
||||
{% for code,locale in locales %}
|
||||
<option value="{{ code }}"{% if code == user.locale %} selected{% endif %}>{{ locale }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-primary">{{ "settings.submit.label" | trans }}</button>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
{{ encore_entry_link_tags('settings') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ encore_entry_script_tags('settings') }}
|
||||
{% endblock %}
|
@ -9,6 +9,7 @@ demomode:
|
||||
menu:
|
||||
overview: "0v3rv13w"
|
||||
add: "4dd @ n3w cr0nj0b"
|
||||
settings: "S3tt1ngz"
|
||||
logout: "L0g0ut"
|
||||
security:
|
||||
login:
|
||||
@ -22,6 +23,32 @@ security:
|
||||
label: "D0 n0t f0rg3t"
|
||||
submit-btn:
|
||||
label: "3nt3r"
|
||||
settings:
|
||||
title: "S3tt1ngz"
|
||||
header: "S3tt1ngz"
|
||||
flashes:
|
||||
inexistinglocale: "L0c4L3 d03z n0t 3x1st"
|
||||
localesaved: "L0c4L3 b s4v3d"
|
||||
repeatpasswordnoto: "P4ssw0rdz 1z n0t 3qu4L"
|
||||
currentpassnotok: "P4ssw0rd b n0t c0rr3ct"
|
||||
passwordsaved: "P4ssw0rd b s4v3d"
|
||||
password:
|
||||
header: "P4ssw0rd"
|
||||
current:
|
||||
label: "Curr3nt p4ssw0rd"
|
||||
placeholder: "abc123"
|
||||
password:
|
||||
label: "N3w p4ssw0rd"
|
||||
placeholder: "abc123"
|
||||
repeat:
|
||||
label: "R3p34t p4ssw0rd"
|
||||
placeholder: "abc123"
|
||||
other:
|
||||
header: "0th3r s3tt1ngz"
|
||||
locale:
|
||||
label: "L0c4L3"
|
||||
submit:
|
||||
label: "Subm1t"
|
||||
job:
|
||||
index:
|
||||
title: "0v3rv13w"
|
||||
|
@ -9,6 +9,7 @@ demomode:
|
||||
menu:
|
||||
overview: "Overview"
|
||||
add: "Add a new cronjob"
|
||||
settings: "Settings"
|
||||
logout: "Logout"
|
||||
security:
|
||||
login:
|
||||
@ -22,6 +23,32 @@ security:
|
||||
label: "Remember, remember"
|
||||
submit-btn:
|
||||
label: "Login"
|
||||
settings:
|
||||
title: "Settings"
|
||||
header: "Settings"
|
||||
flashes:
|
||||
inexistinglocale: "Locale does not exist"
|
||||
localesaved: "Locale is saved"
|
||||
repeatpasswordnoto: "Passwords are not equal"
|
||||
currentpassnotok: "Password is not correct"
|
||||
passwordsaved: "Password is saved"
|
||||
password:
|
||||
header: "Password"
|
||||
current:
|
||||
label: "Current password"
|
||||
placeholder: "abc123"
|
||||
password:
|
||||
label: "New password"
|
||||
placeholder: "abc123"
|
||||
repeat:
|
||||
label: "Repeat password"
|
||||
placeholder: "abc123"
|
||||
other:
|
||||
header: "Other settings"
|
||||
locale:
|
||||
label: "Locale"
|
||||
submit:
|
||||
label: "Submit"
|
||||
job:
|
||||
index:
|
||||
title: "Overview"
|
||||
|
@ -6,10 +6,10 @@ demomode:
|
||||
header: "Aanmeldgegevens voor demo modus:"
|
||||
username: "Gebruikersnaam"
|
||||
password: "Wachtwoord"
|
||||
|
||||
menu:
|
||||
overview: "Overzicht"
|
||||
add: "Taak toevoegen"
|
||||
settings: "Instellingen"
|
||||
logout: "Afmelden"
|
||||
security:
|
||||
login:
|
||||
@ -23,6 +23,32 @@ security:
|
||||
label: "Onthoud mij!"
|
||||
submit-btn:
|
||||
label: "Aanmelden"
|
||||
settings:
|
||||
title: "Instellingen"
|
||||
header: "Instellingen"
|
||||
flashes:
|
||||
inexistinglocale: "Taal bestaat niet"
|
||||
localesaved: "Taal werd opgeslagen"
|
||||
repeatpasswordnotok: "Wachtwoorden zijn niet gelijk"
|
||||
currentpassnotok: "Wachtwoord is not correct"
|
||||
passwordsaved: "Wachtwoord werd opgeslagen"
|
||||
password:
|
||||
header: "Wachtwoord"
|
||||
current:
|
||||
label: "Huidig wachtwoord"
|
||||
placeholder: "abc123"
|
||||
password:
|
||||
label: "Nieuw wachtwoord"
|
||||
placeholder: "abc123"
|
||||
repeat:
|
||||
label: "Herhaal wachtwoord"
|
||||
placeholder: "abc123"
|
||||
other:
|
||||
header: "Andere instellingen"
|
||||
locale:
|
||||
label: "Taal"
|
||||
submit:
|
||||
label: "Verzend!"
|
||||
job:
|
||||
index:
|
||||
title: "Overzicht"
|
||||
|
@ -20,6 +20,7 @@ Encore
|
||||
* Each entry will result in one JavaScript file (e.g. app.js)
|
||||
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
|
||||
*/
|
||||
.addEntry('settings', './assets/js/settings.js')
|
||||
.addEntry('security.login', './assets/js/security/login.js')
|
||||
.addEntry('job.index', './assets/js/job/index.js')
|
||||
.addEntry('job.view', './assets/js/job/view.js')
|
||||
|
Loading…
Reference in New Issue
Block a user