🚀 مُصادَق: تحديث برمجي جديد 2026-05-03 15:51
This commit is contained in:
@@ -24,12 +24,36 @@ final class AuthService
|
||||
{
|
||||
$user = $this->userModel->findByEmail($email);
|
||||
|
||||
if ($user) {
|
||||
if ($user['locked_until'] && strtotime($user['locked_until']) > time()) {
|
||||
throw new \App\Core\Exceptions\HttpException("الحساب مقفل مؤقتاً لعدة محاولات فاشلة، حاول مجدداً لاحقاً", "ACCOUNT_LOCKED", 429);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$user || !password_verify($password, $user['password_hash'])) {
|
||||
throw new Exception("البريد الإلكتروني أو كلمة المرور غير صحيحة");
|
||||
if ($user) {
|
||||
$failedCount = (int)($user['failed_login_count'] ?? 0) + 1;
|
||||
$lockedUntil = null;
|
||||
if ($failedCount >= 5) {
|
||||
$lockedUntil = date('Y-m-d H:i:s', strtotime('+15 minutes'));
|
||||
error_log("[SECURITY] Account locked due to brute force: {$email}");
|
||||
}
|
||||
$this->userModel->update($user['id'], [
|
||||
'failed_login_count' => $failedCount,
|
||||
'locked_until' => $lockedUntil
|
||||
]);
|
||||
}
|
||||
error_log("[SECURITY] Failed login attempt for email: {$email}");
|
||||
throw new \App\Core\Exceptions\HttpException("البريد الإلكتروني أو كلمة المرور غير صحيحة", "INVALID_CREDENTIALS", 401);
|
||||
}
|
||||
|
||||
if (!$user['is_active']) {
|
||||
throw new Exception("هذا الحساب معطل حالياً");
|
||||
throw new \App\Core\Exceptions\HttpException("هذا الحساب معطل حالياً", "ACCOUNT_DISABLED", 403);
|
||||
}
|
||||
|
||||
// Reset failed login count on successful login
|
||||
if ($user['failed_login_count'] > 0) {
|
||||
$this->userModel->update($user['id'], ['failed_login_count' => 0, 'locked_until' => null]);
|
||||
}
|
||||
|
||||
$accessToken = $this->jwtService->issueAccessToken([
|
||||
@@ -51,13 +75,7 @@ final class AuthService
|
||||
return [
|
||||
'access_token' => $accessToken,
|
||||
'refresh_token' => $refreshToken,
|
||||
'user' => [
|
||||
'id' => $user['id'],
|
||||
'name' => $user['name'],
|
||||
'email' => $user['email'],
|
||||
'role' => $user['role'],
|
||||
'assigned_company_id' => $user['assigned_company_id']
|
||||
]
|
||||
'user' => $user
|
||||
];
|
||||
}
|
||||
|
||||
@@ -79,6 +97,11 @@ final class AuthService
|
||||
throw new Exception("جلسة العمل منتهية، يرجى تسجيل الدخول مرة أخرى");
|
||||
}
|
||||
|
||||
return $this->createSession($user);
|
||||
}
|
||||
|
||||
public function createSession(array $user): array
|
||||
{
|
||||
$accessToken = $this->jwtService->issueAccessToken([
|
||||
'user_id' => $user['id'],
|
||||
'tenant_id' => $user['tenant_id'],
|
||||
@@ -100,7 +123,8 @@ final class AuthService
|
||||
'name' => $user['name'],
|
||||
'email' => $user['email'],
|
||||
'role' => $user['role'],
|
||||
'assigned_company_id' => $user['assigned_company_id']
|
||||
'assigned_company_id' => $user['assigned_company_id'],
|
||||
'totp_enabled' => (bool)($user['totp_enabled'] ?? false)
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -112,37 +136,46 @@ final class AuthService
|
||||
throw new Exception("هذا البريد الإلكتروني مسجل مسبقاً");
|
||||
}
|
||||
|
||||
$tenantId = Uuid::uuid4()->toString();
|
||||
$userId = Uuid::uuid4()->toString();
|
||||
$db = \App\Core\Database::getInstance();
|
||||
try {
|
||||
$db->beginTransaction();
|
||||
|
||||
// 2. Create Tenant
|
||||
$this->tenantModel->create([
|
||||
'id' => $tenantId,
|
||||
'name' => $data['tenant_name'],
|
||||
'email' => $data['email'],
|
||||
'status' => 'trial',
|
||||
'trial_ends_at' => date('Y-m-d H:i:s', strtotime('+14 days'))
|
||||
]);
|
||||
$tenantId = Uuid::uuid4()->toString();
|
||||
$userId = Uuid::uuid4()->toString();
|
||||
|
||||
// 3. Create Subscription
|
||||
$this->subscriptionModel->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'plan' => 'basic',
|
||||
'status' => 'trial'
|
||||
]);
|
||||
// 2. Create Tenant
|
||||
$this->tenantModel->create([
|
||||
'id' => $tenantId,
|
||||
'name' => $data['name'] ?? 'مساحة عمل جديدة',
|
||||
'email' => $data['email'],
|
||||
'status' => 'trial',
|
||||
'trial_ends_at' => date('Y-m-d H:i:s', strtotime('+14 days'))
|
||||
]);
|
||||
|
||||
// 4. Create User
|
||||
$this->userModel->create([
|
||||
'id' => $userId,
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => $data['user_name'],
|
||||
'email' => $data['email'],
|
||||
'password_hash' => password_hash($data['password'], PASSWORD_ARGON2ID),
|
||||
'role' => 'admin',
|
||||
'is_active' => 1
|
||||
]);
|
||||
// 3. Create Subscription
|
||||
$this->subscriptionModel->create([
|
||||
'tenant_id' => $tenantId,
|
||||
'plan' => 'basic',
|
||||
'status' => 'trial'
|
||||
]);
|
||||
|
||||
return $this->login($data['email'], $data['password']);
|
||||
// 4. Create User
|
||||
$this->userModel->create([
|
||||
'id' => $userId,
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => $data['name'] ?? 'مسؤول النظام',
|
||||
'email' => $data['email'],
|
||||
'password_hash' => password_hash($data['password'], PASSWORD_ARGON2ID),
|
||||
'role' => 'admin',
|
||||
'is_active' => 1
|
||||
]);
|
||||
|
||||
$db->commit();
|
||||
return $this->login($data['email'], $data['password']);
|
||||
} catch (\Throwable $e) {
|
||||
$db->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
public function logout(string $jti, int $remaining): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user