Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature account create #39

Merged
merged 6 commits into from
Feb 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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');
}
Expand Down
63 changes: 63 additions & 0 deletions lib/Controller/AccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

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;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IL10N;
use OCP\IRequest;

class AccountController extends ApiController {
/** @var IL10N */
private $l10n;
/** @var AccountService */
private $account;

public function __construct(
IRequest $request,
IL10N $l10n,
AccountService $account
) {
parent::__construct(Application::APP_ID, $request);
$this->l10n = $l10n;
$this->account = $account;
}

/**
* @NoAdminRequired
* @CORS
* @NoCSRFRequired
* @return JSONResponse
*/
public function createToSign(string $uuid, string $email, string $password, string $signPassword) {
try {
$data = [
'uuid' => $uuid,
'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
);
}
return new JSONResponse(
[
'message' => $this->l10n->t('Success'),
'action' => JSActions::ACTION_SIGN
],
Http::STATUS_OK
);
}
}
20 changes: 19 additions & 1 deletion lib/Helper/JSConfigHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserManager;

class JSConfigHelper {
/** @var ISession */
Expand All @@ -25,14 +26,18 @@ class JSConfigHelper {
private $root;
/** @var IURLGenerator */
private $urlGenerator;
/** @var IUserManager */
protected $userManager;

public function __construct(
ISession $session,
IRequest $request,
FileMapper $fileMapper,
FileUserMapper $fileUserMapper,
IL10N $l10n,
IRootFolder $root,
IURLGenerator $urlGenerator
IURLGenerator $urlGenerator,
IUserManager $userManager
) {
$this->session = $session;
$this->request = $request;
Expand All @@ -41,6 +46,7 @@ public function __construct(
$this->l10n = $l10n;
$this->root = $root;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
}

/**
Expand All @@ -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;
Expand Down
143 changes: 143 additions & 0 deletions lib/Service/AccountService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

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 {
/** @var IL10N */
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,
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) {
if (!UUIDUtil::validateUUID($data['uuid'])) {
throw new LibresignException($this->l10n->t('Invalid UUID'), 1);
}
try {
$fileUser = $this->getFileUserByUuid($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 ($this->userManager->userExists($data['email'])) {
throw new LibresignException($this->l10n->t('User already exists'), 1);
}
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);
}
}
5 changes: 5 additions & 0 deletions lib/Service/FolderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public function __construct(
$this->l10n = $l10n;
$this->userId = $userId;
}

public function setUserId($userId) {
$this->userId = $userId;
}

/**
* @return Folder
*/
Expand Down
28 changes: 14 additions & 14 deletions lib/Service/WebhookService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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));
}
}

Expand Down
Loading