From 538897c9d5db1a900ac15848808126f56801e897 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 1 Sep 2020 20:26:56 +0200 Subject: [PATCH] Remove old OCS API Signed-off-by: Joas Schilling --- README.md | 6 +- appinfo/routes.php | 5 - lib/Controller/ApiController.php | 181 ----------------- lib/Service/RegistrationService.php | 43 ---- tests/Unit/Controller/ApiControllerTest.php | 188 ------------------ .../Service/RegistrationServiceTest.php | 2 +- 6 files changed, 2 insertions(+), 423 deletions(-) delete mode 100644 lib/Controller/ApiController.php delete mode 100644 tests/Unit/Controller/ApiControllerTest.php rename tests/{Integration => Unit}/Service/RegistrationServiceTest.php (99%) diff --git a/README.md b/README.md index b6edcde..e7bf924 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ From your Nextcloud instance, click: your profile to the upper right -> Apps -> - Add users to a given group - Allow-list with email domains (including wildcard) to register with - Admins will be notified via email for new user creation or require approval -- Supports Nextcloud's Client Login Flow v1 and v2 - Allowing registration in the mobile Apps and Desktop clients +- Supports Nextcloud's Client [Login Flow v1 and v2](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html) - Allowing registration in the mobile Apps and Desktop clients # Web form registration flow @@ -22,10 +22,6 @@ From your Nextcloud instance, click: your profile to the upper right -> Apps -> 4. User is lead to a form where they can choose their username and password 5. New account is created and is logged in automatically -# OCS API registration flow - -The [OCS Api](https://gist.github.com/juliushaertl/5a1d1132e7370b5ad38fbd6da3cae5b8) is deprecated, use the Nextcloud [Login Flow](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html) instead. - # Donate You can donate to Pellaeon the original author of the app: diff --git a/appinfo/routes.php b/appinfo/routes.php index d83acb7..0f152ee 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -20,9 +20,4 @@ return [ ['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'], - ] ]; diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php deleted file mode 100644 index f217525..0000000 --- a/lib/Controller/ApiController.php +++ /dev/null @@ -1,181 +0,0 @@ - - * - * @author Julius Härtl - * - * @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 . - * - */ - -namespace OCA\Registration\Controller; - -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; -use OCP\AppFramework\OCS\OCSBadRequestException; -use OCP\AppFramework\OCS\OCSException; -use OCP\AppFramework\OCS\OCSNotFoundException; -use OCP\AppFramework\OCSController; -use OCP\AppFramework\Http\DataResponse; -use OCP\Defaults; -use OCP\IL10N; -use OCP\IRequest; - -class ApiController extends OCSController { - - /** @var RegistrationService */ - private $registrationService; - /** @var MailService */ - private $mailService; - /** @var IL10N */ - private $l10n; - /** @var Defaults */ - private $defaults; - - public const REGISTRATION_STATUS_COMPLETE = 0; - public const REGISTRATION_STATUS_PENDING = 1; - public const REGISTRATION_STATUS_EXISTING = 2; - - public function __construct($appName, - IRequest $request, - RegistrationService $registrationService, - MailService $mailService, - IL10N $l10n, - Defaults $defaults) { - parent::__construct($appName, $request); - $this->registrationService = $registrationService; - $this->mailService = $mailService; - $this->l10n = $l10n; - $this->defaults = $defaults; - } - - /** - * @PublicPage - * @AnonRateThrottle(limit=5, period=1) - * - * @param string $username - * @param string $displayname - * @param string $email - * @throws \Exception - * @return DataResponse - */ - public function validate($username, $displayname, $email) { - try { - $this->registrationService->validateEmail($email); - $this->registrationService->validateDisplayname($displayname); - $this->registrationService->validateUsername($username); - } catch (RegistrationException $e) { - throw new OCSBadRequestException($e->getMessage()); - } - $data = [ - 'username' => $username, - 'displayname' => $displayname, - 'email' => $email - ]; - return new DataResponse($data, Http::STATUS_OK); - } - - /** - * @PublicPage - * @AnonRateThrottle(limit=10, period=1) - * - * @param string $clientSecret - * @throws \Exception - * @return DataResponse - */ - public function status($clientSecret) { - try { - /** @var Registration $registration */ - $registration = $this->registrationService->getRegistrationForSecret($clientSecret); - } catch (DoesNotExistException $e) { - throw new OCSNotFoundException('No pending registration.'); - } - - if (!$registration->getEmailConfirmed()) { - return new DataResponse( - [ - 'registrationStatus' => self::REGISTRATION_STATUS_PENDING, - 'message' => $this->l10n->t('Your registration is pending. Please confirm your email address.') - ], - Http::STATUS_OK - ); - } else { - // create account if email confirmed and not already created - $user = $this->registrationService->getUserAccount($registration); - if ($user === null) { - $user = $this->registrationService->createAccount($registration); - } - $this->registrationService->loginUser($user->getUID(), $registration->getUsername(), $registration->getPassword(), true); - $appPassword = $this->registrationService->generateAppPassword($user->getUID()); - $data = [ - 'appPassword' => $appPassword, - 'cloudUrl' => $this->defaults->getBaseUrl(), - 'registrationStatus' => self::REGISTRATION_STATUS_COMPLETE - ]; - $this->registrationService->deleteRegistration($registration); - return new DataResponse($data, Http::STATUS_OK); - } - } - - /** - * @PublicPage - * @AnonRateThrottle(limit=5, period=1) - * - * @param string $username - * @param string $displayname - * @param string $email - * @param string $password - * @throws \Exception - * @return DataResponse - */ - public function register($username, $displayname, $email, $password) { - $data = []; - try { - $secret = null; - $registration = $this->registrationService->validateEmail($email); - if ($registration === true) { - $this->registrationService->validateDisplayname($displayname); - $this->registrationService->validateUsername($username); - $registration = $this->registrationService->createRegistration($email, $username, $password, $displayname); - $this->mailService->sendTokenByMail($registration); - $secret = $registration->getClientSecret(); - } else { - $this->registrationService->generateNewToken($registration); - $this->mailService->sendTokenByMail($registration); - return new DataResponse( - [ - 'registrationStatus' => self::REGISTRATION_STATUS_EXISTING, - 'message' => $this->l10n->t('There is already a pending registration with this email, a new verification email has been sent to the address.') - ], - Http::STATUS_OK - ); - } - - $data['message'] = $this->l10n->t('Your registration is pending. Please confirm your email address.'); - $data['registrationStatus'] = self::REGISTRATION_STATUS_PENDING; - if ($secret !== null) { - $data['secret'] = $secret; - } - return new DataResponse($data, Http::STATUS_OK); - } catch (RegistrationException $exception) { - throw new OCSException($exception->getMessage(), $exception->getCode()); - } - } -} diff --git a/lib/Service/RegistrationService.php b/lib/Service/RegistrationService.php index 121597c..bc71ac4 100644 --- a/lib/Service/RegistrationService.php +++ b/lib/Service/RegistrationService.php @@ -284,21 +284,6 @@ class RegistrationService { return $allowedDomains; } - /** - * Find registration entity for token - * - * @param string $token - * @return Registration - * @throws RegistrationException - */ - public function verifyToken(string $token): Registration { - try { - return $this->registrationMapper->findByToken($token); - } catch (DoesNotExistException $exception) { - throw new RegistrationException($this->l10n->t('Invalid verification URL. No registration request with this verification URL is found.', 404)); - } - } - /** * @param $registration * @param string|null $username @@ -378,15 +363,6 @@ class RegistrationService { return $this->registrationMapper->find($email); } - /** - * @param string $token - * @return Registration - * @throws DoesNotExistException - */ - public function getRegistrationForToken(string $token): Registration { - return $this->registrationMapper->findByToken($token); - } - /** * @param string $secret * @return Registration @@ -396,10 +372,6 @@ class RegistrationService { return $this->registrationMapper->findBySecret($secret); } - public function getUserAccount(Registration $registration): ?IUser { - return $this->userManager->get($registration->getUsername()); - } - public function deleteRegistration(Registration $registration): void { $this->registrationMapper->delete($registration); } @@ -463,19 +435,4 @@ class RegistrationService { $this->userSession->login($username, $password); $this->userSession->createSessionToken($this->request, $userId, $username, $password); } - - /** - * Replicates OC::cleanupLoginTokens() since it's protected - * @param string $userId - */ - public function cleanupLoginTokens(string $userId): void { - $cutoff = time() - $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); - $tokens = $this->config->getUserKeys($userId, 'login_token'); - foreach ($tokens as $token) { - $time = $this->config->getUserValue($userId, 'login_token', $token); - if ($time < $cutoff) { - $this->config->deleteUserValue($userId, 'login_token', $token); - } - } - } } diff --git a/tests/Unit/Controller/ApiControllerTest.php b/tests/Unit/Controller/ApiControllerTest.php deleted file mode 100644 index e37d46a..0000000 --- a/tests/Unit/Controller/ApiControllerTest.php +++ /dev/null @@ -1,188 +0,0 @@ - - * @copyright Pellaeon Lin 2014 - */ - -namespace OCA\Registration\Tests\Unit\Controller; - -use OCA\Registration\Controller\ApiController; -use OCA\Registration\Db\Registration; -use OCA\Registration\Service\MailService; -use OCA\Registration\Service\RegistrationService; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\OCS\OCSException; -use OCP\AppFramework\OCS\OCSNotFoundException; -use OCP\Defaults; -use OCP\IL10N; -use OCP\IRequest; -use OCP\IUser; -use ChristophWurst\Nextcloud\Testing\TestCase; - -class ApiControllerTest extends TestCase { - - /** @var IRequest */ - private $request; - /** @var RegistrationService|\PHPUnit_Framework_MockObject_MockObject */ - private $registrationService; - /** @var MailService */ - private $mailService; - /** @var IL10N */ - private $l10n; - /** @var Defaults */ - private $defaults; - /** @var ApiController */ - private $controller; - - public function setUp(): void { - parent::setUp(); - $this->request = $this->createMock(IRequest::class); - $this->registrationService = $this->createMock(RegistrationService::class); - $this->mailService = $this->createMock(MailService::class); - $this->l10n = $this->createMock(IL10N::class); - $this->defaults = $this->createMock(Defaults::class); - $this->controller = new ApiController( - "registration", - $this->request, - $this->registrationService, - $this->mailService, - $this->l10n, - $this->defaults - ); - } - - public function testValidate() { - $this->registrationService - ->expects($this->once()) - ->method('validateEmail') - ->with('test@example.com'); - $this->registrationService - ->expects($this->once()) - ->method('validateDisplayname') - ->with('user test'); - $this->registrationService - ->expects($this->once()) - ->method('validateUsername') - ->with('user1'); - - $expected = new DataResponse([ - 'username' => 'user1', - 'displayname' => 'user test', - 'email' => 'test@example.com' - ], Http::STATUS_OK); - $actual = $this->controller->validate('user1', 'user test', 'test@example.com'); - $this->assertEquals($expected, $actual); - } - - public function testValidateFailEmail() { - $exception = new OCSException('', 999); - - $this->expectException(get_class($exception)); - - $this->registrationService - ->expects($this->once()) - ->method('validateEmail') - ->willThrowException($exception); - - $this->controller->validate('user1', 'user test', 'test@example.com'); - } - - public function testValidateFailDisplayname() { - $exception = new OCSException('', 999); - - $this->expectException(get_class($exception)); - - $this->registrationService - ->expects($this->once()) - ->method('validateDisplayname') - ->willThrowException($exception); - - $this->controller->validate('user1', 'user test', 'test@example.com'); - } - - public function testValidateFailUsername() { - $exception = new OCSException('', 999); - - $this->expectException(get_class($exception)); - - $this->registrationService - ->expects($this->once()) - ->method('validateUsername') - ->willThrowException($exception); - - $this->controller->validate('user1', 'user test', 'test@example.com'); - } - - public function testStatusNoRegistration() { - $exception = new OCSNotFoundException(''); - - $this->expectException(get_class($exception)); - - $this->registrationService - ->method('getRegistrationForSecret') - ->with('L2qdLAtrJTx499ErjwkwnZqGmLdm3Acp') - ->willThrowException($exception); - - $this->controller->status('L2qdLAtrJTx499ErjwkwnZqGmLdm3Acp'); - } - - public function testStatusPendingRegistration() { - $registration = new Registration(); - $registration->setEmailConfirmed(false); - $this->registrationService - ->method('getRegistrationForSecret') - ->with('L2qdLAtrJTx499ErjwkwnZqGmLdm3Acp') - ->willReturn($registration); - - $actual = $this->controller->status('L2qdLAtrJTx499ErjwkwnZqGmLdm3Acp'); - - $expected = new DataResponse( - [ - 'registrationStatus' => 1, - 'message' => $this->l10n->t('Your registration is pending. Please confirm your email address.'), - ], - Http::STATUS_OK - ); - - $this->assertEquals($expected, $actual); - } - - public function testStatusConfirmedRegistration() { - $registration = new Registration(); - $registration->setEmailConfirmed(true); - $registration->setClientSecret('mysecret'); - $registration->setUsername('user'); - $registration->setPassword('password'); - $user = $this->createMock(IUser::class); - $user->method('getUID') - ->willReturn('user'); - $this->registrationService - ->method('getRegistrationForSecret') - ->with('mysecret') - ->willReturn($registration); - $this->registrationService - ->expects($this->once()) - ->method('getUserAccount') - ->with($registration) - ->willReturn($user); - $this->registrationService - ->expects($this->once()) - ->method('loginUser'); - $this->registrationService - ->expects($this->once()) - ->method('generateAppPassword'); - $actual = $this->controller->status('mysecret'); - $expected = new DataResponse([ - 'appPassword' => null, - 'cloudUrl' => $this->defaults->getBaseUrl(), - 'registrationStatus' => 0, - ]); - $this->assertEquals($expected, $actual); - } -} diff --git a/tests/Integration/Service/RegistrationServiceTest.php b/tests/Unit/Service/RegistrationServiceTest.php similarity index 99% rename from tests/Integration/Service/RegistrationServiceTest.php rename to tests/Unit/Service/RegistrationServiceTest.php index 32fd823..7994d07 100644 --- a/tests/Integration/Service/RegistrationServiceTest.php +++ b/tests/Unit/Service/RegistrationServiceTest.php @@ -1,6 +1,6 @@