Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/registration.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2020-07-16 22:15:39 +0300
committerJoas Schilling <coding@schilljs.com>2020-08-18 18:11:26 +0300
commit0b4fac2edfd1aa8dd7bd8225fb9ef239bfa565f6 (patch)
treeccad362547b93fee4318d7815512542d8bf95025 /lib
parent4d5fb2628a1862d2e80ed38fffc7a3a233c14d7f (diff)
Redirect to ClientLoginFlow and ClientLoginFlowV2 when it was used
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Controller/RegisterController.php187
-rw-r--r--lib/Service/LoginFlowService.php107
-rw-r--r--lib/Service/RegistrationService.php38
3 files changed, 218 insertions, 114 deletions
diff --git a/lib/Controller/RegisterController.php b/lib/Controller/RegisterController.php
index ee0b795..94abb43 100644
--- a/lib/Controller/RegisterController.php
+++ b/lib/Controller/RegisterController.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* ownCloud - registration
*
@@ -7,53 +10,63 @@
*
* @author Pellaeon Lin <pellaeon@hs.ntnu.edu.tw>
* @author Julius Härtl <jus@bitgrid.net>
+ * @author 2020 Joas Schilling <coding@schilljs.com>
* @copyright Pellaeon Lin 2014
*/
namespace OCA\Registration\Controller;
+use Exception;
use OCA\Registration\Db\Registration;
+use OCA\Registration\Service\LoginFlowService;
use OCA\Registration\Service\MailService;
use OCA\Registration\Service\RegistrationException;
use OCA\Registration\Service\RegistrationService;
+use OCP\AppFramework\Controller;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\RedirectResponse;
+use OCP\AppFramework\Http\RedirectToDefaultAppResponse;
use OCP\AppFramework\Http\Response;
-use \OCP\IRequest;
-use \OCP\AppFramework\Http\TemplateResponse;
-use \OCP\AppFramework\Http\RedirectResponse;
-use \OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\StandaloneTemplateResponse;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IL10N;
+use OCP\IRequest;
use OCP\IURLGenerator;
-use \OCP\IConfig;
-use \OCP\IL10N;
+use OCP\IConfig;
+use OCP\IL10N;
class RegisterController extends Controller {
/** @var IL10N */
private $l10n;
/** @var IURLGenerator */
- private $urlgenerator;
+ private $urlGenerator;
/** @var IConfig */
private $config;
/** @var RegistrationService */
private $registrationService;
/** @var MailService */
private $mailService;
-
+ /** @var LoginFlowService */
+ private $loginFlowService;
public function __construct(
- $appName,
+ string $appName,
IRequest $request,
IL10N $l10n,
- IURLGenerator $urlgenerator,
+ IURLGenerator $urlGenerator,
IConfig $config,
RegistrationService $registrationService,
+ LoginFlowService $loginFlowService,
MailService $mailService
) {
parent::__construct($appName, $request);
$this->l10n = $l10n;
- $this->urlgenerator = $urlgenerator;
+ $this->urlGenerator = $urlGenerator;
$this->config = $config;
$this->registrationService = $registrationService;
+ $this->loginFlowService = $loginFlowService;
$this->mailService = $mailService;
}
@@ -102,7 +115,7 @@ class RegisterController extends Controller {
}
return new RedirectResponse(
- $this->urlgenerator->linkToRoute(
+ $this->urlGenerator->linkToRoute(
'registration.register.showVerificationForm',
['secret' => $registration->getClientSecret()]
)
@@ -120,12 +133,8 @@ class RegisterController extends Controller {
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');
+ } catch (DoesNotExistException $e) {
+ return $this->validateSecretAndTokenErrorPage();
}
return new TemplateResponse('registration', 'form/verification', [
@@ -151,16 +160,12 @@ class RegisterController extends Controller {
$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');
+ } catch (DoesNotExistException $e) {
+ return $this->validateSecretAndTokenErrorPage();
}
return new RedirectResponse(
- $this->urlgenerator->linkToRoute(
+ $this->urlGenerator->linkToRoute(
'registration.register.showUserForm',
[
'secret' => $secret,
@@ -176,95 +181,101 @@ class RegisterController extends Controller {
*
* @param string $secret
* @param string $token
+ * @param string $username
+ * @param string $message
* @return TemplateResponse
*/
- public function showUserForm(string $secret, string $token): TemplateResponse {
+ public function showUserForm(string $secret, string $token, string $username = '', string $message = ''): TemplateResponse {
try {
- $registration = $this->registrationService->getRegistrationForSecret($secret);
-
- if ($registration->getToken() !== $token) {
- throw new RegistrationException('Invalid verification token');
- }
+ $registration = $this->validateSecretAndToken($secret, $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');
+ return $this->validateSecretAndTokenErrorPage();
}
- try {
- /** @var Registration $registration */
- $registration = $this->registrationService->verifyToken($token);
- $this->registrationService->confirmEmail($registration);
-
- // create account without form if username/password are already stored
- if ($registration->getUsername() !== "" && $registration->getPassword() !== "") {
- $this->registrationService->createAccount($registration);
- return new TemplateResponse('registration', 'message',
- ['msg' => $this->l10n->t('Your account has been successfully created, you can <a href="%s">log in now</a>.', [$this->urlgenerator->getAbsoluteURL('/')])],
- 'guest'
- );
- }
-
- return new TemplateResponse('registration', 'form/user', [
- 'email' => $registration->getEmail(),
- 'email_is_login' => $this->config->getAppValue('registration', 'email_is_login', '0') === '1',
- 'token' => $registration->getToken(),
- ], 'guest');
- } catch (RegistrationException $exception) {
- return $this->renderError($exception->getMessage(), $exception->getHint());
- }
+ return new TemplateResponse('registration', 'form/user', [
+ 'email' => $registration->getEmail(),
+ 'email_is_login' => $this->config->getAppValue('registration', 'email_is_login', '0') === '1',
+ 'username' => $username,
+ 'message' => $message,
+ ], 'guest');
}
/**
* @PublicPage
* @UseSession
*
- * @param $token
+ * @param string $secret
+ * @param string $token
+ * @param string $username
+ * @param string $password
* @return RedirectResponse|TemplateResponse
*/
- public function submitUserForm($token) {
- $registration = $this->registrationService->getRegistrationForToken($token);
+ public function submitUserForm(string $secret, string $token, string $username, string $password): Response {
+ try {
+ $registration = $this->validateSecretAndToken($secret, $token);
+ } catch (RegistrationException $e) {
+ return $this->validateSecretAndTokenErrorPage();
+ }
+
if ($this->config->getAppValue('registration', 'email_is_login', '0') === '1') {
$username = $registration->getEmail();
- } else {
- $username = $this->request->getParam('username');
}
- $password = $this->request->getParam('password');
try {
$user = $this->registrationService->createAccount($registration, $username, $password);
- } catch (\Exception $exception) {
- // Render form with previously sent values
- return new TemplateResponse('registration', 'form',
- [
- 'email' => $registration->getEmail(),
- 'entered_data' => ['user' => $username],
- 'errormsgs' => [$exception->getMessage()],
- 'token' => $token
- ], 'guest');
+ } catch (Exception $exception) {
+ return $this->showUserForm($secret, $token, $username, $exception->getMessage());
}
if ($user->isEnabled()) {
- // log the user
- return $this->registrationService->loginUser($user->getUID(), $username, $password, false);
- } else {
- // warn the user their account needs admin validation
- return new TemplateResponse(
- 'registration',
- 'message',
- ['msg' => $this->l10n->t("Your account has been successfully created, but it still needs approval from an administrator.")],
- 'guest');
+ $this->registrationService->loginUser($user->getUID(), $user->getUID(), $password);
+
+ if ($this->loginFlowService->isUsingLoginFlow(2)) {
+ $response = $this->loginFlowService->tryLoginFlowV2($user);
+ if ($response instanceof Response) {
+ return $response;
+ }
+ }
+
+ if ($this->loginFlowService->isUsingLoginFlow(1)) {
+ $response = $this->loginFlowService->tryLoginFlowV1();
+ if ($response instanceof Response && $response->getStatus() === Http::STATUS_SEE_OTHER) {
+ return $response;
+ }
+ }
+
+ return new RedirectToDefaultAppResponse();
}
+
+ // warn the user their account needs admin validation
+ return new StandaloneTemplateResponse('registration', 'approval-required', [], 'guest');
+ }
+
+ /**
+ * @param string $secret
+ * @param string $token
+ * @return Registration
+ * @throws RegistrationException
+ */
+ protected function validateSecretAndToken(string $secret, string $token): Registration {
+ try {
+ $registration = $this->registrationService->getRegistrationForSecret($secret);
+ } catch (DoesNotExistException $e) {
+ throw new RegistrationException('Invalid secret');
+ }
+
+ if ($registration->getToken() !== $token) {
+ throw new RegistrationException('Invalid token');
+ }
+
+ return $registration;
}
- private function renderError($error, $hint="") {
- return new TemplateResponse('', 'error', [
- 'errors' => [[
- 'error' => $error,
- 'hint' => $hint
- ]]
+ protected function validateSecretAndTokenErrorPage(): TemplateResponse {
+ return new TemplateResponse('core', 'error', [
+ 'errors' => [
+ $this->l10n->t('The verification failed.'),
+ ],
], 'error');
}
}
diff --git a/lib/Service/LoginFlowService.php b/lib/Service/LoginFlowService.php
new file mode 100644
index 0000000..9e5e7e3
--- /dev/null
+++ b/lib/Service/LoginFlowService.php
@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Registration\Service;
+
+use OC\Core\Controller\ClientFlowLoginController;
+use OC\Core\Controller\ClientFlowLoginV2Controller;
+use OC\Core\Service\LoginFlowV2Service;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\StandaloneTemplateResponse;
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\IUser;
+
+class LoginFlowService {
+
+ /** @var IRequest */
+ protected $request;
+ /** @var ISession */
+ protected $session;
+ /** @var LoginFlowV2Service */
+ protected $loginFlowV2Service;
+
+ public function __construct(
+ IRequest $request,
+ ISession $session,
+ LoginFlowV2Service $loginFlowV2Service
+ ) {
+ $this->request = $request;
+ $this->session = $session;
+ $this->loginFlowV2Service = $loginFlowV2Service;
+ }
+
+ public function isUsingLoginFlow(?int $version = null): bool {
+ if (($version === 1 || $version === null) && $this->session->get(ClientFlowLoginController::STATE_NAME) !== null) {
+ return true;
+ }
+
+ if (($version === 2 || $version === null) && $this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME) !== null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function tryLoginFlowV1(): ?Response {
+ /** @var ClientFlowLoginController $controller */
+ $container = \OC::$server->getRegisteredAppContainer('core');
+ $controller = $container->query(ClientFlowLoginController::class);
+ return $controller->generateAppPassword(
+ $this->session->get(ClientFlowLoginController::STATE_NAME)
+ );
+ }
+
+ public function tryLoginFlowV2(IUser $user): ?StandaloneTemplateResponse {
+ $result = $this->loginFlowV2Service->flowDone(
+ $this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME),
+ $this->session->getId(),
+ $this->getServerPath(),
+ $user->getUID()
+ );
+
+ if (!$result) {
+ return null;
+ }
+
+ return new StandaloneTemplateResponse(
+ 'core',
+ 'loginflowv2/done',
+ [],
+ 'guest'
+ );
+ }
+
+ private function getServerPath(): string {
+ $serverPostfix = '';
+
+ if (strpos($this->request->getRequestUri(), '/index.php') !== false) {
+ $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/index.php'));
+ } elseif (strpos($this->request->getRequestUri(), '/login/v2') !== false) {
+ $serverPostfix = substr($this->request->getRequestUri(), 0, strpos($this->request->getRequestUri(), '/login/v2'));
+ }
+
+ $protocol = $this->request->getServerProtocol();
+ return $protocol . '://' . $this->request->getServerHost() . $serverPostfix;
+ }
+}
diff --git a/lib/Service/RegistrationService.php b/lib/Service/RegistrationService.php
index 3d5bb85..49528d8 100644
--- a/lib/Service/RegistrationService.php
+++ b/lib/Service/RegistrationService.php
@@ -40,6 +40,7 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
+use OCP\IUser;
use OCP\Security\ICrypto;
use OCP\Session\Exceptions\SessionNotAvailableException;
use \OCP\IUserManager;
@@ -247,12 +248,12 @@ class RegistrationService {
/**
* @param $registration
- * @param string $username
- * @param string $password
+ * @param string|null $username
+ * @param string|null $password
* @return \OCP\IUser
* @throws RegistrationException|InvalidTokenException
*/
- public function createAccount(Registration $registration, $username = null, $password = null) {
+ public function createAccount(Registration $registration, ?string $username = null, ?string $password = null) {
if ($password === null && $registration->getPassword() === null) {
$generatedPassword = $this->generateRandomDeviceToken();
$registration->setPassword($this->crypto->encrypt($generatedPassword));
@@ -414,33 +415,18 @@ class RegistrationService {
}
/**
- * @param $userId
- * @param $username
- * @param $password
- * @param $decrypt
- * @return RedirectResponse|TemplateResponse
+ * @param string $userId
+ * @param string $username
+ * @param string $password
+ * @param bool $decrypt
*/
- public function loginUser($userId, $username, $password, $decrypt = false) {
+ public function loginUser(string $userId, string $username, string $password, bool $decrypt = false): void {
if ($decrypt) {
$password = $this->crypto->decrypt($password);
}
- if (method_exists($this->usersession, 'createSessionToken')) {
- $this->usersession->login($username, $password);
- $this->usersession->createSessionToken($this->request, $userId, $username, $password);
- return new RedirectResponse($this->urlGenerator->linkTo('', 'index.php'));
- } elseif (\OC_User::login($username, $password)) {
- $this->cleanupLoginTokens($userId);
- // FIXME unsetMagicInCookie will fail from session already closed, so now we always remember
- $logintoken = $this->random->generate(32);
- $this->config->setUserValue($userId, 'login_token', $logintoken, time());
- \OC_User::setMagicInCookie($userId, $logintoken);
- \OC_Util::redirectToDefaultPage();
- }
- // Render message in case redirect failed
- return new TemplateResponse('registration', 'message',
- ['msg' => $this->l10n->t('Your account has been successfully created, you can <a href="%s">log in now</a>.', [$this->urlGenerator->getAbsoluteURL('/')])]
- , 'guest'
- );
+
+ $this->usersession->login($username, $password);
+ $this->usersession->createSessionToken($this->request, $userId, $username, $password);
}
/**