Files
authentication_provider_pas…/lib/Controllers/PasswordController.php
2026-02-10 20:04:26 -05:00

120 lines
3.8 KiB
PHP

<?php
namespace KTXM\AuthenticationProviderPassword\Controllers;
use KTXC\Http\Response\JsonResponse;
use KTXC\SessionIdentity;
use KTXC\SessionTenant;
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 SessionIdentity $sessionIdentity,
private readonly SessionTenant $sessionTenant,
private readonly CredentialStore $credentialStore,
private readonly Provider $provider,
private readonly Crypto $crypto
) {
}
#[AuthenticatedRoute('/password/update', name: 'password.update', methods: ['POST'])]
public function update(string $current_password, string $new_password): JsonResponse
{
$tenantId = $this->sessionTenant->identifier();
$identifier = $this->sessionIdentity->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('/admin/status/{uid}', name: 'password.admin.status', methods: ['GET'])]
public function getStatus(string $uid): JsonResponse
{
$tenantId = $this->sessionTenant->identifier();
if ($tenantId === null) {
return new JsonResponse(['error' => 'Invalid session state'], 400);
}
// TODO: Add permission check for admin operations
$hasCredentials = $this->provider->hasCredentials($tenantId, $uid);
return new JsonResponse([
'enrolled' => $hasCredentials,
'provider' => 'password',
]);
}
/**
* Admin endpoint: Set/reset user password
*/
#[AuthenticatedRoute('/admin/reset', name: 'password.admin.reset', methods: ['POST'])]
public function adminReset(string $uid, string $password): JsonResponse
{
$tenantId = $this->sessionTenant->identifier();
if ($tenantId === null) {
return new JsonResponse(['error' => 'Invalid session state'], 400);
}
// TODO: Add permission check for admin operations
if (strlen($password) < 8) {
return new JsonResponse(['error' => 'Password must be at least 8 characters'], 400);
}
$success = $this->provider->setCredential($tenantId, $uid, $password);
if (!$success) {
return new JsonResponse(['error' => 'Failed to set password'], 500);
}
return new JsonResponse(['success' => true]);
}
/**
* Admin endpoint: Remove user password
*/
#[AuthenticatedRoute('/admin/remove/{uid}', name: 'password.admin.remove', methods: ['DELETE'])]
public function adminRemove(string $uid): JsonResponse
{
$tenantId = $this->sessionTenant->identifier();
if ($tenantId === null) {
return new JsonResponse(['error' => 'Invalid session state'], 400);
}
// TODO: Add permission check for admin operations
$this->credentialStore->delete($tenantId, $uid);
return new JsonResponse(['success' => true]);
}
}