merge signup and google signup handling with username support

This commit is contained in:
Bence Pőcze 2023-09-24 00:47:44 +02:00
parent 36f4b6b4d0
commit b1ed28f4b5
Signed by: bence
GPG Key ID: DC5BD6E95A333E6D
4 changed files with 116 additions and 121 deletions

View File

@ -14,6 +14,7 @@ use MapGuesser\Repository\UserConfirmationRepository;
use MapGuesser\Repository\UserPasswordResetterRepository; use MapGuesser\Repository\UserPasswordResetterRepository;
use MapGuesser\Repository\UserPlayedPlaceRepository; use MapGuesser\Repository\UserPlayedPlaceRepository;
use MapGuesser\Repository\UserRepository; use MapGuesser\Repository\UserRepository;
use MapGuesser\Util\UsernameGenerator;
use SokoWeb\Response\HtmlContent; use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent; use SokoWeb\Response\JsonContent;
use SokoWeb\Response\Redirect; use SokoWeb\Response\Redirect;
@ -89,8 +90,13 @@ class LoginController
return new HtmlContent('login/signup', $data); return new HtmlContent('login/signup', $data);
} }
public function getSignupSuccess(): IContent public function getSignupSuccess()
{ {
if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new Redirect($this->redirectUrl, IRedirect::TEMPORARY);
}
return new HtmlContent('login/signup_success'); return new HtmlContent('login/signup_success');
} }
@ -265,131 +271,128 @@ class LoginController
return new JsonContent(['redirect' => ['target' => $this->redirectUrl]]); return new JsonContent(['redirect' => ['target' => $this->redirectUrl]]);
} }
$user = $this->userRepository->getByEmail(\Container::$request->post('email')); $newUser = new User();
if ($user !== null) { $googleUserData = \Container::$request->session()->get('google_user_data');
if ($user->getActive()) { if ($googleUserData !== null) {
if (!$user->checkPassword(\Container::$request->post('password'))) { $user = $this->userRepository->getByEmail($googleUserData['email']);
return new JsonContent([
'error' => [
'errorText' => 'There is a user already registered with the given email address, ' .
'but the given password is wrong. You can <a href="/password/requestReset?email=' .
urlencode($user->getEmail()) . '" title="Request password reset">request password reset</a>!'
]
]);
}
\Container::$request->setUser($user); if ($user !== null) {
$this->deleteRedirectUrl();
$data = ['redirect' => ['target' => $this->redirectUrl]];
} else {
$data = [
'error' => [
'errorText' => 'There is a user already registered with the given email address. ' .
'Please check your email and click on the activation link!'
]
];
}
return new JsonContent($data);
}
if (!empty($_ENV['RECAPTCHA_SITEKEY'])) {
if (!\Container::$request->post('g-recaptcha-response')) {
return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]);
}
$captchaValidator = new CaptchaValidator();
$captchaResponse = $captchaValidator->validate(\Container::$request->post('g-recaptcha-response'));
if (!$captchaResponse['success']) {
return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]);
}
}
if (filter_var(\Container::$request->post('email'), FILTER_VALIDATE_EMAIL) === false) {
return new JsonContent(['error' => ['errorText' => 'The given email address is not valid.']]);
}
if (\Container::$request->session()->has('tmp_user_data')) {
$tmpUserData = \Container::$request->session()->get('tmp_user_data');
$tmpUser = new User();
$tmpUser->setPassword($tmpUserData['password_hashed']);
if (!$tmpUser->checkPassword(\Container::$request->post('password'))) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
}
} else {
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' => 'There is a user already registered with the email address of this Google account, ' .
'but Google account is not linked to the user. Please <a href="/login?email=' .
urlencode($googleUserData['email']) . '" title="Login">login</a> first to link your Google account!'
] ]
]); ]);
} }
if (\Container::$request->post('password') !== \Container::$request->post('password_confirm')) { $newUser->setActive(true);
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]); $newUser->setEmail($googleUserData['email']);
$newUser->setGoogleSub($googleUserData['sub']);
} else {
$user = $this->userRepository->getByEmailOrUsername(\Container::$request->post('email'));
if ($user !== null) {
if ($user->getActive()) {
if (!$user->checkPassword(\Container::$request->post('password'))) {
return new JsonContent([
'error' => [
'errorText' => 'There is a user already registered with the given email address / username, ' .
'but the given password is wrong. You can <a href="/password/requestReset?email=' .
urlencode($user->getEmail()) . '" title="Request password reset">request password reset</a>!'
]
]);
}
\Container::$request->setUser($user);
$this->deleteRedirectUrl();
$data = ['redirect' => ['target' => $this->redirectUrl]];
} else {
$data = [
'error' => [
'errorText' => 'There is a user already registered with the given email address / username. ' .
'Please check your email and click on the activation link!'
]
];
}
return new JsonContent($data);
} }
if (!empty($_ENV['RECAPTCHA_SITEKEY'])) {
if (!\Container::$request->post('g-recaptcha-response')) {
return new JsonContent(['error' => ['errorText' => 'Please check "I\'m not a robot" in the reCAPTCHA box!']]);
}
$captchaValidator = new CaptchaValidator();
$captchaResponse = $captchaValidator->validate(\Container::$request->post('g-recaptcha-response'));
if (!$captchaResponse['success']) {
return new JsonContent(['error' => ['errorText' => 'reCAPTCHA challenge failed. Please try again!']]);
}
}
if (filter_var(\Container::$request->post('email'), FILTER_VALIDATE_EMAIL) === false) {
return new JsonContent(['error' => ['errorText' => 'The given email address is not valid.']]);
}
if (\Container::$request->session()->has('tmp_user_data')) {
$tmpUserData = \Container::$request->session()->get('tmp_user_data');
$tmpUser = new User();
$tmpUser->setPassword($tmpUserData['password_hashed']);
if (!$tmpUser->checkPassword(\Container::$request->post('password'))) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
}
} else {
if (strlen(\Container::$request->post('password')) < 6) {
return new JsonContent([
'error' => [
'errorText' => 'The given password is too short. Please choose a password that is at least 6 characters long!'
]
]);
}
if (\Container::$request->post('password') !== \Container::$request->post('password_confirm')) {
return new JsonContent(['error' => ['errorText' => 'The given passwords do not match.']]);
}
}
$newUser->setActive(false);
$newUser->setEmail(\Container::$request->post('email'));
$newUser->setPlainPassword(\Container::$request->post('password'));
} }
$user = new User(); if (strlen(\Container::$request->post('username')) > 0 && preg_match('/^[a-zA-Z0-9_\-\.]+$/', \Container::$request->post('username')) !== 1) {
$user->setEmail(\Container::$request->post('email')); return new JsonContent(['error' => ['errorText' => 'Username can contain only english letters, digits, - (hyphen), . (dot), _ (underscore).']]);
$user->setPlainPassword(\Container::$request->post('password')); }
$user->setCreatedDate(new DateTime());
\Container::$persistentDataManager->saveToDb($user); $newUser->setUsername(strlen(\Container::$request->post('username')) > 0 ? \Container::$request->post('username') : (new UsernameGenerator())->generate());
$newUser->setCreatedDate(new DateTime());
$token = bin2hex(random_bytes(16)); \Container::$persistentDataManager->saveToDb($newUser);
$confirmation = new UserConfirmation(); if ($googleUserData !== null) {
$confirmation->setUser($user); $this->sendWelcomeEmail($newUser->getEmail());
$confirmation->setToken($token);
$confirmation->setLastSentDate(new DateTime());
\Container::$persistentDataManager->saveToDb($confirmation); \Container::$request->setUser($newUser);
} else {
$token = bin2hex(random_bytes(16));
$this->sendConfirmationEmail($user->getEmail(), $token, $user->getCreatedDate()); $confirmation = new UserConfirmation();
$confirmation->setUser($newUser);
$confirmation->setToken($token);
$confirmation->setLastSentDate(new DateTime());
\Container::$persistentDataManager->saveToDb($confirmation);
$this->sendConfirmationEmail($newUser->getEmail(), $token, $newUser->getCreatedDate());
}
\Container::$request->session()->delete('tmp_user_data'); \Container::$request->session()->delete('tmp_user_data');
return new JsonContent(['success' => true]);
}
public function signupWithGoogle(): IContent
{
if (\Container::$request->user() !== null) {
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]);
}
$userData = \Container::$request->session()->get('google_user_data');
$user = $this->userRepository->getByEmail($userData['email']);
if ($user === null) {
$sendWelcomeEmail = true;
$user = new User();
$user->setEmail($userData['email']);
$user->setCreatedDate(new DateTime());
} else {
$sendWelcomeEmail = false;
}
$user->setActive(true);
$user->setGoogleSub($userData['sub']);
\Container::$persistentDataManager->saveToDb($user);
if ($sendWelcomeEmail) {
$this->sendWelcomeEmail($user->getEmail());
}
\Container::$request->session()->delete('google_user_data'); \Container::$request->session()->delete('google_user_data');
\Container::$request->setUser($user);
$this->deleteRedirectUrl();
return new JsonContent(['success' => true]); return new JsonContent(['success' => true]);
} }

View File

@ -5,21 +5,13 @@
@section(main) @section(main)
<h2>Sign up</h2> <h2>Sign up</h2>
<div class="box"> <div class="box">
<form id="googleSignupForm" action="/signup/google" method="post" data-redirect-on-success="<?= $redirectUrl ?>"> <form id="googleSignupForm" action="/signup" method="post" data-redirect-on-success="/signup/success">
<?php if ($found): ?> <p class="justify">Please confirm your sign up request. Your account will be linked to your Google account.</p>
<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 type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" value="<?= $email ?>" disabled> <input type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" value="<?= $email ?>" disabled>
<input type="username" class="text big fullWidth marginTop" name="username" placeholder="Username">
<p id="googleSignupFormError" class="formError justify marginTop"></p>
<div class="right"> <div class="right">
<button class="marginTop marginRight" type="submit"> <button class="marginTop marginRight" type="submit">Sign up</button><!--
<?php if ($found): ?>
Link
<?php else: ?>
Sign up
<?php endif; ?>
</button><!--
--><button id="cancelGoogleSignupButton" class="gray marginTop" type="button">Cancel</button> --><button id="cancelGoogleSignupButton" class="gray marginTop" type="button">Cancel</button>
</div> </div>
</form> </form>

View File

@ -8,7 +8,7 @@
<div class="box"> <div class="box">
<form id="signupForm" action="/signup" method="post" data-redirect-on-success="/signup/success"> <form id="signupForm" action="/signup" method="post" data-redirect-on-success="/signup/success">
<?php if (isset($email)): ?> <?php if (isset($email)): ?>
<p class="justify">No user found with the given email address. Sign up with one click!</p> <p class="justify">No user found with the given email address / username. Sign up with one click!</p>
<input type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" autocomplete="username" value="<?= $email ?>" required> <input type="email" class="text big fullWidth marginTop" name="email" placeholder="Email address" autocomplete="username" value="<?= $email ?>" required>
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password confirmation" autocomplete="new-password" required minlength="6" autofocus> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password confirmation" autocomplete="new-password" required minlength="6" autofocus>
<?php else: ?> <?php else: ?>
@ -16,6 +16,7 @@
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" autocomplete="new-password" required minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" autocomplete="new-password" required minlength="6">
<input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" autocomplete="new-password" minlength="6"> <input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" autocomplete="new-password" minlength="6">
<?php endif; ?> <?php endif; ?>
<input type="username" class="text big fullWidth marginTop" name="username" placeholder="Username">
<?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?> <?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?>
<div class="marginTop"> <div class="marginTop">
<div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div> <div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div>

View File

@ -38,7 +38,6 @@ Container::$routeCollection->group('signup', function (RouteCollection $routeCol
$routeCollection->get('signup', '', [LoginController::class, 'getSignupForm']); $routeCollection->get('signup', '', [LoginController::class, 'getSignupForm']);
$routeCollection->post('signup-action', '', [LoginController::class, 'signup']); $routeCollection->post('signup-action', '', [LoginController::class, 'signup']);
$routeCollection->get('signup-google', 'google', [LoginController::class, 'getSignupWithGoogleForm']); $routeCollection->get('signup-google', 'google', [LoginController::class, 'getSignupWithGoogleForm']);
$routeCollection->post('signup-google-action', 'google', [LoginController::class, 'signupWithGoogle']);
$routeCollection->post('signup.reset', 'reset', [LoginController::class, 'resetSignup']); $routeCollection->post('signup.reset', 'reset', [LoginController::class, 'resetSignup']);
$routeCollection->post('signup-google.reset', 'google/reset', [LoginController::class, 'resetGoogleSignup']); $routeCollection->post('signup-google.reset', 'google/reset', [LoginController::class, 'resetGoogleSignup']);
$routeCollection->get('signup.success', 'success', [LoginController::class, 'getSignupSuccess']); $routeCollection->get('signup.success', 'success', [LoginController::class, 'getSignupSuccess']);