3556be7c85
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
134 lines
4.8 KiB
PHP
134 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace KTXM\AuthenticationProviderPassword\Controllers;
|
|
|
|
use KTXC\Http\Response\JsonResponse;
|
|
use KTXC\Service\UserAccountsService;
|
|
use KTXC\Context\IdentityContextInterface;
|
|
use KTXC\Context\TenantContextInterface;
|
|
use KTXF\Controller\ControllerAbstract;
|
|
use KTXF\Routing\Attributes\AuthenticatedRoute;
|
|
use KTXF\Security\Crypto;
|
|
use KTXM\AuthenticationProviderPassword\Provider;
|
|
use KTXM\AuthenticationProviderPassword\Stores\CredentialStore;
|
|
|
|
class PasswordController extends ControllerAbstract
|
|
{
|
|
public function __construct(
|
|
private readonly IdentityContextInterface $identityContext,
|
|
private readonly TenantContextInterface $tenantContext,
|
|
private readonly CredentialStore $credentialStore,
|
|
private readonly Provider $provider,
|
|
private readonly Crypto $crypto,
|
|
private readonly UserAccountsService $userAccountsService
|
|
) {
|
|
}
|
|
|
|
#[AuthenticatedRoute('/password/update', name: 'password.update', methods: ['POST'])]
|
|
public function update(string $current_password, string $new_password): JsonResponse
|
|
{
|
|
$tenantId = $this->tenantContext->identifier();
|
|
$identifier = $this->identityContext->mailAddress();
|
|
|
|
if ($tenantId === null || $identifier === null) {
|
|
return new JsonResponse(['error' => 'Invalid session state'], 400);
|
|
}
|
|
|
|
$credential = $this->credentialStore->fetchByIdentifier($tenantId, $identifier);
|
|
|
|
if (!$credential) {
|
|
return new JsonResponse(['error' => 'No password set'], 400);
|
|
}
|
|
|
|
if (!$this->crypto->verifyPassword($current_password, $credential['secret'])) {
|
|
return new JsonResponse(['error' => 'Invalid current password'], 400);
|
|
}
|
|
|
|
$newHash = $this->crypto->hashPassword($new_password);
|
|
$this->credentialStore->updateSecret($tenantId, $identifier, $newHash);
|
|
|
|
return new JsonResponse(['success' => true]);
|
|
}
|
|
|
|
/**
|
|
* Admin endpoint: Get credential status for a user
|
|
*/
|
|
#[AuthenticatedRoute('/status', name: 'password.admin.status', methods: ['POST'], permissions: ['authentication_provider_password.admin.view', 'authentication_provider_password.admin.manage'])]
|
|
public function getStatus(string $uid): JsonResponse
|
|
{
|
|
$tenantId = $this->tenantContext->identifier();
|
|
|
|
if ($tenantId === null) {
|
|
return new JsonResponse(['error' => 'Invalid session state'], 400);
|
|
}
|
|
|
|
$user = $this->userAccountsService->fetchByIdentifier($uid);
|
|
if (!$user) {
|
|
return new JsonResponse(['error' => 'User not found'], 404);
|
|
}
|
|
|
|
// Credentials are keyed by identity (email/username), not uid
|
|
$hasCredentials = $this->provider->hasCredentials($tenantId, $user['identity']);
|
|
|
|
return new JsonResponse([
|
|
'enrolled' => $hasCredentials,
|
|
'provider' => 'password',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Admin endpoint: Set/reset user password
|
|
*/
|
|
#[AuthenticatedRoute('/reset', name: 'password.admin.reset', methods: ['POST'], permissions: ['authentication_provider_password.admin.manage'])]
|
|
public function adminReset(string $uid, string $password): JsonResponse
|
|
{
|
|
$tenantId = $this->tenantContext->identifier();
|
|
|
|
if ($tenantId === null) {
|
|
return new JsonResponse(['error' => 'Invalid session state'], 400);
|
|
}
|
|
|
|
if (strlen($password) < 8) {
|
|
return new JsonResponse(['error' => 'Password must be at least 8 characters'], 400);
|
|
}
|
|
|
|
$user = $this->userAccountsService->fetchByIdentifier($uid);
|
|
if (!$user) {
|
|
return new JsonResponse(['error' => 'User not found'], 404);
|
|
}
|
|
|
|
// Credentials are keyed by identity (email/username), not uid
|
|
$success = $this->provider->setCredential($tenantId, $user['identity'], $password);
|
|
|
|
if (!$success) {
|
|
return new JsonResponse(['error' => 'Failed to set password'], 500);
|
|
}
|
|
|
|
return new JsonResponse(['success' => true]);
|
|
}
|
|
|
|
/**
|
|
* Admin endpoint: Remove user password
|
|
*/
|
|
#[AuthenticatedRoute('/remove', name: 'password.admin.remove', methods: ['POST'], permissions: ['authentication_provider_password.admin.manage'])]
|
|
public function adminRemove(string $uid): JsonResponse
|
|
{
|
|
$tenantId = $this->tenantContext->identifier();
|
|
|
|
if ($tenantId === null) {
|
|
return new JsonResponse(['error' => 'Invalid session state'], 400);
|
|
}
|
|
|
|
$user = $this->userAccountsService->fetchByIdentifier($uid);
|
|
if (!$user) {
|
|
return new JsonResponse(['error' => 'User not found'], 404);
|
|
}
|
|
|
|
// Credentials are keyed by identity (email/username), not uid
|
|
$this->credentialStore->delete($tenantId, $user['identity']);
|
|
|
|
return new JsonResponse(['success' => true]);
|
|
}
|
|
}
|
|
|