Compare commits

..
Author SHA1 Message Date
bence 10f032a9a5 Merge pull request 'bugfix/fix-ambiguous-sql-field-names' (!65) from bugfix/fix-ambiguous-sql-field-names into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #65
2023-05-02 18:12:04 +02:00
bence c02e35580f use sql field names with tables where join happens
mapguesser/pipeline/pr-develop This commit looks good
2023-05-02 18:10:22 +02:00
bence afd58bb91b update soko-web to 0.10.1 2023-05-02 18:08:53 +02:00
bence fc6792ccfc Merge pull request 'add autocomplete values for username and password fields' (!64) from feature/add-autocompletes-for-usernames-and-passwords into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #64
2023-05-02 14:14:55 +02:00
bence a5ba8e71e4 add autocomplete values for username and password fields
mapguesser/pipeline/pr-develop This commit looks good
2023-05-02 14:10:10 +02:00
bence 184f63585c Merge pull request 'feature/session-handler-changes' (!63) from feature/session-handler-changes into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #63
2023-05-02 13:20:07 +02:00
bence d666593fde session should be valid for a session
mapguesser/pipeline/pr-develop This commit looks good
2023-05-02 13:18:37 +02:00
bence 75fad05362 adapt to new soko-web interfaces 2023-05-02 13:18:14 +02:00
bence 45b34cb514 update to soko-web 0.10 2023-05-02 13:18:03 +02:00
bence a6ba53764b Merge pull request 'feature/update-soko-web-to-0.7' (!62) from feature/update-soko-web-to-0.7 into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #62
2023-04-30 21:07:08 +02:00
bence e70f8a9965 adapt $withRelations usage to soko-web 0.7
mapguesser/pipeline/pr-develop This commit looks good
2023-04-30 21:01:15 +02:00
bence 4aadcab2d2 update soko-web to 0.7 2023-04-30 20:29:43 +02:00
bence 9aea195f85 Merge pull request 'feature/update-soko-web' (!61) from feature/update-soko-web into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #61
2023-04-20 00:41:25 +02:00
bence eafcf2315e use IRouteCollection in app container
mapguesser/pipeline/pr-develop This commit looks good
2023-04-20 00:39:10 +02:00
bence e52300b9e5 adapt Container usage to new soko-web 2023-04-20 00:39:10 +02:00
bence ee4a9f2ce3 remove unnecessary startTransaction and commit calls 2023-04-20 00:39:10 +02:00
bence 8141845ae9 add error view 500 to app config 2023-04-20 00:39:10 +02:00
bence 69f54c861a add view for error 500 2023-04-20 00:39:10 +02:00
bence c9ab7c31b7 pass dbConnection to HttpResponse 2023-04-20 00:30:01 +02:00
bence 82279f11d3 update soko-web to 0.6.1 2023-04-20 00:30:01 +02:00
bence 6cb4e06acc Merge pull request 'remove unnecessary use in web.php' (!60) from bugfix/remove-unnecessary-use into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #60
2023-04-16 22:02:22 +02:00
bence ee33fc1913 remove unnecessary use in web.php
mapguesser/pipeline/pr-develop This commit looks good
2023-04-16 22:00:25 +02:00
bence 4fb1831763 Merge pull request 'feature/adapt-to-new-soko-web' (!59) from feature/adapt-to-new-soko-web into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #59
2023-04-16 21:46:07 +02:00
bence 9dee8ba988 use classes at beginning of web.php
mapguesser/pipeline/pr-develop This commit looks good
2023-04-16 21:44:11 +02:00
bence 82562117b2 adapt code to soko-web 0.4 2023-04-16 21:38:25 +02:00
bence 317a4de5c0 update soko-web to 0.4 2023-04-16 21:37:18 +02:00
bence bf6b5f39a5 Merge pull request 'feature/use-new-features-from-soko-web' (!58) from feature/use-new-features-from-soko-web into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #58
2023-04-16 17:49:41 +02:00
bence ed80fe544f add adminer to docker-compose
mapguesser/pipeline/pr-develop This commit looks good
2023-04-16 17:48:12 +02:00
bence 3e4c24bbc1 implement redirect after login 2023-04-16 17:48:12 +02:00
bence 54a4ee4d60 use ISecured/IAuthenticationRequired correctly in containers 2023-04-16 17:14:27 +02:00
bence 62e0261a0b implement redirect to login for controllers for authentication is required 2023-04-16 17:09:46 +02:00
bence 9d1bb41f02 adapt to soko-web 0.2 2023-04-16 17:01:16 +02:00
bence 59527a1898 update soko-web to 0.3 2023-04-16 17:00:54 +02:00
bence 525d740409 Merge pull request 'MAPG-243 delete assets for view testing (these are in soko-web now)' (!57) from feature/MAPG-243-delete-further-unused-files into develop
mapguesser/pipeline/head This commit looks good
Reviewed-on: #57
2023-04-08 10:56:46 +02:00
bence 0f7828e486 MAPG-243 delete assets for view testing (these are in soko-web now)
mapguesser/pipeline/pr-develop This commit looks good
2023-04-08 10:53:04 +02:00
45 changed files with 491 additions and 704 deletions

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@
} }
], ],
"require": { "require": {
"esoko/soko-web": "0.1", "esoko/soko-web": "0.10.1",
"fzaninotto/faker": "^1.9" "fzaninotto/faker": "^1.9"
}, },
"require-dev": { "require-dev": {
Generated
+4 -4
View File
@@ -4,15 +4,15 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "4c91d823e927375028a2b3c9d974a8bd", "content-hash": "27b6af78f89ef8dde87e918118511571",
"packages": [ "packages": [
{ {
"name": "esoko/soko-web", "name": "esoko/soko-web",
"version": "v0.1", "version": "v0.10.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.esoko.eu/esoko/soko-web.git", "url": "https://git.esoko.eu/esoko/soko-web.git",
"reference": "a17a88e9d44e42cef3d996fc66b4dd1134b85def" "reference": "585d469b695365e6f8c0f9b596dbb18b6d3ce584"
}, },
"require": { "require": {
"phpmailer/phpmailer": "^6.8", "phpmailer/phpmailer": "^6.8",
@@ -33,7 +33,7 @@
"GNU GPL 3.0" "GNU GPL 3.0"
], ],
"description": "Lightweight web framework", "description": "Lightweight web framework",
"time": "2023-04-07T17:32:15+00:00" "time": "2023-05-02T16:06:33+00:00"
}, },
{ {
"name": "fzaninotto/faker", "name": "fzaninotto/faker",
+6
View File
@@ -29,6 +29,12 @@ services:
MYSQL_DATABASE: 'mapguesser' MYSQL_DATABASE: 'mapguesser'
MYSQL_USER: 'mapguesser' MYSQL_USER: 'mapguesser'
MYSQL_PASSWORD: 'mapguesser' MYSQL_PASSWORD: 'mapguesser'
adminer:
image: adminer:4.8.1-standalone
ports:
- 9090:8080
environment:
- ADMINER_DEFAULT_SERVER=mariadb
mail: mail:
image: marcopas/docker-mailslurper:latest image: marcopas/docker-mailslurper:latest
ports: ports:
+3 -1
View File
@@ -15,9 +15,11 @@ $dotenv->load();
class Container class Container
{ {
static SokoWeb\Interfaces\Database\IConnection $dbConnection; static SokoWeb\Interfaces\Database\IConnection $dbConnection;
static SokoWeb\Routing\RouteCollection $routeCollection; static SokoWeb\Interfaces\PersistentData\IPersistentDataManager $persistentDataManager;
static SokoWeb\Interfaces\Routing\IRouteCollection $routeCollection;
static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler; static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler;
static SokoWeb\Interfaces\Request\IRequest $request; static SokoWeb\Interfaces\Request\IRequest $request;
} }
Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']); Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']);
Container::$persistentDataManager = new SokoWeb\PersistentData\PersistentDataManager(Container::$dbConnection);
-50
View File
@@ -1,53 +1,3 @@
<?php <?php
require '../web.php'; require '../web.php';
$method = strtolower($_SERVER['REQUEST_METHOD']);
$url = substr($_SERVER['REQUEST_URI'], strlen('/'));
if (($pos = strpos($url, '?')) !== false) {
$url = substr($url, 0, $pos);
}
$url = rawurldecode($url);
$match = Container::$routeCollection->match($method, $url == '' ? [] : explode('/', $url));
if ($match !== null) {
list($route, $params) = $match;
Container::$request->setParsedRouteParams($params);
$handler = $route->getHandler();
$controller = new $handler[0](Container::$request);
if ($controller instanceof SokoWeb\Interfaces\Authorization\ISecured) {
$authorized = $controller->authorize();
} else {
$authorized = true;
}
if ($method === 'post' && Container::$request->post('anti_csrf_token') !== Container::$request->session()->get('anti_csrf_token')) {
$content = new SokoWeb\Response\JsonContent(['error' => 'no_valid_anti_csrf_token']);
header('Content-Type: text/html; charset=UTF-8', true, 403);
$content->render();
return;
}
if ($authorized) {
$response = call_user_func([$controller, $handler[1]]);
if ($response instanceof SokoWeb\Interfaces\Response\IContent) {
header('Content-Type: ' . $response->getContentType() . '; charset=UTF-8');
$response->render();
return;
} elseif ($response instanceof SokoWeb\Interfaces\Response\IRedirect) {
header('Location: ' . $response->getUrl(), true, $response->getHttpCode());
return;
}
}
}
$content = new SokoWeb\Response\HtmlContent('error/404');
header('Content-Type: text/html; charset=UTF-8', true, 404);
$content->render();
+1 -3
View File
@@ -69,7 +69,7 @@
printTimeForHuman: function (time) { printTimeForHuman: function (time) {
const minutes = Math.floor(time / 60); const minutes = Math.floor(time / 60);
const seconds = time % 60; const seconds = time % 60;
var time_str = ''; var time_str = '';
if (minutes == 1) { if (minutes == 1) {
time_str += '1 minute'; time_str += '1 minute';
@@ -141,9 +141,7 @@
if (document.getElementById('challengeButton')) { if (document.getElementById('challengeButton')) {
document.getElementById('challengeButton').onclick = function () { document.getElementById('challengeButton').onclick = function () {
MapGuesser.showModal('challenge'); MapGuesser.showModal('challenge');
document.getElementById('createNewChallengeButton').href = '/challenge/new/' + this.dataset.mapId;
document.getElementById('playMode').style.visibility = 'hidden'; document.getElementById('playMode').style.visibility = 'hidden';
var timeLimit = document.getElementById('timeLimit').value; var timeLimit = document.getElementById('timeLimit').value;
document.getElementById('timeLimitLabel').innerText = 'Time limit of ' + Util.printTimeForHuman(timeLimit); document.getElementById('timeLimitLabel').innerText = 'Time limit of ' + Util.printTimeForHuman(timeLimit);
}; };
+1 -3
View File
@@ -1,7 +1,6 @@
<?php namespace MapGuesser\Cli; <?php namespace MapGuesser\Cli;
use DateTime; use DateTime;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
@@ -32,8 +31,7 @@ class AddUserCommand extends Command
} }
try { try {
$pdm = new PersistentDataManager(); \Container::$persistentDataManager->saveToDb($user);
$pdm->saveToDb($user);
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln('<error>Adding user failed!</error>'); $output->writeln('<error>Adding user failed!</error>');
$output->writeln(''); $output->writeln('');
+6 -10
View File
@@ -4,7 +4,6 @@ use DateTime;
use SokoWeb\Database\Query\Modify; use SokoWeb\Database\Query\Modify;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use SokoWeb\Interfaces\Database\IResultSet; use SokoWeb\Interfaces\Database\IResultSet;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\Repository\MultiRoomRepository; use MapGuesser\Repository\MultiRoomRepository;
use MapGuesser\Repository\UserConfirmationRepository; use MapGuesser\Repository\UserConfirmationRepository;
use MapGuesser\Repository\UserPasswordResetterRepository; use MapGuesser\Repository\UserPasswordResetterRepository;
@@ -16,8 +15,6 @@ use Symfony\Component\Console\Output\OutputInterface;
class MaintainDatabaseCommand extends Command class MaintainDatabaseCommand extends Command
{ {
private PersistentDataManager $pdm;
private UserRepository $userRepository; private UserRepository $userRepository;
private UserConfirmationRepository $userConfirmationRepository; private UserConfirmationRepository $userConfirmationRepository;
@@ -32,7 +29,6 @@ class MaintainDatabaseCommand extends Command
{ {
parent::__construct(); parent::__construct();
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
$this->userConfirmationRepository = new UserConfirmationRepository(); $this->userConfirmationRepository = new UserConfirmationRepository();
$this->userPasswordResetterRepository = new UserPasswordResetterRepository(); $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
@@ -77,19 +73,19 @@ class MaintainDatabaseCommand extends Command
//TODO: these can be in some wrapper class //TODO: these can be in some wrapper class
$userConfirmation = $this->userConfirmationRepository->getByUser($user); $userConfirmation = $this->userConfirmationRepository->getByUser($user);
if ($userConfirmation !== null) { if ($userConfirmation !== null) {
$this->pdm->deleteFromDb($userConfirmation); \Container::$persistentDataManager->deleteFromDb($userConfirmation);
} }
$userPasswordResetter = $this->userPasswordResetterRepository->getByUser($user); $userPasswordResetter = $this->userPasswordResetterRepository->getByUser($user);
if ($userPasswordResetter !== null) { if ($userPasswordResetter !== null) {
$this->pdm->deleteFromDb($userPasswordResetter); \Container::$persistentDataManager->deleteFromDb($userPasswordResetter);
} }
foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) { foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) {
$this->pdm->deleteFromDb($userPlayedPlace); \Container::$persistentDataManager->deleteFromDb($userPlayedPlace);
} }
$this->pdm->deleteFromDb($user); \Container::$persistentDataManager->deleteFromDb($user);
} }
\Container::$dbConnection->commit(); \Container::$dbConnection->commit();
@@ -98,14 +94,14 @@ class MaintainDatabaseCommand extends Command
private function deleteExpiredPasswordResetters(): void private function deleteExpiredPasswordResetters(): void
{ {
foreach ($this->userPasswordResetterRepository->getAllExpired() as $passwordResetter) { foreach ($this->userPasswordResetterRepository->getAllExpired() as $passwordResetter) {
$this->pdm->deleteFromDb($passwordResetter); \Container::$persistentDataManager->deleteFromDb($passwordResetter);
} }
} }
private function deleteExpiredRooms(): void private function deleteExpiredRooms(): void
{ {
foreach ($this->multiRoomRepository->getAllExpired() as $multiRoom) { foreach ($this->multiRoomRepository->getAllExpired() as $multiRoom) {
$this->pdm->deleteFromDb($multiRoom); \Container::$persistentDataManager->deleteFromDb($multiRoom);
} }
} }
+31 -39
View File
@@ -2,8 +2,7 @@
use DateTime; use DateTime;
use Faker\Factory; use Faker\Factory;
use SokoWeb\Interfaces\Authorization\ISecured; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
@@ -13,7 +12,6 @@ use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\MultiRoom; use MapGuesser\PersistentData\Model\MultiRoom;
use MapGuesser\PersistentData\Model\PlaceInChallenge; use MapGuesser\PersistentData\Model\PlaceInChallenge;
use MapGuesser\PersistentData\Model\UserInChallenge; use MapGuesser\PersistentData\Model\UserInChallenge;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\Repository\ChallengeRepository; use MapGuesser\Repository\ChallengeRepository;
use MapGuesser\Repository\MapRepository; use MapGuesser\Repository\MapRepository;
use MapGuesser\Repository\MultiRoomRepository; use MapGuesser\Repository\MultiRoomRepository;
@@ -21,14 +19,10 @@ use MapGuesser\Repository\PlaceRepository;
use MapGuesser\Repository\UserInChallengeRepository; use MapGuesser\Repository\UserInChallengeRepository;
use SokoWeb\Response\Redirect; use SokoWeb\Response\Redirect;
class GameController implements ISecured class GameController implements IAuthenticationRequired
{ {
const NUMBER_OF_ROUNDS = 5; const NUMBER_OF_ROUNDS = 5;
private IRequest $request;
private PersistentDataManager $pdm;
private MultiConnector $multiConnector; private MultiConnector $multiConnector;
private MultiRoomRepository $multiRoomRepository; private MultiRoomRepository $multiRoomRepository;
@@ -41,10 +35,8 @@ class GameController implements ISecured
private UserInChallengeRepository $userInChallengeRepository; private UserInChallengeRepository $userInChallengeRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->multiConnector = new MultiConnector(); $this->multiConnector = new MultiConnector();
$this->multiRoomRepository = new MultiRoomRepository(); $this->multiRoomRepository = new MultiRoomRepository();
$this->mapRepository = new MapRepository(); $this->mapRepository = new MapRepository();
@@ -53,21 +45,21 @@ class GameController implements ISecured
$this->userInChallengeRepository = new UserInChallengeRepository(); $this->userInChallengeRepository = new UserInChallengeRepository();
} }
public function authorize(): bool public function isAuthenticationRequired(): bool
{ {
return !empty($_ENV['ENABLE_GAME_FOR_GUESTS']) || $this->request->user() !== null; return empty($_ENV['ENABLE_GAME_FOR_GUESTS']);
} }
public function getGame(): IContent public function getGame(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
return new HtmlContent('game', ['mapId' => $mapId]); return new HtmlContent('game', ['mapId' => $mapId]);
} }
public function getNewMultiGame(): IRedirect public function getNewMultiGame(): IRedirect
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
$map = $this->mapRepository->getById($mapId); $map = $this->mapRepository->getById($mapId);
$roomId = bin2hex(random_bytes(3)); $roomId = bin2hex(random_bytes(3));
$token = $this->getMultiToken($roomId); $token = $this->getMultiToken($roomId);
@@ -83,7 +75,7 @@ class GameController implements ISecured
$room->setMembersArray(['owner' => $token, 'all' => []]); $room->setMembersArray(['owner' => $token, 'all' => []]);
$room->setUpdatedDate(new DateTime()); $room->setUpdatedDate(new DateTime());
$this->pdm->saveToDb($room); \Container::$persistentDataManager->saveToDb($room);
$this->multiConnector->sendMessage('create_room', ['roomId' => $roomId]); $this->multiConnector->sendMessage('create_room', ['roomId' => $roomId]);
@@ -97,14 +89,14 @@ class GameController implements ISecured
public function getMultiGame(): IContent public function getMultiGame(): IContent
{ {
$roomId = $this->request->query('roomId'); $roomId = \Container::$request->query('roomId');
return new HtmlContent('game', ['roomId' => $roomId]); return new HtmlContent('game', ['roomId' => $roomId]);
} }
public function getChallenge(): IContent public function getChallenge(): IContent
{ {
$challengeToken = $this->request->query('challengeToken'); $challengeToken = \Container::$request->query('challengeToken');
return new HtmlContent('game', ['challengeToken' => $challengeToken]); return new HtmlContent('game', ['challengeToken' => $challengeToken]);
} }
@@ -121,27 +113,27 @@ class GameController implements ISecured
$challenge->setToken($challengeToken); $challenge->setToken($challengeToken);
$challenge->setCreatedDate(new DateTime()); $challenge->setCreatedDate(new DateTime());
if ($this->request->post('timerEnabled') !== null && $this->request->post('timeLimit') !== null) { if (\Container::$request->post('timerEnabled') !== null && \Container::$request->post('timeLimit') !== null) {
$challenge->setTimeLimit($this->request->post('timeLimit')); $challenge->setTimeLimit(\Container::$request->post('timeLimit'));
} }
if ($this->request->post('timeLimitType') !== null) { if (\Container::$request->post('timeLimitType') !== null) {
$challenge->setTimeLimitType($this->request->post('timeLimitType')); $challenge->setTimeLimitType(\Container::$request->post('timeLimitType'));
} }
if ($this->request->post('noMove') !== null) { if (\Container::$request->post('noMove') !== null) {
$challenge->setNoMove(true); $challenge->setNoMove(true);
} }
if ($this->request->post('noPan') !== null) { if (\Container::$request->post('noPan') !== null) {
$challenge->setNoPan(true); $challenge->setNoPan(true);
} }
if ($this->request->post('noZoom') !== null) { if (\Container::$request->post('noZoom') !== null) {
$challenge->setNoZoom(true); $challenge->setNoZoom(true);
} }
$this->pdm->saveToDb($challenge); \Container::$persistentDataManager->saveToDb($challenge);
// save owner/creator // save owner/creator
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
$userInChallenge = new UserInChallenge(); $userInChallenge = new UserInChallenge();
@@ -150,11 +142,11 @@ class GameController implements ISecured
$userInChallenge->setTimeLeft($challenge->getTimeLimit()); $userInChallenge->setTimeLeft($challenge->getTimeLimit());
$userInChallenge->setIsOwner(true); $userInChallenge->setIsOwner(true);
$this->pdm->saveToDb($userInChallenge); \Container::$persistentDataManager->saveToDb($userInChallenge);
// select places // select places
$mapId = (int) $this->request->post('mapId'); $mapId = (int) \Container::$request->post('mapId');
// $map = $this->mapRepository->getById($mapId); // $map = $this->mapRepository->getById($mapId);
$places = $this->placeRepository->getRandomNPlaces($mapId, static::NUMBER_OF_ROUNDS, $userId); $places = $this->placeRepository->getRandomNPlaces($mapId, static::NUMBER_OF_ROUNDS, $userId);
@@ -165,7 +157,7 @@ class GameController implements ISecured
$placeInChallenge->setPlace($place); $placeInChallenge->setPlace($place);
$placeInChallenge->setChallenge($challenge); $placeInChallenge->setChallenge($challenge);
$placeInChallenge->setRound($round++); $placeInChallenge->setRound($round++);
$this->pdm->saveToDb($placeInChallenge); \Container::$persistentDataManager->saveToDb($placeInChallenge);
} }
return new JsonContent(['challengeToken' => dechex($challengeToken)]); return new JsonContent(['challengeToken' => dechex($challengeToken)]);
@@ -173,9 +165,9 @@ class GameController implements ISecured
public function prepareGame(): IContent public function prepareGame(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
$map = $this->mapRepository->getById($mapId); $map = $this->mapRepository->getById($mapId);
$session = $this->request->session(); $session = \Container::$request->session();
if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) { if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) {
$session->set('state', [ $session->set('state', [
@@ -198,8 +190,8 @@ class GameController implements ISecured
public function prepareMultiGame(): IContent public function prepareMultiGame(): IContent
{ {
$roomId = $this->request->query('roomId'); $roomId = \Container::$request->query('roomId');
$userName = $this->request->post('userName'); $userName = \Container::$request->post('userName');
if (empty($userName)) { if (empty($userName)) {
$faker = Factory::create(); $faker = Factory::create();
$userName = $faker->userName; $userName = $faker->userName;
@@ -228,7 +220,7 @@ class GameController implements ISecured
$room->setMembersArray($members); $room->setMembersArray($members);
$room->setUpdatedDate(new DateTime()); $room->setUpdatedDate(new DateTime());
$this->pdm->saveToDb($room); \Container::$persistentDataManager->saveToDb($room);
$this->multiConnector->sendMessage('join_room', [ $this->multiConnector->sendMessage('join_room', [
'roomId' => $roomId, 'roomId' => $roomId,
@@ -248,8 +240,8 @@ class GameController implements ISecured
public function prepareChallenge(): IContent public function prepareChallenge(): IContent
{ {
$challengeToken_str = $this->request->query('challengeToken'); $challengeToken_str = \Container::$request->query('challengeToken');
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
if (!isset($userId)) if (!isset($userId))
@@ -270,7 +262,7 @@ class GameController implements ISecured
$userInChallenge->setUserId($userId); $userInChallenge->setUserId($userId);
$userInChallenge->setChallenge($challenge); $userInChallenge->setChallenge($challenge);
$userInChallenge->setTimeLeft($challenge->getTimeLimit()); $userInChallenge->setTimeLeft($challenge->getTimeLimit());
$this->pdm->saveToDb($userInChallenge); \Container::$persistentDataManager->saveToDb($userInChallenge);
} }
$map = $this->mapRepository->getByChallenge($challenge); $map = $this->mapRepository->getByChallenge($challenge);
@@ -284,7 +276,7 @@ class GameController implements ISecured
private function getMultiToken(string $roomId): string private function getMultiToken(string $roomId): string
{ {
$session = $this->request->session(); $session = \Container::$request->session();
if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) { if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) {
$token = bin2hex(random_bytes(16)); $token = bin2hex(random_bytes(16));
+36 -47
View File
@@ -1,13 +1,11 @@
<?php namespace MapGuesser\Controller; <?php namespace MapGuesser\Controller;
use DateTime; use DateTime;
use SokoWeb\Interfaces\Authorization\ISecured; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use MapGuesser\Util\Geo\Position; use MapGuesser\Util\Geo\Position;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use MapGuesser\Multi\MultiConnector; use MapGuesser\Multi\MultiConnector;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Guess; use MapGuesser\PersistentData\Model\Guess;
use MapGuesser\PersistentData\Model\Map; use MapGuesser\PersistentData\Model\Map;
@@ -15,25 +13,18 @@ use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\PlaceInChallenge; use MapGuesser\PersistentData\Model\PlaceInChallenge;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserPlayedPlace; use MapGuesser\PersistentData\Model\UserPlayedPlace;
use MapGuesser\Repository\ChallengeRepository;
use MapGuesser\Repository\GuessRepository; use MapGuesser\Repository\GuessRepository;
use MapGuesser\Repository\MapRepository;
use MapGuesser\Repository\MultiRoomRepository; use MapGuesser\Repository\MultiRoomRepository;
use MapGuesser\Repository\PlaceInChallengeRepository; use MapGuesser\Repository\PlaceInChallengeRepository;
use MapGuesser\Repository\PlaceRepository; use MapGuesser\Repository\PlaceRepository;
use MapGuesser\Repository\UserInChallengeRepository; use MapGuesser\Repository\UserInChallengeRepository;
use MapGuesser\Repository\UserPlayedPlaceRepository; use MapGuesser\Repository\UserPlayedPlaceRepository;
use MapGuesser\Repository\UserRepository;
class GameFlowController implements ISecured class GameFlowController implements IAuthenticationRequired
{ {
const NUMBER_OF_ROUNDS = 5; const NUMBER_OF_ROUNDS = 5;
const MAX_SCORE = 1000; const MAX_SCORE = 1000;
private IRequest $request;
private PersistentDataManager $pdm;
private MultiConnector $multiConnector; private MultiConnector $multiConnector;
private MultiRoomRepository $multiRoomRepository; private MultiRoomRepository $multiRoomRepository;
@@ -48,10 +39,8 @@ class GameFlowController implements ISecured
private GuessRepository $guessRepository; private GuessRepository $guessRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->multiConnector = new MultiConnector(); $this->multiConnector = new MultiConnector();
$this->multiRoomRepository = new MultiRoomRepository(); $this->multiRoomRepository = new MultiRoomRepository();
$this->placeRepository = new PlaceRepository(); $this->placeRepository = new PlaceRepository();
@@ -61,15 +50,15 @@ class GameFlowController implements ISecured
$this->guessRepository = new GuessRepository(); $this->guessRepository = new GuessRepository();
} }
public function authorize(): bool public function isAuthenticationRequired(): bool
{ {
return !empty($_ENV['ENABLE_GAME_FOR_GUESTS']) || $this->request->user() !== null; return empty($_ENV['ENABLE_GAME_FOR_GUESTS']);
} }
public function initialData(): IContent public function initialData(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
$session = $this->request->session(); $session = \Container::$request->session();
if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) { if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) {
return new JsonContent(['error' => 'no_session_found']); return new JsonContent(['error' => 'no_session_found']);
@@ -106,8 +95,8 @@ class GameFlowController implements ISecured
public function multiInitialData(): IContent public function multiInitialData(): IContent
{ {
$roomId = $this->request->query('roomId'); $roomId = \Container::$request->query('roomId');
$session = $this->request->session(); $session = \Container::$request->session();
if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) { if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) {
return new JsonContent(['error' => 'no_session_found']); return new JsonContent(['error' => 'no_session_found']);
@@ -125,7 +114,7 @@ class GameFlowController implements ISecured
$this->startNewGame($state, $state['mapId']); $this->startNewGame($state, $state['mapId']);
$room->setStateArray($state); $room->setStateArray($state);
$room->setUpdatedDate(new DateTime()); $room->setUpdatedDate(new DateTime());
$this->pdm->saveToDb($room); \Container::$persistentDataManager->saveToDb($room);
} }
$places = []; $places = [];
@@ -149,7 +138,7 @@ class GameFlowController implements ISecured
// if the last round was played ($currentPlace == null) or history is explicitly requested (for initializing) // if the last round was played ($currentPlace == null) or history is explicitly requested (for initializing)
if (!isset($currentPlace) || $withHistory) { if (!isset($currentPlace) || $withHistory) {
$withRelations = [User::class, PlaceInChallenge::class, Place::class]; $withRelations = ['user', 'place_in_challange', 'place'];
foreach ($this->guessRepository->getAllInChallenge($challenge, $withRelations) as $guess) { foreach ($this->guessRepository->getAllInChallenge($challenge, $withRelations) as $guess) {
$round = $guess->getPlaceInChallenge()->getRound(); $round = $guess->getPlaceInChallenge()->getRound();
@@ -198,7 +187,7 @@ class GameFlowController implements ISecured
$prevRound = $currentRound - 1; $prevRound = $currentRound - 1;
if ($prevRound >= 0) { if ($prevRound >= 0) {
foreach ($this->guessRepository->getAllInChallengeByRound($prevRound, $challenge, [User::class]) as $guess) { foreach ($this->guessRepository->getAllInChallengeByRound($prevRound, $challenge, ['user']) as $guess) {
if ($guess->getUser()->getId() != $userId) { if ($guess->getUser()->getId() != $userId) {
$response['allResults'][] = [ $response['allResults'][] = [
'userName' => $guess->getUser()->getDisplayName(), 'userName' => $guess->getUser()->getDisplayName(),
@@ -224,10 +213,10 @@ class GameFlowController implements ISecured
public function challengeInitialData(): IContent public function challengeInitialData(): IContent
{ {
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
$challengeToken_str = $this->request->query('challengeToken'); $challengeToken_str = \Container::$request->query('challengeToken');
$userInChallenge = $this->userInChallengeRepository->getByUserIdAndToken($userId, $challengeToken_str, [Challenge::class]); $userInChallenge = $this->userInChallengeRepository->getByUserIdAndToken($userId, $challengeToken_str, ['challenge']);
if (!isset($userInChallenge)) { if (!isset($userInChallenge)) {
return new JsonContent(['error' => 'game_not_found']); return new JsonContent(['error' => 'game_not_found']);
@@ -248,15 +237,15 @@ class GameFlowController implements ISecured
public function guess(): IContent public function guess(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
$session = $this->request->session(); $session = \Container::$request->session();
if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) { if (!($state = $session->get('state')) || $state['mapId'] !== $mapId) {
return new JsonContent(['error' => 'no_session_found']); return new JsonContent(['error' => 'no_session_found']);
} }
$last = $state['rounds'][$state['currentRound']]; $last = $state['rounds'][$state['currentRound']];
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng')); $guessPosition = new Position((float) \Container::$request->post('lat'), (float) \Container::$request->post('lng'));
$result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']); $result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']);
$last['guessPosition'] = $guessPosition; $last['guessPosition'] = $guessPosition;
@@ -289,7 +278,7 @@ class GameFlowController implements ISecured
// save the selected place for the round in UserPlayedPlace // save the selected place for the round in UserPlayedPlace
private function saveVisit($placeId): void private function saveVisit($placeId): void
{ {
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
if (isset($userId)) { if (isset($userId)) {
@@ -302,14 +291,14 @@ class GameFlowController implements ISecured
$userPlayedPlace->incrementOccurrences(); $userPlayedPlace->incrementOccurrences();
} }
$userPlayedPlace->setLastTimeDate(new DateTime()); $userPlayedPlace->setLastTimeDate(new DateTime());
$this->pdm->saveToDb($userPlayedPlace); \Container::$persistentDataManager->saveToDb($userPlayedPlace);
} }
} }
public function multiGuess(): IContent public function multiGuess(): IContent
{ {
$roomId = $this->request->query('roomId'); $roomId = \Container::$request->query('roomId');
$session = $this->request->session(); $session = \Container::$request->session();
if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) { if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) {
return new JsonContent(['error' => 'no_session_found']); return new JsonContent(['error' => 'no_session_found']);
@@ -319,7 +308,7 @@ class GameFlowController implements ISecured
$state = $room->getStateArray(); $state = $room->getStateArray();
$last = $state['rounds'][$state['currentRound']]; $last = $state['rounds'][$state['currentRound']];
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng')); $guessPosition = new Position((float) \Container::$request->post('lat'), (float) \Container::$request->post('lng'));
$result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']); $result = $this->evaluateGuess($last['position'], $guessPosition, $state['area']);
$responseFromMulti = $this->multiConnector->sendMessage('guess', [ $responseFromMulti = $this->multiConnector->sendMessage('guess', [
@@ -345,10 +334,10 @@ class GameFlowController implements ISecured
public function challengeGuess(): IContent public function challengeGuess(): IContent
{ {
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
$challengeToken_str = $this->request->query('challengeToken'); $challengeToken_str = \Container::$request->query('challengeToken');
$userInChallenge = $this->userInChallengeRepository->getByUserIdAndToken($userId, $challengeToken_str, [Challenge::class]); $userInChallenge = $this->userInChallengeRepository->getByUserIdAndToken($userId, $challengeToken_str, ['challenge']);
if (!isset($userInChallenge)) { if (!isset($userInChallenge)) {
return new JsonContent(['error' => 'game_not_found']); return new JsonContent(['error' => 'game_not_found']);
@@ -356,7 +345,7 @@ class GameFlowController implements ISecured
$challenge = $userInChallenge->getChallenge(); $challenge = $userInChallenge->getChallenge();
$currentRound = $userInChallenge->getCurrentRound(); $currentRound = $userInChallenge->getCurrentRound();
$currentPlaceInChallenge = $this->placeInChallengeRepository->getByRoundInChallenge($currentRound, $challenge, [Place::class, Map::class]); $currentPlaceInChallenge = $this->placeInChallengeRepository->getByRoundInChallenge($currentRound, $challenge, ['place', 'map']);
$currentPlace = $currentPlaceInChallenge->getPlace(); $currentPlace = $currentPlaceInChallenge->getPlace();
$map = $currentPlace->getMap(); $map = $currentPlace->getMap();
@@ -365,8 +354,8 @@ class GameFlowController implements ISecured
$response = $this->prepareChallengeResponse($userId, $challenge, $nextRound); $response = $this->prepareChallengeResponse($userId, $challenge, $nextRound);
$response['position'] = $currentPlace->getPosition()->toArray(); $response['position'] = $currentPlace->getPosition()->toArray();
if ($this->request->post('lat') && $this->request->post('lng')) { if (\Container::$request->post('lat') && \Container::$request->post('lng')) {
$guessPosition = new Position((float) $this->request->post('lat'), (float) $this->request->post('lng')); $guessPosition = new Position((float) \Container::$request->post('lat'), (float) \Container::$request->post('lng'));
$result = $this->evaluateGuess($currentPlace->getPosition(), $guessPosition, $map->getArea()); $result = $this->evaluateGuess($currentPlace->getPosition(), $guessPosition, $map->getArea());
// save guess // save guess
@@ -376,7 +365,7 @@ class GameFlowController implements ISecured
$guess->setPosition($guessPosition); $guess->setPosition($guessPosition);
$guess->setDistance($result['distance']); $guess->setDistance($result['distance']);
$guess->setScore($result['score']); $guess->setScore($result['score']);
$this->pdm->saveToDb($guess); \Container::$persistentDataManager->saveToDb($guess);
$response['result'] = $result; $response['result'] = $result;
@@ -387,11 +376,11 @@ class GameFlowController implements ISecured
// save user relevant state of challenge // save user relevant state of challenge
$userInChallenge->setCurrentRound($nextRound); $userInChallenge->setCurrentRound($nextRound);
$timeLeft = $this->request->post('timeLeft'); $timeLeft = \Container::$request->post('timeLeft');
if (isset($timeLeft)) { if (isset($timeLeft)) {
$userInChallenge->setTimeLeft(intval($timeLeft)); $userInChallenge->setTimeLeft(intval($timeLeft));
} }
$this->pdm->saveToDb($userInChallenge); \Container::$persistentDataManager->saveToDb($userInChallenge);
if ($challenge->getTimeLimitType() === 'game' && isset($timeLeft)) { if ($challenge->getTimeLimitType() === 'game' && isset($timeLeft)) {
$timeLimit = max(10, intval($timeLeft)); $timeLimit = max(10, intval($timeLeft));
@@ -409,8 +398,8 @@ class GameFlowController implements ISecured
public function multiNextRound(): IContent public function multiNextRound(): IContent
{ {
$roomId = $this->request->query('roomId'); $roomId = \Container::$request->query('roomId');
$session = $this->request->session(); $session = \Container::$request->session();
if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) { if (!($multiState = $session->get('multiState')) || $multiState['roomId'] !== $roomId) {
return new JsonContent(['error' => 'no_session_found']); return new JsonContent(['error' => 'no_session_found']);
@@ -431,7 +420,7 @@ class GameFlowController implements ISecured
$room->setStateArray($state); $room->setStateArray($state);
$room->setUpdatedDate(new DateTime()); $room->setUpdatedDate(new DateTime());
$this->pdm->saveToDb($room); \Container::$persistentDataManager->saveToDb($room);
return new JsonContent(['ok' => true]); return new JsonContent(['ok' => true]);
} }
@@ -446,7 +435,7 @@ class GameFlowController implements ISecured
private function startNewGame(array &$state, int $mapId): void private function startNewGame(array &$state, int $mapId): void
{ {
$session = $this->request->session(); $session = \Container::$request->session();
$userId = $session->get('userId'); $userId = $session->get('userId');
$places = $this->placeRepository->getRandomNPlaces($mapId, static::NUMBER_OF_ROUNDS, $userId); $places = $this->placeRepository->getRandomNPlaces($mapId, static::NUMBER_OF_ROUNDS, $userId);
+1 -9
View File
@@ -1,6 +1,5 @@
<?php namespace MapGuesser\Controller; <?php namespace MapGuesser\Controller;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Interfaces\Response\IRedirect; use SokoWeb\Interfaces\Response\IRedirect;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
@@ -8,13 +7,6 @@ use SokoWeb\Response\Redirect;
class HomeController class HomeController
{ {
private IRequest $request;
public function __construct(IRequest $request)
{
$this->request = $request;
}
public function getIndex(): IRedirect public function getIndex(): IRedirect
{ {
return new Redirect(\Container::$routeCollection->getRoute('maps')->generateLink(), IRedirect::TEMPORARY); return new Redirect(\Container::$routeCollection->getRoute('maps')->generateLink(), IRedirect::TEMPORARY);
@@ -24,6 +16,6 @@ class HomeController
{ {
// session starts with the request, this method just sends valid data to the client // session starts with the request, this method just sends valid data to the client
return new JsonContent(['antiCsrfToken' => $this->request->session()->get('anti_csrf_token')]); return new JsonContent(['antiCsrfToken' => \Container::$request->session()->get('anti_csrf_token')]);
} }
} }
+131 -130
View File
@@ -3,7 +3,6 @@
use DateInterval; use DateInterval;
use DateTime; use DateTime;
use SokoWeb\Http\Request; use SokoWeb\Http\Request;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Interfaces\Response\IRedirect; use SokoWeb\Interfaces\Response\IRedirect;
use SokoWeb\Mailing\Mail; use SokoWeb\Mailing\Mail;
@@ -11,7 +10,6 @@ use SokoWeb\OAuth\GoogleOAuth;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserConfirmation; use MapGuesser\PersistentData\Model\UserConfirmation;
use MapGuesser\PersistentData\Model\UserPasswordResetter; use MapGuesser\PersistentData\Model\UserPasswordResetter;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\Repository\UserConfirmationRepository; use MapGuesser\Repository\UserConfirmationRepository;
use MapGuesser\Repository\UserPasswordResetterRepository; use MapGuesser\Repository\UserPasswordResetterRepository;
use MapGuesser\Repository\UserPlayedPlaceRepository; use MapGuesser\Repository\UserPlayedPlaceRepository;
@@ -24,10 +22,6 @@ use SokoWeb\Util\JwtParser;
class LoginController class LoginController
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private UserRepository $userRepository; private UserRepository $userRepository;
private UserConfirmationRepository $userConfirmationRepository; private UserConfirmationRepository $userConfirmationRepository;
@@ -36,23 +30,27 @@ class LoginController
private UserPlayedPlaceRepository $userPlayedPlaceRepository; private UserPlayedPlaceRepository $userPlayedPlaceRepository;
public function __construct(IRequest $request) private string $redirectUrl;
public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
$this->userConfirmationRepository = new UserConfirmationRepository(); $this->userConfirmationRepository = new UserConfirmationRepository();
$this->userPasswordResetterRepository = new UserPasswordResetterRepository(); $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
$this->userPlayedPlaceRepository = new UserPlayedPlaceRepository(); $this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
$this->redirectUrl = \Container::$request->session()->has('redirect_after_login') ?
\Container::$request->session()->get('redirect_after_login') :
\Container::$routeCollection->getRoute('index')->generateLink();
} }
public function getLoginForm() public function getLoginForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
return new HtmlContent('login/login'); return new HtmlContent('login/login', ['redirectUrl' => $this->redirectUrl]);
} }
public function getGoogleLoginRedirect(): IRedirect public function getGoogleLoginRedirect(): IRedirect
@@ -60,13 +58,13 @@ class LoginController
$state = bin2hex(random_bytes(16)); $state = bin2hex(random_bytes(16));
$nonce = bin2hex(random_bytes(16)); $nonce = bin2hex(random_bytes(16));
$this->request->session()->set('oauth_state', $state); \Container::$request->session()->set('oauth_state', $state);
$this->request->session()->set('oauth_nonce', $nonce); \Container::$request->session()->set('oauth_nonce', $nonce);
$oAuth = new GoogleOAuth(new Request()); $oAuth = new GoogleOAuth(new Request());
$url = $oAuth->getDialogUrl( $url = $oAuth->getDialogUrl(
$state, $state,
$this->request->getBase() . '/' . \Container::$routeCollection->getRoute('login-google-action')->generateLink(), \Container::$request->getBase() . \Container::$routeCollection->getRoute('login-google-action')->generateLink(),
$nonce $nonce
); );
@@ -75,12 +73,13 @@ class LoginController
public function getSignupForm() public function getSignupForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
if ($this->request->session()->has('tmp_user_data')) { if (\Container::$request->session()->has('tmp_user_data')) {
$tmpUserData = $this->request->session()->get('tmp_user_data'); $tmpUserData = \Container::$request->session()->get('tmp_user_data');
$data = ['email' => $tmpUserData['email']]; $data = ['email' => $tmpUserData['email']];
} else { } else {
@@ -97,28 +96,30 @@ class LoginController
public function getSignupWithGoogleForm() public function getSignupWithGoogleForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
if (!$this->request->session()->has('google_user_data')) { if (!\Container::$request->session()->has('google_user_data')) {
return new Redirect(\Container::$routeCollection->getRoute('login-google')->generateLink(), IRedirect::TEMPORARY); return new Redirect(\Container::$routeCollection->getRoute('login-google')->generateLink(), IRedirect::TEMPORARY);
} }
$userData = $this->request->session()->get('google_user_data'); $userData = \Container::$request->session()->get('google_user_data');
$user = $this->userRepository->getByEmail($userData['email']); $user = $this->userRepository->getByEmail($userData['email']);
return new HtmlContent('login/google_signup', ['found' => $user !== null, 'email' => $userData['email']]); return new HtmlContent('login/google_signup', ['found' => $user !== null, 'email' => $userData['email'], 'redirectUrl' => $this->redirectUrl]);
} }
public function getRequestPasswordResetForm() public function getRequestPasswordResetForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
return new HtmlContent('login/password_reset_request', ['email' => $this->request->query('email')]); return new HtmlContent('login/password_reset_request', ['email' => \Container::$request->query('email')]);
} }
public function getRequestPasswordResetSuccess(): IContent public function getRequestPasswordResetSuccess(): IContent
@@ -128,11 +129,12 @@ class LoginController
public function getResetPasswordForm() public function getResetPasswordForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
$token = $this->request->query('token'); $token = \Container::$request->query('token');
$resetter = $this->userPasswordResetterRepository->getByToken($token); $resetter = $this->userPasswordResetterRepository->getByToken($token);
if ($resetter === null || $resetter->getExpiresDate() < new DateTime()) { if ($resetter === null || $resetter->getExpiresDate() < new DateTime()) {
@@ -141,19 +143,20 @@ class LoginController
$user = $this->userRepository->getById($resetter->getUserId()); $user = $this->userRepository->getById($resetter->getUserId());
return new HtmlContent('login/reset_password', ['success' => true, 'token' => $token, 'email' => $user->getEmail()]); return new HtmlContent('login/reset_password', ['success' => true, 'token' => $token, 'email' => $user->getEmail(), 'redirectUrl' => $this->redirectUrl]);
} }
public function login(): IContent public function login(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
$user = $this->userRepository->getByEmail($this->request->post('email')); $user = $this->userRepository->getByEmail(\Container::$request->post('email'));
if ($user === null) { if ($user === null) {
if (strlen($this->request->post('password')) < 6) { if (strlen(\Container::$request->post('password')) < 6) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!' 'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!'
@@ -162,16 +165,16 @@ class LoginController
} }
$tmpUser = new User(); $tmpUser = new User();
$tmpUser->setPlainPassword($this->request->post('password')); $tmpUser->setPlainPassword(\Container::$request->post('password'));
$this->request->session()->set('tmp_user_data', [ \Container::$request->session()->set('tmp_user_data', [
'email' => $this->request->post('email'), 'email' => \Container::$request->post('email'),
'password_hashed' => $tmpUser->getPassword() 'password_hashed' => $tmpUser->getPassword()
]); ]);
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
'target' => '/' . \Container::$routeCollection->getRoute('signup')->generateLink() 'target' => \Container::$routeCollection->getRoute('signup')->generateLink()
] ]
]); ]);
} }
@@ -187,7 +190,7 @@ class LoginController
]); ]);
} }
if (!$user->checkPassword($this->request->post('password'))) { if (!$user->checkPassword(\Container::$request->post('password'))) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given password is wrong. You can <a href="/password/requestReset?email=' . 'errorText' => 'The given password is wrong. You can <a href="/password/requestReset?email=' .
@@ -196,25 +199,27 @@ class LoginController
]); ]);
} }
$this->request->setUser($user); \Container::$request->setUser($user);
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function loginWithGoogle() public function loginWithGoogle()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
if ($this->request->query('state') !== $this->request->session()->get('oauth_state')) { if (\Container::$request->query('state') !== \Container::$request->session()->get('oauth_state')) {
return new HtmlContent('login/google_login'); return new HtmlContent('login/google_login');
} }
$oAuth = new GoogleOAuth(new Request()); $oAuth = new GoogleOAuth(new Request());
$tokenData = $oAuth->getToken( $tokenData = $oAuth->getToken(
$this->request->query('code'), \Container::$request->query('code'),
$this->request->getBase() . '/' . \Container::$routeCollection->getRoute('login-google-action')->generateLink() \Container::$request->getBase() . \Container::$routeCollection->getRoute('login-google-action')->generateLink()
); );
if (!isset($tokenData['id_token'])) { if (!isset($tokenData['id_token'])) {
@@ -224,7 +229,7 @@ class LoginController
$jwtParser = new JwtParser($tokenData['id_token']); $jwtParser = new JwtParser($tokenData['id_token']);
$idToken = $jwtParser->getPayload(); $idToken = $jwtParser->getPayload();
if ($idToken['nonce'] !== $this->request->session()->get('oauth_nonce')) { if ($idToken['nonce'] !== \Container::$request->session()->get('oauth_nonce')) {
return new HtmlContent('login/google_login'); return new HtmlContent('login/google_login');
} }
@@ -235,34 +240,36 @@ class LoginController
$user = $this->userRepository->getByGoogleSub($idToken['sub']); $user = $this->userRepository->getByGoogleSub($idToken['sub']);
if ($user === null) { if ($user === null) {
$this->request->session()->set('google_user_data', ['sub' => $idToken['sub'], 'email' => $idToken['email']]); \Container::$request->session()->set('google_user_data', ['sub' => $idToken['sub'], 'email' => $idToken['email']]);
return new Redirect(\Container::$routeCollection->getRoute('signup-google')->generateLink(), IRedirect::TEMPORARY); return new Redirect(\Container::$routeCollection->getRoute('signup-google')->generateLink(), IRedirect::TEMPORARY);
} }
$this->request->setUser($user); \Container::$request->setUser($user);
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
public function logout(): IRedirect public function logout(): IRedirect
{ {
$this->request->setUser(null); \Container::$request->setUser(null);
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
} }
public function signup(): IContent public function signup(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new JsonContent(['redirect' => ['target' => '/' . \Container::$routeCollection->getRoute('home')->generateLink()]]); $this->deleteRedirectUrl();
return new JsonContent(['redirect' => ['target' => $this->redirectUrl]]);
} }
$user = $this->userRepository->getByEmail($this->request->post('email')); $user = $this->userRepository->getByEmail(\Container::$request->post('email'));
if ($user !== null) { if ($user !== null) {
if ($user->getActive()) { if ($user->getActive()) {
if (!$user->checkPassword($this->request->post('password'))) { if (!$user->checkPassword(\Container::$request->post('password'))) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'There is a user already registered with the given email address, ' . 'errorText' => 'There is a user already registered with the given email address, ' .
@@ -272,9 +279,10 @@ class LoginController
]); ]);
} }
$this->request->setUser($user); \Container::$request->setUser($user);
$data = ['redirect' => ['target' => '/' . \Container::$routeCollection->getRoute('index')->generateLink()]]; $this->deleteRedirectUrl();
$data = ['redirect' => ['target' => $this->redirectUrl]];
} else { } else {
$data = [ $data = [
'error' => [ 'error' => [
@@ -287,32 +295,32 @@ class LoginController
} }
if (!empty($_ENV['RECAPTCHA_SITEKEY'])) { if (!empty($_ENV['RECAPTCHA_SITEKEY'])) {
if (!$this->request->post('g-recaptcha-response')) { if (!\Container::$request->post('g-recaptcha-response')) {
return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]); return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]);
} }
$captchaValidator = new CaptchaValidator(); $captchaValidator = new CaptchaValidator();
$captchaResponse = $captchaValidator->validate($this->request->post('g-recaptcha-response')); $captchaResponse = $captchaValidator->validate(\Container::$request->post('g-recaptcha-response'));
if (!$captchaResponse['success']) { if (!$captchaResponse['success']) {
return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]); return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]);
} }
} }
if (filter_var($this->request->post('email'), FILTER_VALIDATE_EMAIL) === false) { if (filter_var(\Container::$request->post('email'), FILTER_VALIDATE_EMAIL) === false) {
return new JsonContent(['error' => ['errorText' => 'The given email address is not valid.']]); return new JsonContent(['error' => ['errorText' => 'The given email address is not valid.']]);
} }
if ($this->request->session()->has('tmp_user_data')) { if (\Container::$request->session()->has('tmp_user_data')) {
$tmpUserData = $this->request->session()->get('tmp_user_data'); $tmpUserData = \Container::$request->session()->get('tmp_user_data');
$tmpUser = new User(); $tmpUser = new User();
$tmpUser->setPassword($tmpUserData['password_hashed']); $tmpUser->setPassword($tmpUserData['password_hashed']);
if (!$tmpUser->checkPassword($this->request->post('password'))) { if (!$tmpUser->checkPassword(\Container::$request->post('password'))) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]); return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
} }
} else { } else {
if (strlen($this->request->post('password')) < 6) { if (strlen(\Container::$request->post('password')) < 6) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!' 'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!'
@@ -320,19 +328,17 @@ class LoginController
]); ]);
} }
if ($this->request->post('password') !== $this->request->post('password_confirm')) { if (\Container::$request->post('password') !== \Container::$request->post('password_confirm')) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]); return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
} }
} }
$user = new User(); $user = new User();
$user->setEmail($this->request->post('email')); $user->setEmail(\Container::$request->post('email'));
$user->setPlainPassword($this->request->post('password')); $user->setPlainPassword(\Container::$request->post('password'));
$user->setCreatedDate(new DateTime()); $user->setCreatedDate(new DateTime());
\Container::$dbConnection->startTransaction(); \Container::$persistentDataManager->saveToDb($user);
$this->pdm->saveToDb($user);
$token = bin2hex(random_bytes(16)); $token = bin2hex(random_bytes(16));
@@ -341,24 +347,23 @@ class LoginController
$confirmation->setToken($token); $confirmation->setToken($token);
$confirmation->setLastSentDate(new DateTime()); $confirmation->setLastSentDate(new DateTime());
$this->pdm->saveToDb($confirmation); \Container::$persistentDataManager->saveToDb($confirmation);
\Container::$dbConnection->commit();
$this->sendConfirmationEmail($user->getEmail(), $token, $user->getCreatedDate()); $this->sendConfirmationEmail($user->getEmail(), $token, $user->getCreatedDate());
$this->request->session()->delete('tmp_user_data'); \Container::$request->session()->delete('tmp_user_data');
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function signupWithGoogle(): IContent public function signupWithGoogle(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
$userData = $this->request->session()->get('google_user_data'); $userData = \Container::$request->session()->get('google_user_data');
$user = $this->userRepository->getByEmail($userData['email']); $user = $this->userRepository->getByEmail($userData['email']);
@@ -375,112 +380,109 @@ class LoginController
$user->setActive(true); $user->setActive(true);
$user->setGoogleSub($userData['sub']); $user->setGoogleSub($userData['sub']);
$this->pdm->saveToDb($user); \Container::$persistentDataManager->saveToDb($user);
if ($sendWelcomeEmail) { if ($sendWelcomeEmail) {
$this->sendWelcomeEmail($user->getEmail()); $this->sendWelcomeEmail($user->getEmail());
} }
$this->request->session()->delete('google_user_data'); \Container::$request->session()->delete('google_user_data');
$this->request->setUser($user); \Container::$request->setUser($user);
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function resetSignup(): IContent public function resetSignup(): IContent
{ {
$this->request->session()->delete('tmp_user_data'); \Container::$request->session()->delete('tmp_user_data');
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function resetGoogleSignup(): IContent public function resetGoogleSignup(): IContent
{ {
$this->request->session()->delete('google_user_data'); \Container::$request->session()->delete('google_user_data');
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function activate() public function activate()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
$confirmation = $this->userConfirmationRepository->getByToken(substr($this->request->query('token'), 0, 32)); $confirmation = $this->userConfirmationRepository->getByToken(substr(\Container::$request->query('token'), 0, 32));
if ($confirmation === null) { if ($confirmation === null) {
return new HtmlContent('login/activate'); return new HtmlContent('login/activate');
} }
\Container::$dbConnection->startTransaction(); \Container::$persistentDataManager->deleteFromDb($confirmation);
$this->pdm->deleteFromDb($confirmation);
$user = $this->userRepository->getById($confirmation->getUserId()); $user = $this->userRepository->getById($confirmation->getUserId());
$user->setActive(true); $user->setActive(true);
$this->pdm->saveToDb($user); \Container::$persistentDataManager->saveToDb($user);
\Container::$dbConnection->commit(); \Container::$request->setUser($user);
$this->request->setUser($user); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
} }
public function cancel() public function cancel()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
$confirmation = $this->userConfirmationRepository->getByToken(substr($this->request->query('token'), 0, 32)); $confirmation = $this->userConfirmationRepository->getByToken(substr(\Container::$request->query('token'), 0, 32));
if ($confirmation === null) { if ($confirmation === null) {
return new HtmlContent('login/cancel', ['success' => false]); return new HtmlContent('login/cancel', ['success' => false]);
} }
\Container::$dbConnection->startTransaction(); \Container::$persistentDataManager->deleteFromDb($confirmation);
$this->pdm->deleteFromDb($confirmation);
$user = $this->userRepository->getById($confirmation->getUserId()); $user = $this->userRepository->getById($confirmation->getUserId());
foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) { foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) {
$this->pdm->deleteFromDb($userPlayedPlace); \Container::$persistentDataManager->deleteFromDb($userPlayedPlace);
} }
$this->pdm->deleteFromDb($user); \Container::$persistentDataManager->deleteFromDb($user);
\Container::$dbConnection->commit();
return new HtmlContent('login/cancel', ['success' => true]); return new HtmlContent('login/cancel', ['success' => true]);
} }
public function requestPasswordReset(): IContent public function requestPasswordReset(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
'target' => '/' . \Container::$routeCollection->getRoute('home')->generateLink() 'target' => $this->redirectUrl
] ]
]); ]);
} }
if (!empty($_ENV['RECAPTCHA_SITEKEY'])) { if (!empty($_ENV['RECAPTCHA_SITEKEY'])) {
if (!$this->request->post('g-recaptcha-response')) { if (!\Container::$request->post('g-recaptcha-response')) {
return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]); return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]);
} }
$captchaValidator = new CaptchaValidator(); $captchaValidator = new CaptchaValidator();
$captchaResponse = $captchaValidator->validate($this->request->post('g-recaptcha-response')); $captchaResponse = $captchaValidator->validate(\Container::$request->post('g-recaptcha-response'));
if (!$captchaResponse['success']) { if (!$captchaResponse['success']) {
return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]); return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]);
} }
} }
$user = $this->userRepository->getByEmail($this->request->post('email')); $user = $this->userRepository->getByEmail(\Container::$request->post('email'));
if ($user === null) { if ($user === null) {
return new JsonContent([ return new JsonContent([
@@ -519,15 +521,11 @@ class LoginController
$passwordResetter->setToken($token); $passwordResetter->setToken($token);
$passwordResetter->setExpiresDate($expires); $passwordResetter->setExpiresDate($expires);
\Container::$dbConnection->startTransaction();
if ($existingResetter !== null) { if ($existingResetter !== null) {
$this->pdm->deleteFromDb($existingResetter); \Container::$persistentDataManager->deleteFromDb($existingResetter);
} }
$this->pdm->saveToDb($passwordResetter); \Container::$persistentDataManager->saveToDb($passwordResetter);
\Container::$dbConnection->commit();
$this->sendPasswordResetEmail($user->getEmail(), $token, $expires); $this->sendPasswordResetEmail($user->getEmail(), $token, $expires);
@@ -537,26 +535,27 @@ class LoginController
public function resetPassword(): IContent public function resetPassword(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
'target' => '/' . \Container::$routeCollection->getRoute('home')->generateLink() 'target' => $this->redirectUrl
] ]
]); ]);
} }
$token = $this->request->query('token'); $token = \Container::$request->query('token');
$resetter = $this->userPasswordResetterRepository->getByToken($token); $resetter = $this->userPasswordResetterRepository->getByToken($token);
if ($resetter === null || $resetter->getExpiresDate() < new DateTime()) { if ($resetter === null || $resetter->getExpiresDate() < new DateTime()) {
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
'target' => '/' . \Container::$routeCollection->getRoute('password-reset')->generateLink(['token' => $token]) 'target' => \Container::$routeCollection->getRoute('password-reset')->generateLink(['token' => $token])
] ]
]); ]);
} }
if (strlen($this->request->post('password')) < 6) { if (strlen(\Container::$request->post('password')) < 6) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!' 'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!'
@@ -564,23 +563,20 @@ class LoginController
]); ]);
} }
if ($this->request->post('password') !== $this->request->post('password_confirm')) { if (\Container::$request->post('password') !== \Container::$request->post('password_confirm')) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]); return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
} }
\Container::$dbConnection->startTransaction(); \Container::$persistentDataManager->deleteFromDb($resetter);
$this->pdm->deleteFromDb($resetter);
$user = $this->userRepository->getById($resetter->getUserId()); $user = $this->userRepository->getById($resetter->getUserId());
$user->setPlainPassword($this->request->post('password')); $user->setPlainPassword(\Container::$request->post('password'));
$this->pdm->saveToDb($user); \Container::$persistentDataManager->saveToDb($user);
\Container::$dbConnection->commit(); \Container::$request->setUser($user);
$this->request->setUser($user);
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
@@ -591,9 +587,9 @@ class LoginController
$mail->setSubject('Welcome to ' . $_ENV['APP_NAME'] . ' - Activate your account'); $mail->setSubject('Welcome to ' . $_ENV['APP_NAME'] . ' - Activate your account');
$mail->setBodyFromTemplate('signup', [ $mail->setBodyFromTemplate('signup', [
'EMAIL' => $email, 'EMAIL' => $email,
'ACTIVATE_LINK' => $this->request->getBase() . '/' . 'ACTIVATE_LINK' => \Container::$request->getBase() .
\Container::$routeCollection->getRoute('signup.activate')->generateLink(['token' => $token]), \Container::$routeCollection->getRoute('signup.activate')->generateLink(['token' => $token]),
'CANCEL_LINK' => $this->request->getBase() . '/' . 'CANCEL_LINK' => \Container::$request->getBase() .
\Container::$routeCollection->getRoute('signup.cancel')->generateLink(['token' => $token]), \Container::$routeCollection->getRoute('signup.cancel')->generateLink(['token' => $token]),
'ACTIVATABLE_UNTIL' => (clone $created)->add(new DateInterval('P1D'))->format('Y-m-d H:i T') 'ACTIVATABLE_UNTIL' => (clone $created)->add(new DateInterval('P1D'))->format('Y-m-d H:i T')
]); ]);
@@ -610,7 +606,7 @@ class LoginController
$confirmation->setLastSentDate(new DateTime()); $confirmation->setLastSentDate(new DateTime());
$this->pdm->saveToDb($confirmation); \Container::$persistentDataManager->saveToDb($confirmation);
$this->sendConfirmationEmail($user->getEmail(), $confirmation->getToken(), $user->getCreatedDate()); $this->sendConfirmationEmail($user->getEmail(), $confirmation->getToken(), $user->getCreatedDate());
@@ -635,10 +631,15 @@ class LoginController
$mail->setSubject($_ENV['APP_NAME'] . ' - Password reset'); $mail->setSubject($_ENV['APP_NAME'] . ' - Password reset');
$mail->setBodyFromTemplate('password-reset', [ $mail->setBodyFromTemplate('password-reset', [
'EMAIL' => $email, 'EMAIL' => $email,
'RESET_LINK' => $this->request->getBase() . '/' . 'RESET_LINK' => \Container::$request->getBase() .
\Container::$routeCollection->getRoute('password-reset')->generateLink(['token' => $token]), \Container::$routeCollection->getRoute('password-reset')->generateLink(['token' => $token]),
'EXPIRES' => $expires->format('Y-m-d H:i T') 'EXPIRES' => $expires->format('Y-m-d H:i T')
]); ]);
$mail->send(); $mail->send();
} }
private function deleteRedirectUrl(): void
{
\Container::$request->session()->delete('redirect_after_login');
}
} }
+25 -37
View File
@@ -2,14 +2,13 @@
use DateTime; use DateTime;
use SokoWeb\Interfaces\Authentication\IUser; use SokoWeb\Interfaces\Authentication\IUser;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Authorization\ISecured; use SokoWeb\Interfaces\Authorization\ISecured;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Map; use MapGuesser\PersistentData\Model\Map;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\PlaceInChallenge; use MapGuesser\PersistentData\Model\PlaceInChallenge;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\Repository\ChallengeRepository; use MapGuesser\Repository\ChallengeRepository;
use MapGuesser\Repository\GuessRepository; use MapGuesser\Repository\GuessRepository;
use MapGuesser\Repository\MapRepository; use MapGuesser\Repository\MapRepository;
@@ -22,14 +21,10 @@ use SokoWeb\Response\JsonContent;
use MapGuesser\Util\Geo\Bounds; use MapGuesser\Util\Geo\Bounds;
use MapGuesser\Util\Panorama\Pov; use MapGuesser\Util\Panorama\Pov;
class MapAdminController implements ISecured class MapAdminController implements IAuthenticationRequired, ISecured
{ {
private static string $unnamedMapName = '[unnamed map]'; private static string $unnamedMapName = '[unnamed map]';
private IRequest $request;
private PersistentDataManager $pdm;
private MapRepository $mapRepository; private MapRepository $mapRepository;
private PlaceRepository $placeRepository; private PlaceRepository $placeRepository;
@@ -44,10 +39,8 @@ class MapAdminController implements ISecured
private UserInChallengeRepository $userInChallengeRepository; private UserInChallengeRepository $userInChallengeRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->mapRepository = new MapRepository(); $this->mapRepository = new MapRepository();
$this->placeRepository = new PlaceRepository(); $this->placeRepository = new PlaceRepository();
$this->userPlayedPlaceRepository = new UserPlayedPlaceRepository(); $this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
@@ -57,16 +50,19 @@ class MapAdminController implements ISecured
$this->userInChallengeRepository = new UserInChallengeRepository(); $this->userInChallengeRepository = new UserInChallengeRepository();
} }
public function isAuthenticationRequired(): bool
{
return true;
}
public function authorize(): bool public function authorize(): bool
{ {
$user = $this->request->user(); return \Container::$request->user()->hasPermission(IUser::PERMISSION_ADMIN);
return $user !== null && $user->hasPermission(IUser::PERMISSION_ADMIN);
} }
public function getMapEditor(): IContent public function getMapEditor(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
if ($mapId) { if ($mapId) {
$map = $this->mapRepository->getById($mapId); $map = $this->mapRepository->getById($mapId);
@@ -89,7 +85,7 @@ class MapAdminController implements ISecured
public function getPlace(): IContent public function getPlace(): IContent
{ {
$placeId = (int) $this->request->query('placeId'); $placeId = (int) \Container::$request->query('placeId');
$place = $this->placeRepository->getById($placeId); $place = $this->placeRepository->getById($placeId);
@@ -98,16 +94,14 @@ class MapAdminController implements ISecured
public function saveMap(): IContent public function saveMap(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
\Container::$dbConnection->startTransaction();
if ($mapId) { if ($mapId) {
$map = $this->mapRepository->getById($mapId); $map = $this->mapRepository->getById($mapId);
} else { } else {
$map = new Map(); $map = new Map();
$map->setName(self::$unnamedMapName); $map->setName(self::$unnamedMapName);
$this->pdm->saveToDb($map); \Container::$persistentDataManager->saveToDb($map);
} }
if (isset($_POST['added'])) { if (isset($_POST['added'])) {
@@ -129,7 +123,7 @@ class MapAdminController implements ISecured
$place->setPanoIdCachedTimestampDate(new DateTime('-1 day')); $place->setPanoIdCachedTimestampDate(new DateTime('-1 day'));
} }
$this->pdm->saveToDb($place); \Container::$persistentDataManager->saveToDb($place);
$addedIds[] = ['tempId' => $placeRaw['id'], 'id' => $place->getId()]; $addedIds[] = ['tempId' => $placeRaw['id'], 'id' => $place->getId()];
} }
@@ -151,7 +145,7 @@ class MapAdminController implements ISecured
)); ));
$place->setPanoIdCachedTimestampDate(new DateTime('-1 day')); $place->setPanoIdCachedTimestampDate(new DateTime('-1 day'));
$this->pdm->saveToDb($place); \Container::$persistentDataManager->saveToDb($place);
} }
} }
@@ -180,26 +174,20 @@ class MapAdminController implements ISecured
$map->setUnlisted((bool)$_POST['unlisted']); $map->setUnlisted((bool)$_POST['unlisted']);
} }
$this->pdm->saveToDb($map); \Container::$persistentDataManager->saveToDb($map);
\Container::$dbConnection->commit();
return new JsonContent(['mapId' => $map->getId(), 'added' => $addedIds]); return new JsonContent(['mapId' => $map->getId(), 'added' => $addedIds]);
} }
public function deleteMap(): IContent public function deleteMap(): IContent
{ {
$mapId = (int) $this->request->query('mapId'); $mapId = (int) \Container::$request->query('mapId');
$map = $this->mapRepository->getById($mapId); $map = $this->mapRepository->getById($mapId);
\Container::$dbConnection->startTransaction();
$this->deletePlaces($map); $this->deletePlaces($map);
$this->pdm->deleteFromDb($map); \Container::$persistentDataManager->deleteFromDb($map);
\Container::$dbConnection->commit();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
@@ -207,14 +195,14 @@ class MapAdminController implements ISecured
private function deletePlace(Place $place): void private function deletePlace(Place $place): void
{ {
foreach ($this->userPlayedPlaceRepository->getAllByPlace($place) as $userPlayedPlace) { foreach ($this->userPlayedPlaceRepository->getAllByPlace($place) as $userPlayedPlace) {
$this->pdm->deleteFromDb($userPlayedPlace); \Container::$persistentDataManager->deleteFromDb($userPlayedPlace);
} }
foreach ($this->challengeRepository->getAllByPlace($place) as $challenge) { foreach ($this->challengeRepository->getAllByPlace($place) as $challenge) {
$this->deleteChallenge($challenge); $this->deleteChallenge($challenge);
} }
$this->pdm->deleteFromDb($place); \Container::$persistentDataManager->deleteFromDb($place);
} }
private function deletePlaces(Map $map): void private function deletePlaces(Map $map): void
@@ -227,18 +215,18 @@ class MapAdminController implements ISecured
private function deleteChallenge(Challenge $challenge): void private function deleteChallenge(Challenge $challenge): void
{ {
foreach ($this->userInChallengeRepository->getAllByChallenge($challenge) as $userInChallenge) { foreach ($this->userInChallengeRepository->getAllByChallenge($challenge) as $userInChallenge) {
$this->pdm->deleteFromDb($userInChallenge); \Container::$persistentDataManager->deleteFromDb($userInChallenge);
} }
foreach ($this->guessRepository->getAllInChallenge($challenge, [PlaceInChallenge::class]) as $guess) { foreach ($this->guessRepository->getAllInChallenge($challenge, ['place_in_challange']) as $guess) {
$this->pdm->deleteFromDb($guess); \Container::$persistentDataManager->deleteFromDb($guess);
} }
foreach ($this->placeInChallengeRepository->getAllByChallenge($challenge) as $placeInChallenge) { foreach ($this->placeInChallengeRepository->getAllByChallenge($challenge) as $placeInChallenge) {
$this->pdm->deleteFromDb($placeInChallenge); \Container::$persistentDataManager->deleteFromDb($placeInChallenge);
} }
$this->pdm->deleteFromDb($challenge); \Container::$persistentDataManager->deleteFromDb($challenge);
} }
private function calculateMapBounds(Map $map): Bounds private function calculateMapBounds(Map $map): Bounds
+1 -9
View File
@@ -4,19 +4,11 @@ use SokoWeb\Database\Query\Select;
use SokoWeb\Database\RawExpression; use SokoWeb\Database\RawExpression;
use SokoWeb\Interfaces\Authentication\IUser; use SokoWeb\Interfaces\Authentication\IUser;
use SokoWeb\Interfaces\Database\IResultSet; use SokoWeb\Interfaces\Database\IResultSet;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
class MapsController class MapsController
{ {
private IRequest $request;
public function __construct(IRequest $request)
{
$this->request = $request;
}
public function getMaps(): IContent public function getMaps(): IContent
{ {
//TODO: from repository - count should be added //TODO: from repository - count should be added
@@ -37,7 +29,7 @@ class MapsController
$select->groupBy(['maps', 'id']); $select->groupBy(['maps', 'id']);
$select->orderBy('name'); $select->orderBy('name');
$user = $this->request->user(); $user = \Container::$request->user();
$isAdmin = $user !== null && $user->hasPermission(IUser::PERMISSION_ADMIN); $isAdmin = $user !== null && $user->hasPermission(IUser::PERMISSION_ADMIN);
if (!$isAdmin) { if (!$isAdmin) {
$select->where(['maps', 'unlisted'], '=', false); $select->where(['maps', 'unlisted'], '=', false);
+36 -50
View File
@@ -2,12 +2,10 @@
use DateTime; use DateTime;
use SokoWeb\Http\Request; use SokoWeb\Http\Request;
use SokoWeb\Interfaces\Authorization\ISecured; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Interfaces\Response\IRedirect; use SokoWeb\Interfaces\Response\IRedirect;
use SokoWeb\OAuth\GoogleOAuth; use SokoWeb\OAuth\GoogleOAuth;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\Repository\GuessRepository; use MapGuesser\Repository\GuessRepository;
use MapGuesser\Repository\UserConfirmationRepository; use MapGuesser\Repository\UserConfirmationRepository;
@@ -19,12 +17,8 @@ use SokoWeb\Response\JsonContent;
use SokoWeb\Response\Redirect; use SokoWeb\Response\Redirect;
use SokoWeb\Util\JwtParser; use SokoWeb\Util\JwtParser;
class UserController implements ISecured class UserController implements IAuthenticationRequired
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private UserConfirmationRepository $userConfirmationRepository; private UserConfirmationRepository $userConfirmationRepository;
private UserPasswordResetterRepository $userPasswordResetterRepository; private UserPasswordResetterRepository $userPasswordResetterRepository;
@@ -35,10 +29,8 @@ class UserController implements ISecured
private GuessRepository $guessRepository; private GuessRepository $guessRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userConfirmationRepository = new UserConfirmationRepository(); $this->userConfirmationRepository = new UserConfirmationRepository();
$this->userPasswordResetterRepository = new UserPasswordResetterRepository(); $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
$this->userPlayedPlaceRepository = new UserPlayedPlaceRepository(); $this->userPlayedPlaceRepository = new UserPlayedPlaceRepository();
@@ -46,11 +38,9 @@ class UserController implements ISecured
$this->guessRepository = new GuessRepository(); $this->guessRepository = new GuessRepository();
} }
public function authorize(): bool public function isAuthenticationRequired(): bool
{ {
$user = $this->request->user(); return true;
return $user !== null;
} }
public function getAccount(): IContent public function getAccount(): IContent
@@ -58,7 +48,7 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
return new HtmlContent('account/account', ['user' => $user->toArray()]); return new HtmlContent('account/account', ['user' => $user->toArray()]);
} }
@@ -68,19 +58,19 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
$state = bin2hex(random_bytes(16)); $state = bin2hex(random_bytes(16));
$nonce = bin2hex(random_bytes(16)); $nonce = bin2hex(random_bytes(16));
$this->request->session()->set('oauth_state', $state); \Container::$request->session()->set('oauth_state', $state);
$this->request->session()->set('oauth_nonce', $nonce); \Container::$request->session()->set('oauth_nonce', $nonce);
$oAuth = new GoogleOAuth(new Request()); $oAuth = new GoogleOAuth(new Request());
$url = $oAuth->getDialogUrl( $url = $oAuth->getDialogUrl(
$state, $state,
$this->request->getBase() . '/' . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink(), \Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink(),
$nonce, $nonce,
$user->getEmail() $user->getEmail()
); );
@@ -93,16 +83,16 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
if ($this->request->query('state') !== $this->request->session()->get('oauth_state')) { if (\Container::$request->query('state') !== \Container::$request->session()->get('oauth_state')) {
return new HtmlContent('account/google_authenticate', ['success' => false]); return new HtmlContent('account/google_authenticate', ['success' => false]);
} }
$oAuth = new GoogleOAuth(new Request()); $oAuth = new GoogleOAuth(new Request());
$tokenData = $oAuth->getToken( $tokenData = $oAuth->getToken(
$this->request->query('code'), \Container::$request->query('code'),
$this->request->getBase() . '/' . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink() \Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleAuthenticate-action')->generateLink()
); );
if (!isset($tokenData['id_token'])) { if (!isset($tokenData['id_token'])) {
@@ -112,7 +102,7 @@ class UserController implements ISecured
$jwtParser = new JwtParser($tokenData['id_token']); $jwtParser = new JwtParser($tokenData['id_token']);
$idToken = $jwtParser->getPayload(); $idToken = $jwtParser->getPayload();
if ($idToken['nonce'] !== $this->request->session()->get('oauth_nonce')) { if ($idToken['nonce'] !== \Container::$request->session()->get('oauth_nonce')) {
return new HtmlContent('account/google_authenticate', ['success' => false]); return new HtmlContent('account/google_authenticate', ['success' => false]);
} }
@@ -124,7 +114,7 @@ class UserController implements ISecured
} }
$authenticatedWithGoogleUntil = new DateTime('+45 seconds'); $authenticatedWithGoogleUntil = new DateTime('+45 seconds');
$this->request->session()->set('authenticated_with_google_until', $authenticatedWithGoogleUntil); \Container::$request->session()->set('authenticated_with_google_until', $authenticatedWithGoogleUntil);
return new HtmlContent('account/google_authenticate', [ return new HtmlContent('account/google_authenticate', [
'success' => true, 'success' => true,
@@ -137,7 +127,7 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
return new HtmlContent('account/delete', ['user' => $user->toArray()]); return new HtmlContent('account/delete', ['user' => $user->toArray()]);
} }
@@ -147,19 +137,19 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
if (!$this->confirmUserIdentity( if (!$this->confirmUserIdentity(
$user, $user,
$this->request->session()->get('authenticated_with_google_until'), \Container::$request->session()->get('authenticated_with_google_until'),
$this->request->post('password'), \Container::$request->post('password'),
$error $error
)) { )) {
return new JsonContent(['error' => ['errorText' => $error]]); return new JsonContent(['error' => ['errorText' => $error]]);
} }
if (strlen($this->request->post('password_new')) > 0) { if (strlen(\Container::$request->post('password_new')) > 0) {
if (strlen($this->request->post('password_new')) < 6) { if (strlen(\Container::$request->post('password_new')) < 6) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given new password is too short. Please choose a password that is at least 6 characters long!' 'errorText' => 'The given new password is too short. Please choose a password that is at least 6 characters long!'
@@ -167,7 +157,7 @@ class UserController implements ISecured
]); ]);
} }
if ($this->request->post('password_new') !== $this->request->post('password_new_confirm')) { if (\Container::$request->post('password_new') !== \Container::$request->post('password_new_confirm')) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'The given new passwords do not match.' 'errorText' => 'The given new passwords do not match.'
@@ -175,12 +165,12 @@ class UserController implements ISecured
]); ]);
} }
$user->setPlainPassword($this->request->post('password_new')); $user->setPlainPassword(\Container::$request->post('password_new'));
} }
$this->pdm->saveToDb($user); \Container::$persistentDataManager->saveToDb($user);
$this->request->session()->delete('authenticated_with_google_until'); \Container::$request->session()->delete('authenticated_with_google_until');
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
@@ -190,46 +180,42 @@ class UserController implements ISecured
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
if (!$this->confirmUserIdentity( if (!$this->confirmUserIdentity(
$user, $user,
$this->request->session()->get('authenticated_with_google_until'), \Container::$request->session()->get('authenticated_with_google_until'),
$this->request->post('password'), \Container::$request->post('password'),
$error $error
)) { )) {
return new JsonContent(['error' => ['errorText' => $error]]); return new JsonContent(['error' => ['errorText' => $error]]);
} }
\Container::$dbConnection->startTransaction();
$userConfirmation = $this->userConfirmationRepository->getByUser($user); $userConfirmation = $this->userConfirmationRepository->getByUser($user);
if ($userConfirmation !== null) { if ($userConfirmation !== null) {
$this->pdm->deleteFromDb($userConfirmation); \Container::$persistentDataManager->deleteFromDb($userConfirmation);
} }
$userPasswordResetter = $this->userPasswordResetterRepository->getByUser($user); $userPasswordResetter = $this->userPasswordResetterRepository->getByUser($user);
if ($userPasswordResetter !== null) { if ($userPasswordResetter !== null) {
$this->pdm->deleteFromDb($userPasswordResetter); \Container::$persistentDataManager->deleteFromDb($userPasswordResetter);
} }
foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) { foreach ($this->userPlayedPlaceRepository->getAllByUser($user) as $userPlayedPlace) {
$this->pdm->deleteFromDb($userPlayedPlace); \Container::$persistentDataManager->deleteFromDb($userPlayedPlace);
} }
foreach ($this->userInChallengeRepository->getAllByUser($user) as $userInChallenge) { foreach ($this->userInChallengeRepository->getAllByUser($user) as $userInChallenge) {
$this->pdm->deleteFromDb($userInChallenge); \Container::$persistentDataManager->deleteFromDb($userInChallenge);
} }
foreach ($this->guessRepository->getAllByUser($user) as $guess) { foreach ($this->guessRepository->getAllByUser($user) as $guess) {
$this->pdm->deleteFromDb($guess); \Container::$persistentDataManager->deleteFromDb($guess);
} }
$this->pdm->deleteFromDb($user); \Container::$persistentDataManager->deleteFromDb($user);
\Container::$dbConnection->commit(); \Container::$request->session()->delete('authenticated_with_google_until');
$this->request->session()->delete('authenticated_with_google_until');
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
+1 -2
View File
@@ -4,7 +4,6 @@ use DateInterval;
use DateTime; use DateTime;
use SokoWeb\PersistentData\Model\Model; use SokoWeb\PersistentData\Model\Model;
use SokoWeb\Http\Request; use SokoWeb\Http\Request;
use SokoWeb\PersistentData\PersistentDataManager;
use MapGuesser\Util\Geo\Position; use MapGuesser\Util\Geo\Position;
use MapGuesser\Util\Panorama\Pov; use MapGuesser\Util\Panorama\Pov;
@@ -163,7 +162,7 @@ class Place extends Model
$this->panoIdCached = $panoId; $this->panoIdCached = $panoId;
$this->panoIdCachedTimestamp = new DateTime(); $this->panoIdCachedTimestamp = new DateTime();
(new PersistentDataManager())->saveToDb($this); \Container::$persistentDataManager->saveToDb($this);
return $panoId; return $panoId;
} }
+9 -17
View File
@@ -5,20 +5,12 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use SokoWeb\PersistentData\PersistentDataManager;
class ChallengeRepository class ChallengeRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $challengeId): ?Challenge public function getById(int $challengeId): ?Challenge
{ {
return $this->pdm->selectFromDbById($challengeId, Challenge::class); return \Container::$persistentDataManager->selectFromDbById($challengeId, Challenge::class);
} }
public function getByToken(int $token): ?Challenge public function getByToken(int $token): ?Challenge
@@ -26,7 +18,7 @@ class ChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('token', '=', $token); $select->where('token', '=', $token);
return $this->pdm->selectFromDb($select, Challenge::class); return \Container::$persistentDataManager->selectFromDb($select, Challenge::class);
} }
public function getByTokenStr(string $token_str): ?Challenge public function getByTokenStr(string $token_str): ?Challenge
@@ -48,9 +40,9 @@ class ChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('user_in_challenge', ['challenge', 'id'], '=', ['user_in_challenge', 'challenge_id']); $select->innerJoin('user_in_challenge', ['challenge', 'id'], '=', ['user_in_challenge', 'challenge_id']);
$select->innerJoin('users', ['users', 'id'], '=', ['user_in_challenge', 'user_id']); $select->innerJoin('users', ['users', 'id'], '=', ['user_in_challenge', 'user_id']);
$select->where('user_id', '=', $user->getId()); $select->where(['user_in_challenge', 'user_id'], '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, Challenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Challenge::class);
} }
public function getAllByOwner(User $user): Generator public function getAllByOwner(User $user): Generator
@@ -58,18 +50,18 @@ class ChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('user_in_challenge', ['challenge', 'id'], '=', ['user_in_challenge', 'challenge_id']); $select->innerJoin('user_in_challenge', ['challenge', 'id'], '=', ['user_in_challenge', 'challenge_id']);
$select->innerJoin('users', ['users', 'id'], '=', ['user_in_challenge', 'user_id']); $select->innerJoin('users', ['users', 'id'], '=', ['user_in_challenge', 'user_id']);
$select->where('user_id', '=', $user->getId()); $select->where(['user_in_challenge', 'user_id'], '=', $user->getId());
$select->where('is_owner', '=', true); $select->where(['user_in_challenge', 'is_owner'], '=', true);
yield from $this->pdm->selectMultipleFromDb($select, Challenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Challenge::class);
} }
public function getAllByPlace(Place $place): Generator public function getAllByPlace(Place $place): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['challenges', 'id'], '=', ['place_in_challenge', 'challenge_id']); $select->innerJoin('place_in_challenge', ['challenges', 'id'], '=', ['place_in_challenge', 'challenge_id']);
$select->where('place_id', '=', $place->getId()); $select->where(['place_in_challenge', 'place_id'], '=', $place->getId());
yield from $this->pdm->selectMultipleFromDb($select, Challenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Challenge::class);
} }
} }
+19 -27
View File
@@ -7,23 +7,15 @@ use MapGuesser\PersistentData\Model\Guess;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\PlaceInChallenge; use MapGuesser\PersistentData\Model\PlaceInChallenge;
use SokoWeb\PersistentData\PersistentDataManager;
class GuessRepository class GuessRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getAllByUser(User $user): Generator public function getAllByUser(User $user): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, Guess::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class);
} }
public function getAllByUserAndChallenge(User $user, Challenge $challenge): Generator public function getAllByUserAndChallenge(User $user, Challenge $challenge): Generator
@@ -31,9 +23,9 @@ class GuessRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']); $select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
yield from $this->pdm->selectMultipleFromDb($select, Guess::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class);
} }
public function getByUserAndPlaceInChallenge(User $user, Challenge $challenge, Place $place): ?Guess public function getByUserAndPlaceInChallenge(User $user, Challenge $challenge, Place $place): ?Guess
@@ -41,10 +33,10 @@ class GuessRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']); $select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->where('place_id', '=', $place->getId()); $select->where(['place_in_challenge', 'place_id'], '=', $place->getId());
return $this->pdm->selectFromDb($select, Guess::class); return \Container::$persistentDataManager->selectFromDb($select, Guess::class);
} }
public function getAllInChallengeByUser(int $userId, Challenge $challenge): Generator public function getAllInChallengeByUser(int $userId, Challenge $challenge): Generator
@@ -52,46 +44,46 @@ class GuessRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']); $select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
$select->where('user_id', '=', $userId); $select->where('user_id', '=', $userId);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->orderBy('round'); $select->orderBy(['place_in_challenge', 'round']);
yield from $this->pdm->selectMultipleFromDb($select, Guess::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class);
} }
public function getAllInChallenge(Challenge $challenge, array $withRelations = []): Generator public function getAllInChallenge(Challenge $challenge, array $withRelations = []): Generator
{ {
if (count($withRelations)) { if (count($withRelations)) {
$necessaryRelations = [PlaceInChallenge::class]; $necessaryRelations = ['place_in_challenge'];
$withRelations = array_unique(array_merge($withRelations, $necessaryRelations)); $withRelations = array_unique(array_merge($withRelations, $necessaryRelations));
} }
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['guesses__place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->orderBy('round'); $select->orderBy(['guesses__place_in_challenge', 'round']);
yield from $this->pdm->selectMultipleFromDb($select, Guess::class, true, $withRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class, true, $withRelations);
} }
public function getAllInChallengeByRound(int $round, Challenge $challenge, array $withRelations = []): Generator public function getAllInChallengeByRound(int $round, Challenge $challenge, array $withRelations = []): Generator
{ {
if (count($withRelations)) { if (count($withRelations)) {
$necessaryRelations = [PlaceInChallenge::class]; $necessaryRelations = ['place_in_challenge'];
$withRelations = array_unique(array_merge($withRelations, $necessaryRelations)); $withRelations = array_unique(array_merge($withRelations, $necessaryRelations));
} }
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['guesses__place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->where('round', '=', $round); $select->where(['guesses__place_in_challenge', 'round'], '=', $round);
yield from $this->pdm->selectMultipleFromDb($select, Guess::class, true, $withRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class, true, $withRelations);
} }
public function getAllByPlace(Place $place): Generator public function getAllByPlace(Place $place): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']); $select->innerJoin('place_in_challenge', ['place_in_challenge', 'id'], '=', ['guesses', 'place_in_challenge_id']);
$select->where('place_id', '=', $place->getId()); $select->where(['place_in_challenge', 'place_id'], '=', $place->getId());
yield from $this->pdm->selectMultipleFromDb($select, Guess::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Guess::class);
} }
} }
+3 -11
View File
@@ -4,20 +4,12 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Map; use MapGuesser\PersistentData\Model\Map;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use SokoWeb\PersistentData\PersistentDataManager;
class MapRepository class MapRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $mapId): ?Map public function getById(int $mapId): ?Map
{ {
return $this->pdm->selectFromDbById($mapId, Map::class); return \Container::$persistentDataManager->selectFromDbById($mapId, Map::class);
} }
public function getByPlace(Place $place): ?Map public function getByPlace(Place $place): ?Map
@@ -30,9 +22,9 @@ class MapRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('places', ['maps', 'id'], '=', ['places', 'map_id']); $select->innerJoin('places', ['maps', 'id'], '=', ['places', 'map_id']);
$select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']); $select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->limit(1); $select->limit(1);
return $this->pdm->selectFromDb($select, Map::class); return \Container::$persistentDataManager->selectFromDb($select, Map::class);
} }
} }
+3 -11
View File
@@ -4,20 +4,12 @@ use DateTime;
use Generator; use Generator;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\MultiRoom; use MapGuesser\PersistentData\Model\MultiRoom;
use SokoWeb\PersistentData\PersistentDataManager;
class MultiRoomRepository class MultiRoomRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?MultiRoom public function getById(int $id): ?MultiRoom
{ {
return $this->pdm->selectFromDbById($id, MultiRoom::class); return \Container::$persistentDataManager->selectFromDbById($id, MultiRoom::class);
} }
public function getByRoomId(string $roomId): ?MultiRoom public function getByRoomId(string $roomId): ?MultiRoom
@@ -25,7 +17,7 @@ class MultiRoomRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('room_id', '=', $roomId); $select->where('room_id', '=', $roomId);
return $this->pdm->selectFromDb($select, MultiRoom::class); return \Container::$persistentDataManager->selectFromDb($select, MultiRoom::class);
} }
public function getAllExpired(): Generator public function getAllExpired(): Generator
@@ -33,6 +25,6 @@ class MultiRoomRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('updated', '<', (new DateTime('-7 day'))->format('Y-m-d H:i:s')); $select->where('updated', '<', (new DateTime('-7 day'))->format('Y-m-d H:i:s'));
yield from $this->pdm->selectMultipleFromDb($select, MultiRoom::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, MultiRoom::class);
} }
} }
+4 -12
View File
@@ -5,23 +5,15 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\PlaceInChallenge; use MapGuesser\PersistentData\Model\PlaceInChallenge;
use SokoWeb\PersistentData\PersistentDataManager;
class PlaceInChallengeRepository class PlaceInChallengeRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getAllByPlace(Place $place, array $withRelations = []) : Generator public function getAllByPlace(Place $place, array $withRelations = []) : Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('place_id', '=', $place->getId()); $select->where('place_id', '=', $place->getId());
yield from $this->pdm->selectMultipleFromDb($select, PlaceInChallenge::class, true, $withRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, PlaceInChallenge::class, true, $withRelations);
} }
public function getAllByChallenge(Challenge $challenge) : Generator public function getAllByChallenge(Challenge $challenge) : Generator
@@ -29,7 +21,7 @@ class PlaceInChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('challenge_id', '=', $challenge->getId()); $select->where('challenge_id', '=', $challenge->getId());
yield from $this->pdm->selectMultipleFromDb($select, PlaceInChallenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, PlaceInChallenge::class);
} }
public function getByPlaceAndChallenge(Place $place, Challenge $challenge) : ?PlaceInChallenge public function getByPlaceAndChallenge(Place $place, Challenge $challenge) : ?PlaceInChallenge
@@ -38,7 +30,7 @@ class PlaceInChallengeRepository
$select->where('place_id', '=', $place->getId()); $select->where('place_id', '=', $place->getId());
$select->where('challenge_id', '=', $challenge->getId()); $select->where('challenge_id', '=', $challenge->getId());
return $this->pdm->selectFromDb($select, PlaceInChallenge::class); return \Container::$persistentDataManager->selectFromDb($select, PlaceInChallenge::class);
} }
public function getByRoundInChallenge(int $round, Challenge $challenge, array $withRelations = []): ?PlaceInChallenge public function getByRoundInChallenge(int $round, Challenge $challenge, array $withRelations = []): ?PlaceInChallenge
@@ -48,6 +40,6 @@ class PlaceInChallengeRepository
$select->orderBy('round'); $select->orderBy('round');
$select->limit(1, $round); $select->limit(1, $round);
return $this->pdm->selectFromDb($select, PlaceInChallenge::class, true, $withRelations); return \Container::$persistentDataManager->selectFromDb($select, PlaceInChallenge::class, true, $withRelations);
} }
} }
+10 -18
View File
@@ -5,20 +5,12 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\Map; use MapGuesser\PersistentData\Model\Map;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use SokoWeb\PersistentData\PersistentDataManager;
class PlaceRepository class PlaceRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $placeId): ?Place public function getById(int $placeId): ?Place
{ {
return $this->pdm->selectFromDbById($placeId, Place::class); return \Container::$persistentDataManager->selectFromDbById($placeId, Place::class);
} }
public function getAllForMap(Map $map): Generator public function getAllForMap(Map $map): Generator
@@ -26,7 +18,7 @@ class PlaceRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('map_id', '=', $map->getId()); $select->where('map_id', '=', $map->getId());
yield from $this->pdm->selectMultipleFromDb($select, Place::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Place::class);
} }
//TODO: use Map and User instead of id //TODO: use Map and User instead of id
@@ -99,7 +91,7 @@ class PlaceRepository
$select->where('id', 'NOT IN', $exclude); $select->where('id', 'NOT IN', $exclude);
$select->limit(1, $randomOffset); $select->limit(1, $randomOffset);
return $this->pdm->selectFromDb($select, Place::class); return \Container::$persistentDataManager->selectFromDb($select, Place::class);
} }
// Never visited places // Never visited places
@@ -118,7 +110,7 @@ class PlaceRepository
$selectUnvisited = new Select(\Container::$dbConnection, 'places'); $selectUnvisited = new Select(\Container::$dbConnection, 'places');
$selectUnvisited->leftJoin($selectPlacesByCurrentUser, ['places', 'id'], '=', ['places_by_current_user', 'place_id']); $selectUnvisited->leftJoin($selectPlacesByCurrentUser, ['places', 'id'], '=', ['places_by_current_user', 'place_id']);
$selectUnvisited->where('map_id', '=', $mapId); $selectUnvisited->where('map_id', '=', $mapId);
$selectUnvisited->where('last_time', '=', null); $selectUnvisited->where(['places_by_current_user', 'last_time'], '=', null);
$numberOfUnvisitedPlaces = $selectUnvisited->count(); $numberOfUnvisitedPlaces = $selectUnvisited->count();
// look for as many new places as possible but maximum $n // look for as many new places as possible but maximum $n
@@ -182,21 +174,21 @@ class PlaceRepository
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']); $select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->orderBy('round'); $select->orderBy(['place_in_challenge', 'round']);
$select->limit(1, $round); $select->limit(1, $round);
return $this->pdm->selectFromDb($select, Place::class); return \Container::$persistentDataManager->selectFromDb($select, Place::class);
} }
public function getAllInChallenge(Challenge $challenge): Generator public function getAllInChallenge(Challenge $challenge): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']); $select->innerJoin('place_in_challenge', ['places', 'id'], '=', ['place_in_challenge', 'place_id']);
$select->where('challenge_id', '=', $challenge->getId()); $select->where(['place_in_challenge', 'challenge_id'], '=', $challenge->getId());
$select->orderBy('round'); $select->orderBy(['place_in_challenge', 'round']);
yield from $this->pdm->selectMultipleFromDb($select, Place::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, Place::class);
} }
} }
+3 -11
View File
@@ -3,20 +3,12 @@
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserConfirmation; use MapGuesser\PersistentData\Model\UserConfirmation;
use SokoWeb\PersistentData\PersistentDataManager;
class UserConfirmationRepository class UserConfirmationRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $userConfirmationId): ?UserConfirmation public function getById(int $userConfirmationId): ?UserConfirmation
{ {
return $this->pdm->selectFromDbById($userConfirmationId, UserConfirmation::class); return \Container::$persistentDataManager->selectFromDbById($userConfirmationId, UserConfirmation::class);
} }
public function getByToken(string $token): ?UserConfirmation public function getByToken(string $token): ?UserConfirmation
@@ -24,7 +16,7 @@ class UserConfirmationRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('token', '=', $token); $select->where('token', '=', $token);
return $this->pdm->selectFromDb($select, UserConfirmation::class); return \Container::$persistentDataManager->selectFromDb($select, UserConfirmation::class);
} }
public function getByUser(User $user): ?UserConfirmation public function getByUser(User $user): ?UserConfirmation
@@ -32,6 +24,6 @@ class UserConfirmationRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
return $this->pdm->selectFromDb($select, UserConfirmation::class); return \Container::$persistentDataManager->selectFromDb($select, UserConfirmation::class);
} }
} }
+7 -15
View File
@@ -5,23 +5,15 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Challenge; use MapGuesser\PersistentData\Model\Challenge;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserInChallenge; use MapGuesser\PersistentData\Model\UserInChallenge;
use SokoWeb\PersistentData\PersistentDataManager;
class UserInChallengeRepository class UserInChallengeRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getAllByUser(User $user) : Generator public function getAllByUser(User $user) : Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserInChallenge::class);
} }
public function getAllByChallenge(Challenge $challenge) : Generator public function getAllByChallenge(Challenge $challenge) : Generator
@@ -29,7 +21,7 @@ class UserInChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('challenge_id', '=', $challenge->getId()); $select->where('challenge_id', '=', $challenge->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserInChallenge::class);
} }
public function getAllByChallengeWithUsers(Challenge $challenge) : Generator public function getAllByChallengeWithUsers(Challenge $challenge) : Generator
@@ -37,7 +29,7 @@ class UserInChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('challenge_id', '=', $challenge->getId()); $select->where('challenge_id', '=', $challenge->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserInChallenge::class, true, [User::class]); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserInChallenge::class, true, ['user']);
} }
public function getByUserIdAndChallenge(int $userId, Challenge $challenge): ?UserInChallenge public function getByUserIdAndChallenge(int $userId, Challenge $challenge): ?UserInChallenge
@@ -46,13 +38,13 @@ class UserInChallengeRepository
$select->where('user_id', '=', $userId); $select->where('user_id', '=', $userId);
$select->where('challenge_id', '=', $challenge->getId()); $select->where('challenge_id', '=', $challenge->getId());
return $this->pdm->selectFromDb($select, UserInChallenge::class); return \Container::$persistentDataManager->selectFromDb($select, UserInChallenge::class);
} }
public function getByUserIdAndToken(int $userId, string $token_str, array $withRelations = []): ?UserInChallenge public function getByUserIdAndToken(int $userId, string $token_str, array $withRelations = []): ?UserInChallenge
{ {
if (count($withRelations)) { if (count($withRelations)) {
$necessaryRelations = [Challenge::class]; $necessaryRelations = ['challange'];
$withRelations = array_unique(array_merge($withRelations, $necessaryRelations)); $withRelations = array_unique(array_merge($withRelations, $necessaryRelations));
} }
@@ -65,9 +57,9 @@ class UserInChallengeRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $userId); $select->where('user_id', '=', $userId);
$select->where('token', '=', $token); $select->where(['user_in_challenge__challenge', 'token'], '=', $token);
return $this->pdm->selectFromDb($select, UserInChallenge::class, true, $withRelations); return \Container::$persistentDataManager->selectFromDb($select, UserInChallenge::class, true, $withRelations);
} }
public function isUserParticipatingInChallenge(int $userId, Challenge $challenge): bool public function isUserParticipatingInChallenge(int $userId, Challenge $challenge): bool
@@ -5,20 +5,12 @@ use Generator;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\UserPasswordResetter; use MapGuesser\PersistentData\Model\UserPasswordResetter;
use SokoWeb\PersistentData\PersistentDataManager;
class UserPasswordResetterRepository class UserPasswordResetterRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $userConfirmationId): ?UserPasswordResetter public function getById(int $userConfirmationId): ?UserPasswordResetter
{ {
return $this->pdm->selectFromDbById($userConfirmationId, UserPasswordResetter::class); return \Container::$persistentDataManager->selectFromDbById($userConfirmationId, UserPasswordResetter::class);
} }
public function getByToken(string $token): ?UserPasswordResetter public function getByToken(string $token): ?UserPasswordResetter
@@ -26,7 +18,7 @@ class UserPasswordResetterRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('token', '=', $token); $select->where('token', '=', $token);
return $this->pdm->selectFromDb($select, UserPasswordResetter::class); return \Container::$persistentDataManager->selectFromDb($select, UserPasswordResetter::class);
} }
public function getByUser(User $user): ?UserPasswordResetter public function getByUser(User $user): ?UserPasswordResetter
@@ -34,7 +26,7 @@ class UserPasswordResetterRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
return $this->pdm->selectFromDb($select, UserPasswordResetter::class); return \Container::$persistentDataManager->selectFromDb($select, UserPasswordResetter::class);
} }
public function getAllExpired(): Generator public function getAllExpired(): Generator
@@ -42,6 +34,6 @@ class UserPasswordResetterRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('expires', '<', (new DateTime())->format('Y-m-d H:i:s')); $select->where('expires', '<', (new DateTime())->format('Y-m-d H:i:s'));
yield from $this->pdm->selectMultipleFromDb($select, UserPasswordResetter::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserPasswordResetter::class);
} }
} }
+4 -12
View File
@@ -5,23 +5,15 @@ use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use MapGuesser\PersistentData\Model\Place; use MapGuesser\PersistentData\Model\Place;
use MapGuesser\PersistentData\Model\UserPlayedPlace; use MapGuesser\PersistentData\Model\UserPlayedPlace;
use SokoWeb\PersistentData\PersistentDataManager;
class UserPlayedPlaceRepository class UserPlayedPlaceRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getByUser(User $user): Generator public function getByUser(User $user): Generator
{ {
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserPlayedPlace::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserPlayedPlace::class);
} }
public function getAllByPlace(Place $place): Generator public function getAllByPlace(Place $place): Generator
@@ -29,7 +21,7 @@ class UserPlayedPlaceRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('place_id', '=', $place->getId()); $select->where('place_id', '=', $place->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserPlayedPlace::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserPlayedPlace::class);
} }
public function getAllByUser(User $user) : Generator public function getAllByUser(User $user) : Generator
@@ -37,7 +29,7 @@ class UserPlayedPlaceRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, UserPlayedPlace::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, UserPlayedPlace::class);
} }
public function getByUserIdAndPlaceId(int $userId, int $placeId) : ?UserPlayedPlace public function getByUserIdAndPlaceId(int $userId, int $placeId) : ?UserPlayedPlace
@@ -46,6 +38,6 @@ class UserPlayedPlaceRepository
$select->where('user_id', '=', $userId); $select->where('user_id', '=', $userId);
$select->where('place_id', '=', $placeId); $select->where('place_id', '=', $placeId);
return $this->pdm->selectFromDb($select, UserPlayedPlace::class); return \Container::$persistentDataManager->selectFromDb($select, UserPlayedPlace::class);
} }
} }
+4 -12
View File
@@ -6,20 +6,12 @@ use SokoWeb\Interfaces\Repository\IUserRepository;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use MapGuesser\PersistentData\Model\Guess; use MapGuesser\PersistentData\Model\Guess;
use MapGuesser\PersistentData\Model\User; use MapGuesser\PersistentData\Model\User;
use SokoWeb\PersistentData\PersistentDataManager;
class UserRepository implements IUserRepository class UserRepository implements IUserRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $userId): ?User public function getById(int $userId): ?User
{ {
return $this->pdm->selectFromDbById($userId, User::class); return \Container::$persistentDataManager->selectFromDbById($userId, User::class);
} }
public function getByEmail(string $email): ?User public function getByEmail(string $email): ?User
@@ -27,7 +19,7 @@ class UserRepository implements IUserRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('email', '=', $email); $select->where('email', '=', $email);
return $this->pdm->selectFromDb($select, User::class); return \Container::$persistentDataManager->selectFromDb($select, User::class);
} }
public function getByGoogleSub(string $sub): ?User public function getByGoogleSub(string $sub): ?User
@@ -35,7 +27,7 @@ class UserRepository implements IUserRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('google_sub', '=', $sub); $select->where('google_sub', '=', $sub);
return $this->pdm->selectFromDb($select, User::class); return \Container::$persistentDataManager->selectFromDb($select, User::class);
} }
public function getAllInactiveExpired(): Generator public function getAllInactiveExpired(): Generator
@@ -44,7 +36,7 @@ class UserRepository implements IUserRepository
$select->where('active', '=', false); $select->where('active', '=', false);
$select->where('created', '<', (new DateTime('-1 day'))->format('Y-m-d H:i:s')); $select->where('created', '<', (new DateTime('-1 day'))->format('Y-m-d H:i:s'));
yield from $this->pdm->selectMultipleFromDb($select, User::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, User::class);
} }
public function getByGuess(Guess $guess): ?User public function getByGuess(Guess $guess): ?User
+5 -5
View File
@@ -9,12 +9,12 @@
<?php if ($user['password'] !== null && $user['google_sub'] !== null): ?> <?php if ($user['password'] !== null && $user['google_sub'] !== null): ?>
<p class="justify small">Please confirm your identity with your password or with Google to modify your account.</p> <p class="justify small">Please confirm your identity with your password or with Google to modify your account.</p>
<div class="inputWithButton"> <div class="inputWithButton">
<input type="password" class="text name="password" placeholder="Current password" required minlength="6" autofocus><!-- <input type="password" class="text name="password" placeholder="Current password" autocomplete="current-password" required minlength="6" autofocus><!--
--><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button> --><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button>
</div> </div>
<?php elseif ($user['password'] !== null): ?> <?php elseif ($user['password'] !== null): ?>
<p class="justify small">Please confirm your identity with your password to modify your account.</p> <p class="justify small">Please confirm your identity with your password to modify your account.</p>
<input type="password" class="text big fullWidth" name="password" placeholder="Current password" required minlength="6" autofocus> <input type="password" class="text big fullWidth" name="password" placeholder="Current password" autocomplete="current-password" required minlength="6" autofocus>
<?php elseif ($user['google_sub'] !== null): ?> <?php elseif ($user['google_sub'] !== null): ?>
<p class="justify small">Please confirm your identity with Google to modify your account.</p> <p class="justify small">Please confirm your identity with Google to modify your account.</p>
<div class="inputWithButton"> <div class="inputWithButton">
@@ -24,9 +24,9 @@
<?php endif; ?> <?php endif; ?>
<hr> <hr>
<?php /* TODO: disabled for the time being, email modification should be implemented */ ?> <?php /* TODO: disabled for the time being, email modification should be implemented */ ?>
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= $user['email'] ?>" disabled> <input type="email" class="text big fullWidth" name="email" placeholder="Email address" autocomplete="username" value="<?= $user['email'] ?>" disabled>
<input type="password" class="text big fullWidth marginTop" name="password_new" placeholder="New password" minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password_new" placeholder="New password" autocomplete="new-password" minlength="6">
<input type="password" class="text big fullWidth marginTop" name="password_new_confirm" placeholder="New password confirmation" minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password_new_confirm" placeholder="New password confirmation" autocomplete="new-password" minlength="6">
<p id="accountFormError" class="formError justify marginTop"></p> <p id="accountFormError" class="formError justify marginTop"></p>
<div class="right marginTop"> <div class="right marginTop">
<button type="submit" name="submit" disabled>Save</button> <button type="submit" name="submit" disabled>Save</button>
+3 -2
View File
@@ -7,15 +7,16 @@
<div class="box"> <div class="box">
<form id="deleteAccountForm" action="/account/delete" method="post" data-redirect-on-success="/"> <form id="deleteAccountForm" action="/account/delete" method="post" data-redirect-on-success="/">
<p class="justify marginBottom">Are you sure you want to delete your account? This cannot be undone!</p> <p class="justify marginBottom">Are you sure you want to delete your account? This cannot be undone!</p>
<input type="email" style="display: none;" name="email" autocomplete="username" value="<?= $user['email'] ?>">
<?php if ($user['password'] !== null && $user['google_sub'] !== null): ?> <?php if ($user['password'] !== null && $user['google_sub'] !== null): ?>
<p class="justify small">Please confirm your identity with your password or with Google to delete your account.</p> <p class="justify small">Please confirm your identity with your password or with Google to delete your account.</p>
<div class="inputWithButton"> <div class="inputWithButton">
<input type="password" class="text" name="password" placeholder="Current password" required minlength="6" autofocus><!-- <input type="password" class="text" name="password" placeholder="Current password" autocomplete="current-password" required minlength="6" autofocus><!--
--><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button> --><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button>
</div> </div>
<?php elseif ($user['password'] !== null): ?> <?php elseif ($user['password'] !== null): ?>
<p class="justify small">Please confirm your identity with your password to delete your account.</p> <p class="justify small">Please confirm your identity with your password to delete your account.</p>
<input type="password" class="text big fullWidth" name="password" placeholder="Current password" required minlength="6" autofocus> <input type="password" class="text big fullWidth" name="password" placeholder="Current password" autocomplete="current-password" required minlength="6" autofocus>
<?php elseif ($user['google_sub'] !== null): ?> <?php elseif ($user['google_sub'] !== null): ?>
<p class="justify small">Please confirm your identity with Google to delete your account.</p> <p class="justify small">Please confirm your identity with Google to delete your account.</p>
<div class="inputWithButton"> <div class="inputWithButton">
+11
View File
@@ -0,0 +1,11 @@
@extends(templates/layout_normal)
@section(main)
<h2>500 | Internal server error</h2>
<p>An error occured during processing your request. <a href="<?= Container::$routeCollection->getRoute('index')->generateLink() ?>" title="<?= $_ENV['APP_NAME'] ?>">Back to start.</a></p>
<?php if (isset($exceptionToPrint)): ?>
<pre class="marginTop">
<?= $exceptionToPrint ?>
</pre>
<?php endif; ?>
@endsection
+1 -1
View File
@@ -5,7 +5,7 @@
@section(main) @section(main)
<h2>Sign up</h2> <h2>Sign up</h2>
<div class="box"> <div class="box">
<form id="googleSignupForm" action="/signup/google" method="post" data-redirect-on-success="/"> <form id="googleSignupForm" action="/signup/google" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
<?php if ($found): ?> <?php if ($found): ?>
<p class="justify">Please confirm that you link your account to your Google account.</p> <p class="justify">Please confirm that you link your account to your Google account.</p>
<?php else: ?> <?php else: ?>
+3 -3
View File
@@ -3,9 +3,9 @@
@section(main) @section(main)
<h2>Login</h2> <h2>Login</h2>
<div class="box"> <div class="box">
<form id="loginForm" action="/login" method="post" data-redirect-on-success="/"> <form id="loginForm" action="/login" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" required autofocus> <input type="email" class="text big fullWidth" name="email" placeholder="Email address" autocomplete="username" required autofocus>
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" required minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password autocomplete="current-password"" required minlength="6">
<p id="loginFormError" class="formError justify marginTop"></p> <p id="loginFormError" class="formError justify marginTop"></p>
<div class="right marginTop"> <div class="right marginTop">
<button type="submit">Login</button> <button type="submit">Login</button>
+1 -1
View File
@@ -6,7 +6,7 @@
<h2>Request password reset</h2> <h2>Request password reset</h2>
<div class="box"> <div class="box">
<form id="passwordResetForm" action="/password/requestReset" method="post" data-redirect-on-success="/password/requestReset/success"> <form id="passwordResetForm" action="/password/requestReset" method="post" data-redirect-on-success="/password/requestReset/success">
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= isset($email) ? $email : '' ?>" required autofocus> <input type="email" class="text big fullWidth" name="email" placeholder="Email address" autocomplete="username" value="<?= isset($email) ? $email : '' ?>" required autofocus>
<?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?> <?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?>
<div class="marginTop"> <div class="marginTop">
<div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div> <div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div>
+4 -4
View File
@@ -4,10 +4,10 @@
<h2>Reset password</h2> <h2>Reset password</h2>
<div class="box"> <div class="box">
<?php if ($success) : ?> <?php if ($success) : ?>
<form id="resetPasswordForm" action="/password/reset/<?= $token ?>" method="post" data-redirect-on-success="/"> <form id="resetPasswordForm" action="/password/reset/<?= $token ?>" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= $email ?>" disabled> <input type="email" class="text big fullWidth" name="email" placeholder="Email address" autocomplete="username" value="<?= $email ?>" disabled>
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" required minlength="6" autofocus> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" autocomplete="new-password" required minlength="6" autofocus>
<input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" required minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" autocomplete="new-password" required minlength="6">
<p id="resetPasswordFormError" class="formError justify marginTop"></p> <p id="resetPasswordFormError" class="formError justify marginTop"></p>
<div class="right"> <div class="right">
<button class="marginTop" type="submit">Reset password</button> <button class="marginTop" type="submit">Reset password</button>
+5 -5
View File
@@ -9,12 +9,12 @@
<form id="signupForm" action="/signup" method="post" data-redirect-on-success="/signup/success"> <form id="signupForm" action="/signup" method="post" data-redirect-on-success="/signup/success">
<?php if (isset($email)): ?> <?php if (isset($email)): ?>
<p class="justify">No user found with the given email address. Sign up with one click!</p> <p class="justify">No user found with the given email address. Sign up with one click!</p>
<input type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" value="<?= $email ?>" required> <input type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" autocomplete="username" value="<?= $email ?>" required>
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password confirmation" required minlength="6" autofocus> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password confirmation" autocomplete="new-password" required minlength="6" autofocus>
<?php else: ?> <?php else: ?>
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" required autofocus> <input type="email" class="text big fullWidth" name="email" placeholder="Email address" autocomplete="username" required autofocus>
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" required minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" autocomplete="new-password" required minlength="6">
<input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" autocomplete="new-password" minlength="6">
<?php endif; ?> <?php endif; ?>
<?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?> <?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?>
<div class="marginTop"> <div class="marginTop">
+5 -9
View File
@@ -96,16 +96,12 @@ TODO: condition!
</div> </div>
</div> </div>
<div class="buttonContainer"> <div class="buttonContainer">
<?php if (!empty($_ENV['ENABLE_GAME_FOR_GUESTS']) || Container::$request->user()): ?> <?php if ($isAdmin): ?>
<?php if ($isAdmin): ?> <button class="button fullWidth noRightRadius playButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Play map '<?= $map['name'] ?>'">Play this map</button>
<button class="button fullWidth noRightRadius playButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Play map '<?= $map['name'] ?>'">Play this map</button> <a class="button yellow fullWidth noLeftRadius noRightRadius" href="/admin/mapEditor/<?= $map['id']; ?>" title="Edit map '<?= $map['name'] ?>'">Edit</a>
<a class="button yellow fullWidth noLeftRadius noRightRadius" href="/admin/mapEditor/<?= $map['id']; ?>" title="Edit map '<?= $map['name'] ?>'">Edit</a> <button class="button red fullWidth noLeftRadius deleteButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Delete map '<?= $map['name'] ?>'">Delete</button>
<button class="button red fullWidth noLeftRadius deleteButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Delete map '<?= $map['name'] ?>'">Delete</button>
<?php else: ?>
<button class="button fullWidth playButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Play map '<?= $map['name'] ?>'">Play this map</button>
<?php endif; ?>
<?php else: ?> <?php else: ?>
<a href="/login" class="button fullWidth" title="Play map '<?= $map['name'] ?>'">Play this map</a> <button class="button fullWidth playButton" data-map-id="<?= $map['id'] ?>" data-map-name="<?= htmlspecialchars($map['name']) ?>" title="Play map '<?= $map['name'] ?>'">Play this map</button>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
-22
View File
@@ -1,22 +0,0 @@
@css(test1.css)
@js(test1.js)
@js(test2_<?= $some['expression'] ?>)
@extra
<?php phpinfo() ?>
@endextra
@extends(parent)
@section(section1)
<div>Test HTML with @extends - section 1</div>
@endsection
@section(section2)
<div>Test HTML with @extends - section 2</div>
@endsection
@extra
<?php $a = 'test_string' ?>
EXTRA
@endextra
@@ -1,5 +0,0 @@
@extends(parent1)
@extends(parent2)
<div>Test HTML with multiple @extends</div>
@@ -1,6 +0,0 @@
@extends(parent)
@section(section1)
@section(section2)
<div>Test HTML with opening @section before previous closed</div>
@@ -1,4 +0,0 @@
@extends(parent)
<div>Test HTML with @endsection when no section is open</div>
@endsection
@@ -1,3 +0,0 @@
@section(section1)
<div>Test HTML with @section but without @extends</div>
-4
View File
@@ -1,4 +0,0 @@
@css(test.css)
@js(test.js)
@js(test_<?= $some['expression'] ?>)
<div>Test HTML with @css and @js</div>
-5
View File
@@ -1,5 +0,0 @@
@extends(parent)
@section(section1)
<div>Test HTML with @extends</div>
@endsection
-1
View File
@@ -1 +0,0 @@
<div>Test HTML without @extends</div>
+99 -71
View File
@@ -1,5 +1,19 @@
<?php <?php
use SokoWeb\Response\HttpResponse;
use SokoWeb\Routing\RouteCollection;
use SokoWeb\Session\DatabaseSessionHandler;
use SokoWeb\Request\Request;
use SokoWeb\Request\Session;
use MapGuesser\Controller\MapsController;
use MapGuesser\Controller\HomeController;
use MapGuesser\Controller\LoginController;
use MapGuesser\Controller\UserController;
use MapGuesser\Controller\GameController;
use MapGuesser\Controller\GameFlowController;
use MapGuesser\Controller\MapAdminController;
use MapGuesser\Repository\UserRepository;
require 'main.php'; require 'main.php';
if (!empty($_ENV['DEV'])) { if (!empty($_ENV['DEV'])) {
@@ -10,94 +24,88 @@ if (!empty($_ENV['DEV'])) {
ini_set('display_errors', '0'); ini_set('display_errors', '0');
} }
Container::$routeCollection = new SokoWeb\Routing\RouteCollection(); Container::$routeCollection = new RouteCollection();
Container::$routeCollection->get('index', '', [MapGuesser\Controller\MapsController::class, 'getMaps']); Container::$routeCollection->get('index', '', [MapsController::class, 'getMaps']);
Container::$routeCollection->get('startSession', 'startSession.json', [MapGuesser\Controller\HomeController::class, 'startSession']); Container::$routeCollection->get('startSession', 'startSession.json', [HomeController::class, 'startSession']);
Container::$routeCollection->group('login', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('login', function (RouteCollection $routeCollection) {
$routeCollection->get('login', '', [MapGuesser\Controller\LoginController::class, 'getLoginForm']); $routeCollection->get('login', '', [LoginController::class, 'getLoginForm']);
$routeCollection->post('login-action', '', [MapGuesser\Controller\LoginController::class, 'login']); $routeCollection->post('login-action', '', [LoginController::class, 'login']);
$routeCollection->get('login-google', 'google', [MapGuesser\Controller\LoginController::class, 'getGoogleLoginRedirect']); $routeCollection->get('login-google', 'google', [LoginController::class, 'getGoogleLoginRedirect']);
$routeCollection->get('login-google-action', 'google/code', [MapGuesser\Controller\LoginController::class, 'loginWithGoogle']); $routeCollection->get('login-google-action', 'google/code', [LoginController::class, 'loginWithGoogle']);
}); });
Container::$routeCollection->group('signup', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('signup', function (RouteCollection $routeCollection) {
$routeCollection->get('signup', '', [MapGuesser\Controller\LoginController::class, 'getSignupForm']); $routeCollection->get('signup', '', [LoginController::class, 'getSignupForm']);
$routeCollection->post('signup-action', '', [MapGuesser\Controller\LoginController::class, 'signup']); $routeCollection->post('signup-action', '', [LoginController::class, 'signup']);
$routeCollection->get('signup-google', 'google', [MapGuesser\Controller\LoginController::class, 'getSignupWithGoogleForm']); $routeCollection->get('signup-google', 'google', [LoginController::class, 'getSignupWithGoogleForm']);
$routeCollection->post('signup-google-action', 'google', [MapGuesser\Controller\LoginController::class, 'signupWithGoogle']); $routeCollection->post('signup-google-action', 'google', [LoginController::class, 'signupWithGoogle']);
$routeCollection->post('signup.reset', 'reset', [MapGuesser\Controller\LoginController::class, 'resetSignup']); $routeCollection->post('signup.reset', 'reset', [LoginController::class, 'resetSignup']);
$routeCollection->post('signup-google.reset', 'google/reset', [MapGuesser\Controller\LoginController::class, 'resetGoogleSignup']); $routeCollection->post('signup-google.reset', 'google/reset', [LoginController::class, 'resetGoogleSignup']);
$routeCollection->get('signup.success', 'success', [MapGuesser\Controller\LoginController::class, 'getSignupSuccess']); $routeCollection->get('signup.success', 'success', [LoginController::class, 'getSignupSuccess']);
$routeCollection->get('signup.activate', 'activate/{token}', [MapGuesser\Controller\LoginController::class, 'activate']); $routeCollection->get('signup.activate', 'activate/{token}', [LoginController::class, 'activate']);
$routeCollection->get('signup.cancel', 'cancel/{token}', [MapGuesser\Controller\LoginController::class, 'cancel']); $routeCollection->get('signup.cancel', 'cancel/{token}', [LoginController::class, 'cancel']);
}); });
Container::$routeCollection->group('password', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('password', function (RouteCollection $routeCollection) {
$routeCollection->get('password-requestReset', 'requestReset', [MapGuesser\Controller\LoginController::class, 'getRequestPasswordResetForm']); $routeCollection->get('password-requestReset', 'requestReset', [LoginController::class, 'getRequestPasswordResetForm']);
$routeCollection->post('password-requestReset-action', 'requestReset', [MapGuesser\Controller\LoginController::class, 'requestPasswordReset']); $routeCollection->post('password-requestReset-action', 'requestReset', [LoginController::class, 'requestPasswordReset']);
$routeCollection->get('password-requestReset.success', 'requestReset/success', [MapGuesser\Controller\LoginController::class, 'getRequestPasswordResetSuccess']); $routeCollection->get('password-requestReset.success', 'requestReset/success', [LoginController::class, 'getRequestPasswordResetSuccess']);
$routeCollection->get('password-reset', 'reset/{token}', [MapGuesser\Controller\LoginController::class, 'getResetPasswordForm']); $routeCollection->get('password-reset', 'reset/{token}', [LoginController::class, 'getResetPasswordForm']);
$routeCollection->post('password-reset.action', 'reset/{token}', [MapGuesser\Controller\LoginController::class, 'resetPassword']); $routeCollection->post('password-reset.action', 'reset/{token}', [LoginController::class, 'resetPassword']);
}); });
Container::$routeCollection->get('logout', 'logout', [MapGuesser\Controller\LoginController::class, 'logout']); Container::$routeCollection->get('logout', 'logout', [LoginController::class, 'logout']);
Container::$routeCollection->group('account', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('account', function (RouteCollection $routeCollection) {
$routeCollection->get('account', '', [MapGuesser\Controller\UserController::class, 'getAccount']); $routeCollection->get('account', '', [UserController::class, 'getAccount']);
$routeCollection->post('account-action', '', [MapGuesser\Controller\UserController::class, 'saveAccount']); $routeCollection->post('account-action', '', [UserController::class, 'saveAccount']);
$routeCollection->get('account.delete', 'delete', [MapGuesser\Controller\UserController::class, 'getDeleteAccount']); $routeCollection->get('account.delete', 'delete', [UserController::class, 'getDeleteAccount']);
$routeCollection->post('account.delete-action', 'delete', [MapGuesser\Controller\UserController::class, 'deleteAccount']); $routeCollection->post('account.delete-action', 'delete', [UserController::class, 'deleteAccount']);
$routeCollection->get('account.googleAuthenticate', 'googleAuthenticate', [MapGuesser\Controller\UserController::class, 'getGoogleAuthenticateRedirect']); $routeCollection->get('account.googleAuthenticate', 'googleAuthenticate', [UserController::class, 'getGoogleAuthenticateRedirect']);
$routeCollection->get('account.googleAuthenticate-action', 'googleAuthenticate/code', [MapGuesser\Controller\UserController::class, 'authenticateWithGoogle']); $routeCollection->get('account.googleAuthenticate-action', 'googleAuthenticate/code', [UserController::class, 'authenticateWithGoogle']);
}); });
//Container::$routeCollection->get('maps', 'maps', [MapGuesser\Controller\MapsController::class, 'getMaps']); //Container::$routeCollection->get('maps', 'maps', [MapsController::class, 'getMaps']);
Container::$routeCollection->group('game', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('game', function (RouteCollection $routeCollection) {
$routeCollection->get('game', '{mapId}', [MapGuesser\Controller\GameController::class, 'getGame']); $routeCollection->get('game', '{mapId}', [GameController::class, 'getGame']);
$routeCollection->post('game.prepare-json', '{mapId}/prepare.json', [MapGuesser\Controller\GameController::class, 'prepareGame']); $routeCollection->post('game.prepare-json', '{mapId}/prepare.json', [GameController::class, 'prepareGame']);
$routeCollection->post('game.initialData-json', '{mapId}/initialData.json', [MapGuesser\Controller\GameFlowController::class, 'initialData']); $routeCollection->post('game.initialData-json', '{mapId}/initialData.json', [GameFlowController::class, 'initialData']);
$routeCollection->post('game.guess-json', '{mapId}/guess.json', [MapGuesser\Controller\GameFlowController::class, 'guess']); $routeCollection->post('game.guess-json', '{mapId}/guess.json', [GameFlowController::class, 'guess']);
}); });
Container::$routeCollection->group('multiGame', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('multiGame', function (RouteCollection $routeCollection) {
$routeCollection->get('multiGame.new', 'new/{mapId}', [MapGuesser\Controller\GameController::class, 'getNewMultiGame']); $routeCollection->get('multiGame.new', 'new/{mapId}', [GameController::class, 'getNewMultiGame']);
$routeCollection->get('multiGame', '{roomId}', [MapGuesser\Controller\GameController::class, 'getMultiGame']); $routeCollection->get('multiGame', '{roomId}', [GameController::class, 'getMultiGame']);
$routeCollection->post('multiGame.prepare-json', '{roomId}/prepare.json', [MapGuesser\Controller\GameController::class, 'prepareMultiGame']); $routeCollection->post('multiGame.prepare-json', '{roomId}/prepare.json', [GameController::class, 'prepareMultiGame']);
$routeCollection->post('multiGame.initialData-json', '{roomId}/initialData.json', [MapGuesser\Controller\GameFlowController::class, 'multiInitialData']); $routeCollection->post('multiGame.initialData-json', '{roomId}/initialData.json', [GameFlowController::class, 'multiInitialData']);
$routeCollection->post('multiGame.nextRound-json', '{roomId}/nextRound.json', [MapGuesser\Controller\GameFlowController::class, 'multiNextRound']); $routeCollection->post('multiGame.nextRound-json', '{roomId}/nextRound.json', [GameFlowController::class, 'multiNextRound']);
$routeCollection->post('multiGame.guess-json', '{roomId}/guess.json', [MapGuesser\Controller\GameFlowController::class, 'multiGuess']); $routeCollection->post('multiGame.guess-json', '{roomId}/guess.json', [GameFlowController::class, 'multiGuess']);
}); });
Container::$routeCollection->group('challenge', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('challenge', function (RouteCollection $routeCollection) {
$routeCollection->post('challenge.create', 'create.json', [\MapGuesser\Controller\GameController::class, 'createNewChallenge']); $routeCollection->post('challenge.create', 'create.json', [GameController::class, 'createNewChallenge']);
$routeCollection->get('challenge', '{challengeToken}', [MapGuesser\Controller\GameController::class, 'getChallenge']); $routeCollection->get('challenge', '{challengeToken}', [GameController::class, 'getChallenge']);
$routeCollection->post('challenge.prepare-json', '{challengeToken}/prepare.json', [MapGuesser\Controller\GameController::class, 'prepareChallenge']); $routeCollection->post('challenge.prepare-json', '{challengeToken}/prepare.json', [GameController::class, 'prepareChallenge']);
$routeCollection->post('challenge.initialData-json', '{challengeToken}/initialData.json', [MapGuesser\Controller\GameFlowController::class, 'challengeInitialData']); $routeCollection->post('challenge.initialData-json', '{challengeToken}/initialData.json', [GameFlowController::class, 'challengeInitialData']);
$routeCollection->post('challenge.guess-json', '{challengeToken}/guess.json', [MapGuesser\Controller\GameFlowController::class, 'challengeGuess']); $routeCollection->post('challenge.guess-json', '{challengeToken}/guess.json', [GameFlowController::class, 'challengeGuess']);
}); });
Container::$routeCollection->group('admin', function (SokoWeb\Routing\RouteCollection $routeCollection) { Container::$routeCollection->group('admin', function (RouteCollection $routeCollection) {
$routeCollection->get('admin.mapEditor', 'mapEditor/{mapId?}', [MapGuesser\Controller\MapAdminController::class, 'getMapEditor']); $routeCollection->get('admin.mapEditor', 'mapEditor/{mapId?}', [MapAdminController::class, 'getMapEditor']);
$routeCollection->get('admin.place', 'place.json/{placeId}', [MapGuesser\Controller\MapAdminController::class, 'getPlace']); $routeCollection->get('admin.place', 'place.json/{placeId}', [MapAdminController::class, 'getPlace']);
$routeCollection->post('admin.saveMap', 'saveMap/{mapId}/json', [MapGuesser\Controller\MapAdminController::class, 'saveMap']); $routeCollection->post('admin.saveMap', 'saveMap/{mapId}/json', [MapAdminController::class, 'saveMap']);
$routeCollection->post('admin.deleteMap', 'deleteMap/{mapId}', [MapGuesser\Controller\MapAdminController::class, 'deleteMap']); $routeCollection->post('admin.deleteMap', 'deleteMap/{mapId}', [MapAdminController::class, 'deleteMap']);
}); });
if (isset($_COOKIE['COOKIES_CONSENT'])) { if (isset($_COOKIE['COOKIES_CONSENT'])) {
Container::$sessionHandler = new SokoWeb\Session\DatabaseSessionHandler(); Container::$sessionHandler = new DatabaseSessionHandler(
Container::$dbConnection,
'sessions',
new DateTime('-7 days')
);
session_set_save_handler(Container::$sessionHandler, true); session_set_save_handler(Container::$sessionHandler, true);
session_start([ session_start([
'gc_probability' => 0, // old sessions are deleted by MaintainDatabaseCommand 'gc_probability' => 0, // old sessions are deleted by MaintainDatabaseCommand
'cookie_lifetime' => 604800, 'cookie_lifetime' => 0,
'cookie_path' => '/', 'cookie_path' => '/',
'cookie_httponly' => true, 'cookie_httponly' => true,
'cookie_samesite' => 'Lax' 'cookie_samesite' => 'Lax'
]); ]);
if (isset($_COOKIE[session_name()])) {
// extend session cookie lifetime is cookie already exists
setcookie(session_name(), session_id(), [
'expires' => time() + 604800,
'path' => '/',
'httponly' => true,
'samesite' => 'Lax'
]);
}
// this is needed to handle old type of session IDs // this is needed to handle old type of session IDs
if (!Container::$sessionHandler->validateId(session_id())) { if (!Container::$sessionHandler->validateId(session_id())) {
session_regenerate_id(true); session_regenerate_id(true);
@@ -106,14 +114,34 @@ if (isset($_COOKIE['COOKIES_CONSENT'])) {
$_SESSION = []; $_SESSION = [];
} }
Container::$request = new SokoWeb\Request\Request( Container::$request = new Request(
$_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'],
$_GET, $_GET,
$_POST, $_POST,
$_SESSION, getallheaders(),
new MapGuesser\Repository\UserRepository() new Session($_SESSION),
new UserRepository()
); );
if (!Container::$request->session()->has('anti_csrf_token')) { if (!Container::$request->session()->has('anti_csrf_token')) {
Container::$request->session()->set('anti_csrf_token', bin2hex(random_bytes(16))); Container::$request->session()->set('anti_csrf_token', bin2hex(random_bytes(16)));
} }
$appConfig = [
'antiCsrfTokenName' => 'anti_csrf_token',
'antiCsrfTokenErrorResponse' => ['error' => 'no_valid_anti_csrf_token'],
'antiCsrfTokenExceptions' => [],
'loginRouteId' => 'login',
'error404View' => 'error/404',
'error500View' => 'error/500'
];
$httpReponse = new HttpResponse(
Container::$request,
Container::$dbConnection,
Container::$routeCollection,
$appConfig,
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI']
);
$httpReponse->render();