diff --git a/lib/Controller/AdminController.php b/lib/Controller/AdminController.php index b71e6622ef..cc4450d686 100644 --- a/lib/Controller/AdminController.php +++ b/lib/Controller/AdminController.php @@ -14,6 +14,7 @@ use OCA\Libresign\Handler\CertificateEngine\IEngineHandler; use OCA\Libresign\Helper\ConfigureCheckHelper; use OCA\Libresign\ResponseDefinitions; +use OCA\Libresign\Service\Certificate\ValidateService; use OCA\Libresign\Service\CertificatePolicyService; use OCA\Libresign\Service\Install\ConfigureCheckService; use OCA\Libresign\Service\Install\InstallService; @@ -54,6 +55,7 @@ public function __construct( protected ISession $session, private SignatureBackgroundService $signatureBackgroundService, private CertificatePolicyService $certificatePolicyService, + private ValidateService $validateService, ) { parent::__construct(Application::APP_ID, $request); $this->eventSource = $this->eventSourceFactory->create(); @@ -136,15 +138,14 @@ private function generateCertificate( ): IEngineHandler { $names = []; if (isset($rootCert['names'])) { + $this->validateService->validateNames($rootCert['names']); foreach ($rootCert['names'] as $item) { - if (empty($item['id'])) { - throw new LibresignException('Parameter id is required!', 400); - } - $names[$item['id']]['value'] = $this->trimAndThrowIfEmpty($item['id'], $item['value']); + $names[$item['id']]['value'] = trim((string)$item['value']); } } + $this->validateService->validate('CN', $rootCert['commonName']); $this->installService->generate( - $this->trimAndThrowIfEmpty('commonName', $rootCert['commonName']), + trim((string)$rootCert['commonName']), $names, $properties, ); @@ -177,13 +178,6 @@ public function loadCertificate(): DataResponse { return new DataResponse($certificate); } - private function trimAndThrowIfEmpty(string $key, $value): string { - if (empty($value)) { - throw new LibresignException("parameter '{$key}' is required!", 400); - } - return trim((string)$value); - } - /** * Check the configuration of LibreSign * diff --git a/lib/Service/Certificate/RulesService.php b/lib/Service/Certificate/RulesService.php new file mode 100644 index 0000000000..8c1e30bdae --- /dev/null +++ b/lib/Service/Certificate/RulesService.php @@ -0,0 +1,100 @@ + [ + 'required' => true, + 'min' => 1, + 'max' => 64, + ], + 'C' => [ + 'min' => 2, + 'max' => 2, + ], + 'ST' => [ + 'min' => 1, + 'max' => 128, + ], + 'L' => [ + 'min' => 1, + 'max' => 128, + ], + 'O' => [ + 'min' => 1, + 'max' => 64, + ], + 'OU' => [ + 'min' => 1, + 'max' => 64, + ], + ]; + + public function __construct( + protected IL10N $l10n, + ) { + } + + public function getRule(string $fieldName): array { + if (!array_key_exists($fieldName, $this->rules)) { + return []; + } + if (!isset($this->rules[$fieldName]['helperText'])) { + $this->rules[$fieldName]['helperText'] = $this->getHelperText($fieldName); + if (empty($this->rules[$fieldName]['helperText'])) { + unset($this->rules[$fieldName]['helperText']); + } + } + return $this->rules[$fieldName]; + } + + public function getHelperText(string $fieldName): ?string { + return match ($fieldName) { + 'CN' => $this->l10n->t('Common Name (CN)'), + 'C' => $this->l10n->t('Two-letter ISO 3166 country code'), + 'ST' => $this->l10n->t('Full name of states or provinces'), + 'L' => $this->l10n->t('Name of a locality or place, such as a city, county, or other geographic region'), + 'O' => $this->l10n->t('Name of an organization'), + 'OU' => $this->l10n->t('Name of an organizational unit'), + default => null, + }; + } + + public function toArray(): array { + $result = []; + foreach ($this->rules as $field => $rule) { + $result[] = [ + 'id' => $field, + 'label' => $this->getLabel($field), + 'min' => $rule['min'] ?? null, + 'max' => $rule['max'] ?? null, + 'required' => $rule['required'] ?? false, + 'helperText' => $this->getHelperText($field), + ]; + } + return $result; + } + + private function getLabel(string $fieldName): string { + return match ($fieldName) { + 'CN' => $this->l10n->t('Common Name (CN)'), + 'C' => $this->l10n->t('Country'), + 'ST' => $this->l10n->t('State'), + 'L' => $this->l10n->t('Locality'), + 'O' => $this->l10n->t('Organization'), + 'OU' => $this->l10n->t('Organizational Unit'), + default => $fieldName, + }; + } + +} diff --git a/lib/Service/Certificate/ValidateService.php b/lib/Service/Certificate/ValidateService.php new file mode 100644 index 0000000000..64af245851 --- /dev/null +++ b/lib/Service/Certificate/ValidateService.php @@ -0,0 +1,57 @@ +rulesService->getRule($fieldName); + $value = trim($value); + $length = strlen($value); + + if ($fieldName === 'id' && $length === 0) { + throw new InvalidArgumentException('Parameter id is invalid'); + } + + if (!$length && isset($rule['required']) && $rule['required']) { + throw new InvalidArgumentException( + $this->l10n->t("Parameter '%s' is required!", [$fieldName]) + ); + } + + if ($length > $rule['max'] || $length < $rule['min']) { + throw new InvalidArgumentException( + $this->l10n->t( + "Parameter '%s' should be between %s and %s.", + [$fieldName, $rule['min'], $rule['max']] + ) + ); + } + } + + + public function validateNames(array $names) { + foreach ($names as $item) { + if (empty($item['id'])) { + throw new InvalidArgumentException('Parameter id is required!'); + } + $this->validate($item['id'], $item['value']); + } + } + +} diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 648f6c10bc..030bcdda68 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -11,6 +11,7 @@ use OCA\Libresign\AppInfo\Application; use OCA\Libresign\Exception\LibresignException; use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory; +use OCA\Libresign\Service\Certificate\RulesService; use OCA\Libresign\Service\CertificatePolicyService; use OCA\Libresign\Service\IdentifyMethodService; use OCA\Libresign\Service\SignatureBackgroundService; @@ -30,6 +31,7 @@ public function __construct( private IAppConfig $appConfig, private SignatureTextService $signatureTextService, private SignatureBackgroundService $signatureBackgroundService, + private RulesService $rulesService, ) { } public function getForm(): TemplateResponse { @@ -44,6 +46,7 @@ public function getForm(): TemplateResponse { $this->initialState->provideInitialState('certificate_engine', $this->certificateEngineFactory->getEngine()->getName()); $this->initialState->provideInitialState('certificate_policies_oid', $this->certificatePolicyService->getOid()); $this->initialState->provideInitialState('certificate_policies_cps', $this->certificatePolicyService->getCps()); + $this->initialState->provideInitialState('rules_service', $this->rulesService->toArray()); $this->initialState->provideInitialState('config_path', $this->appConfig->getValueString(Application::APP_ID, 'config_path')); $this->initialState->provideInitialState('default_signature_font_size', SignatureTextService::SIGNATURE_DEFAULT_FONT_SIZE); $this->initialState->provideInitialState('default_signature_height', SignatureTextService::DEFAULT_SIGNATURE_HEIGHT); diff --git a/src/helpers/certification.js b/src/helpers/certification.js deleted file mode 100644 index b5fc5bdf2b..0000000000 --- a/src/helpers/certification.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import { Option } from '@marionebl/option' - -import { translate as t } from '@nextcloud/l10n' - -/** - * Return custom options details from ID - * - * @param {string} id identification of custom option - */ -export function selectCustonOption(id) { - return Option.from(options.find(item => item.id === id)) -} - -/** - * More informations: https://www.ietf.org/rfc/rfc5280.txt - */ -export const options = [ - { - id: 'CN', - label: t('libresign', 'Name (CN)'), - max: 64, - value: '', - helperText: t('libresign', 'Name (CN)'), - }, - { - id: 'C', - label: 'Country', - min: 2, - max: 2, - value: '', - helperText: t('libresign', 'Two-letter ISO 3166 country code'), - }, - { - id: 'ST', - label: 'State', - min: 1, - max: 128, - value: '', - helperText: t('libresign', 'Full name of states or provinces'), - }, - { - id: 'L', - label: 'Locality', - min: 1, - max: 128, - value: '', - helperText: t('libresign', 'Name of a locality or place, such as a city, county, or other geographic region'), - }, - { - id: 'O', - label: 'Organization', - min: 1, - max: 64, - value: '', - helperText: t('libresign', 'Name of an organization'), - }, - { - id: 'OU', - label: 'OrganizationalUnit', - min: 1, - max: 64, - value: '', - helperText: t('libresign', 'Name of an organizational unit'), - }, -] diff --git a/src/views/ReadCertificate/CertificateContent.vue b/src/views/ReadCertificate/CertificateContent.vue index deae94f43a..2b211e90c4 100644 --- a/src/views/ReadCertificate/CertificateContent.vue +++ b/src/views/ReadCertificate/CertificateContent.vue @@ -63,8 +63,7 @@