Skip to content

Commit cca71a2

Browse files
committed
feat(auth): make code request context-aware for dashboard login
Implements context-aware logic in the `AuthService.initiateEmailSignIn` method. - The method now accepts an `isDashboardLogin` boolean flag. - If `isDashboardLogin` is true, the service first validates that a user with the provided email exists and has either the 'admin' or 'publisher' role. - An `UnauthorizedException` is thrown if the user does not exist. - A `ForbiddenException` is thrown if the user exists but lacks the required roles. - A verification code is only sent if these checks pass. - If `isDashboardLogin` is false, the original behavior of sending a code without pre-validation is maintained for the user-facing app's sign-in/sign-up flow. This change enforces security at the first step of the dashboard login process, preventing code generation for unauthorized users.
1 parent 8bf722f commit cca71a2

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

lib/src/services/auth_service.dart

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,65 @@ class AuthService {
4141

4242
/// Initiates the email sign-in process.
4343
///
44-
/// Generates a verification code, stores it, and sends it via email.
44+
/// For standard sign-in (user-facing app), it generates a verification code,
45+
/// stores it, and sends it via email without checking for user existence.
46+
///
47+
/// For dashboard login (`isDashboardLogin: true`), it first verifies that a
48+
/// user with the given [email] exists and has either the 'admin' or
49+
/// 'publisher' role before sending the code.
50+
///
51+
/// - [email]: The email address to send the code to.
52+
/// - [isDashboardLogin]: A flag to indicate if this is a login attempt from
53+
/// the dashboard, which enforces stricter checks.
54+
///
4555
/// Throws [InvalidInputException] for invalid email format (via email client).
56+
/// Throws [UnauthorizedException] if `isDashboardLogin` is true and the user
57+
/// does not exist.
58+
/// Throws [ForbiddenException] if `isDashboardLogin` is true and the user
59+
/// exists but lacks the required roles.
4660
/// Throws [OperationFailedException] if code generation/storage/email fails.
47-
Future<void> initiateEmailSignIn(String email) async {
61+
Future<void> initiateEmailSignIn(
62+
String email, {
63+
bool isDashboardLogin = false,
64+
}) async {
4865
try {
66+
// For dashboard login, first validate the user exists and has permissions.
67+
if (isDashboardLogin) {
68+
print('Dashboard login initiated for $email. Verifying user...');
69+
User? user;
70+
try {
71+
final query = {'email': email};
72+
final response = await _userRepository.readAllByQuery(query);
73+
if (response.items.isNotEmpty) {
74+
user = response.items.first;
75+
}
76+
} on HtHttpException catch (e) {
77+
print('Repository error while verifying dashboard user $email: $e');
78+
rethrow;
79+
}
80+
81+
if (user == null) {
82+
print('Dashboard login failed: User $email not found.');
83+
throw const UnauthorizedException(
84+
'This email address is not registered for dashboard access.',
85+
);
86+
}
87+
88+
final hasRequiredRole =
89+
user.roles.contains(UserRoles.admin) ||
90+
user.roles.contains(UserRoles.publisher);
91+
92+
if (!hasRequiredRole) {
93+
print(
94+
'Dashboard login failed: User ${user.id} lacks required roles.',
95+
);
96+
throw const ForbiddenException(
97+
'Your account does not have the required permissions to sign in.',
98+
);
99+
}
100+
print('Dashboard user ${user.id} verified successfully.');
101+
}
102+
49103
// Generate and store the code for standard sign-in
50104
final code = await _verificationCodeStorageService
51105
.generateAndStoreSignInCode(email);

0 commit comments

Comments
 (0)