Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b4dffc7
chore: scenery validate test
Any97Cris Jul 4, 2025
e2b86cf
chore: more steps about tests
Any97Cris Jul 22, 2025
b61ee0c
fix: name of scenario
vitormattos Jul 22, 2025
f793383
fix: adjust table row size
vitormattos Jul 22, 2025
7755fbb
chore: replace Name by Common Name
vitormattos Jul 22, 2025
0b963db
chore: restrict the return type to nullable and string only
vitormattos Jul 22, 2025
75aabdf
chore: cover with more tests
vitormattos Jul 22, 2025
4ccda64
chore: test get helper text with invalid field name
vitormattos Jul 22, 2025
8f5d520
chore: test get rule to valid field
vitormattos Jul 22, 2025
d248628
chore: test get rule to invalid field
vitormattos Jul 22, 2025
ada6d5c
chore: add type hint to return
vitormattos Jul 22, 2025
d000640
fix: consider to return empty array when is invalid field name
vitormattos Jul 22, 2025
ce19a93
fix: run cs:fix
vitormattos Jul 22, 2025
d37fad1
fix: run cs:fix
vitormattos Jul 22, 2025
a8a6074
chore: simplify test and compare actual and expected directly
vitormattos Jul 22, 2025
2b87869
chore: create ValidateServiceTest file
Any97Cris Aug 18, 2025
2c44b61
chore:more test scenarios
Any97Cris Aug 18, 2025
e810867
chore: changes noted in the code review
Any97Cris Aug 19, 2025
c7ed69d
chore: create methods with fields as certification.js
Any97Cris Aug 21, 2025
92e0338
chore: add initial state
Any97Cris Aug 25, 2025
a68e74e
chore: remove some configurations come at certification.js file
Any97Cris Aug 26, 2025
57d678f
chore: delete certification.js file and adjustment some files
Any97Cris Aug 27, 2025
7e38733
chore: add null option
Any97Cris Aug 27, 2025
cb4a7ad
chore: correction of some errors in the AdminTest file
Any97Cris Aug 27, 2025
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
18 changes: 6 additions & 12 deletions lib/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
);
Expand Down Expand Up @@ -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
*
Expand Down
100 changes: 100 additions & 0 deletions lib/Service/Certificate/RulesService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Libresign\Service\Certificate;

use OCP\IL10N;

class RulesService {

private array $rules = [
'CN' => [
'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,
};
}

}
57 changes: 57 additions & 0 deletions lib/Service/Certificate/ValidateService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Libresign\Service\Certificate;

use InvalidArgumentException;
use OCP\IL10N;

class ValidateService {

public function __construct(
protected RulesService $rulesService,
protected IL10N $l10n,
) {
}

public function validate(string $fieldName, string $value): void {
$rule = $this->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']);
}
}

}
3 changes: 3 additions & 0 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +31,7 @@ public function __construct(
private IAppConfig $appConfig,
private SignatureTextService $signatureTextService,
private SignatureBackgroundService $signatureBackgroundService,
private RulesService $rulesService,
) {
}
public function getForm(): TemplateResponse {
Expand All @@ -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);
Expand Down
69 changes: 0 additions & 69 deletions src/helpers/certification.js

This file was deleted.

19 changes: 11 additions & 8 deletions src/views/ReadCertificate/CertificateContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@

<script>

// import CertificateContent from './CertificateContent.vue'
import { selectCustonOption } from '../../helpers/certification.js'
import { loadState } from '@nextcloud/initial-state'

export default {
name: 'CertificateContent',
Expand All @@ -79,6 +78,11 @@ export default {
default: '0',
},
},
data() {
return {
rulesService: loadState('libresign', 'rules_service') || [],
}
},
methods: {
orderList(data) {
const sorted = {};
Expand All @@ -94,13 +98,12 @@ export default {
})
return sorted
},
getRuleById(id) {
return this.rulesService.find(rule => rule.id === id) || {}
},
getLabelFromId(id) {
try {
const item = selectCustonOption(id).unwrap()
return item.label
} catch (error) {
return id
}
const rule = this.getRuleById(id)
return rule.label || id
},
},
}
Expand Down
Loading
Loading