diff options
18 files changed, 672 insertions, 270 deletions
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 70c12e1048..9bc34ba282 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -145,10 +145,10 @@ class AccountController extends AbstractBaseController $tree->setUserPreference($user, 'rootid', $rootid); // Switch to the new theme now - Session::put('theme_id', $theme); + Session::put('theme', $theme); // Switch to the new language now - Session::put('locale', $language); + Session::put('language', $language); return redirect(route('my-account', ['ged' => $tree->name()])); } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index f6e15dbcca..221fd77aef 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -194,8 +194,8 @@ class LoginController extends AbstractBaseController Log::addAuthenticationLog('Login: ' . Auth::user()->userName() . '/' . Auth::user()->realName()); Auth::user()->setPreference('sessiontime', (string) Carbon::now()->unix()); - Session::put('locale', Auth::user()->getPreference('language')); - Session::put('theme_id', Auth::user()->getPreference('theme')); + Session::put('language', Auth::user()->getPreference('language')); + Session::put('theme', Auth::user()->getPreference('theme')); I18N::init(Auth::user()->getPreference('language')); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php deleted file mode 100644 index 884c5ecd3e..0000000000 --- a/app/Http/Controllers/UserController.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php -/** - * webtrees: online genealogy - * Copyright (C) 2019 webtrees development team - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -declare(strict_types=1); - -namespace Fisharebest\Webtrees\Http\Controllers; - -use Fig\Http\Message\StatusCodeInterface; -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Log; -use Fisharebest\Webtrees\Services\UserService; -use Fisharebest\Webtrees\Session; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use function response; - -/** - * User actions - */ -class UserController extends AbstractBaseController -{ - /** - * @var UserService - */ - private $user_service; - - /** - * UserController constructor. - * - * @param UserService $user_service - */ - public function __construct(UserService $user_service) - { - $this->user_service = $user_service; - } - - /** - * Delete a user. - * - * @param ServerRequestInterface $request - * - * @return ResponseInterface - */ - public function delete(ServerRequestInterface $request): ResponseInterface - { - $user_id = (int) $request->getParsedBody()['user_id']; - - $user = $this->user_service->find($user_id); - - if ($user && Auth::isAdmin() && Auth::user() !== $user) { - Log::addAuthenticationLog('Deleted user: ' . $user->userName()); - $this->user_service->delete($user); - } - - return response('', StatusCodeInterface::STATUS_NO_CONTENT); - } - - /** - * Select a language. - * - * @param ServerRequestInterface $request - * - * @return ResponseInterface - */ - public function language(ServerRequestInterface $request): ResponseInterface - { - $language = $request->getParsedBody()['language']; - - I18N::init($language); - Session::put('locale', $language); - Auth::user()->setPreference('language', $language); - - return response('', StatusCodeInterface::STATUS_NO_CONTENT); - } - - /** - * Masquerade as another user. - * - * @param ServerRequestInterface $request - * - * @return ResponseInterface - */ - public function masquerade(ServerRequestInterface $request): ResponseInterface - { - $user_id = (int) $request->get('user_id'); - - $user = $this->user_service->find($user_id); - - if ($user !== null && Auth::isAdmin() && Auth::user() !== $user) { - Log::addAuthenticationLog('Masquerade as user: ' . $user->userName()); - Auth::login($user); - Session::put('masquerade', '1'); - } - - return response('', StatusCodeInterface::STATUS_NO_CONTENT); - } - - /** - * Select a theme. - * - * @param ServerRequestInterface $request - * - * @return ResponseInterface - */ - public function theme(ServerRequestInterface $request): ResponseInterface - { - $theme = $request->getParsedBody()['theme']; - Session::put('theme_id', $theme); - Auth::user()->setPreference('theme', $theme); - - return response('', StatusCodeInterface::STATUS_NO_CONTENT); - } -} diff --git a/app/Http/Middleware/UseLocale.php b/app/Http/Middleware/UseLocale.php index 4ab53f5985..5267ab8544 100644 --- a/app/Http/Middleware/UseLocale.php +++ b/app/Http/Middleware/UseLocale.php @@ -44,7 +44,7 @@ class UseLocale implements MiddlewareInterface // Select a locale define('WT_LOCALE', I18N::init('', $tree)); - Session::put('locale', WT_LOCALE); + Session::put('language', WT_LOCALE); app()->instance(LocaleInterface::class, WebtreesLocale::create(WT_LOCALE)); diff --git a/app/Http/Middleware/UseTheme.php b/app/Http/Middleware/UseTheme.php index db6cf6a296..48550cab49 100644 --- a/app/Http/Middleware/UseTheme.php +++ b/app/Http/Middleware/UseTheme.php @@ -61,7 +61,7 @@ class UseTheme implements MiddlewareInterface app()->instance(ModuleThemeInterface::class, $theme); // Remember this setting - Session::put('theme_id', $theme->name()); + Session::put('theme', $theme->name()); break; } @@ -80,7 +80,7 @@ class UseTheme implements MiddlewareInterface $themes = $this->module_service->findByInterface(ModuleThemeInterface::class); // Last theme used - yield $themes->get(Session::get('theme_id', '')); + yield $themes->get(Session::get('theme', '')); // Default for tree $tree = app(Tree::class); diff --git a/app/Http/RequestHandlers/DeleteUser.php b/app/Http/RequestHandlers/DeleteUser.php new file mode 100644 index 0000000000..b548da8f1d --- /dev/null +++ b/app/Http/RequestHandlers/DeleteUser.php @@ -0,0 +1,71 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\RequestHandlers; + +use Fig\Http\Message\StatusCodeInterface; +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Log; +use Fisharebest\Webtrees\Services\UserService; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use function response; + +/** + * Delete a user. + */ +class DeleteUser implements RequestHandlerInterface, StatusCodeInterface +{ + /** @var UserService */ + private $user_service; + + /** + * @param UserService $user_service + */ + public function __construct(UserService $user_service) + { + $this->user_service = $user_service; + } + + /** + * @param ServerRequestInterface $request + * + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $user_id = (int) $request->getParsedBody()['user_id']; + + $user = $this->user_service->find($user_id); + + if ($user === null) { + throw new NotFoundHttpException('User ID ' . $user_id . ' not found'); + } + + if (Auth::isAdmin($user)) { + throw new AccessDeniedHttpException('Cannot delete an administrator'); + } + + Log::addAuthenticationLog('Deleted user: ' . $user->userName()); + $this->user_service->delete($user); + + return response('', StatusCodeInterface::STATUS_NO_CONTENT); + } +} diff --git a/app/Http/RequestHandlers/MasqueradeAsUser.php b/app/Http/RequestHandlers/MasqueradeAsUser.php new file mode 100644 index 0000000000..959cf06170 --- /dev/null +++ b/app/Http/RequestHandlers/MasqueradeAsUser.php @@ -0,0 +1,76 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\RequestHandlers; + +use Fig\Http\Message\StatusCodeInterface; +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Contracts\UserInterface; +use Fisharebest\Webtrees\Log; +use Fisharebest\Webtrees\Services\UserService; +use Fisharebest\Webtrees\Session; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use function response; + +/** + * Masquerade as another user, for testing and administration. + */ +class MasqueradeAsUser implements RequestHandlerInterface, StatusCodeInterface +{ + /** @var UserInterface */ + private $user; + + /** @var UserService */ + private $user_service; + + /** + * @param UserInterface $user + * @param UserService $user_service + */ + public function __construct(UserInterface $user, UserService $user_service) + { + $this->user = $user; + $this->user_service = $user_service; + } + + /** + * @param ServerRequestInterface $request + * + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $user_id = (int) $request->getParsedBody()['user_id']; + + $user = $this->user_service->find($user_id); + + if ($user === null) { + throw new NotFoundHttpException('User ID ' . $user_id . ' not found'); + } + + if ($this->user->id() !== $user_id) { + Log::addAuthenticationLog('Masquerade as user: ' . $user->userName()); + Auth::login($user); + Session::put('masquerade', '1'); + } + + return response('', StatusCodeInterface::STATUS_NO_CONTENT); + } +} diff --git a/app/Http/Controllers/ModuleController.php b/app/Http/RequestHandlers/ModuleAction.php index 04f41fc0b2..3022d84fbc 100644 --- a/app/Http/Controllers/ModuleController.php +++ b/app/Http/RequestHandlers/ModuleAction.php @@ -15,15 +15,17 @@ */ declare(strict_types=1); -namespace Fisharebest\Webtrees\Http\Controllers; +namespace Fisharebest\Webtrees\Http\RequestHandlers; use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\Contracts\UserInterface; use Fisharebest\Webtrees\Services\ModuleService; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use function app; use function method_exists; use function strpos; use function strtolower; @@ -31,48 +33,54 @@ use function strtolower; /** * Controller for module actions. */ -class ModuleController extends AbstractBaseController +class ModuleAction implements RequestHandlerInterface { - /** - * @var ModuleService - */ + /** @var ModuleService */ private $module_service; + /** @var UserInterface */ + private $user; + /** * ModuleController constructor. * * @param ModuleService $module_service + * @param UserInterface $user */ - public function __construct(ModuleService $module_service) + public function __construct(ModuleService $module_service, UserInterface $user) { $this->module_service = $module_service; + $this->user = $user; } /** * Perform an HTTP action for one of the modules. * * @param ServerRequestInterface $request - * @param UserInterface $user * * @return ResponseInterface */ - public function action(ServerRequestInterface $request, UserInterface $user): ResponseInterface + public function handle(ServerRequestInterface $request): ResponseInterface { - $module_name = $request->get('module', ''); + $module_name = $request->getQueryParams()['module'] ?? $request->getParsedBody()['module'] ?? ''; + $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? ''; // Check that the module is enabled. // The module itself will need to check any tree-level access, // which may be different for each component (tab, menu, etc.) of the module. $module = $this->module_service->findByName($module_name); + if ($module === null) { + throw new NotFoundHttpException('Module ' . $module_name . ' does not exist'); + } + // We'll call a function such as Module::getFooBarAction() $verb = strtolower($request->getMethod()); - $action = $request->get('action', ''); $method = $verb . $action . 'Action'; // Actions with "Admin" in the name are for administrators only. - if (strpos($action, 'Admin') !== false && !Auth::isAdmin($user)) { - throw new AccessDeniedHttpException(); + if (strpos($action, 'Admin') !== false && !Auth::isAdmin($this->user)) { + throw new AccessDeniedHttpException('Admin only action'); } if (!method_exists($module, $method)) { diff --git a/app/Http/RequestHandlers/SelectLanguage.php b/app/Http/RequestHandlers/SelectLanguage.php new file mode 100644 index 0000000000..f75613cd43 --- /dev/null +++ b/app/Http/RequestHandlers/SelectLanguage.php @@ -0,0 +1,59 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\RequestHandlers; + +use Fig\Http\Message\StatusCodeInterface; +use Fisharebest\Webtrees\Contracts\UserInterface; +use Fisharebest\Webtrees\Session; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use function response; + +/** + * Select a new language for the current session. + */ +class SelectLanguage implements RequestHandlerInterface, StatusCodeInterface +{ + /** @var UserInterface */ + private $user; + + /** + * @param UserInterface $user + */ + public function __construct(UserInterface $user) + { + $this->user = $user; + } + + /** + * @param ServerRequestInterface $request + * + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $language = $request->getParsedBody()['language']; + + Session::put('language', $language); + + $this->user->setPreference('language', $language); + + return response('', self::STATUS_NO_CONTENT); + } +} diff --git a/app/Http/RequestHandlers/SelectTheme.php b/app/Http/RequestHandlers/SelectTheme.php new file mode 100644 index 0000000000..fe9deb960b --- /dev/null +++ b/app/Http/RequestHandlers/SelectTheme.php @@ -0,0 +1,59 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\RequestHandlers; + +use Fig\Http\Message\StatusCodeInterface; +use Fisharebest\Webtrees\Contracts\UserInterface; +use Fisharebest\Webtrees\Session; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use function response; + +/** + * Select a new theme for the current session. + */ +class SelectTheme implements RequestHandlerInterface, StatusCodeInterface +{ + /** @var UserInterface */ + private $user; + + /** + * @param UserInterface $user + */ + public function __construct(UserInterface $user) + { + $this->user = $user; + } + + /** + * @param ServerRequestInterface $request + * + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $theme = $request->getParsedBody()['theme']; + + Session::put('theme', $theme); + + $this->user->setPreference('theme', $theme); + + return response('', self::STATUS_NO_CONTENT); + } +} diff --git a/app/I18N.php b/app/I18N.php index bb5ac40c91..48a5129868 100644 --- a/app/I18N.php +++ b/app/I18N.php @@ -316,9 +316,9 @@ class I18N if ($code !== '') { // Create the specified locale self::$locale = Locale::create($code); - } elseif (Session::has('locale') && file_exists(WT_ROOT . 'resources/lang/' . Session::get('locale') . '/messages.mo')) { + } elseif (Session::has('language') && file_exists(WT_ROOT . 'resources/lang/' . Session::get('language') . '/messages.mo')) { // Select a previously used locale - self::$locale = Locale::create(Session::get('locale')); + self::$locale = Locale::create(Session::get('language')); } else { if ($tree instanceof Tree) { $default_locale = Locale::create($tree->getPreference('LANGUAGE', 'en-US')); diff --git a/routes/web.php b/routes/web.php index 9e8b49a315..595a89a755 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,6 +17,12 @@ declare(strict_types=1); namespace Fisharebest\Webtrees; +use Fisharebest\Webtrees\Http\RequestHandlers\DeleteUser; +use Fisharebest\Webtrees\Http\RequestHandlers\MasqueradeAsUser; +use Fisharebest\Webtrees\Http\RequestHandlers\ModuleAction; +use Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage; +use Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme; + /** @var Tree|null $tree */ $tree = app(Tree::class); @@ -129,6 +135,8 @@ if (Auth::isAdmin()) { 'GET:unused-media-thumbnail' => 'MediaFileController@unusedMediaThumbnail', 'GET:broadcast' => 'MessageController@broadcastPage', 'POST:broadcast' => 'MessageController@broadcastAction', + 'POST:delete-user' => DeleteUser::class, + 'POST:masquerade' => MasqueradeAsUser::class, ]; } @@ -255,8 +263,6 @@ if ($tree instanceof Tree && $tree->getPreference('imported') === '1') { 'GET:autocomplete-folder' => 'AutocompleteController@folder', 'GET:autocomplete-page' => 'AutocompleteController@page', 'GET:autocomplete-place' => 'AutocompleteController@place', - //'GET:branches' => 'BranchesController@page', - //'GET:branches-list' => 'BranchesController@list', 'GET:calendar' => 'CalendarController@page', 'GET:calendar-events' => 'CalendarController@calendar', 'GET:help-text' => 'HelpTextController@helpText', @@ -279,13 +285,6 @@ if ($tree instanceof Tree && $tree->getPreference('imported') === '1') { 'GET:report-list' => 'ReportEngineController@reportList', 'GET:report-setup' => 'ReportEngineController@reportSetup', 'GET:report-run' => 'ReportEngineController@reportRun', - //'GET:family-list' => 'ListController@familyList', - //'GET:individual-list' => 'ListController@individualList', - //'GET:media-list' => 'ListController@mediaList', - //'GET:note-list' => 'ListController@noteList', - //'GET:place-hierarchy' => 'PlaceHierarchyController@show', - //'GET:repository-list' => 'ListController@repositoryList', - //'GET:source-list' => 'ListController@sourceList', 'POST:accept-changes' => 'PendingChangesController@acceptChanges', 'POST:reject-changes' => 'PendingChangesController@rejectChanges', 'POST:accept-all-changes' => 'PendingChangesController@acceptAllChanges', @@ -315,13 +314,11 @@ $routes += [ 'GET:verify' => 'Auth\\VerifyEmailController@verify', 'GET:forgot-password' => 'Auth\\ForgotPasswordController@forgotPasswordPage', 'POST:forgot-password' => 'Auth\\ForgotPasswordController@forgotPasswordAction', - 'POST:delete-user' => 'UserController@delete', - 'POST:language' => 'UserController@language', - 'POST:masquerade' => 'UserController@masquerade', - 'POST:theme' => 'UserController@theme', + 'POST:language' => SelectLanguage::class, + 'POST:theme' => SelectTheme::class, 'GET:privacy-policy' => 'StaticPageController@privacyPolicy', - 'GET:module' => 'ModuleController@action', - 'POST:module' => 'ModuleController@action', + 'GET:module' => ModuleAction::class, + 'POST:module' => ModuleAction::class, ]; return $routes; diff --git a/tests/app/Http/Controllers/ModuleControllerTest.php b/tests/app/Http/Controllers/ModuleControllerTest.php deleted file mode 100644 index a8b24b7aed..0000000000 --- a/tests/app/Http/Controllers/ModuleControllerTest.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -/** - * webtrees: online genealogy - * Copyright (C) 2019 webtrees development team - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -declare(strict_types=1); - -namespace Fisharebest\Webtrees\Http\Controllers; - -use Fisharebest\Webtrees\Auth; -use Fisharebest\Webtrees\Module\SiteMapModule; -use Fisharebest\Webtrees\Services\ModuleService; -use Fisharebest\Webtrees\Http\Request; - -/** - * Test the module controller - * - * @covers \Fisharebest\Webtrees\Http\Controllers\AbstractBaseController - * @covers \Fisharebest\Webtrees\Http\Controllers\ModuleController - */ -class ModuleControllerTest extends \Fisharebest\Webtrees\TestCase -{ - protected static $uses_database = true; - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - * @return void - */ - public function testMissingModule(): void - { - $request = new Request(['route' => 'module']); - $controller = new ModuleController(new ModuleService()); - $controller->action($request, Auth::user()); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - * @return void - */ - public function testInvalidModule(): void - { - $request = new Request(['route' => 'module', 'module' => 'no-such-module']); - $controller = new ModuleController(new ModuleService()); - $controller->action($request, Auth::user()); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - * @return void - */ - public function testMissingAction(): void - { - $request = new Request(['route' => 'module', 'module' => 'sitemap']); - $controller = new ModuleController(new ModuleService()); - $controller->action($request, Auth::user()); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - * @return void - */ - public function testInvalidAction(): void - { - $request = new Request(['route' => 'module', 'module' => 'sitemap', 'action' => 'no-such-action']); - $controller = new ModuleController(new ModuleService()); - $controller->action($request, Auth::user()); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - * @return void - */ - public function testVisitorCannotUseAdminAction(): void - { - $request = new Request(['route' => 'module', 'module' => 'sitemap', 'action' => 'DoAdminStuff']); - $controller = new ModuleController(new ModuleService()); - $controller->action($request, Auth::user()); - } - - /** - * @return void - */ - public function testSucessfulAction(): void - { - // The sitemap module is disabled by defualt. - $module_service = $this->createMock(ModuleService::class); - $module_service - ->method('findByName') - ->with('sitemap') - ->willReturn(new SiteMapModule()); - - $request = new Request(['route' => 'module', 'module' => 'sitemap', 'action' => 'Index']); - $controller = new ModuleController($module_service); - $response = $controller->action($request, Auth::user()); - - $this->assertSame(self::STATUS_OK, $response->getStatusCode()); - } -} diff --git a/tests/app/Http/RequestHandlers/DeleteUserTest.php b/tests/app/Http/RequestHandlers/DeleteUserTest.php new file mode 100644 index 0000000000..5da843179e --- /dev/null +++ b/tests/app/Http/RequestHandlers/DeleteUserTest.php @@ -0,0 +1,76 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +use Fisharebest\Webtrees\Http\RequestHandlers\DeleteUser; +use Fisharebest\Webtrees\Services\UserService; +use Fisharebest\Webtrees\TestCase; + +/** + * @covers \Fisharebest\Webtrees\Http\RequestHandlers\DeleteUser + */ +class DeleteUserTest extends TestCase +{ + protected static $uses_database = true; + + /** + * @return void + */ + public function testDeleteUser(): void + { + $user_service = new UserService(); + $user = $user_service->create('user1', 'real1', 'email1', 'pass1'); + $handler = new DeleteUser($user_service); + $request = self::createRequest('POST', ['route' => 'delete-user'], ['user_id' => $user->id()]); + $response = $handler->handle($request); + + // UserService caches user records + app('cache.array')->forget(UserService::class . $user->id()); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + self::assertNull($user_service->find($user->id())); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * @expectedExceptionMessage User ID 98765 not found + * @return void + */ + public function testDeleteNonExistingUser(): void + { + $user_service = new UserService(); + $user_service->create('user1', 'real1', 'email1', 'pass1'); + $handler = new DeleteUser($user_service); + $request = self::createRequest('POST', ['route' => 'delete-user'], ['user_id' => 98765]); + $handler->handle($request); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * @expectedExceptionMessage Cannot delete an administrator + * @return void + */ + public function testCannotDeleteAdministrator(): void + { + $user_service = new UserService(); + $user = $user_service->create('user1', 'real1', 'email1', 'pass1'); + $user->setPreference('canadmin', '1'); + $handler = new DeleteUser($user_service); + $request = self::createRequest('POST', ['route' => 'delete-user'], ['user_id' => $user->id()]); + $handler->handle($request); + } +} + diff --git a/tests/app/Http/RequestHandlers/MasqueradeAsUserTest.php b/tests/app/Http/RequestHandlers/MasqueradeAsUserTest.php new file mode 100644 index 0000000000..90d1043975 --- /dev/null +++ b/tests/app/Http/RequestHandlers/MasqueradeAsUserTest.php @@ -0,0 +1,81 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Http\RequestHandlers\MasqueradeAsUser; +use Fisharebest\Webtrees\Services\UserService; +use Fisharebest\Webtrees\Session; +use Fisharebest\Webtrees\TestCase; + +/** + * @covers \Fisharebest\Webtrees\Http\RequestHandlers\MasqueradeAsUser + */ +class MasqueradeAsUserTest extends TestCase +{ + protected static $uses_database = true; + + /** + * @return void + */ + public function testMasqueradeAsUser(): void + { + $user_service = new UserService(); + $user1 = $user_service->create('user1', 'real1', 'email1', 'pass1'); + $user2 = $user_service->create('user2', 'real2', 'email2', 'pass2'); + Auth::login($user1); + $handler = new MasqueradeAsUser($user1, $user_service); + $request = self::createRequest('POST', ['route' => 'masquerade'], ['user_id' => $user2->id()]); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + self::assertSame($user2->id(), Auth::id()); + self::assertSame('1', Session::get('masquerade')); + } + + /** + * @return void + */ + public function testMasqueradeAsSelf(): void + { + $user_service = new UserService(); + $user = $user_service->create('user', 'real', 'email', 'pass'); + Auth::login($user); + $handler = new MasqueradeAsUser($user, $user_service); + $request = self::createRequest('POST', ['route' => 'masquerade'], ['user_id' => $user->id()]); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + self::assertSame($user->id(), Auth::id()); + self::assertNull(Session::get('masquerade')); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * @expectedExceptionMessage User ID 98765 not found + * @return void + */ + public function testMasqueradeAsNonExistingUser(): void + { + $user_service = new UserService(); + $user = $user_service->create('user', 'real', 'email', 'pass'); + Auth::login($user); + $handler = new MasqueradeAsUser($user, $user_service); + $request = self::createRequest('POST', ['route' => 'masquerade'], ['user_id' => 98765]); + $handler->handle($request); + } +} + diff --git a/tests/app/Http/RequestHandlers/ModuleActionTest.php b/tests/app/Http/RequestHandlers/ModuleActionTest.php new file mode 100644 index 0000000000..57d97a842f --- /dev/null +++ b/tests/app/Http/RequestHandlers/ModuleActionTest.php @@ -0,0 +1,93 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +use Fisharebest\Webtrees\GuestUser; +use Fisharebest\Webtrees\Http\RequestHandlers\ModuleAction; +use Fisharebest\Webtrees\Services\ModuleService; +use Fisharebest\Webtrees\TestCase; +use Fisharebest\Webtrees\Tree; + +/** + * @covers \Fisharebest\Webtrees\Http\RequestHandlers\ModuleAction + */ +class ModuleActionTest extends TestCase +{ + protected static $uses_database = true; + + /** + * @return void + */ + public function testModuleAction(): void + { + $tree = Tree::create('tree', 'tree'); + app()->instance(Tree::class, $tree); + $user = new GuestUser(); + $module_service = new ModuleService(); + $handler = new ModuleAction($module_service, $user); + $request = self::createRequest('GET', ['route' => 'module', 'module' => 'faq', 'action' => 'Show', 'ged' => $tree->name()]); + $response = $handler->handle($request); + + $this->assertSame(self::STATUS_OK, $response->getStatusCode()); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * @expectedExceptionMessage Method getFishAction() not found in faq + * @return void + */ + public function testNonExistingAction(): void + { + $user = new GuestUser(); + $module_service = new ModuleService(); + $handler = new ModuleAction($module_service, $user); + $request = self::createRequest('GET', ['route' => 'module', 'module' => 'faq', 'action' => 'Fish']); + $handler->handle($request); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * @expectedExceptionMessage Module fish does not exist + * @return void + */ + public function testNonExistingModule(): void + { + $user = new GuestUser(); + $module_service = new ModuleService(); + $handler = new ModuleAction($module_service, $user); + $request = self::createRequest('GET', ['route' => 'module', 'module' => 'fish', 'action' => 'Show']); + $response = $handler->handle($request); + + $this->assertSame(self::STATUS_OK, $response->getStatusCode()); + } + + /** + * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * @expectedExceptionMessage Admin only action + * @return void + */ + public function testAdminAction(): void + { + $tree = Tree::create('tree', 'tree'); + app()->instance(Tree::class, $tree); + $user = new GuestUser(); + $module_service = new ModuleService(); + $handler = new ModuleAction($module_service, $user); + $request = self::createRequest('GET', ['route' => 'module', 'module' => 'faq', 'action' => 'Admin', 'ged' => $tree->name()]); + $handler->handle($request); + } +} + diff --git a/tests/app/Http/RequestHandlers/SelectLanguageTest.php b/tests/app/Http/RequestHandlers/SelectLanguageTest.php new file mode 100644 index 0000000000..22d0868df7 --- /dev/null +++ b/tests/app/Http/RequestHandlers/SelectLanguageTest.php @@ -0,0 +1,57 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +use Fisharebest\Webtrees\GuestUser; +use Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage; +use Fisharebest\Webtrees\Services\UserService; +use Fisharebest\Webtrees\TestCase; + +/** + * @covers \Fisharebest\Webtrees\Http\RequestHandlers\SelectLanguage + */ +class SelectLanguageTest extends TestCase +{ + protected static $uses_database = true; + + /** + * @return void + */ + public function testSelectLanguageForGuest(): void + { + $user = new GuestUser(); + $handler = new SelectLanguage($user); + $request = self::createRequest('POST', ['route' => 'language'], ['language' => 'fr']); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + } + + /** + * @return void + */ + public function testSelectLanguageForUser(): void + { + $user_service = new UserService(); + $user = $user_service->create('user', 'real', 'email', 'pass'); + $handler = new SelectLanguage($user); + $request = self::createRequest('POST', ['route' => 'language'], ['language' => 'fr']); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + } +} + diff --git a/tests/app/Http/RequestHandlers/SelectThemeTest.php b/tests/app/Http/RequestHandlers/SelectThemeTest.php new file mode 100644 index 0000000000..f49e6b1f55 --- /dev/null +++ b/tests/app/Http/RequestHandlers/SelectThemeTest.php @@ -0,0 +1,59 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +use Fisharebest\Webtrees\GuestUser; +use Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme; +use Fisharebest\Webtrees\Services\UserService; +use Fisharebest\Webtrees\TestCase; + +/** + * @covers \Fisharebest\Webtrees\Http\RequestHandlers\SelectTheme + */ +class SelectThemeTest extends TestCase +{ + protected static $uses_database = true; + + /** + * @return void + */ + public function testSelectThemeForGuest(): void + { + $user = new GuestUser(); + $handler = new SelectTheme($user); + $request = self::createRequest('POST', ['route' => 'theme'], ['theme' => 'FOO']); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + self::assertSame('FOO', $user->getPreference('theme')); + } + + /** + * @return void + */ + public function testSelectThemeForUser(): void + { + $user_service = new UserService(); + $user = $user_service->create('user', 'real', 'email', 'pass'); + $handler = new SelectTheme($user); + $request = self::createRequest('POST', ['route' => 'theme'], ['theme' => 'FOO']); + $response = $handler->handle($request); + + self::assertSame(self::STATUS_NO_CONTENT, $response->getStatusCode()); + self::assertSame('FOO', $user->getPreference('theme')); + } +} + |
