diff options
24 files changed, 450 insertions, 182 deletions
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Admin; | ||
6 | |||
7 | use Shaarli\Container\ShaarliContainer; | ||
8 | use Shaarli\Front\Exception\OpenShaarliPasswordException; | ||
9 | use Shaarli\Front\Exception\ShaarliFrontException; | ||
10 | use Slim\Http\Request; | ||
11 | use Slim\Http\Response; | ||
12 | use Throwable; | ||
13 | |||
14 | /** | ||
15 | * Class PasswordController | ||
16 | * | ||
17 | * Slim controller used to handle passwords update. | ||
18 | */ | ||
19 | class PasswordController extends ShaarliAdminController | ||
20 | { | ||
21 | public function __construct(ShaarliContainer $container) | ||
22 | { | ||
23 | parent::__construct($container); | ||
24 | |||
25 | $this->assignView( | ||
26 | 'pagetitle', | ||
27 | t('Change password') .' - '. $this->container->conf->get('general.title', 'Shaarli') | ||
28 | ); | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * GET /password - Displays the change password template | ||
33 | */ | ||
34 | public function index(Request $request, Response $response): Response | ||
35 | { | ||
36 | return $response->write($this->render('changepassword')); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * POST /password - Change admin password - existing and new passwords need to be provided. | ||
41 | */ | ||
42 | public function change(Request $request, Response $response): Response | ||
43 | { | ||
44 | $this->checkToken($request); | ||
45 | |||
46 | if ($this->container->conf->get('security.open_shaarli', false)) { | ||
47 | throw new OpenShaarliPasswordException(); | ||
48 | } | ||
49 | |||
50 | $oldPassword = $request->getParam('oldpassword'); | ||
51 | $newPassword = $request->getParam('setpassword'); | ||
52 | |||
53 | if (empty($newPassword) || empty($oldPassword)) { | ||
54 | $this->saveErrorMessage(t('You must provide the current and new password to change it.')); | ||
55 | |||
56 | return $response | ||
57 | ->withStatus(400) | ||
58 | ->write($this->render('changepassword')) | ||
59 | ; | ||
60 | } | ||
61 | |||
62 | // Make sure old password is correct. | ||
63 | $oldHash = sha1( | ||
64 | $oldPassword . | ||
65 | $this->container->conf->get('credentials.login') . | ||
66 | $this->container->conf->get('credentials.salt') | ||
67 | ); | ||
68 | |||
69 | if ($oldHash !== $this->container->conf->get('credentials.hash')) { | ||
70 | $this->saveErrorMessage(t('The old password is not correct.')); | ||
71 | |||
72 | return $response | ||
73 | ->withStatus(400) | ||
74 | ->write($this->render('changepassword')) | ||
75 | ; | ||
76 | } | ||
77 | |||
78 | // Save new password | ||
79 | // Salt renders rainbow-tables attacks useless. | ||
80 | $this->container->conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand())); | ||
81 | $this->container->conf->set( | ||
82 | 'credentials.hash', | ||
83 | sha1( | ||
84 | $newPassword | ||
85 | . $this->container->conf->get('credentials.login') | ||
86 | . $this->container->conf->get('credentials.salt') | ||
87 | ) | ||
88 | ); | ||
89 | |||
90 | try { | ||
91 | $this->container->conf->write($this->container->loginManager->isLoggedIn()); | ||
92 | } catch (Throwable $e) { | ||
93 | throw new ShaarliFrontException($e->getMessage(), 500, $e); | ||
94 | } | ||
95 | |||
96 | $this->saveSuccessMessage(t('Your password has been changed')); | ||
97 | |||
98 | return $response->write($this->render('changepassword')); | ||
99 | } | ||
100 | } | ||
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; | |||
7 | use Shaarli\Container\ShaarliContainer; | 7 | use Shaarli\Container\ShaarliContainer; |
8 | use Shaarli\Front\Controller\Visitor\ShaarliVisitorController; | 8 | use Shaarli\Front\Controller\Visitor\ShaarliVisitorController; |
9 | use Shaarli\Front\Exception\UnauthorizedException; | 9 | use Shaarli\Front\Exception\UnauthorizedException; |
10 | use Shaarli\Front\Exception\WrongTokenException; | ||
11 | use Shaarli\Security\SessionManager; | ||
12 | use Slim\Http\Request; | ||
10 | 13 | ||
14 | /** | ||
15 | * Class ShaarliAdminController | ||
16 | * | ||
17 | * All admin controllers (for logged in users) MUST extend this abstract class. | ||
18 | * It makes sure that the user is properly logged in, and otherwise throw an exception | ||
19 | * which will redirect to the login page. | ||
20 | * | ||
21 | * @package Shaarli\Front\Controller\Admin | ||
22 | */ | ||
11 | abstract class ShaarliAdminController extends ShaarliVisitorController | 23 | abstract class ShaarliAdminController extends ShaarliVisitorController |
12 | { | 24 | { |
13 | public function __construct(ShaarliContainer $container) | 25 | public function __construct(ShaarliContainer $container) |
@@ -18,4 +30,51 @@ abstract class ShaarliAdminController extends ShaarliVisitorController | |||
18 | throw new UnauthorizedException(); | 30 | throw new UnauthorizedException(); |
19 | } | 31 | } |
20 | } | 32 | } |
33 | |||
34 | /** | ||
35 | * Any persistent action to the config or data store must check the XSRF token validity. | ||
36 | */ | ||
37 | protected function checkToken(Request $request): void | ||
38 | { | ||
39 | if (!$this->container->sessionManager->checkToken($request->getParam('token'))) { | ||
40 | throw new WrongTokenException(); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Save a SUCCESS message in user session, which will be displayed on any template page. | ||
46 | */ | ||
47 | protected function saveSuccessMessage(string $message): void | ||
48 | { | ||
49 | $this->saveMessage(SessionManager::KEY_SUCCESS_MESSAGES, $message); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Save a WARNING message in user session, which will be displayed on any template page. | ||
54 | */ | ||
55 | protected function saveWarningMessage(string $message): void | ||
56 | { | ||
57 | $this->saveMessage(SessionManager::KEY_WARNING_MESSAGES, $message); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Save an ERROR message in user session, which will be displayed on any template page. | ||
62 | */ | ||
63 | protected function saveErrorMessage(string $message): void | ||
64 | { | ||
65 | $this->saveMessage(SessionManager::KEY_ERROR_MESSAGES, $message); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Use the sessionManager to save the provided message using the proper type. | ||
70 | * | ||
71 | * @param string $type successed/warnings/errors | ||
72 | */ | ||
73 | protected function saveMessage(string $type, string $message): void | ||
74 | { | ||
75 | $messages = $this->container->sessionManager->getSessionParameter($type) ?? []; | ||
76 | $messages[] = $message; | ||
77 | |||
78 | $this->container->sessionManager->setSessionParameter($type, $messages); | ||
79 | } | ||
21 | } | 80 | } |
diff --git a/application/front/controller/visitor/ShaarliVisitorController.php b/application/front/controller/visitor/ShaarliVisitorController.php index 655b3baa..f12915c1 100644 --- a/application/front/controller/visitor/ShaarliVisitorController.php +++ b/application/front/controller/visitor/ShaarliVisitorController.php | |||
@@ -9,6 +9,14 @@ use Shaarli\Container\ShaarliContainer; | |||
9 | use Slim\Http\Request; | 9 | use Slim\Http\Request; |
10 | use Slim\Http\Response; | 10 | use Slim\Http\Response; |
11 | 11 | ||
12 | /** | ||
13 | * Class ShaarliVisitorController | ||
14 | * | ||
15 | * All controllers accessible by visitors (non logged in users) should extend this abstract class. | ||
16 | * Contains a few helper function for template rendering, plugins, etc. | ||
17 | * | ||
18 | * @package Shaarli\Front\Controller\Visitor | ||
19 | */ | ||
12 | abstract class ShaarliVisitorController | 20 | abstract class ShaarliVisitorController |
13 | { | 21 | { |
14 | /** @var ShaarliContainer */ | 22 | /** @var ShaarliContainer */ |
diff --git a/application/front/exceptions/OpenShaarliPasswordException.php b/application/front/exceptions/OpenShaarliPasswordException.php new file mode 100644 index 00000000..a6f0b3ae --- /dev/null +++ b/application/front/exceptions/OpenShaarliPasswordException.php | |||
@@ -0,0 +1,18 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Exception; | ||
6 | |||
7 | /** | ||
8 | * Class OpenShaarliPasswordException | ||
9 | * | ||
10 | * Raised if the user tries to change the admin password on an open shaarli instance. | ||
11 | */ | ||
12 | class OpenShaarliPasswordException extends ShaarliFrontException | ||
13 | { | ||
14 | public function __construct() | ||
15 | { | ||
16 | parent::__construct(t('You are not supposed to change a password on an Open Shaarli.'), 403); | ||
17 | } | ||
18 | } | ||
diff --git a/application/front/exceptions/ShaarliFrontException.php b/application/front/exceptions/ShaarliFrontException.php index fc8eb92b..73847e6d 100644 --- a/application/front/exceptions/ShaarliFrontException.php +++ b/application/front/exceptions/ShaarliFrontException.php | |||
@@ -9,11 +9,11 @@ use Throwable; | |||
9 | /** | 9 | /** |
10 | * Class ShaarliException | 10 | * Class ShaarliException |
11 | * | 11 | * |
12 | * Abstract exception class used to defined any custom exception thrown during front rendering. | 12 | * Exception class used to defined any custom exception thrown during front rendering. |
13 | * | 13 | * |
14 | * @package Front\Exception | 14 | * @package Front\Exception |
15 | */ | 15 | */ |
16 | abstract class ShaarliFrontException extends \Exception | 16 | class ShaarliFrontException extends \Exception |
17 | { | 17 | { |
18 | /** Override parent constructor to force $message and $httpCode parameters to be set. */ | 18 | /** Override parent constructor to force $message and $httpCode parameters to be set. */ |
19 | public function __construct(string $message, int $httpCode, Throwable $previous = null) | 19 | public function __construct(string $message, int $httpCode, Throwable $previous = null) |
diff --git a/application/front/exceptions/WrongTokenException.php b/application/front/exceptions/WrongTokenException.php new file mode 100644 index 00000000..42002720 --- /dev/null +++ b/application/front/exceptions/WrongTokenException.php | |||
@@ -0,0 +1,18 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Exception; | ||
6 | |||
7 | /** | ||
8 | * Class OpenShaarliPasswordException | ||
9 | * | ||
10 | * Raised if the user tries to perform an action with an invalid XSRF token. | ||
11 | */ | ||
12 | class WrongTokenException extends ShaarliFrontException | ||
13 | { | ||
14 | public function __construct() | ||
15 | { | ||
16 | parent::__construct(t('Wrong token.'), 403); | ||
17 | } | ||
18 | } | ||
diff --git a/application/render/PageBuilder.php b/application/render/PageBuilder.php index f4fefda8..264cd33b 100644 --- a/application/render/PageBuilder.php +++ b/application/render/PageBuilder.php | |||
@@ -7,6 +7,7 @@ use RainTPL; | |||
7 | use Shaarli\ApplicationUtils; | 7 | use Shaarli\ApplicationUtils; |
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | 8 | use Shaarli\Bookmark\BookmarkServiceInterface; |
9 | use Shaarli\Config\ConfigManager; | 9 | use Shaarli\Config\ConfigManager; |
10 | use Shaarli\Security\SessionManager; | ||
10 | use Shaarli\Thumbnailer; | 11 | use Shaarli\Thumbnailer; |
11 | 12 | ||
12 | /** | 13 | /** |
@@ -136,17 +137,28 @@ class PageBuilder | |||
136 | $this->tpl->assign('thumbnails_width', $this->conf->get('thumbnails.width')); | 137 | $this->tpl->assign('thumbnails_width', $this->conf->get('thumbnails.width')); |
137 | $this->tpl->assign('thumbnails_height', $this->conf->get('thumbnails.height')); | 138 | $this->tpl->assign('thumbnails_height', $this->conf->get('thumbnails.height')); |
138 | 139 | ||
139 | if (!empty($_SESSION['warnings'])) { | ||
140 | $this->tpl->assign('global_warnings', $_SESSION['warnings']); | ||
141 | unset($_SESSION['warnings']); | ||
142 | } | ||
143 | |||
144 | $this->tpl->assign('formatter', $this->conf->get('formatter', 'default')); | 140 | $this->tpl->assign('formatter', $this->conf->get('formatter', 'default')); |
145 | 141 | ||
146 | // To be removed with a proper theme configuration. | 142 | // To be removed with a proper theme configuration. |
147 | $this->tpl->assign('conf', $this->conf); | 143 | $this->tpl->assign('conf', $this->conf); |
148 | } | 144 | } |
149 | 145 | ||
146 | protected function finalize(): void | ||
147 | { | ||
148 | // TODO: use the SessionManager | ||
149 | $messageKeys = [ | ||
150 | SessionManager::KEY_SUCCESS_MESSAGES, | ||
151 | SessionManager::KEY_WARNING_MESSAGES, | ||
152 | SessionManager::KEY_ERROR_MESSAGES | ||
153 | ]; | ||
154 | foreach ($messageKeys as $messageKey) { | ||
155 | if (!empty($_SESSION[$messageKey])) { | ||
156 | $this->tpl->assign('global_' . $messageKey, $_SESSION[$messageKey]); | ||
157 | unset($_SESSION[$messageKey]); | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
150 | /** | 162 | /** |
151 | * The following assign() method is basically the same as RainTPL (except lazy loading) | 163 | * The following assign() method is basically the same as RainTPL (except lazy loading) |
152 | * | 164 | * |
@@ -196,6 +208,8 @@ class PageBuilder | |||
196 | $this->initialize(); | 208 | $this->initialize(); |
197 | } | 209 | } |
198 | 210 | ||
211 | $this->finalize(); | ||
212 | |||
199 | $this->tpl->draw($page); | 213 | $this->tpl->draw($page); |
200 | } | 214 | } |
201 | 215 | ||
@@ -213,6 +227,8 @@ class PageBuilder | |||
213 | $this->initialize(); | 227 | $this->initialize(); |
214 | } | 228 | } |
215 | 229 | ||
230 | $this->finalize(); | ||
231 | |||
216 | return $this->tpl->draw($page, true); | 232 | return $this->tpl->draw($page, true); |
217 | } | 233 | } |
218 | 234 | ||
diff --git a/application/security/SessionManager.php b/application/security/SessionManager.php index 8b77d362..0ac17d9a 100644 --- a/application/security/SessionManager.php +++ b/application/security/SessionManager.php | |||
@@ -12,6 +12,10 @@ class SessionManager | |||
12 | public const KEY_VISIBILITY = 'visibility'; | 12 | public const KEY_VISIBILITY = 'visibility'; |
13 | public const KEY_UNTAGGED_ONLY = 'untaggedonly'; | 13 | public const KEY_UNTAGGED_ONLY = 'untaggedonly'; |
14 | 14 | ||
15 | public const KEY_SUCCESS_MESSAGES = 'successes'; | ||
16 | public const KEY_WARNING_MESSAGES = 'warnings'; | ||
17 | public const KEY_ERROR_MESSAGES = 'errors'; | ||
18 | |||
15 | /** @var int Session expiration timeout, in seconds */ | 19 | /** @var int Session expiration timeout, in seconds */ |
16 | public static $SHORT_TIMEOUT = 3600; // 1 hour | 20 | public static $SHORT_TIMEOUT = 3600; // 1 hour |
17 | 21 | ||
@@ -507,56 +507,8 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
507 | 507 | ||
508 | // -------- User wants to change his/her password. | 508 | // -------- User wants to change his/her password. |
509 | if ($targetPage == Router::$PAGE_CHANGEPASSWORD) { | 509 | if ($targetPage == Router::$PAGE_CHANGEPASSWORD) { |
510 | if ($conf->get('security.open_shaarli')) { | 510 | header('Location: ./password'); |
511 | die(t('You are not supposed to change a password on an Open Shaarli.')); | 511 | exit; |
512 | } | ||
513 | |||
514 | if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) { | ||
515 | if (!$sessionManager->checkToken($_POST['token'])) { | ||
516 | die(t('Wrong token.')); // Go away! | ||
517 | } | ||
518 | |||
519 | // Make sure old password is correct. | ||
520 | $oldhash = sha1( | ||
521 | $_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt') | ||
522 | ); | ||
523 | if ($oldhash != $conf->get('credentials.hash')) { | ||
524 | echo '<script>alert("' | ||
525 | . t('The old password is not correct.') | ||
526 | .'");document.location=\'./?do=changepasswd\';</script>'; | ||
527 | exit; | ||
528 | } | ||
529 | // Save new password | ||
530 | // Salt renders rainbow-tables attacks useless. | ||
531 | $conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand())); | ||
532 | $conf->set( | ||
533 | 'credentials.hash', | ||
534 | sha1( | ||
535 | $_POST['setpassword'] | ||
536 | . $conf->get('credentials.login') | ||
537 | . $conf->get('credentials.salt') | ||
538 | ) | ||
539 | ); | ||
540 | try { | ||
541 | $conf->write($loginManager->isLoggedIn()); | ||
542 | } catch (Exception $e) { | ||
543 | error_log( | ||
544 | 'ERROR while writing config file after changing password.' . PHP_EOL . | ||
545 | $e->getMessage() | ||
546 | ); | ||
547 | |||
548 | // TODO: do not handle exceptions/errors in JS. | ||
549 | echo '<script>alert("'. $e->getMessage() .'");document.location=\'./tools\';</script>'; | ||
550 | exit; | ||
551 | } | ||
552 | echo '<script>alert("'. t('Your password has been changed') .'");document.location=\'./tools\';</script>'; | ||
553 | exit; | ||
554 | } else { | ||
555 | // show the change password form. | ||
556 | $PAGE->assign('pagetitle', t('Change password') .' - '. $conf->get('general.title', 'Shaarli')); | ||
557 | $PAGE->renderPage('changepassword'); | ||
558 | exit; | ||
559 | } | ||
560 | } | 512 | } |
561 | 513 | ||
562 | // -------- User wants to change configuration | 514 | // -------- User wants to change configuration |
@@ -1504,6 +1456,8 @@ $app->group('', function () { | |||
1504 | /* -- LOGGED IN -- */ | 1456 | /* -- LOGGED IN -- */ |
1505 | $this->get('/logout', '\Shaarli\Front\Controller\Admin\LogoutController:index')->setName('logout'); | 1457 | $this->get('/logout', '\Shaarli\Front\Controller\Admin\LogoutController:index')->setName('logout'); |
1506 | $this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools'); | 1458 | $this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools'); |
1459 | $this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password'); | ||
1460 | $this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword'); | ||
1507 | 1461 | ||
1508 | $this | 1462 | $this |
1509 | ->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage') | 1463 | ->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage') |
diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php index 94581c09..bd40c0c7 100644 --- a/tests/front/controller/admin/FrontAdminControllerMockHelper.php +++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php | |||
@@ -6,7 +6,6 @@ namespace Shaarli\Front\Controller\Admin; | |||
6 | 6 | ||
7 | use Shaarli\Container\ShaarliTestContainer; | 7 | use Shaarli\Container\ShaarliTestContainer; |
8 | use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper; | 8 | use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper; |
9 | use Shaarli\Security\LoginManager; | ||
10 | 9 | ||
11 | /** | 10 | /** |
12 | * Trait FrontControllerMockHelper | 11 | * Trait FrontControllerMockHelper |
@@ -28,7 +27,7 @@ trait FrontAdminControllerMockHelper | |||
28 | { | 27 | { |
29 | $this->parentCreateContainer(); | 28 | $this->parentCreateContainer(); |
30 | 29 | ||
31 | $this->container->loginManager = $this->createMock(LoginManager::class); | ||
32 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | 30 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); |
31 | $this->container->sessionManager->method('checkToken')->willReturn(true); | ||
33 | } | 32 | } |
34 | } | 33 | } |
diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index ba681b16..78a0fe73 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php | |||
@@ -35,8 +35,6 @@ class LogoutControllerTest extends TestCase | |||
35 | 35 | ||
36 | public function testValidControllerInvoke(): void | 36 | public function testValidControllerInvoke(): void |
37 | { | 37 | { |
38 | $this->createValidContainerMockSet(); | ||
39 | |||
40 | $request = $this->createMock(Request::class); | 38 | $request = $this->createMock(Request::class); |
41 | $response = new Response(); | 39 | $response = new Response(); |
42 | 40 | ||
diff --git a/tests/front/controller/admin/PasswordControllerTest.php b/tests/front/controller/admin/PasswordControllerTest.php new file mode 100644 index 00000000..7262243e --- /dev/null +++ b/tests/front/controller/admin/PasswordControllerTest.php | |||
@@ -0,0 +1,186 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Admin; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Config\ConfigManager; | ||
9 | use Shaarli\Front\Exception\WrongTokenException; | ||
10 | use Shaarli\Security\SessionManager; | ||
11 | use Slim\Http\Request; | ||
12 | use Slim\Http\Response; | ||
13 | |||
14 | class PasswordControllerTest extends TestCase | ||
15 | { | ||
16 | use FrontAdminControllerMockHelper; | ||
17 | |||
18 | /** @var PasswordController */ | ||
19 | protected $controller; | ||
20 | |||
21 | /** @var mixed[] Variables assigned to the template */ | ||
22 | protected $assignedVariables = []; | ||
23 | |||
24 | public function setUp(): void | ||
25 | { | ||
26 | $this->createContainer(); | ||
27 | $this->assignTemplateVars($this->assignedVariables); | ||
28 | |||
29 | $this->controller = new PasswordController($this->container); | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * Test displaying the change password page. | ||
34 | */ | ||
35 | public function testGetPage(): void | ||
36 | { | ||
37 | $request = $this->createMock(Request::class); | ||
38 | $response = new Response(); | ||
39 | |||
40 | $result = $this->controller->index($request, $response); | ||
41 | |||
42 | static::assertSame(200, $result->getStatusCode()); | ||
43 | static::assertSame('changepassword', (string) $result->getBody()); | ||
44 | static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Change the password with valid parameters | ||
49 | */ | ||
50 | public function testPostNewPasswordDefault(): void | ||
51 | { | ||
52 | $request = $this->createMock(Request::class); | ||
53 | $request->method('getParam')->willReturnCallback(function (string $key): string { | ||
54 | if ('oldpassword' === $key) { | ||
55 | return 'old'; | ||
56 | } | ||
57 | if ('setpassword' === $key) { | ||
58 | return 'new'; | ||
59 | } | ||
60 | |||
61 | return $key; | ||
62 | }); | ||
63 | $response = new Response(); | ||
64 | |||
65 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
66 | $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { | ||
67 | if ('credentials.hash' === $key) { | ||
68 | return sha1('old' . 'credentials.login' . 'credentials.salt'); | ||
69 | } | ||
70 | |||
71 | return strpos($key, 'credentials') !== false ? $key : $default; | ||
72 | }); | ||
73 | $this->container->conf->expects(static::once())->method('write')->with(true); | ||
74 | |||
75 | $this->container->conf | ||
76 | ->method('set') | ||
77 | ->willReturnCallback(function (string $key, string $value) { | ||
78 | if ('credentials.hash' === $key) { | ||
79 | static::assertSame(sha1('new' . 'credentials.login' . 'credentials.salt'), $value); | ||
80 | } | ||
81 | }) | ||
82 | ; | ||
83 | |||
84 | $result = $this->controller->change($request, $response); | ||
85 | |||
86 | static::assertSame(200, $result->getStatusCode()); | ||
87 | static::assertSame('changepassword', (string) $result->getBody()); | ||
88 | static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Change the password with a wrong existing password | ||
93 | */ | ||
94 | public function testPostNewPasswordWrongOldPassword(): void | ||
95 | { | ||
96 | $request = $this->createMock(Request::class); | ||
97 | $request->method('getParam')->willReturnCallback(function (string $key): string { | ||
98 | if ('oldpassword' === $key) { | ||
99 | return 'wrong'; | ||
100 | } | ||
101 | if ('setpassword' === $key) { | ||
102 | return 'new'; | ||
103 | } | ||
104 | |||
105 | return $key; | ||
106 | }); | ||
107 | $response = new Response(); | ||
108 | |||
109 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
110 | $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { | ||
111 | if ('credentials.hash' === $key) { | ||
112 | return sha1('old' . 'credentials.login' . 'credentials.salt'); | ||
113 | } | ||
114 | |||
115 | return strpos($key, 'credentials') !== false ? $key : $default; | ||
116 | }); | ||
117 | |||
118 | $this->container->conf->expects(static::never())->method('set'); | ||
119 | $this->container->conf->expects(static::never())->method('write'); | ||
120 | |||
121 | $this->container->sessionManager | ||
122 | ->expects(static::once()) | ||
123 | ->method('setSessionParameter') | ||
124 | ->with(SessionManager::KEY_ERROR_MESSAGES, ['The old password is not correct.']) | ||
125 | ; | ||
126 | |||
127 | $result = $this->controller->change($request, $response); | ||
128 | |||
129 | static::assertSame(400, $result->getStatusCode()); | ||
130 | static::assertSame('changepassword', (string) $result->getBody()); | ||
131 | static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Change the password with a wrong existing password | ||
136 | */ | ||
137 | public function testPostNewPasswordWrongToken(): void | ||
138 | { | ||
139 | $this->container->sessionManager = $this->createMock(SessionManager::class); | ||
140 | $this->container->sessionManager->method('checkToken')->willReturn(false); | ||
141 | |||
142 | $this->container->conf->expects(static::never())->method('set'); | ||
143 | $this->container->conf->expects(static::never())->method('write'); | ||
144 | |||
145 | $request = $this->createMock(Request::class); | ||
146 | $response = new Response(); | ||
147 | |||
148 | $this->expectException(WrongTokenException::class); | ||
149 | |||
150 | $this->controller->change($request, $response); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Change the password with an empty new password | ||
155 | */ | ||
156 | public function testPostNewEmptyPassword(): void | ||
157 | { | ||
158 | $this->container->sessionManager | ||
159 | ->expects(static::once()) | ||
160 | ->method('setSessionParameter') | ||
161 | ->with(SessionManager::KEY_ERROR_MESSAGES, ['You must provide the current and new password to change it.']) | ||
162 | ; | ||
163 | |||
164 | $this->container->conf->expects(static::never())->method('set'); | ||
165 | $this->container->conf->expects(static::never())->method('write'); | ||
166 | |||
167 | $request = $this->createMock(Request::class); | ||
168 | $request->method('getParam')->willReturnCallback(function (string $key): string { | ||
169 | if ('oldpassword' === $key) { | ||
170 | return 'old'; | ||
171 | } | ||
172 | if ('setpassword' === $key) { | ||
173 | return ''; | ||
174 | } | ||
175 | |||
176 | return $key; | ||
177 | }); | ||
178 | $response = new Response(); | ||
179 | |||
180 | $result = $this->controller->change($request, $response); | ||
181 | |||
182 | static::assertSame(400, $result->getStatusCode()); | ||
183 | static::assertSame('changepassword', (string) $result->getBody()); | ||
184 | static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); | ||
185 | } | ||
186 | } | ||
diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php index f50f2fc2..096963cf 100644 --- a/tests/front/controller/admin/SessionFilterControllerTest.php +++ b/tests/front/controller/admin/SessionFilterControllerTest.php | |||
@@ -30,8 +30,6 @@ class SessionFilterControllerTest extends TestCase | |||
30 | */ | 30 | */ |
31 | public function testLinksPerPage(): void | 31 | public function testLinksPerPage(): void |
32 | { | 32 | { |
33 | $this->createValidContainerMockSet(); | ||
34 | |||
35 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 33 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
36 | 34 | ||
37 | $request = $this->createMock(Request::class); | 35 | $request = $this->createMock(Request::class); |
@@ -62,8 +60,6 @@ class SessionFilterControllerTest extends TestCase | |||
62 | */ | 60 | */ |
63 | public function testLinksPerPageNotValid(): void | 61 | public function testLinksPerPageNotValid(): void |
64 | { | 62 | { |
65 | $this->createValidContainerMockSet(); | ||
66 | |||
67 | $request = $this->createMock(Request::class); | 63 | $request = $this->createMock(Request::class); |
68 | $request->method('getUri')->willReturnCallback(function (): Uri { | 64 | $request->method('getUri')->willReturnCallback(function (): Uri { |
69 | $uri = $this->createMock(Uri::class); | 65 | $uri = $this->createMock(Uri::class); |
@@ -92,8 +88,6 @@ class SessionFilterControllerTest extends TestCase | |||
92 | */ | 88 | */ |
93 | public function testVisibility(): void | 89 | public function testVisibility(): void |
94 | { | 90 | { |
95 | $this->createValidContainerMockSet(); | ||
96 | |||
97 | $arg = ['visibility' => 'private']; | 91 | $arg = ['visibility' => 'private']; |
98 | 92 | ||
99 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 93 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
@@ -126,8 +120,6 @@ class SessionFilterControllerTest extends TestCase | |||
126 | */ | 120 | */ |
127 | public function testVisibilityToggleOff(): void | 121 | public function testVisibilityToggleOff(): void |
128 | { | 122 | { |
129 | $this->createValidContainerMockSet(); | ||
130 | |||
131 | $arg = ['visibility' => 'private']; | 123 | $arg = ['visibility' => 'private']; |
132 | 124 | ||
133 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 125 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
@@ -169,8 +161,6 @@ class SessionFilterControllerTest extends TestCase | |||
169 | */ | 161 | */ |
170 | public function testVisibilitySwitch(): void | 162 | public function testVisibilitySwitch(): void |
171 | { | 163 | { |
172 | $this->createValidContainerMockSet(); | ||
173 | |||
174 | $arg = ['visibility' => 'private']; | 164 | $arg = ['visibility' => 'private']; |
175 | 165 | ||
176 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | 166 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); |
@@ -206,8 +196,6 @@ class SessionFilterControllerTest extends TestCase | |||
206 | */ | 196 | */ |
207 | public function testVisibilityInvalidValue(): void | 197 | public function testVisibilityInvalidValue(): void |
208 | { | 198 | { |
209 | $this->createValidContainerMockSet(); | ||
210 | |||
211 | $arg = ['visibility' => 'test']; | 199 | $arg = ['visibility' => 'test']; |
212 | 200 | ||
213 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 201 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
@@ -244,8 +232,6 @@ class SessionFilterControllerTest extends TestCase | |||
244 | */ | 232 | */ |
245 | public function testVisibilityLoggedOut(): void | 233 | public function testVisibilityLoggedOut(): void |
246 | { | 234 | { |
247 | $this->createValidContainerMockSet(); | ||
248 | |||
249 | $arg = ['visibility' => 'test']; | 235 | $arg = ['visibility' => 'test']; |
250 | 236 | ||
251 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 237 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
@@ -283,8 +269,6 @@ class SessionFilterControllerTest extends TestCase | |||
283 | */ | 269 | */ |
284 | public function testUntaggedOnly(): void | 270 | public function testUntaggedOnly(): void |
285 | { | 271 | { |
286 | $this->createValidContainerMockSet(); | ||
287 | |||
288 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 272 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
289 | 273 | ||
290 | $request = $this->createMock(Request::class); | 274 | $request = $this->createMock(Request::class); |
@@ -314,8 +298,6 @@ class SessionFilterControllerTest extends TestCase | |||
314 | */ | 298 | */ |
315 | public function testUntaggedOnlyToggleOff(): void | 299 | public function testUntaggedOnlyToggleOff(): void |
316 | { | 300 | { |
317 | $this->createValidContainerMockSet(); | ||
318 | |||
319 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; | 301 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; |
320 | 302 | ||
321 | $request = $this->createMock(Request::class); | 303 | $request = $this->createMock(Request::class); |
diff --git a/tests/front/controller/admin/ToolsControllerTest.php b/tests/front/controller/admin/ToolsControllerTest.php index 47c5746e..fc756f0f 100644 --- a/tests/front/controller/admin/ToolsControllerTest.php +++ b/tests/front/controller/admin/ToolsControllerTest.php | |||
@@ -24,8 +24,6 @@ class ToolsControllerTestControllerTest extends TestCase | |||
24 | 24 | ||
25 | public function testDefaultInvokeWithHttps(): void | 25 | public function testDefaultInvokeWithHttps(): void |
26 | { | 26 | { |
27 | $this->createValidContainerMockSet(); | ||
28 | |||
29 | $request = $this->createMock(Request::class); | 27 | $request = $this->createMock(Request::class); |
30 | $response = new Response(); | 28 | $response = new Response(); |
31 | 29 | ||
@@ -49,8 +47,6 @@ class ToolsControllerTestControllerTest extends TestCase | |||
49 | 47 | ||
50 | public function testDefaultInvokeWithoutHttps(): void | 48 | public function testDefaultInvokeWithoutHttps(): void |
51 | { | 49 | { |
52 | $this->createValidContainerMockSet(); | ||
53 | |||
54 | $request = $this->createMock(Request::class); | 50 | $request = $this->createMock(Request::class); |
55 | $response = new Response(); | 51 | $response = new Response(); |
56 | 52 | ||
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index 6ff769fc..872420fd 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php | |||
@@ -27,8 +27,6 @@ class DailyControllerTest extends TestCase | |||
27 | 27 | ||
28 | public function testValidIndexControllerInvokeDefault(): void | 28 | public function testValidIndexControllerInvokeDefault(): void |
29 | { | 29 | { |
30 | $this->createValidContainerMockSet(); | ||
31 | |||
32 | $currentDay = new \DateTimeImmutable('2020-05-13'); | 30 | $currentDay = new \DateTimeImmutable('2020-05-13'); |
33 | 31 | ||
34 | $request = $this->createMock(Request::class); | 32 | $request = $this->createMock(Request::class); |
@@ -169,8 +167,6 @@ class DailyControllerTest extends TestCase | |||
169 | */ | 167 | */ |
170 | public function testValidIndexControllerInvokeNoFutureOrPast(): void | 168 | public function testValidIndexControllerInvokeNoFutureOrPast(): void |
171 | { | 169 | { |
172 | $this->createValidContainerMockSet(); | ||
173 | |||
174 | $currentDay = new \DateTimeImmutable('2020-05-13'); | 170 | $currentDay = new \DateTimeImmutable('2020-05-13'); |
175 | 171 | ||
176 | $request = $this->createMock(Request::class); | 172 | $request = $this->createMock(Request::class); |
@@ -243,8 +239,6 @@ class DailyControllerTest extends TestCase | |||
243 | */ | 239 | */ |
244 | public function testValidIndexControllerInvokeHeightAdjustment(): void | 240 | public function testValidIndexControllerInvokeHeightAdjustment(): void |
245 | { | 241 | { |
246 | $this->createValidContainerMockSet(); | ||
247 | |||
248 | $currentDay = new \DateTimeImmutable('2020-05-13'); | 242 | $currentDay = new \DateTimeImmutable('2020-05-13'); |
249 | 243 | ||
250 | $request = $this->createMock(Request::class); | 244 | $request = $this->createMock(Request::class); |
@@ -314,8 +308,6 @@ class DailyControllerTest extends TestCase | |||
314 | */ | 308 | */ |
315 | public function testValidIndexControllerInvokeNoBookmark(): void | 309 | public function testValidIndexControllerInvokeNoBookmark(): void |
316 | { | 310 | { |
317 | $this->createValidContainerMockSet(); | ||
318 | |||
319 | $request = $this->createMock(Request::class); | 311 | $request = $this->createMock(Request::class); |
320 | $response = new Response(); | 312 | $response = new Response(); |
321 | 313 | ||
@@ -363,8 +355,6 @@ class DailyControllerTest extends TestCase | |||
363 | */ | 355 | */ |
364 | public function testValidRssControllerInvokeDefault(): void | 356 | public function testValidRssControllerInvokeDefault(): void |
365 | { | 357 | { |
366 | $this->createValidContainerMockSet(); | ||
367 | |||
368 | $dates = [ | 358 | $dates = [ |
369 | new \DateTimeImmutable('2020-05-17'), | 359 | new \DateTimeImmutable('2020-05-17'), |
370 | new \DateTimeImmutable('2020-05-15'), | 360 | new \DateTimeImmutable('2020-05-15'), |
@@ -439,8 +429,6 @@ class DailyControllerTest extends TestCase | |||
439 | */ | 429 | */ |
440 | public function testValidRssControllerInvokeTriggerCache(): void | 430 | public function testValidRssControllerInvokeTriggerCache(): void |
441 | { | 431 | { |
442 | $this->createValidContainerMockSet(); | ||
443 | |||
444 | $request = $this->createMock(Request::class); | 432 | $request = $this->createMock(Request::class); |
445 | $response = new Response(); | 433 | $response = new Response(); |
446 | 434 | ||
@@ -465,8 +453,6 @@ class DailyControllerTest extends TestCase | |||
465 | */ | 453 | */ |
466 | public function testValidRssControllerInvokeNoBookmark(): void | 454 | public function testValidRssControllerInvokeNoBookmark(): void |
467 | { | 455 | { |
468 | $this->createValidContainerMockSet(); | ||
469 | |||
470 | $request = $this->createMock(Request::class); | 456 | $request = $this->createMock(Request::class); |
471 | $response = new Response(); | 457 | $response = new Response(); |
472 | 458 | ||
diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php index fd4679ea..fb417e2a 100644 --- a/tests/front/controller/visitor/FeedControllerTest.php +++ b/tests/front/controller/visitor/FeedControllerTest.php | |||
@@ -30,8 +30,6 @@ class FeedControllerTest extends TestCase | |||
30 | */ | 30 | */ |
31 | public function testDefaultRssController(): void | 31 | public function testDefaultRssController(): void |
32 | { | 32 | { |
33 | $this->createValidContainerMockSet(); | ||
34 | |||
35 | $request = $this->createMock(Request::class); | 33 | $request = $this->createMock(Request::class); |
36 | $response = new Response(); | 34 | $response = new Response(); |
37 | 35 | ||
@@ -71,8 +69,6 @@ class FeedControllerTest extends TestCase | |||
71 | */ | 69 | */ |
72 | public function testDefaultAtomController(): void | 70 | public function testDefaultAtomController(): void |
73 | { | 71 | { |
74 | $this->createValidContainerMockSet(); | ||
75 | |||
76 | $request = $this->createMock(Request::class); | 72 | $request = $this->createMock(Request::class); |
77 | $response = new Response(); | 73 | $response = new Response(); |
78 | 74 | ||
@@ -112,8 +108,6 @@ class FeedControllerTest extends TestCase | |||
112 | */ | 108 | */ |
113 | public function testAtomControllerWithParameters(): void | 109 | public function testAtomControllerWithParameters(): void |
114 | { | 110 | { |
115 | $this->createValidContainerMockSet(); | ||
116 | |||
117 | $request = $this->createMock(Request::class); | 111 | $request = $this->createMock(Request::class); |
118 | $request->method('getParams')->willReturn(['parameter' => 'value']); | 112 | $request->method('getParams')->willReturn(['parameter' => 'value']); |
119 | $response = new Response(); | 113 | $response = new Response(); |
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index bc3266b5..d16b6949 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php | |||
@@ -31,18 +31,12 @@ trait FrontControllerMockHelper | |||
31 | protected $container; | 31 | protected $container; |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Mock the container instance | 34 | * Mock the container instance and initialize container's services used by tests |
35 | */ | 35 | */ |
36 | protected function createContainer(): void | 36 | protected function createContainer(): void |
37 | { | 37 | { |
38 | $this->container = $this->createMock(ShaarliTestContainer::class); | 38 | $this->container = $this->createMock(ShaarliTestContainer::class); |
39 | } | ||
40 | 39 | ||
41 | /** | ||
42 | * Initialize container's services used by tests | ||
43 | */ | ||
44 | protected function createValidContainerMockSet(): void | ||
45 | { | ||
46 | $this->container->loginManager = $this->createMock(LoginManager::class); | 40 | $this->container->loginManager = $this->createMock(LoginManager::class); |
47 | 41 | ||
48 | // Config | 42 | // Config |
diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php index 9d223316..faa8ac71 100644 --- a/tests/front/controller/visitor/LoginControllerTest.php +++ b/tests/front/controller/visitor/LoginControllerTest.php | |||
@@ -26,8 +26,6 @@ class LoginControllerTest extends TestCase | |||
26 | 26 | ||
27 | public function testValidControllerInvoke(): void | 27 | public function testValidControllerInvoke(): void |
28 | { | 28 | { |
29 | $this->createValidContainerMockSet(); | ||
30 | |||
31 | $request = $this->createMock(Request::class); | 29 | $request = $this->createMock(Request::class); |
32 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | 30 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); |
33 | $response = new Response(); | 31 | $response = new Response(); |
@@ -57,8 +55,6 @@ class LoginControllerTest extends TestCase | |||
57 | 55 | ||
58 | public function testValidControllerInvokeWithUserName(): void | 56 | public function testValidControllerInvokeWithUserName(): void |
59 | { | 57 | { |
60 | $this->createValidContainerMockSet(); | ||
61 | |||
62 | $request = $this->createMock(Request::class); | 58 | $request = $this->createMock(Request::class); |
63 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | 59 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); |
64 | $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); | 60 | $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); |
@@ -90,8 +86,6 @@ class LoginControllerTest extends TestCase | |||
90 | 86 | ||
91 | public function testLoginControllerWhileLoggedIn(): void | 87 | public function testLoginControllerWhileLoggedIn(): void |
92 | { | 88 | { |
93 | $this->createValidContainerMockSet(); | ||
94 | |||
95 | $request = $this->createMock(Request::class); | 89 | $request = $this->createMock(Request::class); |
96 | $response = new Response(); | 90 | $response = new Response(); |
97 | 91 | ||
@@ -106,8 +100,6 @@ class LoginControllerTest extends TestCase | |||
106 | 100 | ||
107 | public function testLoginControllerOpenShaarli(): void | 101 | public function testLoginControllerOpenShaarli(): void |
108 | { | 102 | { |
109 | $this->createValidContainerMockSet(); | ||
110 | |||
111 | $request = $this->createMock(Request::class); | 103 | $request = $this->createMock(Request::class); |
112 | $response = new Response(); | 104 | $response = new Response(); |
113 | 105 | ||
@@ -129,8 +121,6 @@ class LoginControllerTest extends TestCase | |||
129 | 121 | ||
130 | public function testLoginControllerWhileBanned(): void | 122 | public function testLoginControllerWhileBanned(): void |
131 | { | 123 | { |
132 | $this->createValidContainerMockSet(); | ||
133 | |||
134 | $request = $this->createMock(Request::class); | 124 | $request = $this->createMock(Request::class); |
135 | $response = new Response(); | 125 | $response = new Response(); |
136 | 126 | ||
diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php index 52475318..5f9f5b12 100644 --- a/tests/front/controller/visitor/OpenSearchControllerTest.php +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php | |||
@@ -24,8 +24,6 @@ class OpenSearchControllerTest extends TestCase | |||
24 | 24 | ||
25 | public function testOpenSearchController(): void | 25 | public function testOpenSearchController(): void |
26 | { | 26 | { |
27 | $this->createValidContainerMockSet(); | ||
28 | |||
29 | $request = $this->createMock(Request::class); | 27 | $request = $this->createMock(Request::class); |
30 | $response = new Response(); | 28 | $response = new Response(); |
31 | 29 | ||
diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php index 7ac842cb..3dc3f292 100644 --- a/tests/front/controller/visitor/PictureWallControllerTest.php +++ b/tests/front/controller/visitor/PictureWallControllerTest.php | |||
@@ -28,8 +28,6 @@ class PictureWallControllerTest extends TestCase | |||
28 | 28 | ||
29 | public function testValidControllerInvokeDefault(): void | 29 | public function testValidControllerInvokeDefault(): void |
30 | { | 30 | { |
31 | $this->createValidContainerMockSet(); | ||
32 | |||
33 | $request = $this->createMock(Request::class); | 31 | $request = $this->createMock(Request::class); |
34 | $request->expects(static::once())->method('getQueryParams')->willReturn([]); | 32 | $request->expects(static::once())->method('getQueryParams')->willReturn([]); |
35 | $response = new Response(); | 33 | $response = new Response(); |
@@ -106,8 +104,6 @@ class PictureWallControllerTest extends TestCase | |||
106 | { | 104 | { |
107 | $this->expectException(ThumbnailsDisabledException::class); | 105 | $this->expectException(ThumbnailsDisabledException::class); |
108 | 106 | ||
109 | $this->createValidContainerMockSet(); | ||
110 | |||
111 | $request = $this->createMock(Request::class); | 107 | $request = $this->createMock(Request::class); |
112 | $response = new Response(); | 108 | $response = new Response(); |
113 | 109 | ||
diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php index e2e88da3..1f7d57ad 100644 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php | |||
@@ -67,8 +67,6 @@ class ShaarliControllerTest extends TestCase | |||
67 | 67 | ||
68 | public function testAssignView(): void | 68 | public function testAssignView(): void |
69 | { | 69 | { |
70 | $this->createValidContainerMockSet(); | ||
71 | |||
72 | $this->assignTemplateVars($this->assignedValues); | 70 | $this->assignTemplateVars($this->assignedValues); |
73 | 71 | ||
74 | $self = $this->controller->assignView('variableName', 'variableValue'); | 72 | $self = $this->controller->assignView('variableName', 'variableValue'); |
@@ -79,8 +77,6 @@ class ShaarliControllerTest extends TestCase | |||
79 | 77 | ||
80 | public function testRender(): void | 78 | public function testRender(): void |
81 | { | 79 | { |
82 | $this->createValidContainerMockSet(); | ||
83 | |||
84 | $this->assignTemplateVars($this->assignedValues); | 80 | $this->assignTemplateVars($this->assignedValues); |
85 | 81 | ||
86 | $this->container->bookmarkService | 82 | $this->container->bookmarkService |
@@ -120,8 +116,6 @@ class ShaarliControllerTest extends TestCase | |||
120 | */ | 116 | */ |
121 | public function testRedirectFromRefererDefault(): void | 117 | public function testRedirectFromRefererDefault(): void |
122 | { | 118 | { |
123 | $this->createValidContainerMockSet(); | ||
124 | |||
125 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 119 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
126 | 120 | ||
127 | $response = new Response(); | 121 | $response = new Response(); |
@@ -137,8 +131,6 @@ class ShaarliControllerTest extends TestCase | |||
137 | */ | 131 | */ |
138 | public function testRedirectFromRefererWithUnmatchedLoopTerm(): void | 132 | public function testRedirectFromRefererWithUnmatchedLoopTerm(): void |
139 | { | 133 | { |
140 | $this->createValidContainerMockSet(); | ||
141 | |||
142 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 134 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
143 | 135 | ||
144 | $response = new Response(); | 136 | $response = new Response(); |
@@ -154,8 +146,6 @@ class ShaarliControllerTest extends TestCase | |||
154 | */ | 146 | */ |
155 | public function testRedirectFromRefererWithMatchingLoopTermInPath(): void | 147 | public function testRedirectFromRefererWithMatchingLoopTermInPath(): void |
156 | { | 148 | { |
157 | $this->createValidContainerMockSet(); | ||
158 | |||
159 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 149 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
160 | 150 | ||
161 | $response = new Response(); | 151 | $response = new Response(); |
@@ -171,8 +161,6 @@ class ShaarliControllerTest extends TestCase | |||
171 | */ | 161 | */ |
172 | public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void | 162 | public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void |
173 | { | 163 | { |
174 | $this->createValidContainerMockSet(); | ||
175 | |||
176 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 164 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
177 | 165 | ||
178 | $response = new Response(); | 166 | $response = new Response(); |
@@ -189,8 +177,6 @@ class ShaarliControllerTest extends TestCase | |||
189 | */ | 177 | */ |
190 | public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void | 178 | public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void |
191 | { | 179 | { |
192 | $this->createValidContainerMockSet(); | ||
193 | |||
194 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 180 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
195 | 181 | ||
196 | $response = new Response(); | 182 | $response = new Response(); |
@@ -207,8 +193,6 @@ class ShaarliControllerTest extends TestCase | |||
207 | */ | 193 | */ |
208 | public function testRedirectFromRefererWithLoopTermInDomain(): void | 194 | public function testRedirectFromRefererWithLoopTermInDomain(): void |
209 | { | 195 | { |
210 | $this->createValidContainerMockSet(); | ||
211 | |||
212 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 196 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
213 | 197 | ||
214 | $response = new Response(); | 198 | $response = new Response(); |
@@ -225,8 +209,6 @@ class ShaarliControllerTest extends TestCase | |||
225 | */ | 209 | */ |
226 | public function testRedirectFromRefererWithMatchingClearedParam(): void | 210 | public function testRedirectFromRefererWithMatchingClearedParam(): void |
227 | { | 211 | { |
228 | $this->createValidContainerMockSet(); | ||
229 | |||
230 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | 212 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; |
231 | 213 | ||
232 | $response = new Response(); | 214 | $response = new Response(); |
diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php index e636d496..9a6a4bc0 100644 --- a/tests/front/controller/visitor/TagCloudControllerTest.php +++ b/tests/front/controller/visitor/TagCloudControllerTest.php | |||
@@ -28,8 +28,6 @@ class TagCloudControllerTest extends TestCase | |||
28 | */ | 28 | */ |
29 | public function testValidCloudControllerInvokeDefault(): void | 29 | public function testValidCloudControllerInvokeDefault(): void |
30 | { | 30 | { |
31 | $this->createValidContainerMockSet(); | ||
32 | |||
33 | $allTags = [ | 31 | $allTags = [ |
34 | 'ghi' => 1, | 32 | 'ghi' => 1, |
35 | 'abc' => 3, | 33 | 'abc' => 3, |
@@ -94,8 +92,6 @@ class TagCloudControllerTest extends TestCase | |||
94 | */ | 92 | */ |
95 | public function testValidCloudControllerInvokeWithParameters(): void | 93 | public function testValidCloudControllerInvokeWithParameters(): void |
96 | { | 94 | { |
97 | $this->createValidContainerMockSet(); | ||
98 | |||
99 | $request = $this->createMock(Request::class); | 95 | $request = $this->createMock(Request::class); |
100 | $request | 96 | $request |
101 | ->method('getQueryParam') | 97 | ->method('getQueryParam') |
@@ -161,8 +157,6 @@ class TagCloudControllerTest extends TestCase | |||
161 | */ | 157 | */ |
162 | public function testEmptyCloud(): void | 158 | public function testEmptyCloud(): void |
163 | { | 159 | { |
164 | $this->createValidContainerMockSet(); | ||
165 | |||
166 | $request = $this->createMock(Request::class); | 160 | $request = $this->createMock(Request::class); |
167 | $response = new Response(); | 161 | $response = new Response(); |
168 | 162 | ||
@@ -209,8 +203,6 @@ class TagCloudControllerTest extends TestCase | |||
209 | */ | 203 | */ |
210 | public function testValidListControllerInvokeDefault(): void | 204 | public function testValidListControllerInvokeDefault(): void |
211 | { | 205 | { |
212 | $this->createValidContainerMockSet(); | ||
213 | |||
214 | $allTags = [ | 206 | $allTags = [ |
215 | 'def' => 12, | 207 | 'def' => 12, |
216 | 'abc' => 3, | 208 | 'abc' => 3, |
@@ -271,8 +263,6 @@ class TagCloudControllerTest extends TestCase | |||
271 | */ | 263 | */ |
272 | public function testValidListControllerInvokeWithParameters(): void | 264 | public function testValidListControllerInvokeWithParameters(): void |
273 | { | 265 | { |
274 | $this->createValidContainerMockSet(); | ||
275 | |||
276 | $request = $this->createMock(Request::class); | 266 | $request = $this->createMock(Request::class); |
277 | $request | 267 | $request |
278 | ->method('getQueryParam') | 268 | ->method('getQueryParam') |
@@ -336,8 +326,6 @@ class TagCloudControllerTest extends TestCase | |||
336 | */ | 326 | */ |
337 | public function testEmptyList(): void | 327 | public function testEmptyList(): void |
338 | { | 328 | { |
339 | $this->createValidContainerMockSet(); | ||
340 | |||
341 | $request = $this->createMock(Request::class); | 329 | $request = $this->createMock(Request::class); |
342 | $response = new Response(); | 330 | $response = new Response(); |
343 | 331 | ||
diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php index 9a2b1f71..1242a2e9 100644 --- a/tests/front/controller/visitor/TagControllerTest.php +++ b/tests/front/controller/visitor/TagControllerTest.php | |||
@@ -23,8 +23,6 @@ class TagControllerTest extends TestCase | |||
23 | 23 | ||
24 | public function testAddTagWithReferer(): void | 24 | public function testAddTagWithReferer(): void |
25 | { | 25 | { |
26 | $this->createValidContainerMockSet(); | ||
27 | |||
28 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; | 26 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; |
29 | 27 | ||
30 | $request = $this->createMock(Request::class); | 28 | $request = $this->createMock(Request::class); |
@@ -41,8 +39,6 @@ class TagControllerTest extends TestCase | |||
41 | 39 | ||
42 | public function testAddTagWithRefererAndExistingSearch(): void | 40 | public function testAddTagWithRefererAndExistingSearch(): void |
43 | { | 41 | { |
44 | $this->createValidContainerMockSet(); | ||
45 | |||
46 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | 42 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; |
47 | 43 | ||
48 | $request = $this->createMock(Request::class); | 44 | $request = $this->createMock(Request::class); |
@@ -59,8 +55,6 @@ class TagControllerTest extends TestCase | |||
59 | 55 | ||
60 | public function testAddTagWithoutRefererAndExistingSearch(): void | 56 | public function testAddTagWithoutRefererAndExistingSearch(): void |
61 | { | 57 | { |
62 | $this->createValidContainerMockSet(); | ||
63 | |||
64 | $request = $this->createMock(Request::class); | 58 | $request = $this->createMock(Request::class); |
65 | $response = new Response(); | 59 | $response = new Response(); |
66 | 60 | ||
@@ -75,8 +69,6 @@ class TagControllerTest extends TestCase | |||
75 | 69 | ||
76 | public function testAddTagRemoveLegacyQueryParam(): void | 70 | public function testAddTagRemoveLegacyQueryParam(): void |
77 | { | 71 | { |
78 | $this->createValidContainerMockSet(); | ||
79 | |||
80 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; | 72 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; |
81 | 73 | ||
82 | $request = $this->createMock(Request::class); | 74 | $request = $this->createMock(Request::class); |
@@ -93,8 +85,6 @@ class TagControllerTest extends TestCase | |||
93 | 85 | ||
94 | public function testAddTagResetPagination(): void | 86 | public function testAddTagResetPagination(): void |
95 | { | 87 | { |
96 | $this->createValidContainerMockSet(); | ||
97 | |||
98 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; | 88 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; |
99 | 89 | ||
100 | $request = $this->createMock(Request::class); | 90 | $request = $this->createMock(Request::class); |
@@ -111,8 +101,6 @@ class TagControllerTest extends TestCase | |||
111 | 101 | ||
112 | public function testAddTagWithRefererAndEmptySearch(): void | 102 | public function testAddTagWithRefererAndEmptySearch(): void |
113 | { | 103 | { |
114 | $this->createValidContainerMockSet(); | ||
115 | |||
116 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; | 104 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; |
117 | 105 | ||
118 | $request = $this->createMock(Request::class); | 106 | $request = $this->createMock(Request::class); |
@@ -129,8 +117,6 @@ class TagControllerTest extends TestCase | |||
129 | 117 | ||
130 | public function testAddTagWithoutNewTagWithReferer(): void | 118 | public function testAddTagWithoutNewTagWithReferer(): void |
131 | { | 119 | { |
132 | $this->createValidContainerMockSet(); | ||
133 | |||
134 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | 120 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; |
135 | 121 | ||
136 | $request = $this->createMock(Request::class); | 122 | $request = $this->createMock(Request::class); |
@@ -145,8 +131,6 @@ class TagControllerTest extends TestCase | |||
145 | 131 | ||
146 | public function testAddTagWithoutNewTagWithoutReferer(): void | 132 | public function testAddTagWithoutNewTagWithoutReferer(): void |
147 | { | 133 | { |
148 | $this->createValidContainerMockSet(); | ||
149 | |||
150 | $request = $this->createMock(Request::class); | 134 | $request = $this->createMock(Request::class); |
151 | $response = new Response(); | 135 | $response = new Response(); |
152 | 136 | ||
@@ -159,8 +143,6 @@ class TagControllerTest extends TestCase | |||
159 | 143 | ||
160 | public function testRemoveTagWithoutMatchingTag(): void | 144 | public function testRemoveTagWithoutMatchingTag(): void |
161 | { | 145 | { |
162 | $this->createValidContainerMockSet(); | ||
163 | |||
164 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | 146 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; |
165 | 147 | ||
166 | $request = $this->createMock(Request::class); | 148 | $request = $this->createMock(Request::class); |
@@ -177,8 +159,6 @@ class TagControllerTest extends TestCase | |||
177 | 159 | ||
178 | public function testRemoveTagWithoutTagsearch(): void | 160 | public function testRemoveTagWithoutTagsearch(): void |
179 | { | 161 | { |
180 | $this->createValidContainerMockSet(); | ||
181 | |||
182 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; | 162 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; |
183 | 163 | ||
184 | $request = $this->createMock(Request::class); | 164 | $request = $this->createMock(Request::class); |
@@ -195,8 +175,6 @@ class TagControllerTest extends TestCase | |||
195 | 175 | ||
196 | public function testRemoveTagWithoutReferer(): void | 176 | public function testRemoveTagWithoutReferer(): void |
197 | { | 177 | { |
198 | $this->createValidContainerMockSet(); | ||
199 | |||
200 | $request = $this->createMock(Request::class); | 178 | $request = $this->createMock(Request::class); |
201 | $response = new Response(); | 179 | $response = new Response(); |
202 | 180 | ||
@@ -211,8 +189,6 @@ class TagControllerTest extends TestCase | |||
211 | 189 | ||
212 | public function testRemoveTagWithoutTag(): void | 190 | public function testRemoveTagWithoutTag(): void |
213 | { | 191 | { |
214 | $this->createValidContainerMockSet(); | ||
215 | |||
216 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; | 192 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; |
217 | 193 | ||
218 | $request = $this->createMock(Request::class); | 194 | $request = $this->createMock(Request::class); |
@@ -227,8 +203,6 @@ class TagControllerTest extends TestCase | |||
227 | 203 | ||
228 | public function testRemoveTagWithoutTagWithoutReferer(): void | 204 | public function testRemoveTagWithoutTagWithoutReferer(): void |
229 | { | 205 | { |
230 | $this->createValidContainerMockSet(); | ||
231 | |||
232 | $request = $this->createMock(Request::class); | 206 | $request = $this->createMock(Request::class); |
233 | $response = new Response(); | 207 | $response = new Response(); |
234 | 208 | ||
diff --git a/tpl/default/page.header.html b/tpl/default/page.header.html index ca7dc1bc..4afcca73 100644 --- a/tpl/default/page.header.html +++ b/tpl/default/page.header.html | |||
@@ -184,6 +184,20 @@ | |||
184 | </div> | 184 | </div> |
185 | {/if} | 185 | {/if} |
186 | 186 | ||
187 | {if="!empty($global_errors) && $is_logged_in"} | ||
188 | <div class="pure-g new-version-message pure-alert pure-alert-error pure-alert-closable" id="shaarli-errors-alert"> | ||
189 | <div class="pure-u-2-24"></div> | ||
190 | <div class="pure-u-20-24"> | ||
191 | {loop="$global_errors"} | ||
192 | <p>{$value}</p> | ||
193 | {/loop} | ||
194 | </div> | ||
195 | <div class="pure-u-2-24"> | ||
196 | <i class="fa fa-times pure-alert-close"></i> | ||
197 | </div> | ||
198 | </div> | ||
199 | {/if} | ||
200 | |||
187 | {if="!empty($global_warnings) && $is_logged_in"} | 201 | {if="!empty($global_warnings) && $is_logged_in"} |
188 | <div class="pure-g pure-alert pure-alert-warning pure-alert-closable" id="shaarli-warnings-alert"> | 202 | <div class="pure-g pure-alert pure-alert-warning pure-alert-closable" id="shaarli-warnings-alert"> |
189 | <div class="pure-u-2-24"></div> | 203 | <div class="pure-u-2-24"></div> |
@@ -198,4 +212,18 @@ | |||
198 | </div> | 212 | </div> |
199 | {/if} | 213 | {/if} |
200 | 214 | ||
215 | {if="!empty($global_successes) && $is_logged_in"} | ||
216 | <div class="pure-g new-version-message pure-alert pure-alert-success pure-alert-closable" id="shaarli-success-alert"> | ||
217 | <div class="pure-u-2-24"></div> | ||
218 | <div class="pure-u-20-24"> | ||
219 | {loop="$global_successes"} | ||
220 | <p>{$value}</p> | ||
221 | {/loop} | ||
222 | </div> | ||
223 | <div class="pure-u-2-24"> | ||
224 | <i class="fa fa-times pure-alert-close"></i> | ||
225 | </div> | ||
226 | </div> | ||
227 | {/if} | ||
228 | |||
201 | <div class="clear"></div> | 229 | <div class="clear"></div> |