MAPG-69 merge SignupController to LoginController and introduce Google login/sign up
This commit is contained in:
		
							parent
							
								
									d1c9e221f7
								
							
						
					
					
						commit
						9697163457
					
				
							
								
								
									
										9
									
								
								mail/signup-noconfirm.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								mail/signup-noconfirm.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					Hi,
 | 
				
			||||||
 | 
					<br><br>
 | 
				
			||||||
 | 
					You recently signed up on MapGuesser with this Google account ({{EMAIL}}).
 | 
				
			||||||
 | 
					<br><br>
 | 
				
			||||||
 | 
					Have fun on MapGuesser!
 | 
				
			||||||
 | 
					<br><br>
 | 
				
			||||||
 | 
					Regards,<br>
 | 
				
			||||||
 | 
					MapGuesser<br>
 | 
				
			||||||
 | 
					<a href="{{BASE_URL}}" title="MapGuesser">{{BASE_URL}}</a>
 | 
				
			||||||
@ -10,4 +10,5 @@ However if you want to immediately delete it, please click on the following link
 | 
				
			|||||||
Have fun on MapGuesser!
 | 
					Have fun on MapGuesser!
 | 
				
			||||||
<br><br>
 | 
					<br><br>
 | 
				
			||||||
Regards,<br>
 | 
					Regards,<br>
 | 
				
			||||||
MapGuesser
 | 
					MapGuesser<br>
 | 
				
			||||||
 | 
					<a href="{{BASE_URL}}" title="MapGuesser">{{BASE_URL}}</a>
 | 
				
			||||||
 | 
				
			|||||||
@ -107,6 +107,10 @@ hr {
 | 
				
			|||||||
    margin-right: 10px;
 | 
					    margin-right: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.center {
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.right {
 | 
					.right {
 | 
				
			||||||
    text-align: right;
 | 
					    text-align: right;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,31 +3,84 @@
 | 
				
			|||||||
use MapGuesser\Interfaces\Request\IRequest;
 | 
					use MapGuesser\Interfaces\Request\IRequest;
 | 
				
			||||||
use MapGuesser\Interfaces\Response\IContent;
 | 
					use MapGuesser\Interfaces\Response\IContent;
 | 
				
			||||||
use MapGuesser\Interfaces\Response\IRedirect;
 | 
					use MapGuesser\Interfaces\Response\IRedirect;
 | 
				
			||||||
 | 
					use MapGuesser\Mailing\Mail;
 | 
				
			||||||
 | 
					use MapGuesser\OAuth\GoogleOAuth;
 | 
				
			||||||
 | 
					use MapGuesser\PersistentData\Model\User;
 | 
				
			||||||
 | 
					use MapGuesser\PersistentData\Model\UserConfirmation;
 | 
				
			||||||
 | 
					use MapGuesser\PersistentData\PersistentDataManager;
 | 
				
			||||||
 | 
					use MapGuesser\Repository\UserConfirmationRepository;
 | 
				
			||||||
use MapGuesser\Repository\UserRepository;
 | 
					use MapGuesser\Repository\UserRepository;
 | 
				
			||||||
use MapGuesser\Response\HtmlContent;
 | 
					use MapGuesser\Response\HtmlContent;
 | 
				
			||||||
use MapGuesser\Response\JsonContent;
 | 
					use MapGuesser\Response\JsonContent;
 | 
				
			||||||
use MapGuesser\Response\Redirect;
 | 
					use MapGuesser\Response\Redirect;
 | 
				
			||||||
 | 
					use MapGuesser\Util\JwtParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LoginController
 | 
					class LoginController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private IRequest $request;
 | 
					    private IRequest $request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private PersistentDataManager $pdm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private UserRepository $userRepository;
 | 
					    private UserRepository $userRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private UserConfirmationRepository $userConfirmationRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(IRequest $request)
 | 
					    public function __construct(IRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->request = $request;
 | 
					        $this->request = $request;
 | 
				
			||||||
 | 
					        $this->pdm = new PersistentDataManager();
 | 
				
			||||||
        $this->userRepository = new UserRepository();
 | 
					        $this->userRepository = new UserRepository();
 | 
				
			||||||
 | 
					        $this->userConfirmationRepository = new UserConfirmationRepository();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getLoginForm()
 | 
					    public function getLoginForm()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->request->user() !== null) {
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
            return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [];
 | 
					        $data = [];
 | 
				
			||||||
        return new HtmlContent('login', $data);
 | 
					        return new HtmlContent('login/login', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getGoogleLoginRedirect()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $state = bin2hex(random_bytes(16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->request->session()->set('oauth_state', $state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $oAuth = new GoogleOAuth();
 | 
				
			||||||
 | 
					        $url = $oAuth->getDialogUrl($state, $this->request->getBase() . '/' . \Container::$routeCollection->getRoute('login-google-action')->generateLink());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Redirect($url, IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getSignupForm()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = [];
 | 
				
			||||||
 | 
					        return new HtmlContent('login/signup', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getSignupWithGoogleForm()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$this->request->session()->has('google_user_data')) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('login-google')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $userData = $this->request->session()->get('google_user_data');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getByEmail($userData['email']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = ['found' => $user !== null, 'email' => $userData['email']];
 | 
				
			||||||
 | 
					        return new HtmlContent('login/google_signup', $data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function login(): IContent
 | 
					    public function login(): IContent
 | 
				
			||||||
@ -60,10 +113,219 @@ class LoginController
 | 
				
			|||||||
        return new JsonContent($data);
 | 
					        return new JsonContent($data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function loginWithGoogle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->request->query('state') !== $this->request->session()->get('oauth_state')) {
 | 
				
			||||||
 | 
					            $data = [];
 | 
				
			||||||
 | 
					            return new HtmlContent('login/google_login', $data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $oAuth = new GoogleOAuth();
 | 
				
			||||||
 | 
					        $tokenData = $oAuth->getToken($this->request->query('code'), $this->request->getBase() . '/' . \Container::$routeCollection->getRoute('login-google-action')->generateLink());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!isset($tokenData['id_token'])) {
 | 
				
			||||||
 | 
					            $data = [];
 | 
				
			||||||
 | 
					            return new HtmlContent('login/google_login', $data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $jwtParser = new JwtParser($tokenData['id_token']);
 | 
				
			||||||
 | 
					        $userData = $jwtParser->getPayload();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$userData['email_verified']) {
 | 
				
			||||||
 | 
					            $data = [];
 | 
				
			||||||
 | 
					            return new HtmlContent('login/google_login', $data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getByGoogleSub($userData['sub']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($user === null) {
 | 
				
			||||||
 | 
					            $this->request->session()->set('google_user_data', $userData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('signup-google')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->request->setUser($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function logout(): IRedirect
 | 
					    public function logout(): IRedirect
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->request->setUser(null);
 | 
					        $this->request->setUser(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					        return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function signup(): IContent
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            $data = ['error' => 'logged_in'];
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (filter_var($this->request->post('email'), FILTER_VALIDATE_EMAIL) === false) {
 | 
				
			||||||
 | 
					            $data = ['error' => 'email_not_valid'];
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getByEmail($this->request->post('email'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($user !== null) {
 | 
				
			||||||
 | 
					            if ($user->getActive()) {
 | 
				
			||||||
 | 
					                $data = ['error' => 'user_found'];
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $data = ['error' => 'not_active_user_found'];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strlen($this->request->post('password')) < 6) {
 | 
				
			||||||
 | 
					            $data = ['error' => 'passwords_too_short'];
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->request->post('password') !== $this->request->post('password_confirm')) {
 | 
				
			||||||
 | 
					            $data = ['error' => 'passwords_not_match'];
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = new User();
 | 
				
			||||||
 | 
					        $user->setEmail($this->request->post('email'));
 | 
				
			||||||
 | 
					        $user->setPlainPassword($this->request->post('password'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->startTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->saveToDb($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $token = hash('sha256', serialize($user) . random_bytes(10) . microtime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $confirmation = new UserConfirmation();
 | 
				
			||||||
 | 
					        $confirmation->setUser($user);
 | 
				
			||||||
 | 
					        $confirmation->setToken($token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->saveToDb($confirmation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->sendConfirmationEmail($user->getEmail(), $token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = ['success' => true];
 | 
				
			||||||
 | 
					        return new JsonContent($data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function signupWithGoogle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            $data = ['success' => true];
 | 
				
			||||||
 | 
					            return new JsonContent($data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $userData = $this->request->session()->get('google_user_data');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getByEmail($userData['email']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($user === null) {
 | 
				
			||||||
 | 
					            $user = new User();
 | 
				
			||||||
 | 
					            $user->setEmail($userData['email']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user->setActive(true);
 | 
				
			||||||
 | 
					        $user->setGoogleSub($userData['sub']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->saveToDb($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->sendWelcomeEmail($user->getEmail());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->request->session()->delete('google_user_data');
 | 
				
			||||||
 | 
					        $this->request->setUser($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = ['success' => true];
 | 
				
			||||||
 | 
					        return new JsonContent($data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function activate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $confirmation = $this->userConfirmationRepository->getByToken($this->request->query('token'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($confirmation === null) {
 | 
				
			||||||
 | 
					            $data = [];
 | 
				
			||||||
 | 
					            return new HtmlContent('login/activate', $data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->startTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->deleteFromDb($confirmation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getById($confirmation->getUserId());
 | 
				
			||||||
 | 
					        $user->setActive(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->saveToDb($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->request->setUser($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function cancel()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->request->user() !== null) {
 | 
				
			||||||
 | 
					            return new Redirect(\Container::$routeCollection->getRoute('index')->generateLink(), IRedirect::TEMPORARY);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $confirmation = $this->userConfirmationRepository->getByToken($this->request->query('token'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($confirmation === null) {
 | 
				
			||||||
 | 
					            $data = ['success' => false];
 | 
				
			||||||
 | 
					            return new HtmlContent('login/cancel', $data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->startTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->deleteFromDb($confirmation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->userRepository->getById($confirmation->getUserId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->pdm->deleteFromDb($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        \Container::$dbConnection->commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = ['success' => true];
 | 
				
			||||||
 | 
					        return new HtmlContent('login/cancel', $data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function sendConfirmationEmail(string $email, string $token): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $mail = new Mail();
 | 
				
			||||||
 | 
					        $mail->addRecipient($email);
 | 
				
			||||||
 | 
					        $mail->setSubject('Welcome to MapGuesser - Activate your account');
 | 
				
			||||||
 | 
					        $mail->setBodyFromTemplate('signup', [
 | 
				
			||||||
 | 
					            'EMAIL' => $email,
 | 
				
			||||||
 | 
					            'ACTIVATE_LINK' => $this->request->getBase() . '/'. \Container::$routeCollection->getRoute('signup.activate')->generateLink(['token' => $token]),
 | 
				
			||||||
 | 
					            'CANCEL_LINK' => $this->request->getBase() . '/' . \Container::$routeCollection->getRoute('signup.cancel')->generateLink(['token' => $token]),
 | 
				
			||||||
 | 
					            'BASE_URL' => $this->request->getBase(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $mail->send();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function sendWelcomeEmail(string $email): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $mail = new Mail();
 | 
				
			||||||
 | 
					        $mail->addRecipient($email);
 | 
				
			||||||
 | 
					        $mail->setSubject('Welcome to MapGuesser');
 | 
				
			||||||
 | 
					        $mail->setBodyFromTemplate('signup-noconfirm', [
 | 
				
			||||||
 | 
					            'EMAIL' => $email,
 | 
				
			||||||
 | 
					            'BASE_URL' => $this->request->getBase(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $mail->send();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,170 +0,0 @@
 | 
				
			|||||||
<?php namespace MapGuesser\Controller;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use MapGuesser\Interfaces\Request\IRequest;
 | 
					 | 
				
			||||||
use MapGuesser\Interfaces\Response\IContent;
 | 
					 | 
				
			||||||
use MapGuesser\Interfaces\Response\IRedirect;
 | 
					 | 
				
			||||||
use MapGuesser\Mailing\Mail;
 | 
					 | 
				
			||||||
use MapGuesser\PersistentData\PersistentDataManager;
 | 
					 | 
				
			||||||
use MapGuesser\PersistentData\Model\User;
 | 
					 | 
				
			||||||
use MapGuesser\PersistentData\Model\UserConfirmation;
 | 
					 | 
				
			||||||
use MapGuesser\Repository\UserConfirmationRepository;
 | 
					 | 
				
			||||||
use MapGuesser\Repository\UserRepository;
 | 
					 | 
				
			||||||
use MapGuesser\Response\HtmlContent;
 | 
					 | 
				
			||||||
use MapGuesser\Response\JsonContent;
 | 
					 | 
				
			||||||
use MapGuesser\Response\Redirect;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class SignupController
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private IRequest $request;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private PersistentDataManager $pdm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private UserRepository $userRepository;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private UserConfirmationRepository $userConfirmationRepository;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function __construct(IRequest $request)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->request = $request;
 | 
					 | 
				
			||||||
        $this->pdm = new PersistentDataManager();
 | 
					 | 
				
			||||||
        $this->userRepository = new UserRepository();
 | 
					 | 
				
			||||||
        $this->userConfirmationRepository = new UserConfirmationRepository();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function getSignupForm()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->request->user() !== null) {
 | 
					 | 
				
			||||||
            return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $data = [];
 | 
					 | 
				
			||||||
        return new HtmlContent('signup/signup', $data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function signup(): IContent
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->request->user() !== null) {
 | 
					 | 
				
			||||||
            //TODO: return with some error
 | 
					 | 
				
			||||||
            $data = ['success' => true];
 | 
					 | 
				
			||||||
            return new JsonContent($data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (filter_var($this->request->post('email'), FILTER_VALIDATE_EMAIL) === false) {
 | 
					 | 
				
			||||||
            $data = ['error' => 'email_not_valid'];
 | 
					 | 
				
			||||||
            return new JsonContent($data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user = $this->userRepository->getByEmail($this->request->post('email'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($user !== null) {
 | 
					 | 
				
			||||||
            if ($user->getActive()) {
 | 
					 | 
				
			||||||
                $data = ['error' => 'user_found'];
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                $data = ['error' => 'not_active_user_found'];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return new JsonContent($data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (strlen($this->request->post('password')) < 6) {
 | 
					 | 
				
			||||||
            $data = ['error' => 'passwords_too_short'];
 | 
					 | 
				
			||||||
            return new JsonContent($data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->request->post('password') !== $this->request->post('password_confirm')) {
 | 
					 | 
				
			||||||
            $data = ['error' => 'passwords_not_match'];
 | 
					 | 
				
			||||||
            return new JsonContent($data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user = new User();
 | 
					 | 
				
			||||||
        $user->setEmail($this->request->post('email'));
 | 
					 | 
				
			||||||
        $user->setPlainPassword($this->request->post('password'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->startTransaction();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->saveToDb($user);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $token = hash('sha256', serialize($user) . random_bytes(10) . microtime());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $confirmation = new UserConfirmation();
 | 
					 | 
				
			||||||
        $confirmation->setUser($user);
 | 
					 | 
				
			||||||
        $confirmation->setToken($token);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->saveToDb($confirmation);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->commit();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->sendConfirmationEmail($user->getEmail(), $token);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $data = ['success' => true];
 | 
					 | 
				
			||||||
        return new JsonContent($data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function activate()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->request->user() !== null) {
 | 
					 | 
				
			||||||
            return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $confirmation = $this->userConfirmationRepository->getByToken($this->request->query('token'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($confirmation === null) {
 | 
					 | 
				
			||||||
            $data = [];
 | 
					 | 
				
			||||||
            return new HtmlContent('signup/activate', $data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->startTransaction();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->deleteFromDb($confirmation);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user = $this->userRepository->getById($confirmation->getUserId());
 | 
					 | 
				
			||||||
        $user->setActive(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->saveToDb($user);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->commit();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->request->setUser($user);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function cancel()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->request->user() !== null) {
 | 
					 | 
				
			||||||
            return new Redirect([\Container::$routeCollection->getRoute('index'), []], IRedirect::TEMPORARY);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $confirmation = $this->userConfirmationRepository->getByToken($this->request->query('token'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($confirmation === null) {
 | 
					 | 
				
			||||||
            $data = ['success' => false];
 | 
					 | 
				
			||||||
            return new HtmlContent('signup/cancel', $data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->startTransaction();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->deleteFromDb($confirmation);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user = $this->userRepository->getById($confirmation->getUserId());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->pdm->deleteFromDb($user);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        \Container::$dbConnection->commit();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $data = ['success' => true];
 | 
					 | 
				
			||||||
        return new HtmlContent('signup/cancel', $data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function sendConfirmationEmail($email, $token): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $mail = new Mail();
 | 
					 | 
				
			||||||
        $mail->addRecipient($email);
 | 
					 | 
				
			||||||
        $mail->setSubject('Welcome to MapGuesser - Activate your account');
 | 
					 | 
				
			||||||
        $mail->setBodyFromTemplate('signup', [
 | 
					 | 
				
			||||||
            'EMAIL' => $email,
 | 
					 | 
				
			||||||
            'ACTIVATE_LINK' => $this->request->getBase() . '/signup/activate/' . $token,
 | 
					 | 
				
			||||||
            'CANCEL_LINK' => $this->request->getBase() . '/signup/cancel/' . $token,
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
        $mail->send();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								views/login/google_login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								views/login/google_login.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<?php require ROOT . '/views/templates/main_header.php'; ?>
 | 
				
			||||||
 | 
					<?php require ROOT . '/views/templates/header.php'; ?>
 | 
				
			||||||
 | 
					<div class="main">
 | 
				
			||||||
 | 
					    <h2>Login up with Google</h2>
 | 
				
			||||||
 | 
					    <div class="box">
 | 
				
			||||||
 | 
					        <p class="error justify">Authenticating with Google failed. Please <a href="/login/google" title="Login with Google">retry</a>!</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<?php require ROOT . '/views/templates/main_footer.php'; ?>
 | 
				
			||||||
							
								
								
									
										40
									
								
								views/login/google_signup.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								views/login/google_signup.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					<?php require ROOT . '/views/templates/main_header.php'; ?>
 | 
				
			||||||
 | 
					<?php require ROOT . '/views/templates/header.php'; ?>
 | 
				
			||||||
 | 
					<div class="main">
 | 
				
			||||||
 | 
					    <h2>Sign up</h2>
 | 
				
			||||||
 | 
					    <div class="box">
 | 
				
			||||||
 | 
					        <form id="googleSignupForm" action="/signup/google" method="post">
 | 
				
			||||||
 | 
					            <?php if ($found): ?>
 | 
				
			||||||
 | 
					                <p class="justify">Please confirm that you link your account to your Google account.</p>
 | 
				
			||||||
 | 
					            <?php else: ?>
 | 
				
			||||||
 | 
					                <p class="justify">Please confirm your sign up request. Your account will be linked to your Google account.</p>
 | 
				
			||||||
 | 
					            <?php endif; ?>
 | 
				
			||||||
 | 
					            <input class="big fullWidth marginTop" type="email" name="email" placeholder="Email address" value="<?= $email ?>" disabled>
 | 
				
			||||||
 | 
					            <div class="right marginTop">
 | 
				
			||||||
 | 
					                <button type="submit">
 | 
				
			||||||
 | 
					                    <?php if ($found): ?>
 | 
				
			||||||
 | 
					                        Link
 | 
				
			||||||
 | 
					                    <?php else: ?>
 | 
				
			||||||
 | 
					                        Sign up
 | 
				
			||||||
 | 
					                    <?php endif; ?>
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					    (function () {
 | 
				
			||||||
 | 
					        var form = document.getElementById('googleSignupForm');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        form.onsubmit = function (e) {
 | 
				
			||||||
 | 
					            document.getElementById('loading').style.visibility = 'visible';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            e.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            MapGuesser.httpRequest('POST', form.action, function () {
 | 
				
			||||||
 | 
					                window.location.replace('/');
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    })();
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<?php require ROOT . '/views/templates/main_footer.php'; ?>
 | 
				
			||||||
@ -15,6 +15,10 @@ $jsFiles = [
 | 
				
			|||||||
            <div class="right marginTop">
 | 
					            <div class="right marginTop">
 | 
				
			||||||
                <button type="submit">Login</button>
 | 
					                <button type="submit">Login</button>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <hr>
 | 
				
			||||||
 | 
					            <div class="center">
 | 
				
			||||||
 | 
					                <a class="button yellow" href="/login/google" title="Login with Google">Login with Google</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@ -16,6 +16,10 @@ $jsFiles = [
 | 
				
			|||||||
            <div class="right marginTop">
 | 
					            <div class="right marginTop">
 | 
				
			||||||
                <button type="submit">Sign up</button>
 | 
					                <button type="submit">Sign up</button>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <hr>
 | 
				
			||||||
 | 
					            <div class="center">
 | 
				
			||||||
 | 
					                <a class="button yellow" href="/login/google" title="Signup with Google">Signup with Google</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										12
									
								
								web.php
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								web.php
									
									
									
									
									
								
							@ -15,10 +15,14 @@ Container::$routeCollection = new MapGuesser\Routing\RouteCollection();
 | 
				
			|||||||
Container::$routeCollection->get('index', '', [MapGuesser\Controller\HomeController::class, 'getIndex']);
 | 
					Container::$routeCollection->get('index', '', [MapGuesser\Controller\HomeController::class, 'getIndex']);
 | 
				
			||||||
Container::$routeCollection->get('login', 'login', [MapGuesser\Controller\LoginController::class, 'getLoginForm']);
 | 
					Container::$routeCollection->get('login', 'login', [MapGuesser\Controller\LoginController::class, 'getLoginForm']);
 | 
				
			||||||
Container::$routeCollection->post('login-action', 'login', [MapGuesser\Controller\LoginController::class, 'login']);
 | 
					Container::$routeCollection->post('login-action', 'login', [MapGuesser\Controller\LoginController::class, 'login']);
 | 
				
			||||||
Container::$routeCollection->get('signup', 'signup', [MapGuesser\Controller\SignupController::class, 'getSignupForm']);
 | 
					Container::$routeCollection->get('login-google', 'login/google', [MapGuesser\Controller\LoginController::class, 'getGoogleLoginRedirect']);
 | 
				
			||||||
Container::$routeCollection->post('signup-action', 'signup', [MapGuesser\Controller\SignupController::class, 'signup']);
 | 
					Container::$routeCollection->get('login-google-action', 'login/google/code', [MapGuesser\Controller\LoginController::class, 'loginWithGoogle']);
 | 
				
			||||||
Container::$routeCollection->get('signup.activate', 'signup/activate/{token}', [MapGuesser\Controller\SignupController::class, 'activate']);
 | 
					Container::$routeCollection->get('signup', 'signup', [MapGuesser\Controller\LoginController::class, 'getSignupForm']);
 | 
				
			||||||
Container::$routeCollection->get('signup.cancel', 'signup/cancel/{token}', [MapGuesser\Controller\SignupController::class, 'cancel']);
 | 
					Container::$routeCollection->post('signup-action', 'signup', [MapGuesser\Controller\LoginController::class, 'signup']);
 | 
				
			||||||
 | 
					Container::$routeCollection->get('signup-google', 'signup/google', [MapGuesser\Controller\LoginController::class, 'getSignupWithGoogleForm']);
 | 
				
			||||||
 | 
					Container::$routeCollection->post('signup-google-action', 'signup/google', [MapGuesser\Controller\LoginController::class, 'signupWithGoogle']);
 | 
				
			||||||
 | 
					Container::$routeCollection->get('signup.activate', 'signup/activate/{token}', [MapGuesser\Controller\LoginController::class, 'activate']);
 | 
				
			||||||
 | 
					Container::$routeCollection->get('signup.cancel', 'signup/cancel/{token}', [MapGuesser\Controller\LoginController::class, 'cancel']);
 | 
				
			||||||
Container::$routeCollection->get('logout', 'logout', [MapGuesser\Controller\LoginController::class, 'logout']);
 | 
					Container::$routeCollection->get('logout', 'logout', [MapGuesser\Controller\LoginController::class, 'logout']);
 | 
				
			||||||
Container::$routeCollection->get('profile', 'profile', [MapGuesser\Controller\UserController::class, 'getProfile']);
 | 
					Container::$routeCollection->get('profile', 'profile', [MapGuesser\Controller\UserController::class, 'getProfile']);
 | 
				
			||||||
Container::$routeCollection->post('profile-action', 'profile', [MapGuesser\Controller\UserController::class, 'saveProfile']);
 | 
					Container::$routeCollection->post('profile-action', 'profile', [MapGuesser\Controller\UserController::class, 'saveProfile']);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user