From 56bc06e6f0738625c8771a279a10b0563f9868c4 Mon Sep 17 00:00:00 2001 From: jeroen Date: Thu, 8 Sep 2022 12:28:38 +0200 Subject: [PATCH] NEW FEATURE: settings page --- assets/js/settings.js | 2 + assets/scss/settings.scss | 4 + config/routes.yaml | 16 +++- src/Controller/SecurityController.php | 45 ----------- src/Controller/UserController.php | 107 ++++++++++++++++++++++++++ src/Repository/UserRepository.php | 21 +++-- templates/base.html.twig | 1 + templates/settings.html.twig | 44 +++++++++++ translations/messages.en-l33t.yaml | 27 +++++++ translations/messages.en.yaml | 27 +++++++ translations/messages.nl.yaml | 28 ++++++- webpack.config.js | 1 + 12 files changed, 267 insertions(+), 56 deletions(-) create mode 100644 assets/js/settings.js create mode 100644 assets/scss/settings.scss delete mode 100644 src/Controller/SecurityController.php create mode 100644 src/Controller/UserController.php create mode 100644 templates/settings.html.twig diff --git a/assets/js/settings.js b/assets/js/settings.js new file mode 100644 index 0000000..f4b34c9 --- /dev/null +++ b/assets/js/settings.js @@ -0,0 +1,2 @@ +import 'bootstrap'; +import '/assets/scss/settings.scss'; \ No newline at end of file diff --git a/assets/scss/settings.scss b/assets/scss/settings.scss new file mode 100644 index 0000000..71cf1e0 --- /dev/null +++ b/assets/scss/settings.scss @@ -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"; \ No newline at end of file diff --git a/config/routes.yaml b/config/routes.yaml index 237082b..832948d 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -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' diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php deleted file mode 100644 index 61e44d4..0000000 --- a/src/Controller/SecurityController.php +++ /dev/null @@ -1,45 +0,0 @@ -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 - { - - } -} \ No newline at end of file diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php new file mode 100644 index 0000000..db45fce --- /dev/null +++ b/src/Controller/UserController.php @@ -0,0 +1,107 @@ +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 + { + + } +} \ No newline at end of file diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 73a1b6e..740b70a 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -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(); } } \ No newline at end of file diff --git a/templates/base.html.twig b/templates/base.html.twig index 723bb00..8806383 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -25,6 +25,7 @@ diff --git a/templates/settings.html.twig b/templates/settings.html.twig new file mode 100644 index 0000000..5e8e1ef --- /dev/null +++ b/templates/settings.html.twig @@ -0,0 +1,44 @@ +{% extends "base.html.twig" %} +{% block title %}{{ "settings.title" | trans }}{% endblock %} +{% block content %} +

{{ "settings.header" | trans }}

+
+ +

{{ "settings.password.header" | trans }}

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +

{{ "settings.other.header" | trans }}

+
+ + +
+ +
+ +{% endblock %} + +{% block styles %} + {{ encore_entry_link_tags('settings') }} +{% endblock %} + +{% block scripts %} + {{ encore_entry_script_tags('settings') }} +{% endblock %} \ No newline at end of file diff --git a/translations/messages.en-l33t.yaml b/translations/messages.en-l33t.yaml index 37eea5f..4696c29 100644 --- a/translations/messages.en-l33t.yaml +++ b/translations/messages.en-l33t.yaml @@ -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" diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index e75f5f3..2930bbe 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -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" diff --git a/translations/messages.nl.yaml b/translations/messages.nl.yaml index 818f69f..0cfdd86 100644 --- a/translations/messages.nl.yaml +++ b/translations/messages.nl.yaml @@ -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" diff --git a/webpack.config.js b/webpack.config.js index 091a0de..9af2a43 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -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')