Compare commits

...
Author SHA1 Message Date
bence ad18c7cb25 Merge pull request 'use IRouteCollection in app container' (!29) from bugfix/fix-app-container into master
rvr-nextgen/pipeline/head This commit looks good
Reviewed-on: #29
2023-04-20 00:34:26 +02:00
bence a2fb166b55 use IRouteCollection in app container
rvr-nextgen/pipeline/pr-master This commit looks good
2023-04-20 00:33:06 +02:00
bence f0a7b34212 Merge pull request 'feature/update-soko-web' (!28) from feature/update-soko-web into master
rvr-nextgen/pipeline/head This commit looks good
Reviewed-on: #28
2023-04-19 23:43:27 +02:00
bence dccb34971b adapt Container usage to new soko-web
rvr-nextgen/pipeline/pr-master This commit looks good
2023-04-19 23:38:43 +02:00
bence 36f767ea9b update soko-web version 2023-04-19 23:38:43 +02:00
bence c0739eeddf Merge pull request 'feature/activate-audit-logging' (!27) from feature/activate-audit-logging into master
rvr-nextgen/pipeline/head This commit looks good
Reviewed-on: #27
2023-04-19 00:58:44 +02:00
bence cac30c9203 add auditLogger instance to app container
rvr-nextgen/pipeline/pr-master This commit looks good
2023-04-18 23:37:55 +02:00
bence 89b0ce768b add db table for audit log 2023-04-18 23:37:55 +02:00
bence 656ce219ef add class AuditLogger 2023-04-18 23:37:55 +02:00
bence fd30911dd3 Merge pull request 'feature/update-to-soko-web-0.5' (!26) from feature/update-to-soko-web-0.5 into master
rvr-nextgen/pipeline/head This commit looks good
Reviewed-on: #26
2023-04-18 23:30:33 +02:00
bence b4cfa7aab2 remove unnecessary startTransaction and commit calls
rvr-nextgen/pipeline/pr-master This commit looks good
2023-04-18 23:29:04 +02:00
bence 617ae903ae add error view 500 to app config 2023-04-18 23:29:04 +02:00
bence a7997429b7 add view for error 500 2023-04-18 23:26:42 +02:00
bence 4d5e982370 pass dbConnection to HttpResponse 2023-04-18 23:26:42 +02:00
bence 46ea01efe1 update soko-web to 0.5 2023-04-18 23:20:29 +02:00
25 changed files with 184 additions and 252 deletions

No files matched your search

+5 -1
View File
@@ -15,9 +15,13 @@ $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\Database\IAuditLogger $auditLogger;
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::$auditLogger = new RVR\Database\AuditLogger(Container::$dbConnection, 'audit_log');
Container::$persistentDataManager = new SokoWeb\PersistentData\PersistentDataManager(Container::$dbConnection, Container::$auditLogger);
+1 -1
View File
@@ -10,7 +10,7 @@
} }
], ],
"require": { "require": {
"esoko/soko-web": "0.4", "esoko/soko-web": "0.6",
"firebase/php-jwt": "^6.4" "firebase/php-jwt": "^6.4"
}, },
"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": "f7786e07bcb0373560ae67549fa28f0b", "content-hash": "7b9e3854a5b7ef69d360c1dfbac75c17",
"packages": [ "packages": [
{ {
"name": "esoko/soko-web", "name": "esoko/soko-web",
"version": "v0.4", "version": "0.6",
"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": "948b36c80d324e07339a543d97b9e629487f3a45" "reference": "5e0579463cf0f4203c46e0d4f9c09cd283dbf0b8"
}, },
"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-16T18:52:06+00:00" "time": "2023-04-19T21:35:03+00:00"
}, },
{ {
"name": "firebase/php-jwt", "name": "firebase/php-jwt",
@@ -0,0 +1,12 @@
CREATE TABLE `audit_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`local_table` varchar(255) NOT NULL,
`local_id` int(10) unsigned NOT NULL,
`type` enum('insert','update','delete') NOT NULL,
`date` timestamp NOT NULL DEFAULT current_timestamp(),
`modifier_id` int(10) unsigned NULL,
`column` varchar(255) NULL,
`old` text NULL,
`new` text NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+1 -3
View File
@@ -1,7 +1,6 @@
<?php namespace RVR\Cli; <?php namespace RVR\Cli;
use DateTime; use DateTime;
use SokoWeb\PersistentData\PersistentDataManager;
use RVR\PersistentData\Model\OAuthClient; use RVR\PersistentData\Model\OAuthClient;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
@@ -33,8 +32,7 @@ class AddOAuthClientCommand extends Command
} }
try { try {
$pdm = new PersistentDataManager(); \Container::$persistentDataManager->saveToDb($oAuthClient);
$pdm->saveToDb($oAuthClient);
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln('<error>Adding OAuth client failed!</error>'); $output->writeln('<error>Adding OAuth client failed!</error>');
$output->writeln(''); $output->writeln('');
+1 -3
View File
@@ -1,6 +1,5 @@
<?php namespace RVR\Cli; <?php namespace RVR\Cli;
use SokoWeb\PersistentData\PersistentDataManager;
use RVR\Repository\OAuthClientRepository; use RVR\Repository\OAuthClientRepository;
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 AddOAuthRedirectUriCommand extends Command
$oAuthClient->setRedirectUrisArray($redirectUris); $oAuthClient->setRedirectUrisArray($redirectUris);
try { try {
$pdm = new PersistentDataManager(); \Container::$persistentDataManager->saveToDb($oAuthClient);
$pdm->saveToDb($oAuthClient);
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln('<error>Adding redirect URI failed!</error>'); $output->writeln('<error>Adding redirect URI failed!</error>');
$output->writeln(''); $output->writeln('');
+1 -3
View File
@@ -1,7 +1,6 @@
<?php namespace RVR\Cli; <?php namespace RVR\Cli;
use DateTime; use DateTime;
use SokoWeb\PersistentData\PersistentDataManager;
use RVR\PersistentData\Model\User; use RVR\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;
@@ -36,8 +35,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('');
+1 -5
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 RVR\Repository\UserPasswordResetterRepository; use RVR\Repository\UserPasswordResetterRepository;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -12,15 +11,12 @@ use Symfony\Component\Console\Output\OutputInterface;
class MaintainDatabaseCommand extends Command class MaintainDatabaseCommand extends Command
{ {
private PersistentDataManager $pdm;
private UserPasswordResetterRepository $userPasswordResetterRepository; private UserPasswordResetterRepository $userPasswordResetterRepository;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->pdm = new PersistentDataManager();
$this->userPasswordResetterRepository = new UserPasswordResetterRepository(); $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
} }
@@ -54,7 +50,7 @@ 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);
} }
} }
+1 -3
View File
@@ -1,6 +1,5 @@
<?php namespace RVR\Cli; <?php namespace RVR\Cli;
use SokoWeb\PersistentData\PersistentDataManager;
use RVR\Repository\OAuthClientRepository; use RVR\Repository\OAuthClientRepository;
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 RemoveOAuthRedirectUriCommand extends Command
$oAuthClient->setRedirectUrisArray($redirectUris); $oAuthClient->setRedirectUrisArray($redirectUris);
try { try {
$pdm = new PersistentDataManager(); \Container::$persistentDataManager->saveToDb($oAuthClient);
$pdm->saveToDb($oAuthClient);
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln('<error>Removing redirect URI failed!</error>'); $output->writeln('<error>Removing redirect URI failed!</error>');
$output->writeln(''); $output->writeln('');
+23 -31
View File
@@ -8,28 +8,20 @@ use RVR\Repository\CommunityRepository;
use RVR\Repository\CommunityMemberRepository; use RVR\Repository\CommunityMemberRepository;
use RVR\Repository\UserRepository; use RVR\Repository\UserRepository;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\PersistentData\PersistentDataManager;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
class CommunityController implements IAuthenticationRequired class CommunityController implements IAuthenticationRequired
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private UserRepository $userRepository; private UserRepository $userRepository;
private CommunityRepository $communityRepository; private CommunityRepository $communityRepository;
private CommunityMemberRepository $communityMemberRepository; private CommunityMemberRepository $communityMemberRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
$this->communityRepository = new CommunityRepository(); $this->communityRepository = new CommunityRepository();
$this->communityMemberRepository = new CommunityMemberRepository(); $this->communityMemberRepository = new CommunityMemberRepository();
@@ -42,7 +34,7 @@ class CommunityController implements IAuthenticationRequired
public function getCommunityHome(): ?IContent public function getCommunityHome(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), false, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), false, $community, $ownCommunityMember)) {
return null; return null;
} }
@@ -62,7 +54,7 @@ class CommunityController implements IAuthenticationRequired
public function getCommunityEdit(): ?IContent public function getCommunityEdit(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
return null; return null;
} }
@@ -73,7 +65,7 @@ class CommunityController implements IAuthenticationRequired
public function getMembersEdit(): ?IContent public function getMembersEdit(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
return null; return null;
} }
@@ -95,60 +87,60 @@ class CommunityController implements IAuthenticationRequired
public function newMember(): ?IContent public function newMember(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
return null; return null;
} }
$user = $this->userRepository->getById($this->request->post('user_id')); $user = $this->userRepository->getById(\Container::$request->post('user_id'));
$communityMember = new CommunityMember(); $communityMember = new CommunityMember();
$communityMember->setCommunity($community); $communityMember->setCommunity($community);
$communityMember->setUser($user); $communityMember->setUser($user);
$this->pdm->saveToDb($communityMember); \Container::$persistentDataManager->saveToDb($communityMember);
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function editMember(): ?IContent public function editMember(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
return null; return null;
} }
$communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id')); $communityMember = $this->communityMemberRepository->getById(\Container::$request->post('community_member_id'));
if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) { if ($communityMember->getUserId() === \Container::$request->user()->getUniqueId()) {
return new JsonContent([ return new JsonContent([
'error' => ['errorText' => 'Own user cannot be edited.'] 'error' => ['errorText' => 'Own user cannot be edited.']
]); ]);
} }
$communityMember->setOwner($this->request->post('owner')); $communityMember->setOwner(\Container::$request->post('owner'));
$this->pdm->saveToDb($communityMember); \Container::$persistentDataManager->saveToDb($communityMember);
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function deleteMember(): ?IContent public function deleteMember(): ?IContent
{ {
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
return null; return null;
} }
$communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id')); $communityMember = $this->communityMemberRepository->getById(\Container::$request->post('community_member_id'));
if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) { if ($communityMember->getUserId() === \Container::$request->user()->getUniqueId()) {
return new JsonContent([ return new JsonContent([
'error' => ['errorText' => 'Own user cannot be deleted.'] 'error' => ['errorText' => 'Own user cannot be deleted.']
]); ]);
} }
$this->pdm->deleteFromDb($communityMember); \Container::$persistentDataManager->deleteFromDb($communityMember);
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
public function saveCommunity(): ?IContent public function saveCommunity(): ?IContent
{ {
$communityId = $this->request->query('communityId'); $communityId = \Container::$request->query('communityId');
if ($communityId){ if ($communityId){
if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) { if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) {
return null; return null;
@@ -157,8 +149,8 @@ class CommunityController implements IAuthenticationRequired
$community = new Community(); $community = new Community();
} }
$name = $this->request->post('name'); $name = \Container::$request->post('name');
$currency = $this->request->post('currency'); $currency = \Container::$request->post('currency');
if (strlen($name) === 0 || strlen($currency) === 0 || strlen($currency) > 3) { if (strlen($name) === 0 || strlen($currency) === 0 || strlen($currency) > 3) {
return new JsonContent([ return new JsonContent([
'error' => ['errorText' => 'Please fill all required fields!'] 'error' => ['errorText' => 'Please fill all required fields!']
@@ -170,19 +162,19 @@ class CommunityController implements IAuthenticationRequired
if (!$communityId) { if (!$communityId) {
$community->setCreatedDate(new DateTime()); $community->setCreatedDate(new DateTime());
} }
$this->pdm->saveToDb($community); \Container::$persistentDataManager->saveToDb($community);
if (!$communityId) { if (!$communityId) {
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
$communityMember = new CommunityMember(); $communityMember = new CommunityMember();
$communityMember->setCommunity($community); $communityMember->setCommunity($community);
$communityMember->setUser($user); $communityMember->setUser($user);
$communityMember->setOwner(true); $communityMember->setOwner(true);
$this->pdm->saveToDb($communityMember); \Container::$persistentDataManager->saveToDb($communityMember);
} }
return new JsonContent([ return new JsonContent([
@@ -204,7 +196,7 @@ class CommunityController implements IAuthenticationRequired
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
$ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($community, $user); $ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($community, $user);
if ($ownCommunityMember === null || ($needToBeOwner && !$ownCommunityMember->getOwner())) { if ($ownCommunityMember === null || ($needToBeOwner && !$ownCommunityMember->getOwner())) {
+2 -6
View File
@@ -3,19 +3,15 @@
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use RVR\Repository\CommunityMemberRepository; use RVR\Repository\CommunityMemberRepository;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
class HomeController implements IAuthenticationRequired class HomeController implements IAuthenticationRequired
{ {
private IRequest $request;
private CommunityMemberRepository $communityMemberRepository; private CommunityMemberRepository $communityMemberRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->communityMemberRepository = new CommunityMemberRepository(); $this->communityMemberRepository = new CommunityMemberRepository();
} }
@@ -29,7 +25,7 @@ class HomeController implements IAuthenticationRequired
/** /**
* @var User $user * @var User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
$ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true); $ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true);
$communities = []; $communities = [];
+39 -55
View File
@@ -2,13 +2,11 @@
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;
use SokoWeb\OAuth\GoogleOAuth; use SokoWeb\OAuth\GoogleOAuth;
use RVR\PersistentData\Model\UserPasswordResetter; use RVR\PersistentData\Model\UserPasswordResetter;
use SokoWeb\PersistentData\PersistentDataManager;
use RVR\Repository\UserPasswordResetterRepository; use RVR\Repository\UserPasswordResetterRepository;
use RVR\Repository\UserRepository; use RVR\Repository\UserRepository;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
@@ -19,30 +17,24 @@ use SokoWeb\Util\JwtParser;
class LoginController class LoginController
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private UserRepository $userRepository; private UserRepository $userRepository;
private UserPasswordResetterRepository $userPasswordResetterRepository; private UserPasswordResetterRepository $userPasswordResetterRepository;
private string $redirectUrl; private string $redirectUrl;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
$this->userPasswordResetterRepository = new UserPasswordResetterRepository(); $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
$this->redirectUrl = $this->request->session()->has('redirect_after_login') ? $this->redirectUrl = \Container::$request->session()->has('redirect_after_login') ?
$this->request->session()->get('redirect_after_login') : \Container::$request->session()->get('redirect_after_login') :
\Container::$routeCollection->getRoute('home')->generateLink(); \Container::$routeCollection->getRoute('home')->generateLink();
} }
public function getLoginForm() public function getLoginForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY); return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
} }
@@ -55,13 +47,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
); );
@@ -70,12 +62,12 @@ class LoginController
public function getRequestPasswordResetForm() public function getRequestPasswordResetForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY); 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
@@ -85,12 +77,12 @@ class LoginController
public function getResetPasswordForm() public function getResetPasswordForm()
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY); 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()) {
@@ -104,22 +96,22 @@ class LoginController
public function login(): IContent public function login(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }
$user = $this->userRepository->getByEmailOrUsername($this->request->post('email')); $user = $this->userRepository->getByEmailOrUsername(\Container::$request->post('email'));
if ($user === null || !$user->checkPassword($this->request->post('password'))) { if ($user === null || !$user->checkPassword(\Container::$request->post('password'))) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
'errorText' => 'No user found with the given email address / username or the given password is wrong. You can <a href="' . 'errorText' => 'No user found with the given email address / username or the given password is wrong. You can <a href="' .
\Container::$routeCollection->getRoute('password-requestReset')->generateLink(['email' => $this->request->post('email')]) . '" title="Request password reset">request password reset</a>!' \Container::$routeCollection->getRoute('password-requestReset')->generateLink(['email' => \Container::$request->post('email')]) . '" title="Request password reset">request password reset</a>!'
] ]
]); ]);
} }
$this->request->setUser($user); \Container::$request->setUser($user);
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
@@ -129,19 +121,19 @@ class LoginController
{ {
$defaultError = 'Authentication with Google failed. Please <a href="' . \Container::$routeCollection->getRoute('login-google')->generateLink() . '" title="Login with Google">try again</a>!'; $defaultError = 'Authentication with Google failed. Please <a href="' . \Container::$routeCollection->getRoute('login-google')->generateLink() . '" title="Login with Google">try again</a>!';
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY); 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_error', ['error' => $defaultError]); return new HtmlContent('login/google_login_error', ['error' => $defaultError]);
} }
$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'])) {
@@ -151,7 +143,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_error', ['error' => $defaultError]); return new HtmlContent('login/google_login_error', ['error' => $defaultError]);
} }
@@ -164,7 +156,7 @@ class LoginController
return new HtmlContent('login/google_login_error', ['error' => 'No user found for this Google account.']); return new HtmlContent('login/google_login_error', ['error' => 'No user found for this Google account.']);
} }
$this->request->setUser($user); \Container::$request->setUser($user);
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY); return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
@@ -172,14 +164,14 @@ class LoginController
public function logout(): IRedirect public function logout(): IRedirect
{ {
$this->request->setUser(null); \Container::$request->setUser(null);
return new Redirect(\Container::$routeCollection->getRoute('home')->generateLink(), IRedirect::TEMPORARY); return new Redirect(\Container::$routeCollection->getRoute('home')->generateLink(), IRedirect::TEMPORARY);
} }
public function requestPasswordReset(): IContent public function requestPasswordReset(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
@@ -189,18 +181,18 @@ 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!']]);
} }
} }
$user = $this->userRepository->getByEmailOrUsername($this->request->post('email')); $user = $this->userRepository->getByEmailOrUsername(\Container::$request->post('email'));
if ($user === null) { if ($user === null) {
return new JsonContent([ return new JsonContent([
'error' => [ 'error' => [
@@ -226,15 +218,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);
@@ -243,7 +231,7 @@ class LoginController
public function resetPassword(): IContent public function resetPassword(): IContent
{ {
if ($this->request->user() !== null) { if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl(); $this->deleteRedirectUrl();
return new JsonContent([ return new JsonContent([
'redirect' => [ 'redirect' => [
@@ -252,7 +240,7 @@ class LoginController
]); ]);
} }
$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()) {
@@ -263,7 +251,7 @@ class LoginController
]); ]);
} }
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!'
@@ -271,22 +259,18 @@ 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(); $this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
@@ -299,7 +283,7 @@ 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')
]); ]);
@@ -308,6 +292,6 @@ class LoginController
private function deleteRedirectUrl(): void private function deleteRedirectUrl(): void
{ {
$this->request->session()->delete('redirect_after_login'); \Container::$request->session()->delete('redirect_after_login');
} }
} }
+8 -16
View File
@@ -5,24 +5,16 @@ use RVR\PersistentData\Model\OAuthToken;
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use RVR\Repository\OAuthClientRepository; use RVR\Repository\OAuthClientRepository;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IRedirect; use SokoWeb\Interfaces\Response\IRedirect;
use SokoWeb\Response\Redirect; use SokoWeb\Response\Redirect;
use SokoWeb\PersistentData\PersistentDataManager;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
class OAuthAuthController implements IAuthenticationRequired class OAuthAuthController implements IAuthenticationRequired
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private OAuthClientRepository $oAuthClientRepository; private OAuthClientRepository $oAuthClientRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->oAuthClientRepository = new OAuthClientRepository(); $this->oAuthClientRepository = new OAuthClientRepository();
} }
@@ -33,11 +25,11 @@ class OAuthAuthController implements IAuthenticationRequired
public function auth() public function auth()
{ {
$redirectUri = $this->request->query('redirect_uri'); $redirectUri = \Container::$request->query('redirect_uri');
$clientId = $this->request->query('client_id'); $clientId = \Container::$request->query('client_id');
$scope = $this->request->query('scope') ? $this->request->query('scope'): ''; $scope = \Container::$request->query('scope') ? \Container::$request->query('scope'): '';
$state = $this->request->query('state'); $state = \Container::$request->query('state');
$nonce = $this->request->query('nonce') ? $this->request->query('nonce'): ''; $nonce = \Container::$request->query('nonce') ? \Container::$request->query('nonce'): '';
if (!$clientId || !$redirectUri || !$state) { if (!$clientId || !$redirectUri || !$state) {
return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']); return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
@@ -62,7 +54,7 @@ class OAuthAuthController implements IAuthenticationRequired
/** /**
* @var ?User $user * @var ?User $user
*/ */
$user = $this->request->user(); $user = \Container::$request->user();
$code = bin2hex(random_bytes(16)); $code = bin2hex(random_bytes(16));
$accessToken = bin2hex(random_bytes(16)); $accessToken = bin2hex(random_bytes(16));
@@ -74,7 +66,7 @@ class OAuthAuthController implements IAuthenticationRequired
$token->setAccessToken($accessToken); $token->setAccessToken($accessToken);
$token->setCreatedDate(new DateTime()); $token->setCreatedDate(new DateTime());
$token->setExpiresDate(new DateTime('+5 minutes')); $token->setExpiresDate(new DateTime('+5 minutes'));
$this->pdm->saveToDb($token); \Container::$persistentDataManager->saveToDb($token);
$redirectUriQuery = array_merge($redirectUriQuery, [ $redirectUriQuery = array_merge($redirectUriQuery, [
'state' => $state, 'state' => $state,
+9 -13
View File
@@ -6,23 +6,19 @@ use RVR\Repository\OAuthTokenRepository;
use RVR\Repository\UserRepository; use RVR\Repository\UserRepository;
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use RVR\Repository\OAuthClientRepository; use RVR\Repository\OAuthClientRepository;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
class OAuthController class OAuthController
{ {
private IRequest $request;
private OAuthClientRepository $oAuthClientRepository; private OAuthClientRepository $oAuthClientRepository;
private OAuthTokenRepository $oAuthTokenRepository; private OAuthTokenRepository $oAuthTokenRepository;
private UserRepository $userRepository; private UserRepository $userRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->oAuthClientRepository = new OAuthClientRepository(); $this->oAuthClientRepository = new OAuthClientRepository();
$this->oAuthTokenRepository = new OAuthTokenRepository(); $this->oAuthTokenRepository = new OAuthTokenRepository();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
@@ -30,9 +26,9 @@ class OAuthController
public function getToken(): ?IContent public function getToken(): ?IContent
{ {
$clientId = $this->request->post('client_id'); $clientId = \Container::$request->post('client_id');
$clientSecret = $this->request->post('client_secret'); $clientSecret = \Container::$request->post('client_secret');
$code = $this->request->post('code'); $code = \Container::$request->post('code');
if (!$clientId || !$clientSecret || !$code) { if (!$clientId || !$clientSecret || !$code) {
return new JsonContent([ return new JsonContent([
@@ -80,7 +76,7 @@ class OAuthController
public function getUserInfo() : IContent public function getUserInfo() : IContent
{ {
$authorization = $this->request->header('Authorization'); $authorization = \Container::$request->header('Authorization');
if ($authorization === null) { if ($authorization === null) {
return new JsonContent([ return new JsonContent([
'error' => 'No Authorization header was sent.' 'error' => 'No Authorization header was sent.'
@@ -108,10 +104,10 @@ class OAuthController
{ {
return new JsonContent([ return new JsonContent([
'issuer' => $_ENV['APP_URL'], 'issuer' => $_ENV['APP_URL'],
'authorization_endpoint' => $this->request->getBase() . \Container::$routeCollection->getRoute('oauth-auth')->generateLink(), 'authorization_endpoint' => \Container::$request->getBase() . \Container::$routeCollection->getRoute('oauth-auth')->generateLink(),
'token_endpoint' => $this->request->getBase() . \Container::$routeCollection->getRoute('oauth-token')->generateLink(), 'token_endpoint' => \Container::$request->getBase() . \Container::$routeCollection->getRoute('oauth-token')->generateLink(),
'userinfo_endpoint' => $this->request->getBase() . \Container::$routeCollection->getRoute('oauth-userinfo')->generateLink(), 'userinfo_endpoint' => \Container::$request->getBase() . \Container::$routeCollection->getRoute('oauth-userinfo')->generateLink(),
'jwks_uri' => $this->request->getBase() . \Container::$routeCollection->getRoute('oauth-certs')->generateLink(), 'jwks_uri' => \Container::$request->getBase() . \Container::$routeCollection->getRoute('oauth-certs')->generateLink(),
'response_types_supported' => 'response_types_supported' =>
[ [
'code', 'code',
+24 -32
View File
@@ -3,11 +3,9 @@
use DateTime; use DateTime;
use SokoWeb\Http\Request; use SokoWeb\Http\Request;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; 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 RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
@@ -17,16 +15,10 @@ use RVR\Repository\UserRepository;
class UserController implements IAuthenticationRequired class UserController implements IAuthenticationRequired
{ {
private IRequest $request;
private PersistentDataManager $pdm;
private UserRepository $userRepository; private UserRepository $userRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
} }
@@ -40,7 +32,7 @@ class UserController implements IAuthenticationRequired
/** /**
* @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()]);
} }
@@ -50,19 +42,19 @@ class UserController implements IAuthenticationRequired
/** /**
* @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()
); );
@@ -75,16 +67,16 @@ class UserController implements IAuthenticationRequired
/** /**
* @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'])) {
@@ -94,7 +86,7 @@ class UserController implements IAuthenticationRequired
$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]);
} }
@@ -106,7 +98,7 @@ class UserController implements IAuthenticationRequired
} }
$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,
@@ -119,18 +111,18 @@ class UserController implements IAuthenticationRequired
/** /**
* @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]]);
} }
$newEmail = $this->request->post('email'); $newEmail = \Container::$request->post('email');
if ($newEmail !== $user->getEmail()) { if ($newEmail !== $user->getEmail()) {
if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) { if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) {
return new JsonContent(['error' => ['errorText' => 'Please provide a valid email address.']]); return new JsonContent(['error' => ['errorText' => 'Please provide a valid email address.']]);
@@ -143,7 +135,7 @@ class UserController implements IAuthenticationRequired
$user->setEmail($newEmail); $user->setEmail($newEmail);
} }
$newUsername = $this->request->post('username'); $newUsername = \Container::$request->post('username');
if ($newUsername !== $user->getUsername()) { if ($newUsername !== $user->getUsername()) {
if (strlen($newUsername) > 0) { if (strlen($newUsername) > 0) {
if (filter_var($newUsername, FILTER_VALIDATE_EMAIL)) { if (filter_var($newUsername, FILTER_VALIDATE_EMAIL)) {
@@ -160,7 +152,7 @@ class UserController implements IAuthenticationRequired
} }
} }
$newPassword = $this->request->post('password_new'); $newPassword = \Container::$request->post('password_new');
if (strlen($newPassword) > 0) { if (strlen($newPassword) > 0) {
if (strlen($newPassword) < 6) { if (strlen($newPassword) < 6) {
return new JsonContent([ return new JsonContent([
@@ -170,7 +162,7 @@ class UserController implements IAuthenticationRequired
]); ]);
} }
if ($newPassword !== $this->request->post('password_new_confirm')) { if ($newPassword !== \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.'
@@ -181,13 +173,13 @@ class UserController implements IAuthenticationRequired
$user->setPlainPassword($newPassword); $user->setPlainPassword($newPassword);
} }
$user->setNickname($this->request->post('nickname')); $user->setNickname(\Container::$request->post('nickname'));
$user->setPhone($this->request->post('phone')); $user->setPhone(\Container::$request->post('phone'));
$user->setIdNumber($this->request->post('id_number')); $user->setIdNumber(\Container::$request->post('id_number'));
$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]);
} }
+2 -6
View File
@@ -2,19 +2,15 @@
use RVR\Repository\UserRepository; use RVR\Repository\UserRepository;
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired; use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent; use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
class UserSearchController implements IAuthenticationRequired class UserSearchController implements IAuthenticationRequired
{ {
private IRequest $request;
private UserRepository $userRepository; private UserRepository $userRepository;
public function __construct(IRequest $request) public function __construct()
{ {
$this->request = $request;
$this->userRepository = new UserRepository(); $this->userRepository = new UserRepository();
} }
@@ -25,7 +21,7 @@ class UserSearchController implements IAuthenticationRequired
public function searchUser(): IContent public function searchUser(): IContent
{ {
$users = iterator_to_array($this->userRepository->searchByName($this->request->query('q'))); $users = iterator_to_array($this->userRepository->searchByName(\Container::$request->query('q')));
usort($users, function($a, $b) { usort($users, function($a, $b) {
return strnatcmp($a->getDisplayName(), $b->getDisplayName()); return strnatcmp($a->getDisplayName(), $b->getDisplayName());
}); });
+15
View File
@@ -0,0 +1,15 @@
<?php namespace RVR\Database;
use SokoWeb\Database\AuditLoggerBase;
class AuditLogger extends AuditLoggerBase
{
protected function getModifierId()
{
$user = \Container::$request->user();
if ($user === null) {
return null;
}
return $user->getUniqueId();
}
}
+4 -12
View File
@@ -5,20 +5,12 @@ use RVR\PersistentData\Model\Community;
use RVR\PersistentData\Model\CommunityMember; use RVR\PersistentData\Model\CommunityMember;
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use SokoWeb\PersistentData\PersistentDataManager;
class CommunityMemberRepository class CommunityMemberRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?CommunityMember public function getById(int $id): ?CommunityMember
{ {
return $this->pdm->selectFromDbById($id, CommunityMember::class); return \Container::$persistentDataManager->selectFromDbById($id, CommunityMember::class);
} }
public function getAllByCommunity(Community $community, bool $useRelations = false): Generator public function getAllByCommunity(Community $community, bool $useRelations = false): Generator
@@ -26,7 +18,7 @@ class CommunityMemberRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('community_id', '=', $community->getId()); $select->where('community_id', '=', $community->getId());
yield from $this->pdm->selectMultipleFromDb($select, CommunityMember::class, $useRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations);
} }
public function getAllByUser(User $user, bool $useRelations = false): Generator public function getAllByUser(User $user, bool $useRelations = false): Generator
@@ -34,7 +26,7 @@ class CommunityMemberRepository
$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, CommunityMember::class, $useRelations); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations);
} }
public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember
@@ -43,6 +35,6 @@ class CommunityMemberRepository
$select->where('community_id', '=', $community->getId()); $select->where('community_id', '=', $community->getId());
$select->where('user_id', '=', $user->getId()); $select->where('user_id', '=', $user->getId());
return $this->pdm->selectFromDb($select, CommunityMember::class); return \Container::$persistentDataManager->selectFromDb($select, CommunityMember::class);
} }
} }
+1 -9
View File
@@ -1,19 +1,11 @@
<?php namespace RVR\Repository; <?php namespace RVR\Repository;
use RVR\PersistentData\Model\Community; use RVR\PersistentData\Model\Community;
use SokoWeb\PersistentData\PersistentDataManager;
class CommunityRepository class CommunityRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?Community public function getById(int $id): ?Community
{ {
return $this->pdm->selectFromDbById($id, Community::class); return \Container::$persistentDataManager->selectFromDbById($id, Community::class);
} }
} }
+2 -10
View File
@@ -2,20 +2,12 @@
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use RVR\PersistentData\Model\OAuthClient; use RVR\PersistentData\Model\OAuthClient;
use SokoWeb\PersistentData\PersistentDataManager;
class OAuthClientRepository class OAuthClientRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?OAuthClient public function getById(int $id): ?OAuthClient
{ {
return $this->pdm->selectFromDbById($id, OAuthClient::class); return \Container::$persistentDataManager->selectFromDbById($id, OAuthClient::class);
} }
public function getByClientId(string $clientId): ?OAuthClient public function getByClientId(string $clientId): ?OAuthClient
@@ -23,6 +15,6 @@ class OAuthClientRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('client_id', '=', $clientId); $select->where('client_id', '=', $clientId);
return $this->pdm->selectFromDb($select, OAuthClient::class); return \Container::$persistentDataManager->selectFromDb($select, OAuthClient::class);
} }
} }
+4 -12
View File
@@ -4,20 +4,12 @@ use DateTime;
use Generator; use Generator;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use RVR\PersistentData\Model\OAuthToken; use RVR\PersistentData\Model\OAuthToken;
use SokoWeb\PersistentData\PersistentDataManager;
class OAuthTokenRepository class OAuthTokenRepository
{ {
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?OAuthToken public function getById(int $id): ?OAuthToken
{ {
return $this->pdm->selectFromDbById($id, OAuthToken::class); return \Container::$persistentDataManager->selectFromDbById($id, OAuthToken::class);
} }
public function getByCode(string $code): ?OAuthToken public function getByCode(string $code): ?OAuthToken
@@ -25,7 +17,7 @@ class OAuthTokenRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('code', '=', $code); $select->where('code', '=', $code);
return $this->pdm->selectFromDb($select, OAuthToken::class); return \Container::$persistentDataManager->selectFromDb($select, OAuthToken::class);
} }
public function getByAccessToken(string $accessToken): ?OAuthToken public function getByAccessToken(string $accessToken): ?OAuthToken
@@ -33,7 +25,7 @@ class OAuthTokenRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('access_token', '=', $accessToken); $select->where('access_token', '=', $accessToken);
return $this->pdm->selectFromDb($select, OAuthToken::class); return \Container::$persistentDataManager->selectFromDb($select, OAuthToken::class);
} }
public function getAllExpired(): Generator public function getAllExpired(): Generator
@@ -41,6 +33,6 @@ class OAuthTokenRepository
$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, OAuthToken::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, OAuthToken::class);
} }
} }
@@ -5,20 +5,12 @@ use Generator;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use RVR\PersistentData\Model\User; use RVR\PersistentData\Model\User;
use RVR\PersistentData\Model\UserPasswordResetter; use RVR\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);
} }
} }
+5 -13
View File
@@ -4,20 +4,12 @@ use Generator;
use SokoWeb\Interfaces\Repository\IUserRepository; use SokoWeb\Interfaces\Repository\IUserRepository;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use RVR\PersistentData\Model\User; use RVR\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
@@ -25,7 +17,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 getByUsername(string $username): ?User public function getByUsername(string $username): ?User
@@ -33,7 +25,7 @@ class UserRepository implements IUserRepository
$select = new Select(\Container::$dbConnection); $select = new Select(\Container::$dbConnection);
$select->where('username', '=', $username); $select->where('username', '=', $username);
return $this->pdm->selectFromDb($select, User::class); return \Container::$persistentDataManager->selectFromDb($select, User::class);
} }
public function getByEmailOrUsername(string $emailOrUsername): ?User public function getByEmailOrUsername(string $emailOrUsername): ?User
@@ -50,7 +42,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 searchByName(string $name): Generator public function searchByName(string $name): Generator
@@ -60,6 +52,6 @@ class UserRepository implements IUserRepository
$select->orWhere('nickname', 'LIKE', '%' . $name . '%'); $select->orWhere('nickname', 'LIKE', '%' . $name . '%');
$select->limit(10); $select->limit(10);
yield from $this->pdm->selectMultipleFromDb($select, User::class); yield from \Container::$persistentDataManager->selectMultipleFromDb($select, User::class);
} }
} }
+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('home')->generateLink() ?>" title="<?= $_ENV['APP_NAME'] ?>">Back to start.</a></p>
<?php if (isset($exceptionToPrint)): ?>
<pre class="marginTop">
<?= $exceptionToPrint ?>
</pre>
<?php endif; ?>
@endsection
+4 -2
View File
@@ -69,7 +69,7 @@ Container::$routeCollection->group('communities', function (RouteCollection $rou
}); });
}); });
Container::$sessionHandler = new DatabaseSessionHandler(); Container::$sessionHandler = new DatabaseSessionHandler(Container::$dbConnection);
session_set_save_handler(Container::$sessionHandler, true); session_set_save_handler(Container::$sessionHandler, true);
session_start([ session_start([
@@ -108,11 +108,13 @@ $appConfig = [
'antiCsrfTokenErrorResponse' => ['error' => 'no_valid_anti_csrf_token'], 'antiCsrfTokenErrorResponse' => ['error' => 'no_valid_anti_csrf_token'],
'antiCsrfTokenExceptions' => ['/oauth/token'], 'antiCsrfTokenExceptions' => ['/oauth/token'],
'loginRouteId' => 'login', 'loginRouteId' => 'login',
'error404View' => 'error/404' 'error404View' => 'error/404',
'error500View' => 'error/500'
]; ];
$httpReponse = new HttpResponse( $httpReponse = new HttpResponse(
Container::$request, Container::$request,
Container::$dbConnection,
Container::$routeCollection, Container::$routeCollection,
$appConfig, $appConfig,
$_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_METHOD'],