major update
This commit is contained in:
@@ -8,6 +8,7 @@ use MintyPHP\Repository\User\UserWriteRepository;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\Service\User\UserAccountService;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
use MintyPHP\Service\Audit\SystemAuditService;
|
||||
use MintyPHP\Session;
|
||||
use MintyPHP\Support\Flash;
|
||||
|
||||
@@ -22,7 +23,8 @@ class AuthService
|
||||
private readonly EmailVerificationService $emailVerificationService,
|
||||
private readonly AuthPermissionGateway $permissionGateway,
|
||||
private readonly AuthTenantSsoGateway $tenantSsoGateway,
|
||||
private readonly AuthSavedFilterGateway $savedFilterGateway
|
||||
private readonly AuthSavedFilterGateway $savedFilterGateway,
|
||||
private readonly SystemAuditService $systemAuditService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -33,6 +35,10 @@ class AuthService
|
||||
// Check if email is verified before attempting login
|
||||
$existingUser = $this->userReadRepository->findByEmail($email);
|
||||
if ($existingUser && empty($existingUser['email_verified_at'])) {
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'email_not_verified',
|
||||
'metadata' => ['email_hash' => \MintyPHP\Http\RequestContext::hashValue(strtolower($email))],
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Please verify your email first',
|
||||
@@ -45,6 +51,10 @@ class AuthService
|
||||
$user = Auth::login($email, $password);
|
||||
|
||||
if (!$user) {
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'invalid_credentials',
|
||||
'metadata' => ['email_hash' => \MintyPHP\Http\RequestContext::hashValue(strtolower($email))],
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Email/password not valid',
|
||||
@@ -54,6 +64,10 @@ class AuthService
|
||||
|
||||
if (!($_SESSION['user']['active'] ?? 1)) {
|
||||
Auth::logout();
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'account_inactive',
|
||||
'metadata' => ['email_hash' => \MintyPHP\Http\RequestContext::hashValue(strtolower($email))],
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Account is inactive',
|
||||
@@ -64,6 +78,10 @@ class AuthService
|
||||
$userId = (int) ($_SESSION['user']['id'] ?? 0);
|
||||
if ($userId > 0 && !$this->isLocalPasswordLoginAllowedForUser($userId)) {
|
||||
Auth::logout();
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'password_login_disabled',
|
||||
'metadata' => ['email_hash' => \MintyPHP\Http\RequestContext::hashValue(strtolower($email))],
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Password login is disabled for all assigned tenants',
|
||||
@@ -75,6 +93,10 @@ class AuthService
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
if (!empty($_SESSION['no_active_tenant'])) {
|
||||
Auth::logout();
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'no_active_tenant',
|
||||
'metadata' => ['email_hash' => \MintyPHP\Http\RequestContext::hashValue(strtolower($email))],
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'No active tenant assigned',
|
||||
@@ -84,6 +106,11 @@ class AuthService
|
||||
$this->userWriteRepository->updateLastLogin($userId, 'local');
|
||||
}
|
||||
|
||||
$this->recordAuthEvent('auth.login.success', 'success', [
|
||||
'actor_user_id' => $userId > 0 ? $userId : null,
|
||||
'actor_tenant_id' => (int) ($_SESSION['current_tenant']['id'] ?? 0),
|
||||
]);
|
||||
|
||||
return ['ok' => true];
|
||||
}
|
||||
|
||||
@@ -154,10 +181,19 @@ class AuthService
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
if (!empty($_SESSION['no_active_tenant'])) {
|
||||
Auth::logout();
|
||||
$this->recordAuthEvent('auth.login.failed', 'failed', [
|
||||
'error_code' => 'login_no_active_tenant',
|
||||
'actor_user_id' => $userId,
|
||||
]);
|
||||
return ['ok' => false, 'error' => 'login_no_active_tenant'];
|
||||
}
|
||||
|
||||
$this->userWriteRepository->updateLastLogin($userId, $loginProvider);
|
||||
$this->recordAuthEvent('auth.login.success', 'success', [
|
||||
'actor_user_id' => $userId,
|
||||
'actor_tenant_id' => (int) ($_SESSION['current_tenant']['id'] ?? 0),
|
||||
'metadata' => ['provider' => $loginProvider],
|
||||
]);
|
||||
return ['ok' => true, 'user' => $user];
|
||||
}
|
||||
|
||||
@@ -214,17 +250,27 @@ class AuthService
|
||||
|
||||
public function logout(): void
|
||||
{
|
||||
$actorUserId = (int) ($_SESSION['user']['id'] ?? 0);
|
||||
$actorTenantId = (int) ($_SESSION['current_tenant']['id'] ?? 0);
|
||||
$this->rememberMeService->forgetCurrentUser();
|
||||
Auth::logout();
|
||||
$this->recordAuthEvent('auth.logout', 'success', [
|
||||
'actor_user_id' => $actorUserId > 0 ? $actorUserId : null,
|
||||
'actor_tenant_id' => $actorTenantId > 0 ? $actorTenantId : null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function logoutAndRedirect(string $target = 'login'): void
|
||||
{
|
||||
$this->rememberMeService->forgetCurrentUser();
|
||||
Auth::logout();
|
||||
$this->logout();
|
||||
Router::redirect($target);
|
||||
}
|
||||
|
||||
private function recordAuthEvent(string $eventType, string $outcome, array $context = []): void
|
||||
{
|
||||
$this->systemAuditService->record($eventType, $outcome, $context);
|
||||
}
|
||||
|
||||
public function refreshSessionAuthState(int $userId): array
|
||||
{
|
||||
if ($userId <= 0) {
|
||||
|
||||
Reference in New Issue
Block a user