diff --git a/appinfo/routes.php b/appinfo/routes.php
index 7db7778..d83acb7 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -13,14 +13,16 @@
return [
'routes' => [
['name' => 'settings#admin', 'url' => '/settings', 'verb' => 'POST'],
- ['name' => 'register#askEmail', 'url' => '/', 'verb' => 'GET'],
- ['name' => 'register#validateEmail', 'url' => '/', 'verb' => 'POST'],
- ['name' => 'register#verifyToken', 'url' => '/verify/{token}', 'verb' => 'GET'],
- ['name' => 'register#createAccount', 'url' => '/verify/{token}', 'verb' => 'POST']
+ ['name' => 'register#showEmailForm', 'url' => '/', 'verb' => 'GET'],
+ ['name' => 'register#submitEmailForm', 'url' => '/', 'verb' => 'POST'],
+ ['name' => 'register#showVerificationForm', 'url' => '/verify/{secret}', 'verb' => 'GET'],
+ ['name' => 'register#submitVerificationForm', 'url' => '/verify/{secret}', 'verb' => 'POST'],
+ ['name' => 'register#showUserForm', 'url' => '/register/{secret}/{token}', 'verb' => 'GET'],
+ ['name' => 'register#submitUserForm', 'url' => '/register/{secret}/{token}', 'verb' => 'POST'],
],
'ocs' => [
['root' => '/registration', 'name' => 'api#validate', 'url' => '/v1/validate', 'verb' => 'POST'],
['root' => '/registration', 'name' => 'api#status', 'url' => '/v1/status', 'verb' => 'POST'],
- ['root' => '/registration', 'name' => 'api#register', 'url' => '/v1/register', 'verb' => 'POST']
+ ['root' => '/registration', 'name' => 'api#register', 'url' => '/v1/register', 'verb' => 'POST'],
]
];
diff --git a/css/style.css b/css/style.css
index 3987ce6..7171a26 100644
--- a/css/style.css
+++ b/css/style.css
@@ -1,8 +1,14 @@
-#body-login #email, #body-login #username, #body-login #password {
+#body-login #email,
+#body-login #token,
+#body-login #username,
+#body-login #password {
width: calc(100% - 56px);
padding-left: 36px;
}
-#email-icon, #username-icon, #password-icon {
+#email-icon,
+#token-icon,
+#username-icon,
+#password-icon {
position: absolute;
left: 16px;
top: 22px;
diff --git a/img/verify.svg b/img/verify.svg
new file mode 100644
index 0000000..f1b2091
--- /dev/null
+++ b/img/verify.svg
@@ -0,0 +1 @@
+
diff --git a/lib/Controller/RegisterController.php b/lib/Controller/RegisterController.php
index deb7e55..ee0b795 100644
--- a/lib/Controller/RegisterController.php
+++ b/lib/Controller/RegisterController.php
@@ -16,6 +16,8 @@ use OCA\Registration\Db\Registration;
use OCA\Registration\Service\MailService;
use OCA\Registration\Service\RegistrationException;
use OCA\Registration\Service\RegistrationService;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Http\Response;
use \OCP\IRequest;
use \OCP\AppFramework\Http\TemplateResponse;
use \OCP\AppFramework\Http\RedirectResponse;
@@ -59,64 +61,138 @@ class RegisterController extends Controller {
* @NoCSRFRequired
* @PublicPage
*
- * @param $errormsg
- * @param $entered
+ * @param string $email
+ * @param string $message
* @return TemplateResponse
*/
- public function askEmail($errormsg, $entered) {
+ public function showEmailForm(string $email = '', string $message = ''): TemplateResponse {
$params = [
- 'errormsg' => $errormsg ? $errormsg : $this->request->getParam('errormsg'),
- 'entered' => $entered ? $entered : $this->request->getParam('entered')
+ 'email' => $email,
+ 'message' => $message,
];
- return new TemplateResponse('registration', 'register', $params, 'guest');
+ return new TemplateResponse('registration', 'form/email', $params, 'guest');
}
/**
- * User POST email, if email is valid and not duplicate, we send token by mail
* @PublicPage
* @AnonRateThrottle(limit=5, period=1)
*
* @param string $email
* @return TemplateResponse
*/
- public function validateEmail($email) {//TODO rename to receiveUserEmail
- if (!$this->registrationService->checkAllowedDomains($email)) {//TODO Duplicate code with Service
- return new TemplateResponse('registration', 'domains', [
- 'domains' => $this->registrationService->getAllowedDomains()
- ], 'guest');
- }
+ public function submitEmailForm(string $email): Response {
try {
- $reg = $this->registrationService->validateEmail($email);
- if ($reg === true) {
+ // Registration already in progress, update token and continue with verification
+ $registration = $this->registrationService->getRegistrationForEmail($email);
+ $this->registrationService->generateNewToken($registration);
+ } catch (DoesNotExistException $e) {
+ // No registration in progress
+ try {
+ $this->registrationService->validateEmail($email);
$registration = $this->registrationService->createRegistration($email);
- $this->mailService->sendTokenByMail($registration);
- } else {
- $this->registrationService->generateNewToken($reg);
- $this->mailService->sendTokenByMail($reg);
- return new TemplateResponse('registration', 'message', ['msg' =>
- $this->l10n->t('There is already a pending registration with this email, a new verification email has been sent to the address.')
- ], 'guest');
+ } catch (RegistrationException $e) {
+ return $this->showEmailForm($email, $e->getMessage());
}
- } catch (RegistrationException $e) {
- return new TemplateResponse('registration', 'message', ['msg' =>
- $e->getMessage().'
'.$e->getHint()
- ], 'guest');
}
+ try {
+ $this->mailService->sendTokenByMail($registration);
+ } catch (RegistrationException $e) {
+ return $this->showEmailForm($email, $e->getMessage());
+ }
- return new TemplateResponse('registration', 'message', ['msg' =>
- $this->l10n->t('Verification email successfully sent.')
- ], 'guest');
+ return new RedirectResponse(
+ $this->urlgenerator->linkToRoute(
+ 'registration.register.showVerificationForm',
+ ['secret' => $registration->getClientSecret()]
+ )
+ );
}
/**
* @NoCSRFRequired
* @PublicPage
*
- * @param $token
+ * @param string $secret
+ * @param string $message
* @return TemplateResponse
*/
- public function verifyToken($token) {
+ public function showVerificationForm(string $secret, string $message = ''): TemplateResponse {
+ try {
+ $this->registrationService->getRegistrationForSecret($secret);
+ } catch (RegistrationException $e) {
+ return new TemplateResponse('core', 'error', [
+ 'errors' => [
+ $this->l10n->t('The verification secret does not exist anymore'),
+ ],
+ ], 'error');
+ }
+
+ return new TemplateResponse('registration', 'form/verification', [
+ 'message' => $message,
+ ], 'guest');
+ }
+
+ /**
+ * @PublicPage
+ * @AnonRateThrottle(limit=5, period=1)
+ *
+ * @param string $secret
+ * @param string $token
+ * @return Response
+ */
+ public function submitVerificationForm(string $secret, string $token): Response {
+ try {
+ $registration = $this->registrationService->getRegistrationForSecret($secret);
+
+ if ($registration->getToken() !== $token) {
+ return $this->showVerificationForm(
+ $secret,
+ $this->l10n->t('The entered verification code is wrong')
+ );
+ }
+ } catch (RegistrationException $e) {
+ return new TemplateResponse('core', 'error', [
+ 'errors' => [
+ $this->l10n->t('The verification secret does not exist anymore'),
+ ],
+ ], 'error');
+ }
+
+ return new RedirectResponse(
+ $this->urlgenerator->linkToRoute(
+ 'registration.register.showUserForm',
+ [
+ 'secret' => $secret,
+ 'token' => $token,
+ ]
+ )
+ );
+ }
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * @param string $secret
+ * @param string $token
+ * @return TemplateResponse
+ */
+ public function showUserForm(string $secret, string $token): TemplateResponse {
+ try {
+ $registration = $this->registrationService->getRegistrationForSecret($secret);
+
+ if ($registration->getToken() !== $token) {
+ throw new RegistrationException('Invalid verification token');
+ }
+ } catch (RegistrationException $e) {
+ return new TemplateResponse('core', 'error', [
+ 'errors' => [
+ $this->l10n->t('The verification secret does not exist anymore or the verification token is invalid'),
+ ],
+ ], 'error');
+ }
+
try {
/** @var Registration $registration */
$registration = $this->registrationService->verifyToken($token);
@@ -131,7 +207,7 @@ class RegisterController extends Controller {
);
}
- return new TemplateResponse('registration', 'form', [
+ return new TemplateResponse('registration', 'form/user', [
'email' => $registration->getEmail(),
'email_is_login' => $this->config->getAppValue('registration', 'email_is_login', '0') === '1',
'token' => $registration->getToken(),
@@ -148,7 +224,7 @@ class RegisterController extends Controller {
* @param $token
* @return RedirectResponse|TemplateResponse
*/
- public function createAccount($token) {
+ public function submitUserForm($token) {
$registration = $this->registrationService->getRegistrationForToken($token);
if ($this->config->getAppValue('registration', 'email_is_login', '0') === '1') {
$username = $registration->getEmail();
diff --git a/lib/RegistrationLoginOption.php b/lib/RegistrationLoginOption.php
index d436574..ceda53e 100644
--- a/lib/RegistrationLoginOption.php
+++ b/lib/RegistrationLoginOption.php
@@ -47,7 +47,7 @@ class RegistrationLoginOption implements IAlternativeLogin {
}
public function getLink(): string {
- return $this->url->linkToRoute('registration.register.askEmail');
+ return $this->url->linkToRoute('registration.register.showEmailForm');
}
public function getClass(): string {
diff --git a/lib/Service/MailService.php b/lib/Service/MailService.php
index 5d8f581..0a8b688 100644
--- a/lib/Service/MailService.php
+++ b/lib/Service/MailService.php
@@ -81,7 +81,10 @@ class MailService {
* @throws RegistrationException
*/
public function sendTokenByMail(Registration $registration): void {
- $link = $this->urlGenerator->linkToRouteAbsolute('registration.register.verifyToken', ['token' => $registration->getToken()]);
+ $link = $this->urlGenerator->linkToRouteAbsolute('registration.register.showUserForm', [
+ 'secret' => $registration->getClientSecret(),
+ 'token' => $registration->getToken(),
+ ]);
$subject = $this->l10n->t('Verify your %s registration request', [$this->defaults->getName()]);
$template = $this->mailer->createEMailTemplate('registration_verify', [
@@ -100,6 +103,10 @@ class MailService {
$body
);
+ $template->addBodyText(
+ $this->l10n->t('Verification code: %s', $registration->getToken())
+ );
+
$template->addBodyButton(
$this->l10n->t('Continue registration'),
$link
diff --git a/lib/Service/RegistrationService.php b/lib/Service/RegistrationService.php
index e29c2ee..3d5bb85 100644
--- a/lib/Service/RegistrationService.php
+++ b/lib/Service/RegistrationService.php
@@ -135,24 +135,24 @@ class RegistrationService {
$registration->setPassword($password);
}
$this->registrationMapper->generateNewToken($registration);
- if ($password !== '' && $username !== '') {
- $this->registrationMapper->generateClientSecret($registration);
- }
+ $this->registrationMapper->generateClientSecret($registration);
$this->registrationMapper->insert($registration);
return $registration;
}
/**
* @param string $email
- * @return Registration|true if there is a pending reg with this email, return the pending reg, if there are no problems with the email, return true.
* @throws RegistrationException
*/
- public function validateEmail($email) {
+ public function validateEmail(string $email): void {
$this->mailService->validateEmail($email);
// check for pending registrations
try {
- return $this->registrationMapper->find($email);//if not found DB will throw a exception
+ $this->registrationMapper->find($email);//if not found DB will throw a exception
+ throw new RegistrationException(
+ $this->l10n->t('A user has already taken this email, maybe you already have an account?')
+ );
} catch (DoesNotExistException $e) {
}
@@ -171,7 +171,6 @@ class RegistrationService {
)
);
}
- return true;
}
/**
@@ -235,10 +234,10 @@ class RegistrationService {
* Find registration entity for token
*
* @param string $token
- * @return string
+ * @return Registration
* @throws RegistrationException
*/
- public function verifyToken($token) {
+ public function verifyToken(string $token): Registration {
try {
return $this->registrationMapper->findByToken($token);
} catch (DoesNotExistException $exception) {
@@ -327,18 +326,29 @@ class RegistrationService {
}
/**
- * @param $token
+ * @param string $email
* @return Registration
+ * @throws DoesNotExistException
*/
- public function getRegistrationForToken($token) {
+ public function getRegistrationForEmail(string $email): Registration {
+ return $this->registrationMapper->find($email);
+ }
+
+ /**
+ * @param string $token
+ * @return Registration
+ * @throws DoesNotExistException
+ */
+ public function getRegistrationForToken(string $token): Registration {
return $this->registrationMapper->findByToken($token);
}
/**
- * @param $secret
+ * @param string $secret
* @return Registration
+ * @throws DoesNotExistException
*/
- public function getRegistrationForSecret($secret) {
+ public function getRegistrationForSecret(string $secret): Registration {
return $this->registrationMapper->findBySecret($secret);
}
diff --git a/templates/form/email.php b/templates/form/email.php
new file mode 100644
index 0000000..e68727e
--- /dev/null
+++ b/templates/form/email.php
@@ -0,0 +1,26 @@
+
+