From be047cb2699f97483e67d84896f8646bf8183072 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 10:34:17 -0300 Subject: [PATCH 1/6] Simplify test --- tests/Unit/Service/WebhookServiceTest.php | 63 ++--------------------- 1 file changed, 3 insertions(+), 60 deletions(-) diff --git a/tests/Unit/Service/WebhookServiceTest.php b/tests/Unit/Service/WebhookServiceTest.php index 28fa2b0d1..f95b3b810 100644 --- a/tests/Unit/Service/WebhookServiceTest.php +++ b/tests/Unit/Service/WebhookServiceTest.php @@ -43,6 +43,9 @@ public function setUp(): void { $this->config = $this->createMock(IConfig::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->l10n = $this->createMock(IL10N::class); + $this->l10n + ->method('t') + ->will($this->returnArgument(0)); $this->file = $this->createMock(FileMapper::class); $this->fileUser = $this->createMock(FileUserMapper::class); $this->user = $this->createMock(IUser::class); @@ -62,10 +65,6 @@ public function setUp(): void { public function testEmptyFile() { $this->expectExceptionMessage('Empty file'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'name' => 'test', 'userManager' => $this->user @@ -75,10 +74,6 @@ public function testEmptyFile() { public function testValidateInvalidBase64File() { $this->expectExceptionMessage('Invalid base64 file'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'qwert'], 'name' => 'test', @@ -89,10 +84,6 @@ public function testValidateInvalidBase64File() { public function testValidateFileUrl() { $this->expectExceptionMessage('Invalid url file'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['url' => 'qwert'], 'name' => 'test', @@ -103,10 +94,6 @@ public function testValidateFileUrl() { public function testValidateNameIsMandatory() { $this->expectExceptionMessage('Name is mandatory'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['url' => 'qwert'], 'userManager' => $this->user @@ -116,10 +103,6 @@ public function testValidateNameIsMandatory() { public function testValidateInvalidName() { $this->expectExceptionMessage('The name can only contain "a-z", "A-Z", "0-9" and "-_" chars.'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['url' => 'qwert'], 'userManager' => $this->user, @@ -130,10 +113,6 @@ public function testValidateInvalidName() { public function testValidateEmptyUserCollection() { $this->expectExceptionMessage('Empty users collection'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $response = $this->createMock(IResponse::class); $response ->method('getHeaders') @@ -156,10 +135,6 @@ public function testValidateEmptyUserCollection() { public function testValidateEmptyUsersCollection() { $this->expectExceptionMessage('Empty users collection'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -170,10 +145,6 @@ public function testValidateEmptyUsersCollection() { public function testValidateUserCollectionNotArray() { $this->expectExceptionMessage('User collection need to be an array'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -185,10 +156,6 @@ public function testValidateUserCollectionNotArray() { public function testValidateUserEmptyCollection() { $this->expectExceptionMessage('Empty users collection'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -200,10 +167,6 @@ public function testValidateUserEmptyCollection() { public function testValidateUserInvalidCollection() { $this->expectExceptionMessage('User collection need to be an array: user 0'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -217,10 +180,6 @@ public function testValidateUserInvalidCollection() { public function testValidateUserEmpty() { $this->expectExceptionMessage('User collection need to be an array with values: user 0'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -234,10 +193,6 @@ public function testValidateUserEmpty() { public function testValidateUserWithoutEmail() { $this->expectExceptionMessage('User need to be email: user 0'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -253,10 +208,6 @@ public function testValidateUserWithoutEmail() { public function testValidateUserWithInvalidEmail() { $this->expectExceptionMessage('Invalid email: user 0'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -272,10 +223,6 @@ public function testValidateUserWithInvalidEmail() { public function testValidateUserDuplicatedEmail() { $this->expectExceptionMessage('Remove duplicated users, email need to be unique'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', @@ -298,10 +245,6 @@ public function testIndexWithoutPermission() { ->method('getAppValue') ->willReturn('["admin"]'); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); - $this->service->validate([ 'file' => ['base64' => 'dGVzdA=='], 'name' => 'test', From f6c82198bfc60b95991f67adc3d803d8ee0572b8 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 11:44:22 -0300 Subject: [PATCH 2/6] Start implementing endpoint for create user to sign --- appinfo/routes.php | 1 + lib/Controller/AccountController.php | 58 +++++++++ lib/Service/AccountService.php | 46 +++++++ .../Unit/Controller/AccountControllerTest.php | 45 +++++++ tests/Unit/Service/AccountServiceTest.php | 113 ++++++++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 lib/Controller/AccountController.php create mode 100644 lib/Service/AccountService.php create mode 100644 tests/Unit/Controller/AccountControllerTest.php create mode 100644 tests/Unit/Service/AccountServiceTest.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 673090f62..047fe18fc 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -7,6 +7,7 @@ 'verb' => 'OPTIONS', 'requirements' => ['path' => '.+'], ], ['name' => 'webhook#register', 'url' => '/api/0.1/webhook/register', 'verb' => 'POST'], ['name' => 'libresign#sign', 'url' => '/api/0.1/sign', 'verb' => 'POST'], + ['name' => 'account#createToSign', 'url' => '/api/0.1/account/create/{uuid}', 'verb' => 'POST'], ['name' => 'signature#generate', 'url' => '/api/0.1/signature/generate', 'verb' => 'POST'], ['name' => 'signature#hasRootCert', 'url' => '/api/0.1/signature/has-root-cert', 'verb' => 'GET'], // Admin config diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php new file mode 100644 index 000000000..b2a737eae --- /dev/null +++ b/lib/Controller/AccountController.php @@ -0,0 +1,58 @@ +l10n = $l10n; + $this->account = $account; + } + + /** + * @NoAdminRequired + * @CORS + * @NoCSRFRequired + * @return JSONResponse + */ + public function createToSign(string $uuid, string $email) { + try { + $data = [ + 'uuid' => $uuid, + 'email' => $email + ]; + $this->account->validateCreateToSign($data); + } catch (\Throwable $th) { + return new JSONResponse( + [ + 'message' => $th->getMessage(), + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } + return new JSONResponse( + [ + 'message' => $this->l10n->t('Success'), + 'data' => $return + ], + Http::STATUS_OK + ); + } +} diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php new file mode 100644 index 000000000..999fe02d7 --- /dev/null +++ b/lib/Service/AccountService.php @@ -0,0 +1,46 @@ +l10n = $l10n; + $this->fileUserMapper = $fileUserMapper; + } + + public function validateCreateToSign(array $data) { + if (!UUIDUtil::validateUUID($data['uuid'])) { + throw new LibresignException($this->l10n->t('Invalid UUID'), 1); + } + try { + $fileUser = $this->fileUserMapper->getByUuid($data['uuid']); + } catch (\Throwable $th) { + throw new LibresignException($this->l10n->t('UUID not found'), 1); + } + if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { + throw new LibresignException($this->l10n->t('Invalid email'), 1); + } + if ($fileUser->getEmail() != $data['email']) { + throw new LibresignException($this->l10n->t('Dont is your file'), 1); + } + if ($data['password'] != $data['confirmPassword']) { + throw new LibresignException($this->l10n->t('Password and confirmation dont match'), 1); + } + if ($data['signPassword'] != $data['signConfirmPassword']) { + throw new LibresignException($this->l10n->t('Password and confirmation of signature dont match'), 1); + } + } +} diff --git a/tests/Unit/Controller/AccountControllerTest.php b/tests/Unit/Controller/AccountControllerTest.php new file mode 100644 index 000000000..d93426b91 --- /dev/null +++ b/tests/Unit/Controller/AccountControllerTest.php @@ -0,0 +1,45 @@ +request = $this->createMock(IRequest::class); + $this->l10n = $this->createMock(IL10N::class); + $this->account = $this->createMock(AccountService::class); + $this->controller = new AccountController( + $this->request, + $this->l10n, + $this->account + ); + } + + public function testCreateSuccess() { + $this->l10n + ->method('t') + ->will($this->returnArgument(0)); + + $actual = $this->controller->createToSign('uuid', 'email'); + $expected = new JSONResponse([ + 'message' => 'Success', + 'data' => null + ], Http::STATUS_OK); + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/Unit/Service/AccountServiceTest.php b/tests/Unit/Service/AccountServiceTest.php new file mode 100644 index 000000000..e2b2c174c --- /dev/null +++ b/tests/Unit/Service/AccountServiceTest.php @@ -0,0 +1,113 @@ +l10n = $this->createMock(IL10N::class); + $this->l10n + ->method('t') + ->will($this->returnArgument(0)); + $this->fileUserMapper = $this->createMock(FileUserMapper::class); + $this->service = new AccountService( + $this->l10n, + $this->fileUserMapper + ); + } + + public function testValidateInvalidUuid() { + $this->expectExceptionMessage('Invalid UUID'); + $this->service->validateCreateToSign([ + 'uuid' => 'invalid' + ]); + } + + public function testValidateUuidNotFound() { + $this->fileUserMapper + ->method('getByUuid') + ->willReturnCallback(function () { + throw new \Exception("Beep, beep, not found!", 1); + }); + $this->expectExceptionMessage('UUID not found'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012' + ]); + } + + public function testValidateInvalidEmail() { + $this->expectExceptionMessage('Invalid email'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012', + 'email' => 'invalid' + ]); + } + + public function testValidateDontIsYourFile() { + $fileUser = $this->createMock(FileUser::class); + $fileUser + ->method('__call') + ->with($this->equalTo('getEmail'), $this->anything()) + ->will($this->returnValue('valid@test.coop')); + $this->fileUserMapper + ->method('getByUuid') + ->will($this->returnValue($fileUser)); + $this->expectExceptionMessage('Dont is your file'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012', + 'email' => 'invalid@test.coop' + ]); + } + + public function testValidatePasswordDontMatch() { + $fileUser = $this->createMock(FileUser::class); + $fileUser + ->method('__call') + ->with($this->equalTo('getEmail'), $this->anything()) + ->will($this->returnValue('valid@test.coop')); + $this->fileUserMapper + ->method('getByUuid') + ->will($this->returnValue($fileUser)); + $this->expectExceptionMessage('Password and confirmation dont match'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012', + 'email' => 'valid@test.coop', + 'password' => '123456789', + 'confirmPassword' => 'abcdefghi' + ]); + } + + public function testValidateSignPasswordDontMatch() { + $fileUser = $this->createMock(FileUser::class); + $fileUser + ->method('__call') + ->with($this->equalTo('getEmail'), $this->anything()) + ->will($this->returnValue('valid@test.coop')); + $this->fileUserMapper + ->method('getByUuid') + ->will($this->returnValue($fileUser)); + $this->expectExceptionMessage('Password and confirmation of signature dont match'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012', + 'email' => 'valid@test.coop', + 'password' => '123456789', + 'confirmPassword' => '123456789', + 'signPassword' => '123456789', + 'signConfirmPassword' => 'abcdefghi' + ]); + } +} From 2b4b9d2e65b57dcd1be8c0ebe331fa755df4469b Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 11:45:53 -0300 Subject: [PATCH 3/6] Remove unecessary cast --- lib/Service/WebhookService.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/Service/WebhookService.php b/lib/Service/WebhookService.php index 33c353664..e4e8b5e92 100644 --- a/lib/Service/WebhookService.php +++ b/lib/Service/WebhookService.php @@ -67,42 +67,42 @@ private function validateUserManager(IUser $user) { private function validateFile($data) { if (empty($data['name'])) { - throw new \Exception((string)$this->l10n->t('Name is mandatory')); + throw new \Exception($this->l10n->t('Name is mandatory')); } if (!preg_match('/^[\w \-_]+$/', $data['name'])) { - throw new \Exception((string)$this->l10n->t('The name can only contain "a-z", "A-Z", "0-9" and "-_" chars.')); + throw new \Exception($this->l10n->t('The name can only contain "a-z", "A-Z", "0-9" and "-_" chars.')); } if (empty($data['file'])) { - throw new \Exception((string)$this->l10n->t('Empty file')); + throw new \Exception($this->l10n->t('Empty file')); } if (empty($data['file']['url']) && empty($data['file']['base64'])) { - throw new \Exception((string)$this->l10n->t('Inform url or base64 to sign')); + throw new \Exception($this->l10n->t('Inform url or base64 to sign')); } if (!empty($data['file']['url'])) { if (!filter_var($data['file']['url'], FILTER_VALIDATE_URL)) { - throw new \Exception((string)$this->l10n->t('Invalid url file')); + throw new \Exception($this->l10n->t('Invalid url file')); } $response = $this->client->newClient()->get($data['file']['url']); $contentType = $response->getHeaders()['Content-Type'][0]; if ($contentType != 'application/pdf') { - throw new \Exception((string)$this->l10n->t('The URL should be a PDF.')); + throw new \Exception($this->l10n->t('The URL should be a PDF.')); } } if (!empty($data['file']['base64'])) { $input = base64_decode($data['file']['base64']); $base64 = base64_encode($input); if ($data['file']['base64'] != $base64) { - throw new \Exception((string)$this->l10n->t('Invalid base64 file')); + throw new \Exception($this->l10n->t('Invalid base64 file')); } } } private function validateUsers($data) { if (empty($data['users'])) { - throw new \Exception((string)$this->l10n->t('Empty users collection')); + throw new \Exception($this->l10n->t('Empty users collection')); } if (!is_array($data['users'])) { - throw new \Exception((string)$this->l10n->t('User collection need to be an array')); + throw new \Exception($this->l10n->t('User collection need to be an array')); } $emails = []; foreach ($data['users'] as $index => $user) { @@ -111,22 +111,22 @@ private function validateUsers($data) { } $uniques = array_unique($emails); if (count($emails) > count($uniques)) { - throw new \Exception((string)$this->l10n->t('Remove duplicated users, email need to be unique')); + throw new \Exception($this->l10n->t('Remove duplicated users, email need to be unique')); } } private function validateUser($user, $index) { if (!is_array($user)) { - throw new \Exception((string)$this->l10n->t('User collection need to be an array: user ' . $index)); + throw new \Exception($this->l10n->t('User collection need to be an array: user ' . $index)); } if (!$user) { - throw new \Exception((string)$this->l10n->t('User collection need to be an array with values: user ' . $index)); + throw new \Exception($this->l10n->t('User collection need to be an array with values: user ' . $index)); } if (empty($user['email'])) { - throw new \Exception((string)$this->l10n->t('User need to be email: user ' . $index)); + throw new \Exception($this->l10n->t('User need to be email: user ' . $index)); } if (!filter_var($user['email'], FILTER_VALIDATE_EMAIL)) { - throw new \Exception((string)$this->l10n->t('Invalid email: user ' . $index)); + throw new \Exception($this->l10n->t('Invalid email: user ' . $index)); } } From e2910a42234b88c49eaf810c38b5361f1688e3be Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 12:16:48 -0300 Subject: [PATCH 4/6] Validate if user exists --- lib/AppInfo/Application.php | 4 +++- lib/Helper/JSConfigHelper.php | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index cc37db1eb..c67ac3a63 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -17,6 +17,7 @@ use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; +use OCP\IUserManager; use OCP\Util; class Application extends App implements IBootstrap { @@ -58,7 +59,8 @@ private function registerHooks($context): void { $context->getServerContainer()->get(FileUserMapper::class), $this->getContainer()->get(IL10N::class), $context->getServerContainer()->get(IRootFolder::class), - $context->getServerContainer()->get(IURLGenerator::class) + $context->getServerContainer()->get(IURLGenerator::class), + $context->getServerContainer()->get(IUserManager::class) ); Util::connectHook('\OCP\Config', 'js', $jsConfigHelper, 'extendJsConfig'); } diff --git a/lib/Helper/JSConfigHelper.php b/lib/Helper/JSConfigHelper.php index 6f7c716ec..f446be71c 100644 --- a/lib/Helper/JSConfigHelper.php +++ b/lib/Helper/JSConfigHelper.php @@ -9,6 +9,7 @@ use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; +use OCP\IUserManager; class JSConfigHelper { /** @var ISession */ @@ -25,6 +26,9 @@ class JSConfigHelper { private $root; /** @var IURLGenerator */ private $urlGenerator; + /** @var IUserManager */ + protected $userManager; + public function __construct( ISession $session, IRequest $request, @@ -32,7 +36,8 @@ public function __construct( FileUserMapper $fileUserMapper, IL10N $l10n, IRootFolder $root, - IURLGenerator $urlGenerator + IURLGenerator $urlGenerator, + IUserManager $userManager ) { $this->session = $session; $this->request = $request; @@ -41,6 +46,7 @@ public function __construct( $this->l10n = $l10n; $this->root = $root; $this->urlGenerator = $urlGenerator; + $this->userManager = $userManager; } /** @@ -66,6 +72,18 @@ public function extendJsConfig(array $settings) { $settings['array']['oc_appconfig'] = json_encode($appConfig); return; } + if ($this->userManager->userExists($data['email'])) { + $appConfig['libresign']['action'] = JSActions::ACTION_REDIRECT; + $appConfig['libresign']['errors'][] = $this->l10n->t('User already exists. Please loggin.'); + $appConfig['libresign']['redirect'] = $this->urlGenerator->linkToRoute('core.login.showLoginForm', [ + 'redirect_url' => $this->urlGenerator->linkToRoute( + 'libresign.Page.sign', + ['uuid' => $uuid] + ), + ]); + $settings['array']['oc_appconfig'] = json_encode($appConfig); + return; + } $appConfig['libresign']['action'] = JSActions::ACTION_CREATE_USER; $settings['array']['oc_appconfig'] = json_encode($appConfig); return; From 5390660f90b88bb275638671471a1272066b4182 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 12:50:55 -0300 Subject: [PATCH 5/6] Validate password --- lib/Service/AccountService.php | 8 +++--- tests/Unit/Service/AccountServiceTest.php | 30 +++++++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 999fe02d7..cfc95b476 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -36,11 +36,11 @@ public function validateCreateToSign(array $data) { if ($fileUser->getEmail() != $data['email']) { throw new LibresignException($this->l10n->t('Dont is your file'), 1); } - if ($data['password'] != $data['confirmPassword']) { - throw new LibresignException($this->l10n->t('Password and confirmation dont match'), 1); + if ($this->userManager->userExists($data['email'])) { + throw new LibresignException($this->l10n->t('User already exists'), 1); } - if ($data['signPassword'] != $data['signConfirmPassword']) { - throw new LibresignException($this->l10n->t('Password and confirmation of signature dont match'), 1); + if (empty($data['password'])) { + throw new LibresignException($this->l10n->t('Password is mandatory'), 1); } } } diff --git a/tests/Unit/Service/AccountServiceTest.php b/tests/Unit/Service/AccountServiceTest.php index e2b2c174c..58a467063 100644 --- a/tests/Unit/Service/AccountServiceTest.php +++ b/tests/Unit/Service/AccountServiceTest.php @@ -73,7 +73,7 @@ public function testValidateDontIsYourFile() { ]); } - public function testValidatePasswordDontMatch() { + public function testValidateuserAlreadyExists() { $fileUser = $this->createMock(FileUser::class); $fileUser ->method('__call') @@ -82,12 +82,30 @@ public function testValidatePasswordDontMatch() { $this->fileUserMapper ->method('getByUuid') ->will($this->returnValue($fileUser)); - $this->expectExceptionMessage('Password and confirmation dont match'); + $this->userManager + ->method('userExists') + ->will($this->returnValue(true)); + $this->expectExceptionMessage('User already exists'); + $this->service->validateCreateToSign([ + 'uuid' => '12345678-1234-1234-1234-123456789012', + 'email' => 'valid@test.coop' + ]); + } + + public function testValidatePasswordEmpty() { + $fileUser = $this->createMock(FileUser::class); + $fileUser + ->method('__call') + ->with($this->equalTo('getEmail'), $this->anything()) + ->will($this->returnValue('valid@test.coop')); + $this->fileUserMapper + ->method('getByUuid') + ->will($this->returnValue($fileUser)); + $this->expectExceptionMessage('Password is mandatory'); $this->service->validateCreateToSign([ 'uuid' => '12345678-1234-1234-1234-123456789012', 'email' => 'valid@test.coop', - 'password' => '123456789', - 'confirmPassword' => 'abcdefghi' + 'password' => '', ]); } @@ -100,14 +118,12 @@ public function testValidateSignPasswordDontMatch() { $this->fileUserMapper ->method('getByUuid') ->will($this->returnValue($fileUser)); - $this->expectExceptionMessage('Password and confirmation of signature dont match'); + $this->expectExceptionMessage('Password to sign is mandatory'); $this->service->validateCreateToSign([ 'uuid' => '12345678-1234-1234-1234-123456789012', 'email' => 'valid@test.coop', 'password' => '123456789', - 'confirmPassword' => '123456789', 'signPassword' => '123456789', - 'signConfirmPassword' => 'abcdefghi' ]); } } From 341f8cf338a91346f02cabcb0f608f7afe3ab638 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Fri, 12 Feb 2021 23:02:36 -0300 Subject: [PATCH 6/6] Create user --- lib/Controller/AccountController.php | 11 +- lib/Service/AccountService.php | 101 +++++++++++++++++- lib/Service/FolderService.php | 5 + .../Unit/Controller/AccountControllerTest.php | 5 +- tests/Unit/Service/AccountServiceTest.php | 34 +++++- tests/Unit/Service/WebhookServiceTest.php | 8 +- 6 files changed, 150 insertions(+), 14 deletions(-) diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index b2a737eae..b23648277 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -3,6 +3,7 @@ namespace OCA\Libresign\Controller; use OCA\Libresign\AppInfo\Application; +use OCA\Libresign\Helper\JSActions; use OCA\Libresign\Service\AccountService; use OCP\AppFramework\ApiController; use OCP\AppFramework\Http; @@ -32,17 +33,21 @@ public function __construct( * @NoCSRFRequired * @return JSONResponse */ - public function createToSign(string $uuid, string $email) { + public function createToSign(string $uuid, string $email, string $password, string $signPassword) { try { $data = [ 'uuid' => $uuid, - 'email' => $email + 'email' => $email, + 'password' => $password, + 'signPassword' => $signPassword ]; $this->account->validateCreateToSign($data); + $this->account->createToSign($uuid, $email, $password, $signPassword); } catch (\Throwable $th) { return new JSONResponse( [ 'message' => $th->getMessage(), + 'action' => JSActions::ACTION_DO_NOTHING ], Http::STATUS_UNPROCESSABLE_ENTITY ); @@ -50,7 +55,7 @@ public function createToSign(string $uuid, string $email) { return new JSONResponse( [ 'message' => $this->l10n->t('Success'), - 'data' => $return + 'action' => JSActions::ACTION_SIGN ], Http::STATUS_OK ); diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index cfc95b476..f576c1673 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -2,9 +2,17 @@ namespace OCA\Libresign\Service; +use OC\Files\Filesystem; +use OCA\Libresign\AppInfo\Application; +use OCA\Libresign\Db\FileUser; use OCA\Libresign\Db\FileUserMapper; use OCA\Libresign\Exception\LibresignException; +use OCA\Libresign\Handler\CfsslHandler; +use OCA\Settings\Mailer\NewUserMailHelper; +use OCP\Files\File; +use OCP\IConfig; use OCP\IL10N; +use OCP\IUserManager; use Sabre\DAV\UUIDUtil; class AccountService { @@ -12,13 +20,37 @@ class AccountService { private $l10n; /** @var FileUserMapper */ private $fileUserMapper; + /** @var IUserManager */ + protected $userManager; + /** @var SignatureService */ + private $signature; + /** @var FolderService */ + private $folder; + /** @var IConfig */ + private $config; + /** @var NewUserMailHelper */ + private $newUserMail; + /** @var CfsslHandler */ + private $cfsslHandler; public function __construct( IL10N $l10n, - FileUserMapper $fileUserMapper + FileUserMapper $fileUserMapper, + IUserManager $userManager, + SignatureService $signature, + FolderService $folder, + IConfig $config, + NewUserMailHelper $newUserMail, + CfsslHandler $cfsslHandler ) { $this->l10n = $l10n; $this->fileUserMapper = $fileUserMapper; + $this->userManager = $userManager; + $this->signature = $signature; + $this->folder = $folder; + $this->config = $config; + $this->newUserMail = $newUserMail; + $this->cfsslHandler = $cfsslHandler; } public function validateCreateToSign(array $data) { @@ -26,7 +58,7 @@ public function validateCreateToSign(array $data) { throw new LibresignException($this->l10n->t('Invalid UUID'), 1); } try { - $fileUser = $this->fileUserMapper->getByUuid($data['uuid']); + $fileUser = $this->getFileUserByUuid($data['uuid']); } catch (\Throwable $th) { throw new LibresignException($this->l10n->t('UUID not found'), 1); } @@ -42,5 +74,70 @@ public function validateCreateToSign(array $data) { if (empty($data['password'])) { throw new LibresignException($this->l10n->t('Password is mandatory'), 1); } + if (empty($data['signPassword'])) { + throw new LibresignException($this->l10n->t('Password to sign is mandatory'), 1); + } + } + + /** + * Get fileUser by Uuid + * + * @param string $uuid + * @return FileUser + */ + private function getFileUserByUuid($uuid) { + if (!$this->fileUser) { + $this->fileUser = $this->fileUserMapper->getByUuid($uuid); + } + return $this->fileUser; + } + + public function createToSign($uuid, $uid, $password, $signPassword) { + $fileUser = $this->getFileUserByUuid($uuid); + $newUser = $this->userManager->createUser($uid, $password); + $fileUser->setUserId($newUser->getUID()); + $this->fileUserMapper->update($fileUser); + + $newUser->setEMailAddress($uid); + if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') { + try { + $emailTemplate = $this->newUserMail->generateTemplate($newUser, false); + $this->newUserMail->sendMail($newUser, $emailTemplate); + } catch (\Exception $e) { + throw new LibresignException('Unable to send the invitation', 1); + } + } + $this->folder->setUserId($newUser->getUID()); + + $content = $this->cfsslHandler->generateCertificate( + $this->config->getAppValue(Application::APP_ID, 'commonName'), + [], + $this->config->getAppValue(Application::APP_ID, 'country'), + $this->config->getAppValue(Application::APP_ID, 'organization'), + $this->config->getAppValue(Application::APP_ID, 'organizationUnit'), + $signPassword, + $this->config->getAppValue(Application::APP_ID, 'cfsslUri') + ); + if (!$content) { + throw new LibresignException('Failure on generate certificate', 1); + } + $this->savePfx($uid, $content); + } + + private function savePfx($uid, $content) { + Filesystem::initMountPoints($uid); + $folder = $this->folder->getFolderForUser(); + $filename = 'signature.pfx'; + if ($folder->nodeExists($filename)) { + $node = $folder->get($filename); + if (!$node instanceof File) { + throw new LibresignException("path {$filename} already exists and is not a file!", 400); + } + $node->putContent($content); + return $node; + } + + $file = $folder->newFile($filename); + $file->putContent($content); } } diff --git a/lib/Service/FolderService.php b/lib/Service/FolderService.php index 3703caff2..0a6f728a1 100644 --- a/lib/Service/FolderService.php +++ b/lib/Service/FolderService.php @@ -27,6 +27,11 @@ public function __construct( $this->l10n = $l10n; $this->userId = $userId; } + + public function setUserId($userId) { + $this->userId = $userId; + } + /** * @return Folder */ diff --git a/tests/Unit/Controller/AccountControllerTest.php b/tests/Unit/Controller/AccountControllerTest.php index d93426b91..cf9737416 100644 --- a/tests/Unit/Controller/AccountControllerTest.php +++ b/tests/Unit/Controller/AccountControllerTest.php @@ -3,6 +3,7 @@ namespace OCA\Libresign\Tests\Unit\Controller; use OCA\Libresign\Controller\AccountController; +use OCA\Libresign\Helper\JSActions; use OCA\Libresign\Service\AccountService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; @@ -35,10 +36,10 @@ public function testCreateSuccess() { ->method('t') ->will($this->returnArgument(0)); - $actual = $this->controller->createToSign('uuid', 'email'); + $actual = $this->controller->createToSign('uuid', 'email', 'password', 'signPassword'); $expected = new JSONResponse([ 'message' => 'Success', - 'data' => null + 'action' => JSActions::ACTION_SIGN ], Http::STATUS_OK); $this->assertEquals($expected, $actual); } diff --git a/tests/Unit/Service/AccountServiceTest.php b/tests/Unit/Service/AccountServiceTest.php index 58a467063..6297b36c4 100644 --- a/tests/Unit/Service/AccountServiceTest.php +++ b/tests/Unit/Service/AccountServiceTest.php @@ -4,8 +4,14 @@ use OCA\Libresign\Db\FileUser; use OCA\Libresign\Db\FileUserMapper; +use OCA\Libresign\Handler\CfsslHandler; use OCA\Libresign\Service\AccountService; +use OCA\Libresign\Service\FolderService; +use OCA\Libresign\Service\SignatureService; +use OCA\Settings\Mailer\NewUserMailHelper; +use OCP\IConfig; use OCP\IL10N; +use OCP\IUserManager; use PHPUnit\Framework\TestCase; /** @@ -17,6 +23,18 @@ final class AccountServiceTest extends TestCase { private $l10n; /** @var FileUserMapper */ private $fileUserMapper; + /** @var IUserManager */ + protected $userManager; + /** @var SignatureService */ + private $signatureService; + /** @var FolderService */ + private $folder; + /** @var IConfig */ + private $config; + /** @var NewUserMailHelper */ + private $newUserMail; + /** @var CfsslHandler */ + private $cfsslHandler; public function setUp(): void { $this->l10n = $this->createMock(IL10N::class); @@ -24,9 +42,21 @@ public function setUp(): void { ->method('t') ->will($this->returnArgument(0)); $this->fileUserMapper = $this->createMock(FileUserMapper::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->signature = $this->createMock(SignatureService::class); + $this->folder = $this->createMock(FolderService::class); + $this->config = $this->createMock(IConfig::class); + $this->newUserMail = $this->createMock(NewUserMailHelper::class); + $this->cfsslHandler = $this->createMock(CfsslHandler::class); $this->service = new AccountService( $this->l10n, - $this->fileUserMapper + $this->fileUserMapper, + $this->userManager, + $this->signature, + $this->folder, + $this->config, + $this->newUserMail, + $this->cfsslHandler ); } @@ -123,7 +153,7 @@ public function testValidateSignPasswordDontMatch() { 'uuid' => '12345678-1234-1234-1234-123456789012', 'email' => 'valid@test.coop', 'password' => '123456789', - 'signPassword' => '123456789', + 'signPassword' => '', ]); } } diff --git a/tests/Unit/Service/WebhookServiceTest.php b/tests/Unit/Service/WebhookServiceTest.php index f95b3b810..142555161 100644 --- a/tests/Unit/Service/WebhookServiceTest.php +++ b/tests/Unit/Service/WebhookServiceTest.php @@ -34,9 +34,7 @@ final class WebhookServiceTest extends TestCase { private $fileUser; /** @var IUser */ private $user; - /** @var FolderService */ - private $folderService; - /** @var ClientService */ + /** @var IClientService */ private $client; public function setUp(): void { @@ -49,15 +47,15 @@ public function setUp(): void { $this->file = $this->createMock(FileMapper::class); $this->fileUser = $this->createMock(FileUserMapper::class); $this->user = $this->createMock(IUser::class); - $this->folderService = $this->createMock(FolderService::class); $this->client = $this->createMock(IClientService::class); + $this->folder = $this->createMock(FolderService::class); $this->service = new WebhookService( $this->config, $this->groupManager, $this->l10n, $this->file, $this->fileUser, - $this->folderService, + $this->folder, $this->client ); }