From ef00f9d2033f6de11e71bf3a909399cae6f73a9f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 13:35:48 +0200 Subject: Process password change controller through Slim --- .../front/controller/admin/PasswordController.php | 100 +++++++++++++++++++++ .../controller/admin/ShaarliAdminController.php | 59 ++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 application/front/controller/admin/PasswordController.php (limited to 'application/front/controller/admin') diff --git a/application/front/controller/admin/PasswordController.php b/application/front/controller/admin/PasswordController.php new file mode 100644 index 00000000..6e8f0bcb --- /dev/null +++ b/application/front/controller/admin/PasswordController.php @@ -0,0 +1,100 @@ +assignView( + 'pagetitle', + t('Change password') .' - '. $this->container->conf->get('general.title', 'Shaarli') + ); + } + + /** + * GET /password - Displays the change password template + */ + public function index(Request $request, Response $response): Response + { + return $response->write($this->render('changepassword')); + } + + /** + * POST /password - Change admin password - existing and new passwords need to be provided. + */ + public function change(Request $request, Response $response): Response + { + $this->checkToken($request); + + if ($this->container->conf->get('security.open_shaarli', false)) { + throw new OpenShaarliPasswordException(); + } + + $oldPassword = $request->getParam('oldpassword'); + $newPassword = $request->getParam('setpassword'); + + if (empty($newPassword) || empty($oldPassword)) { + $this->saveErrorMessage(t('You must provide the current and new password to change it.')); + + return $response + ->withStatus(400) + ->write($this->render('changepassword')) + ; + } + + // Make sure old password is correct. + $oldHash = sha1( + $oldPassword . + $this->container->conf->get('credentials.login') . + $this->container->conf->get('credentials.salt') + ); + + if ($oldHash !== $this->container->conf->get('credentials.hash')) { + $this->saveErrorMessage(t('The old password is not correct.')); + + return $response + ->withStatus(400) + ->write($this->render('changepassword')) + ; + } + + // Save new password + // Salt renders rainbow-tables attacks useless. + $this->container->conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand())); + $this->container->conf->set( + 'credentials.hash', + sha1( + $newPassword + . $this->container->conf->get('credentials.login') + . $this->container->conf->get('credentials.salt') + ) + ); + + try { + $this->container->conf->write($this->container->loginManager->isLoggedIn()); + } catch (Throwable $e) { + throw new ShaarliFrontException($e->getMessage(), 500, $e); + } + + $this->saveSuccessMessage(t('Your password has been changed')); + + return $response->write($this->render('changepassword')); + } +} diff --git a/application/front/controller/admin/ShaarliAdminController.php b/application/front/controller/admin/ShaarliAdminController.php index ea703f62..3385006c 100644 --- a/application/front/controller/admin/ShaarliAdminController.php +++ b/application/front/controller/admin/ShaarliAdminController.php @@ -7,7 +7,19 @@ namespace Shaarli\Front\Controller\Admin; use Shaarli\Container\ShaarliContainer; use Shaarli\Front\Controller\Visitor\ShaarliVisitorController; use Shaarli\Front\Exception\UnauthorizedException; +use Shaarli\Front\Exception\WrongTokenException; +use Shaarli\Security\SessionManager; +use Slim\Http\Request; +/** + * Class ShaarliAdminController + * + * All admin controllers (for logged in users) MUST extend this abstract class. + * It makes sure that the user is properly logged in, and otherwise throw an exception + * which will redirect to the login page. + * + * @package Shaarli\Front\Controller\Admin + */ abstract class ShaarliAdminController extends ShaarliVisitorController { public function __construct(ShaarliContainer $container) @@ -18,4 +30,51 @@ abstract class ShaarliAdminController extends ShaarliVisitorController throw new UnauthorizedException(); } } + + /** + * Any persistent action to the config or data store must check the XSRF token validity. + */ + protected function checkToken(Request $request): void + { + if (!$this->container->sessionManager->checkToken($request->getParam('token'))) { + throw new WrongTokenException(); + } + } + + /** + * Save a SUCCESS message in user session, which will be displayed on any template page. + */ + protected function saveSuccessMessage(string $message): void + { + $this->saveMessage(SessionManager::KEY_SUCCESS_MESSAGES, $message); + } + + /** + * Save a WARNING message in user session, which will be displayed on any template page. + */ + protected function saveWarningMessage(string $message): void + { + $this->saveMessage(SessionManager::KEY_WARNING_MESSAGES, $message); + } + + /** + * Save an ERROR message in user session, which will be displayed on any template page. + */ + protected function saveErrorMessage(string $message): void + { + $this->saveMessage(SessionManager::KEY_ERROR_MESSAGES, $message); + } + + /** + * Use the sessionManager to save the provided message using the proper type. + * + * @param string $type successed/warnings/errors + */ + protected function saveMessage(string $type, string $message): void + { + $messages = $this->container->sessionManager->getSessionParameter($type) ?? []; + $messages[] = $message; + + $this->container->sessionManager->setSessionParameter($type, $messages); + } } -- cgit v1.2.3