feature/RVRNEXT-2-implement-login-to-old-rvr #6
@ -19,3 +19,5 @@ GOOGLE_OAUTH_CLIENT_SECRET=your_google_oauth_client_secret
 | 
			
		||||
GOOGLE_ANALITICS_ID=your_google_analytics_id
 | 
			
		||||
RECAPTCHA_SITEKEY=your_recaptcha_sitekey
 | 
			
		||||
RECAPTCHA_SECRET=your_recaptcha_secret
 | 
			
		||||
JWT_RSA_PRIVATE_KEY=jwt-rsa256-private.pem
 | 
			
		||||
JWT_RSA_PUBLIC_KEY=jwt-rsa256-public.pem
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -2,3 +2,4 @@
 | 
			
		||||
installed
 | 
			
		||||
vendor
 | 
			
		||||
node_modules
 | 
			
		||||
*.pem
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,8 @@
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "require": {
 | 
			
		||||
    "esoko/soko-web": "0.1"
 | 
			
		||||
    "esoko/soko-web": "0.1",
 | 
			
		||||
    "firebase/php-jwt": "^6.4"
 | 
			
		||||
  },
 | 
			
		||||
  "require-dev": {
 | 
			
		||||
    "phpunit/phpunit": "^9.6",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										65
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@ -4,7 +4,7 @@
 | 
			
		||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
			
		||||
        "This file is @generated automatically"
 | 
			
		||||
    ],
 | 
			
		||||
    "content-hash": "3479948070678fa4e980114fbe8b71b5",
 | 
			
		||||
    "content-hash": "f2dcf297a4a619bc5edfe7b4fac0836e",
 | 
			
		||||
    "packages": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "esoko/soko-web",
 | 
			
		||||
@ -35,6 +35,69 @@
 | 
			
		||||
            "description": "Lightweight web framework",
 | 
			
		||||
            "time": "2023-04-07T17:32:15+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "firebase/php-jwt",
 | 
			
		||||
            "version": "v6.4.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/firebase/php-jwt.git",
 | 
			
		||||
                "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/firebase/php-jwt/zipball/4dd1e007f22a927ac77da5a3fbb067b42d3bc224",
 | 
			
		||||
                "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": "^7.1||^8.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "guzzlehttp/guzzle": "^6.5||^7.4",
 | 
			
		||||
                "phpspec/prophecy-phpunit": "^1.1",
 | 
			
		||||
                "phpunit/phpunit": "^7.5||^9.5",
 | 
			
		||||
                "psr/cache": "^1.0||^2.0",
 | 
			
		||||
                "psr/http-client": "^1.0",
 | 
			
		||||
                "psr/http-factory": "^1.0"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-sodium": "Support EdDSA (Ed25519) signatures",
 | 
			
		||||
                "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Firebase\\JWT\\": "src"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "BSD-3-Clause"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Neuman Vong",
 | 
			
		||||
                    "email": "neuman+pear@twilio.com",
 | 
			
		||||
                    "role": "Developer"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Anant Narayanan",
 | 
			
		||||
                    "email": "anant@php.net",
 | 
			
		||||
                    "role": "Developer"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
 | 
			
		||||
            "homepage": "https://github.com/firebase/php-jwt",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "jwt",
 | 
			
		||||
                "php"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/firebase/php-jwt/issues",
 | 
			
		||||
                "source": "https://github.com/firebase/php-jwt/tree/v6.4.0"
 | 
			
		||||
            },
 | 
			
		||||
            "time": "2023-02-09T21:01:23+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "graham-campbell/result-type",
 | 
			
		||||
            "version": "v1.1.1",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								database/migrations/structure/20230408_1129_oauth.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								database/migrations/structure/20230408_1129_oauth.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
CREATE TABLE `oauth_tokens` (
 | 
			
		||||
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 | 
			
		||||
  `nonce` varchar(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
 | 
			
		||||
  `user_id` int(10) unsigned DEFAULT NULL,
 | 
			
		||||
  `code` varchar(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
 | 
			
		||||
  `created` timestamp NOT NULL DEFAULT current_timestamp(),
 | 
			
		||||
  `expires` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
 | 
			
		||||
  PRIMARY KEY (`id`),
 | 
			
		||||
  UNIQUE KEY `code` (`code`)
 | 
			
		||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
 | 
			
		||||
@ -27,21 +27,27 @@ class LoginController
 | 
			
		||||
 | 
			
		||||
    private UserPasswordResetterRepository $userPasswordResetterRepository;
 | 
			
		||||
 | 
			
		||||
    private string $redirectUrl;
 | 
			
		||||
 | 
			
		||||
    public function __construct(IRequest $request)
 | 
			
		||||
    {
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
        $this->pdm = new PersistentDataManager();
 | 
			
		||||
        $this->userRepository = new UserRepository();
 | 
			
		||||
        $this->userPasswordResetterRepository = new UserPasswordResetterRepository();
 | 
			
		||||
        $this->redirectUrl = $this->request->session()->has('redirect_after_login') ?
 | 
			
		||||
            $this->request->session()->get('redirect_after_login') :
 | 
			
		||||
            \Container::$routeCollection->getRoute('index')->generateLink();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLoginForm()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->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', ['redirectUrl' => $this->getRedirectUrl()]);
 | 
			
		||||
        return new HtmlContent('login/login', ['redirectUrl' => $this->redirectUrl]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGoogleLoginRedirect(): IRedirect
 | 
			
		||||
@ -65,7 +71,8 @@ class LoginController
 | 
			
		||||
    public function getRequestPasswordResetForm()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->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')]);
 | 
			
		||||
@ -79,7 +86,8 @@ class LoginController
 | 
			
		||||
    public function getResetPasswordForm()
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->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');
 | 
			
		||||
@ -91,7 +99,7 @@ class LoginController
 | 
			
		||||
 | 
			
		||||
        $user = $this->userRepository->getById($resetter->getUserId());
 | 
			
		||||
 | 
			
		||||
        return new HtmlContent('login/reset_password', ['success' => true, 'token' => $token, 'email' => $user->getEmail(), 'redirectUrl' => $this->getRedirectUrl()]);
 | 
			
		||||
        return new HtmlContent('login/reset_password', ['success' => true, 'token' => $token, 'email' => $user->getEmail(), 'redirectUrl' => $this->redirectUrl]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function login(): IContent
 | 
			
		||||
@ -123,7 +131,7 @@ class LoginController
 | 
			
		||||
 | 
			
		||||
        if ($this->request->user() !== null) {
 | 
			
		||||
            $this->deleteRedirectUrl();
 | 
			
		||||
            return new Redirect($this->getRedirectUrl(), IRedirect::TEMPORARY);
 | 
			
		||||
            return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->request->query('state') !== $this->request->session()->get('oauth_state')) {
 | 
			
		||||
@ -159,7 +167,7 @@ class LoginController
 | 
			
		||||
        $this->request->setUser($user);
 | 
			
		||||
 | 
			
		||||
        $this->deleteRedirectUrl();
 | 
			
		||||
        return new Redirect($this->getRedirectUrl(), IRedirect::TEMPORARY);
 | 
			
		||||
        return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function logout(): IRedirect
 | 
			
		||||
@ -175,7 +183,7 @@ class LoginController
 | 
			
		||||
            $this->deleteRedirectUrl();
 | 
			
		||||
            return new JsonContent([
 | 
			
		||||
                'redirect' => [
 | 
			
		||||
                    'target' => $this->getRedirectUrl()
 | 
			
		||||
                    'target' => $this->redirectUrl
 | 
			
		||||
                ]
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
@ -239,7 +247,7 @@ class LoginController
 | 
			
		||||
            $this->deleteRedirectUrl();
 | 
			
		||||
            return new JsonContent([
 | 
			
		||||
                'redirect' => [
 | 
			
		||||
                    'target' => $this->getRedirectUrl()
 | 
			
		||||
                    'target' => $this->redirectUrl
 | 
			
		||||
                ]
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
@ -298,15 +306,6 @@ class LoginController
 | 
			
		||||
        $mail->send();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getRedirectUrl(): string
 | 
			
		||||
    {
 | 
			
		||||
        $redirectUrl = $this->request->session()->get('redirect_after_login');
 | 
			
		||||
        if ($redirectUrl === null) {
 | 
			
		||||
            return \Container::$routeCollection->getRoute('index')->generateLink();
 | 
			
		||||
        }
 | 
			
		||||
        return $redirectUrl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function deleteRedirectUrl(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->request->session()->delete('redirect_after_login');
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										124
									
								
								src/Controller/OAuthLoginController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								src/Controller/OAuthLoginController.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,124 @@
 | 
			
		||||
<?php namespace RVR\Controller;
 | 
			
		||||
 | 
			
		||||
use DateTime;
 | 
			
		||||
use Firebase\JWT\JWT;
 | 
			
		||||
use RVR\PersistentData\Model\OAuthToken;
 | 
			
		||||
use RVR\Repository\OAuthTokenRepository;
 | 
			
		||||
use RVR\Repository\UserRepository;
 | 
			
		||||
use RVR\PersistentData\Model\User;
 | 
			
		||||
use SokoWeb\Interfaces\Request\IRequest;
 | 
			
		||||
use SokoWeb\Interfaces\Response\IContent;
 | 
			
		||||
use SokoWeb\Interfaces\Response\IRedirect;
 | 
			
		||||
use SokoWeb\Response\Redirect;
 | 
			
		||||
use SokoWeb\PersistentData\PersistentDataManager;
 | 
			
		||||
use SokoWeb\Response\HtmlContent;
 | 
			
		||||
use SokoWeb\Response\JsonContent;
 | 
			
		||||
 | 
			
		||||
class OAuthLoginController
 | 
			
		||||
{
 | 
			
		||||
    private IRequest $request;
 | 
			
		||||
 | 
			
		||||
    private PersistentDataManager $pdm;
 | 
			
		||||
 | 
			
		||||
    public function __construct(IRequest $request)
 | 
			
		||||
    {
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
        $this->pdm = new PersistentDataManager();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function startOauth()
 | 
			
		||||
    {
 | 
			
		||||
        $redirectUri = $this->request->query('redirect_uri');
 | 
			
		||||
        $state = $this->request->query('state');
 | 
			
		||||
        $nonce = $this->request->query('nonce');
 | 
			
		||||
 | 
			
		||||
        if (!$redirectUri || !$state) {
 | 
			
		||||
            return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->request->session()->set('oauth_state', [
 | 
			
		||||
            'redirect_uri' => $redirectUri,
 | 
			
		||||
            'state' => $state,
 | 
			
		||||
            'nonce' => $nonce === null ? '' : $nonce
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $this->request->session()->set('redirect_after_login', \Container::$routeCollection->getRoute('oauth-finish')->generateLink());
 | 
			
		||||
 | 
			
		||||
        return new Redirect(\Container::$routeCollection->getRoute('login')->generateLink(), IRedirect::TEMPORARY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function finishOauth()
 | 
			
		||||
    {
 | 
			
		||||
        $oauthState = $this->request->session()->get('oauth_state');
 | 
			
		||||
        if ($oauthState === null) {
 | 
			
		||||
            return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->request->session()->delete('oauth_state');
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @var ?User $user
 | 
			
		||||
         */
 | 
			
		||||
        $user = $this->request->user();
 | 
			
		||||
        if ($user === null) {
 | 
			
		||||
            return new HtmlContent('oauth/oauth_error', ['error' => 'You are not logged in. Please start authentication again.']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $code = bin2hex(random_bytes(16));
 | 
			
		||||
 | 
			
		||||
        $token = new OAuthToken();
 | 
			
		||||
        $token->setNonce($oauthState['nonce']);
 | 
			
		||||
        $token->setUser($user);
 | 
			
		||||
        $token->setCode($code);
 | 
			
		||||
        $token->setCreatedDate(new DateTime());
 | 
			
		||||
        $token->setExpiresDate(new DateTime('+5 minutes'));
 | 
			
		||||
        $this->pdm->saveToDb($token);
 | 
			
		||||
 | 
			
		||||
        $redirectUri = $oauthState['redirect_uri'];
 | 
			
		||||
        $additionalUriParams = [
 | 
			
		||||
            'state' => $oauthState['state'],
 | 
			
		||||
            'code' => $code
 | 
			
		||||
        ];
 | 
			
		||||
        $and = (strpos($redirectUri, '?') !== false) ? '&' : '?';
 | 
			
		||||
        $finalRedirectUri = $redirectUri . $and .  http_build_query($additionalUriParams);
 | 
			
		||||
 | 
			
		||||
        return new Redirect($finalRedirectUri, IRedirect::TEMPORARY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getToken(): ?IContent
 | 
			
		||||
    {
 | 
			
		||||
        $oAuthTokenRepository = new OAuthTokenRepository();
 | 
			
		||||
        $userRepository = new UserRepository();
 | 
			
		||||
        $token = $oAuthTokenRepository->getByCode($this->request->query('code'));
 | 
			
		||||
 | 
			
		||||
        if ($token === null || $token->getExpiresDate() < new DateTime()) {
 | 
			
		||||
            return new JsonContent([
 | 
			
		||||
                'error' => 'The provided code is invalid.'
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $user = $userRepository->getById($token->getUserId());
 | 
			
		||||
 | 
			
		||||
        $payload = [
 | 
			
		||||
            'iss' => $_ENV['APP_URL'],
 | 
			
		||||
            'iat' => (int)$token->getCreatedDate()->format('U'),
 | 
			
		||||
            'nbf' => (int)$token->getCreatedDate()->format('U'),
 | 
			
		||||
            'exp' => (int)$token->getExpiresDate()->format('U'),
 | 
			
		||||
            'nonce' => $token->getNonce(),
 | 
			
		||||
            'sub' => $user->getId(),
 | 
			
		||||
            'email' => $user->getEmail()
 | 
			
		||||
        ];
 | 
			
		||||
        $privateKey = file_get_contents(ROOT . '/' . $_ENV['JWT_RSA_PRIVATE_KEY']);
 | 
			
		||||
        $jwt = JWT::encode($payload, $privateKey, 'RS256');
 | 
			
		||||
 | 
			
		||||
        return new JsonContent([
 | 
			
		||||
            'id_token' => $jwt
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getJwtPublicKey(): IContent
 | 
			
		||||
    {
 | 
			
		||||
        $publicKey = file_get_contents(ROOT . '/' . $_ENV['JWT_RSA_PUBLIC_KEY']);
 | 
			
		||||
        return new JsonContent(['pubkey' => $publicKey]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										105
									
								
								src/PersistentData/Model/OAuthToken.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/PersistentData/Model/OAuthToken.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
<?php namespace RVR\PersistentData\Model;
 | 
			
		||||
 | 
			
		||||
use DateTime;
 | 
			
		||||
use SokoWeb\PersistentData\Model\Model;
 | 
			
		||||
 | 
			
		||||
class OAuthToken extends Model
 | 
			
		||||
{
 | 
			
		||||
    protected static string $table = 'oauth_tokens';
 | 
			
		||||
 | 
			
		||||
    protected static array $fields = ['nonce', 'user_id', 'code', 'created', 'expires'];
 | 
			
		||||
 | 
			
		||||
    protected static array $relations = ['user' => User::class];
 | 
			
		||||
 | 
			
		||||
    private string $nonce = '';
 | 
			
		||||
 | 
			
		||||
    private ?User $user = null;
 | 
			
		||||
 | 
			
		||||
    private ?int $userId = null;
 | 
			
		||||
 | 
			
		||||
    private string $code = '';
 | 
			
		||||
 | 
			
		||||
    private DateTime $created;
 | 
			
		||||
 | 
			
		||||
    private DateTime $expires;
 | 
			
		||||
 | 
			
		||||
    public function setNonce(string $nonce): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->nonce = $nonce;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setUser(User $user): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->user = $user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setUserId(int $userId): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->userId = $userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCode(string $code): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->code = $code;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCreatedDate(DateTime $created): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->created = $created;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setExpiresDate(DateTime $expires): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->expires = $expires;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCreated(string $created): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->created = new DateTime($created);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setExpires(string $expires): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->expires = new DateTime($expires);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getNonce(): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->nonce;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getUser(): ?User
 | 
			
		||||
    {
 | 
			
		||||
        return $this->user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getUserId(): ?int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getCode(): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->code;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getCreatedDate(): DateTime
 | 
			
		||||
    {
 | 
			
		||||
        return $this->created;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getCreated(): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->created->format('Y-m-d H:i:s');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getExpiresDate(): DateTime
 | 
			
		||||
    {
 | 
			
		||||
        return $this->expires;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getExpires(): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->expires->format('Y-m-d H:i:s');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								src/Repository/OAuthTokenRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/Repository/OAuthTokenRepository.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
<?php namespace RVR\Repository;
 | 
			
		||||
 | 
			
		||||
use DateTime;
 | 
			
		||||
use Generator;
 | 
			
		||||
use SokoWeb\Database\Query\Select;
 | 
			
		||||
use RVR\PersistentData\Model\OAuthToken;
 | 
			
		||||
use SokoWeb\PersistentData\PersistentDataManager;
 | 
			
		||||
 | 
			
		||||
class OAuthTokenRepository
 | 
			
		||||
{
 | 
			
		||||
    private PersistentDataManager $pdm;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        $this->pdm = new PersistentDataManager();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getById(int $id): ?OAuthToken
 | 
			
		||||
    {
 | 
			
		||||
        return $this->pdm->selectFromDbById($id, OAuthToken::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getByCode(string $code): ?OAuthToken
 | 
			
		||||
    {
 | 
			
		||||
        $select = new Select(\Container::$dbConnection);
 | 
			
		||||
        $select->where('code', '=', $code);
 | 
			
		||||
 | 
			
		||||
        return $this->pdm->selectFromDb($select, OAuthToken::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllExpired(): Generator
 | 
			
		||||
    {
 | 
			
		||||
        $select = new Select(\Container::$dbConnection);
 | 
			
		||||
        $select->where('expires', '<', (new DateTime())->format('Y-m-d H:i:s'));
 | 
			
		||||
 | 
			
		||||
        yield from $this->pdm->selectMultipleFromDb($select, OAuthToken::class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								views/oauth/oauth_error.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								views/oauth/oauth_error.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
@extends(templates/layout_normal)
 | 
			
		||||
 | 
			
		||||
@section(main)
 | 
			
		||||
    <h2>OAuth error</h2>
 | 
			
		||||
    <div class="box">
 | 
			
		||||
        <p class="error justify"><?= $error ?></p>
 | 
			
		||||
    </div>
 | 
			
		||||
@endsection
 | 
			
		||||
							
								
								
									
										6
									
								
								web.php
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								web.php
									
									
									
									
									
								
							@ -20,6 +20,12 @@ Container::$routeCollection->group('login', function (SokoWeb\Routing\RouteColle
 | 
			
		||||
    $routeCollection->get('login-google', 'google', [RVR\Controller\LoginController::class, 'getGoogleLoginRedirect']);
 | 
			
		||||
    $routeCollection->get('login-google-action', 'google/code', [RVR\Controller\LoginController::class, 'loginWithGoogle']);
 | 
			
		||||
});
 | 
			
		||||
Container::$routeCollection->group('oauth', function (SokoWeb\Routing\RouteCollection $routeCollection) {
 | 
			
		||||
    $routeCollection->get('oauth-start', 'start', [RVR\Controller\OAuthLoginController::class, 'startOauth']);
 | 
			
		||||
    $routeCollection->get('oauth-finish', 'finish', [RVR\Controller\OAuthLoginController::class, 'finishOauth']);
 | 
			
		||||
    $routeCollection->get('oauth-getToken', 'getToken', [RVR\Controller\OAuthLoginController::class, 'getToken']);
 | 
			
		||||
    $routeCollection->get('oauth-getJwtPublicKey', 'getJwtPublicKey', [RVR\Controller\OAuthLoginController::class, 'getJwtPublicKey']);
 | 
			
		||||
});
 | 
			
		||||
Container::$routeCollection->group('password', function (SokoWeb\Routing\RouteCollection $routeCollection) {
 | 
			
		||||
    $routeCollection->get('password-requestReset', 'requestReset', [RVR\Controller\LoginController::class, 'getRequestPasswordResetForm']);
 | 
			
		||||
    $routeCollection->post('password-requestReset-action', 'requestReset', [RVR\Controller\LoginController::class, 'requestPasswordReset']);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user