diff --git a/lib/Handler/CertificateEngine/AEngineHandler.php b/lib/Handler/CertificateEngine/AEngineHandler.php index b6d597636e..6e9fe58b86 100644 --- a/lib/Handler/CertificateEngine/AEngineHandler.php +++ b/lib/Handler/CertificateEngine/AEngineHandler.php @@ -709,9 +709,10 @@ protected function checkRootCertificateExpiry(): ?ConfigureCheckHelper { } public function toArray(): array { + $generated = $this->isSetupOk(); $return = [ - 'configPath' => $this->getCurrentConfigPath(), - 'generated' => $this->isSetupOk(), + 'configPath' => $this->getConfigPathForApi($generated), + 'generated' => $generated, 'rootCert' => [ 'commonName' => $this->getCommonName(), 'names' => [], @@ -725,12 +726,32 @@ public function toArray(): array { foreach ($names as $name => $value) { $return['rootCert']['names'][] = [ 'id' => $name, - 'value' => $value, + 'value' => $this->filterNameValue($name, $value, $generated), ]; } return $return; } + private function getConfigPathForApi(bool $generated): string { + return $generated ? $this->getCurrentConfigPath() : ''; + } + + private function filterNameValue(string $name, mixed $value, bool $generated): mixed { + if ($name === 'OU' && is_array($value) && !$generated) { + $filtered = $this->removeCaIdFromOrganizationalUnit($value); + return empty($filtered) ? null : $filtered; + } + return $value; + } + + private function removeCaIdFromOrganizationalUnit(array $organizationalUnits): array { + $filtered = array_filter( + $organizationalUnits, + fn ($item) => !str_starts_with($item, 'libresign-ca-id:') + ); + return array_values($filtered); + } + protected function getCrlDistributionUrl(): string { $caIdParsed = $this->caIdentifierService->getCaIdParsed(); return $this->urlGenerator->linkToRouteAbsolute('libresign.crl.getRevocationList', [ diff --git a/tests/php/Unit/Handler/CertificateEngine/AEngineHandlerTest.php b/tests/php/Unit/Handler/CertificateEngine/AEngineHandlerTest.php index fa8cc013d7..d44484aee8 100644 --- a/tests/php/Unit/Handler/CertificateEngine/AEngineHandlerTest.php +++ b/tests/php/Unit/Handler/CertificateEngine/AEngineHandlerTest.php @@ -32,7 +32,7 @@ final class AEngineHandlerTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { $this->config = \OCP\Server::get(IConfig::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->appDataFactory = \OCP\Server::get(IAppDataFactory::class); $this->dateTimeFormatter = \OCP\Server::get(IDateTimeFormatter::class); $this->tempManager = \OCP\Server::get(ITempManager::class); @@ -40,9 +40,6 @@ public function setUp(): void { $this->urlGenerator = \OCP\Server::get(IURLGenerator::class); $this->caIdentifierService = \OCP\Server::get(CaIdentifierService::class); $this->logger = \OCP\Server::get(LoggerInterface::class); - - $this->appConfig->deleteKey(Application::APP_ID, 'certificate_engine'); - $this->appConfig->deleteKey(Application::APP_ID, 'identify_methods'); } private function getInstance(): OpenSslHandler { @@ -232,4 +229,181 @@ public static function dataProviderIdentifyMethodsOtherEngines(): array { 'First time cfssl' => ['', 'cfssl', null, 'no previous config'], ]; } + + #[DataProvider('dataProviderToArray')] + public function testToArrayReturnsExpectedStructure( + bool $isSetupOk, + array $certificateData, + array $expectedKeys, + string $description, + ): void { + $instance = $this->getInstance(); + + foreach ($certificateData as $setter => $value) { + $method = 'set' . ucfirst($setter); + if (method_exists($instance, $method)) { + $instance->$method($value); + } + } + + if (!$isSetupOk) { + $this->appConfig->deleteKey(Application::APP_ID, 'config_path'); + } + + $result = $instance->toArray(); + + foreach ($expectedKeys as $key) { + $this->assertArrayHasKey($key, $result, "toArray() should contain '$key': $description"); + } + + $this->assertIsBool($result['generated'], "generated should be boolean: $description"); + } + + #[DataProvider('dataProviderToArrayConfigPath')] + public function testToArrayFiltersConfigPathWhenNotGenerated( + bool $certificateGenerated, + string $expectedConfigPath, + string $description, + ): void { + $instance = $this->getInstance(); + + $tempPath = $this->tempManager->getTemporaryFolder('test-config'); + $instance->setConfigPath($tempPath); + + if ($certificateGenerated) { + file_put_contents($tempPath . DIRECTORY_SEPARATOR . 'ca.pem', 'fake-cert'); + file_put_contents($tempPath . DIRECTORY_SEPARATOR . 'ca-key.pem', 'fake-key'); + } + + $result = $instance->toArray(); + + if ($expectedConfigPath === '') { + $this->assertEmpty($result['configPath'], "configPath should be empty: $description"); + } else { + $this->assertNotEmpty($result['configPath'], "configPath should not be empty: $description"); + } + + $this->assertEquals($certificateGenerated, $result['generated'], "generated flag: $description"); + } + + #[DataProvider('dataProviderToArrayCaIdFiltering')] + public function testToArrayFiltersCaIdFromOrganizationalUnitWhenNotGenerated( + bool $certificateGenerated, + array $organizationalUnits, + array $expectedOuValues, + string $description, + ): void { + $instance = $this->getInstance(); + + $tempPath = $this->tempManager->getTemporaryFolder('test-config'); + $instance->setConfigPath($tempPath); + $instance->setOrganizationalUnit($organizationalUnits); + $instance->setCountry('BR'); + + if ($certificateGenerated) { + file_put_contents($tempPath . DIRECTORY_SEPARATOR . 'ca.pem', 'fake-cert'); + file_put_contents($tempPath . DIRECTORY_SEPARATOR . 'ca-key.pem', 'fake-key'); + } + + $result = $instance->toArray(); + + $ouFound = null; + foreach ($result['rootCert']['names'] as $name) { + if ($name['id'] === 'OU') { + $ouFound = $name['value']; + break; + } + } + + if (!empty($expectedOuValues)) { + $this->assertNotNull($ouFound, "OU should be present in names array: $description"); + $this->assertEquals( + $expectedOuValues, + $ouFound, + "OrganizationalUnit filtering: $description" + ); + } else { + $this->assertNull($ouFound, "OU should not be present when filtered to empty: $description"); + } + } + + public static function dataProviderToArray(): array { + return [ + 'Basic structure with minimal data' => [ + false, + ['commonName' => 'Test CA'], + ['configPath', 'generated', 'rootCert', 'policySection'], + 'minimal certificate data', + ], + 'Complete certificate data' => [ + false, + [ + 'commonName' => 'LibreSign CA', + 'country' => 'BR', + 'state' => 'Santa Catarina', + 'locality' => 'Florianópolis', + 'organization' => 'LibreCode', + 'organizationalUnit' => ['Engineering', 'Security'], + ], + ['configPath', 'generated', 'rootCert', 'policySection'], + 'full certificate data', + ], + ]; + } + + public static function dataProviderToArrayConfigPath(): array { + return [ + 'Certificate not generated' => [ + false, + '', + 'configPath should be empty when certificate not generated', + ], + 'Certificate generated' => [ + true, + '/path/to/config', + 'configPath should be set when certificate is generated', + ], + ]; + } + + public static function dataProviderToArrayCaIdFiltering(): array { + return [ + 'OU without CA ID - not generated' => [ + false, + ['Engineering', 'Security'], + ['Engineering', 'Security'], + 'normal OU values should pass through when not generated', + ], + 'OU without CA ID - generated' => [ + true, + ['Engineering', 'Security'], + ['Engineering', 'Security'], + 'normal OU values should pass through when generated', + ], + 'OU with CA ID - not generated (filtered)' => [ + false, + ['libresign-ca-id:abc123_g:1_e:openssl', 'Engineering', 'Security'], + ['Engineering', 'Security'], + 'CA ID should be filtered when certificate not generated', + ], + 'OU with CA ID - generated (kept)' => [ + true, + ['libresign-ca-id:abc123_g:1_e:openssl', 'Engineering', 'Security'], + ['libresign-ca-id:abc123_g:1_e:openssl', 'Engineering', 'Security'], + 'CA ID should be kept when certificate is generated', + ], + 'OU with only CA ID - not generated' => [ + false, + ['libresign-ca-id:abc123_g:1_e:openssl'], + [], + 'OU should be empty when only CA ID and not generated', + ], + 'OU with only CA ID - generated' => [ + true, + ['libresign-ca-id:abc123_g:1_e:openssl'], + ['libresign-ca-id:abc123_g:1_e:openssl'], + 'OU with only CA ID should be kept when generated', + ], + ]; + } } diff --git a/tests/php/Unit/Handler/CertificateEngine/CertificateEngineFactoryTest.php b/tests/php/Unit/Handler/CertificateEngine/CertificateEngineFactoryTest.php index abf843d0df..56a4c12354 100644 --- a/tests/php/Unit/Handler/CertificateEngine/CertificateEngineFactoryTest.php +++ b/tests/php/Unit/Handler/CertificateEngine/CertificateEngineFactoryTest.php @@ -28,7 +28,7 @@ public function tearDown(): void { } public function setUp(): void { - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->openSslHandler = $this->createMock(OpenSslHandler::class); $this->cfsslHandler = $this->createMock(CfsslHandler::class); $this->noneHandler = $this->createMock(NoneHandler::class); diff --git a/tests/php/Unit/Handler/CertificateEngine/OpenSslHandlerTest.php b/tests/php/Unit/Handler/CertificateEngine/OpenSslHandlerTest.php index 1bfcf1f70c..332a0cfa77 100644 --- a/tests/php/Unit/Handler/CertificateEngine/OpenSslHandlerTest.php +++ b/tests/php/Unit/Handler/CertificateEngine/OpenSslHandlerTest.php @@ -39,7 +39,7 @@ final class OpenSslHandlerTest extends \OCA\Libresign\Tests\Unit\TestCase { private string $tempDir; public function setUp(): void { $this->config = \OCP\Server::get(IConfig::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->appDataFactory = \OCP\Server::get(IAppDataFactory::class); $this->dateTimeFormatter = \OCP\Server::get(IDateTimeFormatter::class); $this->tempManager = \OCP\Server::get(ITempManager::class); diff --git a/tests/php/Unit/Handler/FooterHandlerTest.php b/tests/php/Unit/Handler/FooterHandlerTest.php index cdc099041f..bc83f924c7 100644 --- a/tests/php/Unit/Handler/FooterHandlerTest.php +++ b/tests/php/Unit/Handler/FooterHandlerTest.php @@ -27,7 +27,7 @@ final class FooterHandlerTest extends \OCA\Libresign\Tests\Unit\TestCase { private ITempManager $tempManager; private FooterHandler $footerHandler; public function setUp(): void { - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->pdfParserService = $this->createMock(PdfParserService::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->tempManager = \OCP\Server::get(ITempManager::class); diff --git a/tests/php/Unit/Handler/PdfTest.php b/tests/php/Unit/Handler/PdfTest.php index 03d60a7d49..3973ea51ca 100644 --- a/tests/php/Unit/Handler/PdfTest.php +++ b/tests/php/Unit/Handler/PdfTest.php @@ -24,7 +24,7 @@ final class PdfTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { parent::setUp(); $this->javaHelper = $this->createMock(JavaHelper::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->l10n = \OCP\Server::get(IL10NFactory::class)->get(Application::APP_ID); } diff --git a/tests/php/Unit/Handler/SignEngine/JSignPdfHandlerTest.php b/tests/php/Unit/Handler/SignEngine/JSignPdfHandlerTest.php index 8483a95541..c955db57b5 100644 --- a/tests/php/Unit/Handler/SignEngine/JSignPdfHandlerTest.php +++ b/tests/php/Unit/Handler/SignEngine/JSignPdfHandlerTest.php @@ -63,7 +63,7 @@ public static function setUpBeforeClass(): void { } } public function setUp(): void { - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->loggerInterface = $this->createMock(LoggerInterface::class); $this->tempManager = \OCP\Server::get(ITempManager::class); $this->signatureBackgroundService = $this->createMock(SignatureBackgroundService::class); diff --git a/tests/php/Unit/Handler/SignEngine/Pkcs12HandlerTest.php b/tests/php/Unit/Handler/SignEngine/Pkcs12HandlerTest.php index 3fd013e10a..419120c9c9 100644 --- a/tests/php/Unit/Handler/SignEngine/Pkcs12HandlerTest.php +++ b/tests/php/Unit/Handler/SignEngine/Pkcs12HandlerTest.php @@ -37,7 +37,7 @@ final class Pkcs12HandlerTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { $this->folderService = $this->createMock(FolderService::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->certificateEngineFactory = $this->createMock(CertificateEngineFactory::class); $this->l10n = \OCP\Server::get(IL10NFactory::class)->get(Application::APP_ID); $this->footerHandler = $this->createMock(FooterHandler::class); diff --git a/tests/php/Unit/Helper/JavaHelperTest.php b/tests/php/Unit/Helper/JavaHelperTest.php index 8688ddf816..ae67e609d4 100644 --- a/tests/php/Unit/Helper/JavaHelperTest.php +++ b/tests/php/Unit/Helper/JavaHelperTest.php @@ -23,7 +23,7 @@ class JavaHelperTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { parent::setUp(); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->l10n = $this->createMock(IL10N::class); $this->logger = $this->createMock(LoggerInterface::class); } diff --git a/tests/php/Unit/Service/CertificatePolicyServiceTest.php b/tests/php/Unit/Service/CertificatePolicyServiceTest.php index 9ce7120ebf..20b8f15175 100644 --- a/tests/php/Unit/Service/CertificatePolicyServiceTest.php +++ b/tests/php/Unit/Service/CertificatePolicyServiceTest.php @@ -33,7 +33,7 @@ final class CertificatePolicyServiceTest extends \OCA\Libresign\Tests\Unit\TestC public function setUp(): void { $this->appData = $this->createMock(IAppData::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->l10n = \OCP\Server::get(IL10NFactory::class)->get(Application::APP_ID); } diff --git a/tests/php/Unit/Service/FileServiceTest.php b/tests/php/Unit/Service/FileServiceTest.php index 48e0a9cd4b..d47ac2f403 100644 --- a/tests/php/Unit/Service/FileServiceTest.php +++ b/tests/php/Unit/Service/FileServiceTest.php @@ -103,7 +103,7 @@ private function getService(): FileService { $this->accountManager = $this->createMock(IAccountManager::class); $this->client = \OCP\Server::get(IClientService::class); $this->dateTimeFormatter = \OCP\Server::get(IDateTimeFormatter::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->urlGenerator = \OCP\Server::get(IURLGenerator::class); $this->mimeTypeDetector = \OCP\Server::get(IMimeTypeDetector::class); $this->pkcs12Handler = \OCP\Server::get(Pkcs12Handler::class); diff --git a/tests/php/Unit/Service/FooterServiceTest.php b/tests/php/Unit/Service/FooterServiceTest.php index 372f9b652d..3d8b2a2b18 100644 --- a/tests/php/Unit/Service/FooterServiceTest.php +++ b/tests/php/Unit/Service/FooterServiceTest.php @@ -23,7 +23,7 @@ class FooterServiceTest extends TestCase { public function setUp(): void { parent::setUp(); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->footerHandler = $this->createMock(FooterHandler::class); $this->service = new FooterService($this->appConfig, $this->footerHandler); } diff --git a/tests/php/Unit/Service/IdentifyMethod/PasswordTest.php b/tests/php/Unit/Service/IdentifyMethod/PasswordTest.php index edd6cd2b67..0a1ec6fe31 100644 --- a/tests/php/Unit/Service/IdentifyMethod/PasswordTest.php +++ b/tests/php/Unit/Service/IdentifyMethod/PasswordTest.php @@ -43,7 +43,7 @@ final class PasswordTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { $this->identifyService = $this->createMock(IdentifyService::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->folderService = $this->createMock(FolderService::class); $this->certificateEngineFactory = $this->createMock(CertificateEngineFactory::class); $this->l10n = \OCP\Server::get(IL10NFactory::class)->get(Application::APP_ID); diff --git a/tests/php/Unit/Service/Install/ConfigureCheckServiceTest.php b/tests/php/Unit/Service/Install/ConfigureCheckServiceTest.php index 11024ba59f..6c38f56f57 100644 --- a/tests/php/Unit/Service/Install/ConfigureCheckServiceTest.php +++ b/tests/php/Unit/Service/Install/ConfigureCheckServiceTest.php @@ -48,7 +48,7 @@ final class ConfigureCheckServiceTest extends \OCA\Libresign\Tests\Unit\TestCase public function setUp(): void { self::$mockExtensionLoaded = []; - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->systemConfig = $this->createMock(SystemConfig::class); $this->ocAppConfig = $this->createMock(AppConfig::class); $this->appManager = $this->createMock(IAppManager::class); diff --git a/tests/php/Unit/Service/Install/SignSetupServiceTest.php b/tests/php/Unit/Service/Install/SignSetupServiceTest.php index 0d6613a267..bdb5e8a04f 100644 --- a/tests/php/Unit/Service/Install/SignSetupServiceTest.php +++ b/tests/php/Unit/Service/Install/SignSetupServiceTest.php @@ -35,7 +35,7 @@ public function setUp(): void { $this->fileAccessHelper = new FileAccessHelper(); $this->appManager = $this->createMock(IAppManager::class); $this->config = $this->createMock(IConfig::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->appDataFactory = \OCP\Server::get(IAppDataFactory::class); $this->tempManager = \OCP\Server::get(ITempManager::class); } diff --git a/tests/php/Unit/Service/ReminderServiceTest.php b/tests/php/Unit/Service/ReminderServiceTest.php index 4fb9e03dbb..f696f11162 100644 --- a/tests/php/Unit/Service/ReminderServiceTest.php +++ b/tests/php/Unit/Service/ReminderServiceTest.php @@ -31,7 +31,7 @@ final class ReminderServiceTest extends \OCA\Libresign\Tests\Unit\TestCase { public function setUp(): void { $this->jobList = $this->createMock(IJobList::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->dateTimeZone = Server::get(IDateTimeZone::class); $this->time = $this->createMock(ITimeFactory::class); $this->signRequestMapper = $this->createMock(SignRequestMapper::class); diff --git a/tests/php/Unit/Service/SignFileServiceTest.php b/tests/php/Unit/Service/SignFileServiceTest.php index ef6a4b0801..0aa0657747 100644 --- a/tests/php/Unit/Service/SignFileServiceTest.php +++ b/tests/php/Unit/Service/SignFileServiceTest.php @@ -105,7 +105,7 @@ public function setUp(): void { $this->userManager = $this->createMock(IUserManager::class); $this->folderService = $this->createMock(FolderService::class); $this->logger = $this->createMock(LoggerInterface::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->validateHelper = $this->createMock(\OCA\Libresign\Helper\ValidateHelper::class); $this->signerElementsService = $this->createMock(SignerElementsService::class); $this->root = $this->createMock(\OCP\Files\IRootFolder::class); diff --git a/tests/php/Unit/Service/SignatureBackgroundServiceTest.php b/tests/php/Unit/Service/SignatureBackgroundServiceTest.php index a30af60e6e..7046dde0f7 100644 --- a/tests/php/Unit/Service/SignatureBackgroundServiceTest.php +++ b/tests/php/Unit/Service/SignatureBackgroundServiceTest.php @@ -23,7 +23,7 @@ final class SignatureBackgroundServiceTest extends \OCA\Libresign\Tests\Unit\Tes public function setUp(): void { $this->appData = $this->createMock(IAppData::class); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->config = $this->createMock(IConfig::class); $this->tempManager = $this->createMock(ITempManager::class); } diff --git a/tests/php/Unit/Service/SignatureTextServiceTest.php b/tests/php/Unit/Service/SignatureTextServiceTest.php index 9cc80b076a..2518e0db17 100644 --- a/tests/php/Unit/Service/SignatureTextServiceTest.php +++ b/tests/php/Unit/Service/SignatureTextServiceTest.php @@ -30,7 +30,7 @@ final class SignatureTextServiceTest extends \OCA\Libresign\Tests\Unit\TestCase public function setUp(): void { $this->l10n = \OCP\Server::get(IL10NFactory::class)->get(Application::APP_ID); - $this->appConfig = $this->getMockAppConfig(); + $this->appConfig = $this->getMockAppConfigWithReset(); $this->dateTimeZone = \OCP\Server::get(IDateTimeZone::class); $this->request = $this->createMock(IRequest::class); $this->userSession = $this->createMock(IUserSession::class); diff --git a/tests/php/Unit/TestCase.php b/tests/php/Unit/TestCase.php index 1d4bf6c77c..f9aec1c274 100644 --- a/tests/php/Unit/TestCase.php +++ b/tests/php/Unit/TestCase.php @@ -77,6 +77,14 @@ public static function getMockAppConfig(): IAppConfig { return $service; } + public static function getMockAppConfigWithReset(): IAppConfig { + $appConfig = self::getMockAppConfig(); + if ($appConfig instanceof AppConfigOverwrite) { + $appConfig->reset(); + } + return $appConfig; + } + public function mockConfig($config):void { $service = \OCP\Server::get(\OCP\IConfig::class); if (!$service instanceof AllConfigOverwrite) { diff --git a/tests/php/lib/AppConfigOverwrite.php b/tests/php/lib/AppConfigOverwrite.php index ccbf98c0a5..cec9323c0a 100644 --- a/tests/php/lib/AppConfigOverwrite.php +++ b/tests/php/lib/AppConfigOverwrite.php @@ -122,6 +122,12 @@ public function deleteKey(string $app, string $key): void { $this->markDeleted($app, $key); } + public function reset(): self { + $this->overWrite = []; + $this->deleted = []; + return $this; + } + private function isDeleted(string $app, string $key): bool { return isset($this->deleted[$app][$key]); }