diff --git a/src/ApiResource/ShareSettings.php b/src/ApiResource/ShareSettings.php new file mode 100644 index 0000000..160511e --- /dev/null +++ b/src/ApiResource/ShareSettings.php @@ -0,0 +1,57 @@ + ['share_settings:read']], + provider: ShareSettingsProvider::class, + security: "is_granted('ROLE_ADMIN')", + ), + new Put( + uriTemplate: '/settings/share', + denormalizationContext: ['groups' => ['share_settings:write']], + normalizationContext: ['groups' => ['share_settings:read']], + provider: ShareSettingsProvider::class, + processor: ShareSettingsProcessor::class, + security: "is_granted('ROLE_ADMIN')", + ), + ], +)] +final class ShareSettings +{ + #[Groups(['share_settings:read', 'share_settings:write'])] + public ?string $host = null; + + #[Groups(['share_settings:read', 'share_settings:write'])] + public ?string $shareName = null; + + #[Groups(['share_settings:read', 'share_settings:write'])] + public ?string $basePath = null; + + #[Groups(['share_settings:read', 'share_settings:write'])] + public ?string $domain = null; + + #[Groups(['share_settings:read', 'share_settings:write'])] + public ?string $username = null; + + #[Groups(['share_settings:write'])] + public ?string $password = null; + + #[Groups(['share_settings:read', 'share_settings:write'])] + public bool $enabled = false; + + #[Groups(['share_settings:read'])] + public bool $hasPassword = false; +} diff --git a/src/State/ShareSettingsProcessor.php b/src/State/ShareSettingsProcessor.php new file mode 100644 index 0000000..ce43f86 --- /dev/null +++ b/src/State/ShareSettingsProcessor.php @@ -0,0 +1,54 @@ +configRepository->findSingleton() ?? new ShareConfiguration(); + + $config->setHost($data->host); + $config->setShareName($data->shareName); + $config->setBasePath($data->basePath); + $config->setDomain($data->domain); + $config->setUsername($data->username); + $config->setEnabled($data->enabled); + + if (null !== $data->password && '' !== $data->password) { + $config->setEncryptedPassword($this->tokenEncryptor->encrypt($data->password)); + } + + $this->em->persist($config); + $this->em->flush(); + + $result = new ShareSettings(); + $result->host = $config->getHost(); + $result->shareName = $config->getShareName(); + $result->basePath = $config->getBasePath(); + $result->domain = $config->getDomain(); + $result->username = $config->getUsername(); + $result->enabled = $config->isEnabled(); + $result->hasPassword = $config->hasPassword(); + + return $result; + } +} diff --git a/src/State/ShareSettingsProvider.php b/src/State/ShareSettingsProvider.php new file mode 100644 index 0000000..0b43e3c --- /dev/null +++ b/src/State/ShareSettingsProvider.php @@ -0,0 +1,35 @@ +configRepository->findSingleton(); + $dto = new ShareSettings(); + + if (null !== $config) { + $dto->host = $config->getHost(); + $dto->shareName = $config->getShareName(); + $dto->basePath = $config->getBasePath(); + $dto->domain = $config->getDomain(); + $dto->username = $config->getUsername(); + $dto->enabled = $config->isEnabled(); + $dto->hasPassword = $config->hasPassword(); + } + + return $dto; + } +} diff --git a/tests/Functional/Controller/ShareSettingsTest.php b/tests/Functional/Controller/ShareSettingsTest.php new file mode 100644 index 0000000..b257b08 --- /dev/null +++ b/tests/Functional/Controller/ShareSettingsTest.php @@ -0,0 +1,54 @@ +request('GET', '/api/settings/share'); + + self::assertResponseStatusCodeSame(401); + } + + public function testGetSettingsReturns403ForRoleUser(): void + { + $client = static::createClient(); + $container = static::getContainer(); + $em = $container->get('doctrine.orm.entity_manager'); + + $user = $em->getRepository(User::class)->findOneBy(['username' => 'alice']); + $client->loginUser($user); + + $client->request('GET', '/api/settings/share'); + + self::assertResponseStatusCodeSame(403); + } + + public function testAdminCanReadSettingsWithoutPasswordLeak(): void + { + $client = static::createClient(); + $container = static::getContainer(); + $em = $container->get('doctrine.orm.entity_manager'); + + $admin = $em->getRepository(User::class)->findOneBy(['username' => 'admin']); + $client->loginUser($admin); + + $client->request('GET', '/api/settings/share'); + + self::assertResponseIsSuccessful(); + $data = json_decode($client->getResponse()->getContent(), true); + self::assertArrayHasKey('hasPassword', $data); + self::assertArrayNotHasKey('password', $data); + self::assertArrayNotHasKey('encryptedPassword', $data); + } +}