1
1
import 'dart:io' ;
2
2
3
3
import 'package:dart_frog/dart_frog.dart' ;
4
+ import 'package:ht_api/src/helpers/response_helper.dart' ;
4
5
import 'package:ht_api/src/rbac/permission_service.dart' ;
5
6
import 'package:ht_api/src/registry/model_registry.dart' ;
6
7
import 'package:ht_api/src/services/dashboard_summary_service.dart' ;
7
8
import 'package:ht_api/src/services/user_preference_limit_service.dart' ; // Import UserPreferenceLimitService
8
9
import 'package:ht_data_repository/ht_data_repository.dart' ;
9
10
import 'package:ht_shared/ht_shared.dart' ;
10
11
11
- import '../../../../_middleware.dart' ; // Assuming RequestId is here
12
-
13
12
/// Handles requests for the /api/v1/data/[id] endpoint.
14
13
/// Dispatches requests to specific handlers based on the HTTP method.
15
14
Future <Response > onRequest (RequestContext context, String id) async {
16
15
// Read dependencies provided by middleware
17
16
final modelName = context.read <String >();
18
17
final modelConfig = context.read <ModelConfig <dynamic >>();
19
- final requestId = context.read <RequestId >().id;
20
18
// User is guaranteed non-null by requireAuthentication() middleware
21
19
final authenticatedUser = context.read <User >();
22
20
final permissionService = context
@@ -35,7 +33,6 @@ Future<Response> onRequest(RequestContext context, String id) async {
35
33
modelConfig,
36
34
authenticatedUser,
37
35
permissionService, // Pass PermissionService
38
- requestId,
39
36
);
40
37
case HttpMethod .put:
41
38
return _handlePut (
@@ -46,7 +43,6 @@ Future<Response> onRequest(RequestContext context, String id) async {
46
43
authenticatedUser,
47
44
permissionService, // Pass PermissionService
48
45
userPreferenceLimitService, // Pass the limit service
49
- requestId,
50
46
);
51
47
case HttpMethod .delete:
52
48
return _handleDelete (
@@ -56,7 +52,6 @@ Future<Response> onRequest(RequestContext context, String id) async {
56
52
modelConfig,
57
53
authenticatedUser,
58
54
permissionService, // Pass PermissionService
59
- requestId,
60
55
);
61
56
default :
62
57
// Methods not allowed on the item endpoint
@@ -74,7 +69,6 @@ Future<Response> _handleGet(
74
69
ModelConfig <dynamic > modelConfig,
75
70
User authenticatedUser,
76
71
PermissionService permissionService,
77
- String requestId,
78
72
) async {
79
73
// Authorization check is handled by authorizationMiddleware before this.
80
74
// This handler only needs to perform the ownership check if required.
@@ -143,7 +137,7 @@ Future<Response> _handleGet(
143
137
// Ensure getOwnerId is provided for models requiring ownership check
144
138
if (modelConfig.getOwnerId == null ) {
145
139
print (
146
- '[ReqID: $ requestId ] Configuration Error: Model "$modelName " requires '
140
+ 'Configuration Error: Model "$modelName " requires '
147
141
'ownership check for GET item but getOwnerId is not provided.' ,
148
142
);
149
143
// Throw an exception to be caught by the errorHandler
@@ -162,25 +156,11 @@ Future<Response> _handleGet(
162
156
}
163
157
}
164
158
165
- // Create metadata including the request ID and current timestamp
166
- final metadata = ResponseMetadata (
167
- requestId: requestId,
168
- timestamp: DateTime .now ().toUtc (), // Use UTC for consistency
169
- );
170
-
171
- // Wrap the item in SuccessApiResponse with metadata
172
- final successResponse = SuccessApiResponse <dynamic >(
159
+ return ResponseHelper .success (
160
+ context: context,
173
161
data: item,
174
- metadata : metadata, // Include the created metadata
162
+ toJsonT : (data) => (data as dynamic ). toJson () as Map < String , dynamic >,
175
163
);
176
-
177
- // Provide the correct toJsonT for the specific model type
178
- final responseJson = successResponse.toJson (
179
- (item) => (item as dynamic ).toJson (), // Assuming all models have toJson
180
- );
181
-
182
- // Return 200 OK with the wrapped and serialized response
183
- return Response .json (body: responseJson);
184
164
}
185
165
186
166
// --- PUT Handler ---
@@ -195,7 +175,6 @@ Future<Response> _handlePut(
195
175
PermissionService permissionService, // Receive PermissionService
196
176
UserPreferenceLimitService
197
177
userPreferenceLimitService, // Receive Limit Service
198
- String requestId,
199
178
) async {
200
179
// Authorization check is handled by authorizationMiddleware before this.
201
180
// This handler only needs to perform the ownership check if required.
@@ -212,9 +191,8 @@ Future<Response> _handlePut(
212
191
itemToUpdate = modelConfig.fromJson (requestBody);
213
192
} on TypeError catch (e) {
214
193
// Catch errors during deserialization (e.g., missing required fields)
215
- // Include requestId in the server log
216
194
print (
217
- '[ReqID: $ requestId ] Deserialization TypeError in PUT /data/[id]: $e ' ,
195
+ 'Deserialization TypeError in PUT /data/[id]: $e ' ,
218
196
);
219
197
// Throw BadRequestException to be caught by the errorHandler
220
198
throw const BadRequestException (
@@ -235,8 +213,7 @@ Future<Response> _handlePut(
235
213
} catch (e) {
236
214
// Ignore if getId throws, means ID might not be in the body,
237
215
// which is acceptable depending on the model/client.
238
- // Log for debugging if needed.
239
- print ('[ReqID: $requestId ] Warning: Could not get ID from PUT body: $e ' );
216
+ print ('Warning: Could not get ID from PUT body: $e ' );
240
217
}
241
218
242
219
// --- Handler-Level Limit Check (for UserContentPreferences PUT) ---
@@ -247,7 +224,7 @@ Future<Response> _handlePut(
247
224
// Ensure the itemToUpdate is the correct type for the limit service
248
225
if (itemToUpdate is ! UserContentPreferences ) {
249
226
print (
250
- '[ReqID: $ requestId ] Type Error: Expected UserContentPreferences '
227
+ 'Type Error: Expected UserContentPreferences '
251
228
'for limit check, but got ${itemToUpdate .runtimeType }.' ,
252
229
);
253
230
throw const OperationFailedException (
@@ -264,7 +241,7 @@ Future<Response> _handlePut(
264
241
} catch (e) {
265
242
// Catch unexpected errors from the limit service
266
243
print (
267
- '[ReqID: $ requestId ] Unexpected error during limit check for '
244
+ 'Unexpected error during limit check for '
268
245
'UserContentPreferences PUT: $e ' ,
269
246
);
270
247
throw const OperationFailedException (
@@ -381,7 +358,7 @@ Future<Response> _handlePut(
381
358
// Ensure getOwnerId is provided for models requiring ownership check
382
359
if (modelConfig.getOwnerId == null ) {
383
360
print (
384
- '[ReqID: $ requestId ] Configuration Error: Model "$modelName " requires '
361
+ 'Configuration Error: Model "$modelName " requires '
385
362
'ownership check for PUT but getOwnerId is not provided.' ,
386
363
);
387
364
// Throw an exception to be caught by the errorHandler
@@ -396,9 +373,8 @@ Future<Response> _handlePut(
396
373
if (itemOwnerId != authenticatedUser.id) {
397
374
// This scenario should ideally not happen if the repository correctly
398
375
// enforced ownership during the update call when userId was passed.
399
- // But as a defense-in-depth, we check here.
400
376
print (
401
- '[ReqID: $ requestId ] Ownership check failed AFTER PUT for item $id . '
377
+ 'Ownership check failed AFTER PUT for item $id . '
402
378
'Item owner: $itemOwnerId , User: ${authenticatedUser .id }' ,
403
379
);
404
380
// Throw ForbiddenException to be caught by the errorHandler
@@ -408,25 +384,11 @@ Future<Response> _handlePut(
408
384
}
409
385
}
410
386
411
- // Create metadata including the request ID and current timestamp
412
- final metadata = ResponseMetadata (
413
- requestId: requestId,
414
- timestamp: DateTime .now ().toUtc (), // Use UTC for consistency
415
- );
416
-
417
- // Wrap the updated item in SuccessApiResponse with metadata
418
- final successResponse = SuccessApiResponse <dynamic >(
387
+ return ResponseHelper .success (
388
+ context: context,
419
389
data: updatedItem,
420
- metadata : metadata ,
390
+ toJsonT : (data) => (data as dynamic ). toJson () as Map < String , dynamic > ,
421
391
);
422
-
423
- // Provide the correct toJsonT for the specific model type
424
- final responseJson = successResponse.toJson (
425
- (item) => (item as dynamic ).toJson (), // Assuming all models have toJson
426
- );
427
-
428
- // Return 200 OK with the wrapped and serialized response
429
- return Response .json (body: responseJson);
430
392
}
431
393
432
394
// --- DELETE Handler ---
@@ -438,7 +400,6 @@ Future<Response> _handleDelete(
438
400
ModelConfig <dynamic > modelConfig,
439
401
User authenticatedUser,
440
402
PermissionService permissionService,
441
- String requestId,
442
403
) async {
443
404
// Authorization check is handled by authorizationMiddleware before this.
444
405
// This handler only needs to perform the ownership check if required.
@@ -463,7 +424,7 @@ Future<Response> _handleDelete(
463
424
// Ensure getOwnerId is provided for models requiring ownership check
464
425
if (modelConfig.getOwnerId == null ) {
465
426
print (
466
- '[ReqID: $ requestId ] Configuration Error: Model "$modelName " requires '
427
+ 'Configuration Error: Model "$modelName " requires '
467
428
'ownership check for DELETE but getOwnerId is not provided.' ,
468
429
);
469
430
// Throw an exception to be caught by the errorHandler
@@ -503,7 +464,7 @@ Future<Response> _handleDelete(
503
464
); // userId should be null for AppConfig
504
465
default :
505
466
print (
506
- '[ReqID: $ requestId ] Error: Unsupported model type "$modelName " reached _handleDelete ownership check.' ,
467
+ 'Error: Unsupported model type "$modelName " reached _handleDelete ownership check.' ,
507
468
);
508
469
// Throw an exception to be caught by the errorHandler
509
470
throw OperationFailedException (
@@ -571,9 +532,9 @@ Future<Response> _handleDelete(
571
532
); // userId should be null for AppConfig
572
533
default :
573
534
// This case should ideally be caught by the data/_middleware.dart,
574
- // but added for safety. Consider logging this unexpected state.
535
+ // but added for safety.
575
536
print (
576
- '[ReqID: $ requestId ] Error: Unsupported model type "$modelName " reached _handleDelete.' ,
537
+ 'Error: Unsupported model type "$modelName " reached _handleDelete.' ,
577
538
);
578
539
// Throw an exception to be caught by the errorHandler
579
540
throw OperationFailedException (
0 commit comments