@@ -2,28 +2,14 @@ import 'dart:io';
22
33import 'package:core/core.dart' ; // For exceptions
44import 'package:dart_frog/dart_frog.dart' ;
5+ import 'package:flutter_news_app_api_server_full_source_code/src/middlewares/rate_limiter_middleware.dart' ;
56import 'package:flutter_news_app_api_server_full_source_code/src/services/auth_service.dart' ;
67import 'package:logging/logging.dart' ;
78
89// Create a logger for this file.
910final _logger = Logger ('request_code_handler' );
1011
11- /// Handles POST requests to `/api/v1/auth/request-code` .
12- ///
13- /// Initiates an email-based sign-in process. This endpoint is context-aware.
14- ///
15- /// - For the user-facing app, it sends a verification code to the provided
16- /// email, supporting both sign-in and sign-up.
17- /// - For the dashboard, the request body must include `"isDashboardLogin": true` .
18- /// In this mode, it first verifies the user exists and has 'admin' or
19- /// 'publisher' roles before sending a code, effectively acting as a
20- /// login-only gate.
21- Future <Response > onRequest (RequestContext context) async {
22- // Ensure this is a POST request
23- if (context.request.method != HttpMethod .post) {
24- return Response (statusCode: HttpStatus .methodNotAllowed);
25- }
26-
12+ Future <Response > _onRequest (RequestContext context) async {
2713 // Read the AuthService provided by middleware
2814 final authService = context.read <AuthService >();
2915
@@ -70,25 +56,53 @@ Future<Response> onRequest(RequestContext context) async {
7056 }
7157
7258 try {
73- // Call the AuthService to handle the logic, passing the context flag.
74- await authService.initiateEmailSignIn (
75- email,
76- isDashboardLogin: isDashboardLogin,
77- );
59+ // Call the AuthService to handle the logic, passing the context flag.
60+ await authService.initiateEmailSignIn (
61+ email,
62+ isDashboardLogin: isDashboardLogin,
63+ );
7864
79- // Return 202 Accepted: The request is accepted for processing,
80- // but the processing (email sending) hasn't necessarily completed.
81- // 200 OK is also acceptable if you consider the API call itself complete.
82- return Response (statusCode: HttpStatus .accepted);
83- } on HttpException catch (_) {
84- // Let the central errorHandler middleware handle known exceptions
85- rethrow ;
86- } catch (e, s) {
87- // Catch unexpected errors from the service layer
88- _logger.severe ('Unexpected error in /request-code handler' , e, s);
89- // Let the central errorHandler handle this as a 500
90- throw const OperationFailedException (
91- 'An unexpected error occurred while requesting the sign-in code.' ,
92- );
65+ // Return 202 Accepted: The request is accepted for processing,
66+ // but the processing (email sending) hasn't necessarily completed.
67+ // 200 OK is also acceptable if you consider the API call itself complete.
68+ return Response (statusCode: HttpStatus .accepted);
69+ } on HttpException catch (_) {
70+ // Let the central errorHandler middleware handle known exceptions
71+ rethrow ;
72+ } catch (e, s) {
73+ // Catch unexpected errors from the service layer
74+ _logger.severe ('Unexpected error in /request-code handler' , e, s);
75+ // Let the central errorHandler handle this as a 500
76+ throw const OperationFailedException (
77+ 'An unexpected error occurred while requesting the sign-in code.' ,
78+ );
79+ }
80+ }
81+
82+ /// Handles POST requests to `/api/v1/auth/request-code` .
83+ ///
84+ /// Initiates an email-based sign-in process. This endpoint is context-aware.
85+ ///
86+ /// - For the user-facing app, it sends a verification code to the provided
87+ /// email, supporting both sign-in and sign-up.
88+ /// - For the dashboard, the request body must include `"isDashboardLogin": true` .
89+ /// In this mode, it first verifies the user exists and has 'admin' or
90+ /// 'publisher' roles before sending a code, effectively acting as a
91+ /// login-only gate.
92+ Future <Response > onRequest (RequestContext context) async {
93+ // Ensure this is a POST request
94+ if (context.request.method != HttpMethod .post) {
95+ return Response (statusCode: HttpStatus .methodNotAllowed);
9396 }
97+
98+ // Apply the rate limiter middleware before calling the actual handler.
99+ final handler = const Pipeline ().addMiddleware (
100+ rateLimiter (
101+ limit: 3 ,
102+ window: const Duration (hours: 24 ),
103+ keyExtractor: ipKeyExtractor,
104+ ),
105+ ).addHandler (_onRequest);
106+
107+ return handler (context);
94108}
0 commit comments