mirror of
https://github.com/LibreSign/libresign.git
synced 2025-12-18 05:20:45 +01:00
- Add reset() method to AppConfigOverwrite that clears overWrite and deleted arrays and returns self - Integrate reset() directly into getMockAppConfig() to ensure clean state on every call - All tests now automatically get clean AppConfig state without explicit reset calls - Prevents state pollution across test suites by resetting at the source - Simplifies test code by removing need for separate reset wrapper method Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
353 lines
9.9 KiB
PHP
353 lines
9.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace Test;
|
|
|
|
/**
|
|
* Overwrite opendir in the Test namespace.
|
|
*/
|
|
|
|
function testCaseWillIgnore(string $node): bool {
|
|
$libresignPath = current(glob(\OC::$SERVERROOT . '/data/appdata_*/libresign'));
|
|
$knownEntries = [
|
|
$libresignPath . '/aarch',
|
|
$libresignPath . '/arm64',
|
|
$libresignPath . '/cfssl_config',
|
|
$libresignPath . '/x86_64',
|
|
];
|
|
foreach ($knownEntries as $ignored) {
|
|
if (str_starts_with($node, $ignored)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function rmdir($dir) {
|
|
if (testCaseWillIgnore($dir)) {
|
|
return false;
|
|
}
|
|
return \rmdir($dir);
|
|
}
|
|
|
|
function unlink($file) {
|
|
if (testCaseWillIgnore($file)) {
|
|
return false;
|
|
}
|
|
return \unlink($file);
|
|
}
|
|
|
|
namespace OCA\Libresign\Tests\Unit;
|
|
|
|
use donatj\MockWebServer\MockWebServer;
|
|
use donatj\MockWebServer\Response as MockWebServerResponse;
|
|
use OC\Memcache\Factory as CacheFactory;
|
|
use OC\SystemConfig;
|
|
use OCA\Libresign\AppInfo\Application;
|
|
use OCA\Libresign\Db\File;
|
|
use OCA\Libresign\Db\signRequestMapper;
|
|
use OCA\Libresign\Service\RequestSignatureService;
|
|
use OCA\Libresign\Tests\lib\AllConfigOverwrite;
|
|
use OCA\Libresign\Tests\lib\AppConfigOverwrite;
|
|
use OCA\Libresign\Tests\lib\ConfigOverwrite;
|
|
use OCP\IAppConfig;
|
|
use OCP\IConfig;
|
|
|
|
class TestCase extends \Test\TestCase {
|
|
protected static MockWebServer $server;
|
|
private RequestSignatureService $requestSignatureService;
|
|
private signRequestMapper $signRequestMapper;
|
|
private array $users = [];
|
|
|
|
public static function getMockAppConfig(): IAppConfig {
|
|
\OC::$server->registerParameter('appName', 'libresign');
|
|
$service = \OCP\Server::get(\OCP\IAppConfig::class);
|
|
if (!$service instanceof AppConfigOverwrite) {
|
|
\OC::$server->registerService(\OCP\IAppConfig::class, fn (): AppConfigOverwrite => new AppConfigOverwrite(
|
|
\OCP\Server::get(\OCP\IDBConnection::class),
|
|
\OCP\Server::get(\OCP\IConfig::class),
|
|
\OCP\Server::get(\OC\Config\ConfigManager::class),
|
|
\OCP\Server::get(\OC\Config\PresetManager::class),
|
|
\OCP\Server::get(\Psr\Log\LoggerInterface::class),
|
|
\OCP\Server::get(\OCP\Security\ICrypto::class),
|
|
\OCP\Server::get(CacheFactory::class),
|
|
));
|
|
$service = \OCP\Server::get(\OCP\IAppConfig::class);
|
|
}
|
|
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) {
|
|
\OC::$server->registerService(\OCP\IConfig::class, function ():AllConfigOverwrite {
|
|
$configOverwrite = new ConfigOverwrite(\OC::$configDir);
|
|
$systemConfig = new SystemConfig($configOverwrite);
|
|
return new AllConfigOverwrite($systemConfig);
|
|
});
|
|
$service = \OCP\Server::get(\OCP\IConfig::class);
|
|
}
|
|
if (is_subclass_of($service, IConfig::class)) {
|
|
foreach ($config as $app => $keys) {
|
|
foreach ($keys as $key => $value) {
|
|
if (is_array($value) || is_object($value)) {
|
|
$value = json_encode($value);
|
|
}
|
|
$service->setAppValue($app, $key, $value);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
public function haveDependents(): bool {
|
|
$reflector = new \ReflectionClass(static::class);
|
|
|
|
$methods = $reflector->getMethods();
|
|
foreach ($methods as $method) {
|
|
$docblock = $reflector->getMethod($method->getName())->getDocComment();
|
|
if (!$docblock) {
|
|
return false;
|
|
}
|
|
if (preg_match('#@depends ' . $this->name() . '\n#s', $docblock)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function iDependOnOthers(): bool {
|
|
$reflector = new \ReflectionClass(static::class);
|
|
$docblock = $reflector->getMethod($this->name())->getDocComment();
|
|
if (!$docblock) {
|
|
return false;
|
|
}
|
|
if (preg_match('#@depends #s', $docblock)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static function setUpBeforeClass(): void {
|
|
parent::setUpBeforeClass();
|
|
self::$server = new MockWebServer();
|
|
self::$server->start();
|
|
}
|
|
|
|
public function setUp(): void {
|
|
static::getMockAppConfig();
|
|
$this->getBinariesFromCache();
|
|
if ($this->iDependOnOthers() || !$this->IsDatabaseAccessAllowed()) {
|
|
return;
|
|
}
|
|
$this->cleanDatabase();
|
|
}
|
|
|
|
public function tearDown(): void {
|
|
$this->backupBinaries();
|
|
if ($this->haveDependents() || !$this->IsDatabaseAccessAllowed()) {
|
|
return;
|
|
}
|
|
$this->cleanDatabase();
|
|
}
|
|
|
|
public static function tearDownAfterClass(): void {
|
|
try {
|
|
parent::tearDownAfterClass();
|
|
} catch (\Throwable) {
|
|
}
|
|
}
|
|
|
|
private function cleanDatabase(): void {
|
|
$db = \OCP\Server::get(\OCP\IDBConnection::class);
|
|
if (!$db) {
|
|
return;
|
|
}
|
|
$this->deleteUsers();
|
|
|
|
$delete = $db->getQueryBuilder();
|
|
$delete->delete('libresign_file')->executeStatement();
|
|
$delete->delete('libresign_sign_request')->executeStatement();
|
|
$delete->delete('libresign_user_element')->executeStatement();
|
|
$delete->delete('libresign_file_element')->executeStatement();
|
|
$delete->delete('libresign_id_docs')->executeStatement();
|
|
}
|
|
|
|
/**
|
|
* Create user
|
|
*/
|
|
public function createAccount(string $username, string $password, string $groupName = 'testGroup'):\OC\User\User {
|
|
$this->users[] = $username;
|
|
$this->mockConfig([
|
|
'core' => [
|
|
'newUser.sendEmail' => 'no'
|
|
]
|
|
]);
|
|
|
|
$userManager = \OCP\Server::get(\OCP\IUserManager::class);
|
|
$groupManager = \OCP\Server::get(\OCP\IGroupManager::class);
|
|
|
|
$user = $userManager->get($username);
|
|
if (!$user) {
|
|
$user = @$userManager->createUser($username, $password);
|
|
}
|
|
$group = $groupManager->get($groupName);
|
|
if (!$group) {
|
|
$group = $groupManager->createGroup($groupName);
|
|
}
|
|
|
|
if ($group && $user) {
|
|
$group->addUser($user);
|
|
}
|
|
return $user;
|
|
}
|
|
|
|
public function markUserExists($username): void {
|
|
$this->users[] = $username;
|
|
}
|
|
|
|
public function deleteUsers():void {
|
|
foreach ($this->users as $username) {
|
|
$this->deleteUserIfExists($username);
|
|
}
|
|
}
|
|
|
|
public function deleteUserIfExists($username): void {
|
|
$user = \OCP\Server::get(\OCP\IUserManager::class)->get($username);
|
|
if ($user) {
|
|
try {
|
|
$user->delete();
|
|
} catch (\Throwable) {
|
|
}
|
|
}
|
|
}
|
|
|
|
private function getBinariesFromCache(): void {
|
|
$appPath = $this->getFullLiresignAppFolder();
|
|
if (!$appPath) {
|
|
return;
|
|
}
|
|
$cachePath = preg_replace('/\/.*\/appdata_[a-z0-9]*/', (string)\OCP\Server::get(\OCP\ITempManager::class)->getTempBaseDir(), $appPath);
|
|
if (!file_exists($cachePath)) {
|
|
return;
|
|
}
|
|
if (!is_dir($appPath)) {
|
|
mkdir($appPath, 0777, true);
|
|
}
|
|
$this->recursiveCopy($cachePath, $appPath);
|
|
}
|
|
|
|
private function getFullLiresignAppFolder(): string {
|
|
$path = '../../data/appdata_' . \OC_Util::getInstanceId() . '/libresign';
|
|
if (!is_dir($path)) {
|
|
mkdir($path, 0777, true);
|
|
$user = fileowner(__FILE__);
|
|
chown($path, $user);
|
|
@chgrp($path, $user);
|
|
}
|
|
return realpath($path);
|
|
}
|
|
|
|
private function backupBinaries(): void {
|
|
$appPath = $this->getFullLiresignAppFolder();
|
|
if (!is_readable($appPath)) {
|
|
return;
|
|
}
|
|
$isEmpty = count(scandir($appPath)) == 2;
|
|
if ($isEmpty) {
|
|
return;
|
|
}
|
|
$cachePath = preg_replace('/\/.*\/appdata_[a-z0-9]*/', (string)\OCP\Server::get(\OCP\ITempManager::class)->getTempBaseDir(), $appPath);
|
|
if (!file_exists($cachePath)) {
|
|
mkdir($cachePath);
|
|
}
|
|
$this->recursiveCopy($appPath, $cachePath);
|
|
}
|
|
|
|
private function recursiveCopy(string $source, string $dest): void {
|
|
foreach (
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS),
|
|
\RecursiveIteratorIterator::SELF_FIRST) as $item
|
|
) {
|
|
$newDest = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathname();
|
|
if (!file_exists($newDest)) {
|
|
if ($item->isDir()) {
|
|
mkdir($newDest);
|
|
} else {
|
|
copy($item->getPathname(), $newDest);
|
|
}
|
|
}
|
|
if (fileperms($item->getPathname()) !== fileperms($newDest)) {
|
|
chmod($newDest, fileperms($item->getPathname()));
|
|
}
|
|
}
|
|
}
|
|
|
|
public function requestSignFile($data): File {
|
|
self::$server->setResponseOfPath('/api/v1/cfssl/newcert', new MockWebServerResponse(
|
|
file_get_contents(__DIR__ . '/../fixtures/cfssl/newcert-with-success.json')
|
|
));
|
|
|
|
$appConfig = static::getMockAppConfig();
|
|
$appConfig->setValueBool(Application::APP_ID, 'notifyUnsignedUser', false);
|
|
$appConfig->setValueString(Application::APP_ID, 'commonName', 'CommonName');
|
|
$appConfig->setValueString(Application::APP_ID, 'country', 'Brazil');
|
|
$appConfig->setValueString(Application::APP_ID, 'organization', 'Organization');
|
|
$appConfig->setValueString(Application::APP_ID, 'organizationalUnit', 'organizationalUnit');
|
|
$appConfig->setValueString(Application::APP_ID, 'cfsslUri', self::$server->getServerRoot() . '/api/v1/cfssl/');
|
|
|
|
if (!isset($data['settings'])) {
|
|
$data['settings']['separator'] = '_';
|
|
$data['settings']['folderPatterns'][] = [
|
|
'name' => 'date',
|
|
'setting' => 'Y-m-d\TH:i:s.u'
|
|
];
|
|
$data['settings']['folderPatterns'][] = [
|
|
'name' => 'name'
|
|
];
|
|
$data['settings']['folderPatterns'][] = [
|
|
'name' => 'userId'
|
|
];
|
|
}
|
|
$file = $this->getRequestSignatureService()->save($data);
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* @return \OCA\Libresign\Service\RequestSignatureService
|
|
*/
|
|
private function getRequestSignatureService(): \OCA\Libresign\Service\RequestSignatureService {
|
|
if (!isset($this->requestSignatureService)) {
|
|
$this->requestSignatureService = \OCP\Server::get(\OCA\Libresign\Service\RequestSignatureService::class);
|
|
}
|
|
return $this->requestSignatureService;
|
|
}
|
|
|
|
public function getSignersFromFileId(int $fileId): array {
|
|
return $this->getSignRequestMapper()->getByFileId($fileId);
|
|
}
|
|
|
|
/**
|
|
* @return \OCA\Libresign\Db\signRequestMapper
|
|
*/
|
|
private function getSignRequestMapper(): \OCA\Libresign\Db\SignRequestMapper {
|
|
if (!isset($this->signRequestMapper)) {
|
|
$this->signRequestMapper = \OCP\Server::get(\OCA\Libresign\Db\SignRequestMapper::class);
|
|
}
|
|
return $this->signRequestMapper;
|
|
}
|
|
}
|