@@ -17,7 +17,8 @@ Future<Response> onRequest(RequestContext context, String id) async {
17
17
final requestId = context.read <RequestId >().id;
18
18
// User is guaranteed non-null by requireAuthentication() middleware
19
19
final authenticatedUser = context.read <User >();
20
- final permissionService = context.read <PermissionService >(); // Read PermissionService
20
+ final permissionService =
21
+ context.read <PermissionService >(); // Read PermissionService
21
22
22
23
// The main try/catch block here is removed to let the errorHandler middleware
23
24
// handle all exceptions thrown by the handlers below.
@@ -82,12 +83,11 @@ Future<Response> _handleGet(
82
83
// Note: This is for data *scoping* by the repository, not the permission check.
83
84
// We infer user-owned based on the presence of getOwnerId function.
84
85
if (modelConfig.getOwnerId != null ) {
85
- userIdForRepoCall = authenticatedUser.id;
86
+ userIdForRepoCall = authenticatedUser.id;
86
87
} else {
87
- userIdForRepoCall = null ;
88
+ userIdForRepoCall = null ;
88
89
}
89
90
90
-
91
91
// Repository exceptions (like NotFoundException) will propagate up to the
92
92
// main onRequest try/catch (which is now removed, so they go to errorHandler).
93
93
switch (modelName) {
@@ -104,8 +104,8 @@ Future<Response> _handleGet(
104
104
final repo = context.read <HtDataRepository <Country >>();
105
105
item = await repo.read (id: id, userId: userIdForRepoCall);
106
106
case 'user' : // Handle User model specifically if needed, or rely on generic
107
- final repo = context.read <HtDataRepository <User >>();
108
- item = await repo.read (id: id, userId: userIdForRepoCall);
107
+ final repo = context.read <HtDataRepository <User >>();
108
+ item = await repo.read (id: id, userId: userIdForRepoCall);
109
109
// Add cases for other models as they are added to ModelRegistry
110
110
default :
111
111
// This case should ideally be caught by middleware, but added for safety
@@ -122,7 +122,7 @@ Future<Response> _handleGet(
122
122
! permissionService.isAdmin (authenticatedUser)) {
123
123
// Ensure getOwnerId is provided for models requiring ownership check
124
124
if (modelConfig.getOwnerId == null ) {
125
- print (
125
+ print (
126
126
'[ReqID: $requestId ] Configuration Error: Model "$modelName " requires '
127
127
'ownership check for GET but getOwnerId is not provided.' ,
128
128
);
@@ -142,7 +142,6 @@ Future<Response> _handleGet(
142
142
}
143
143
}
144
144
145
-
146
145
// Create metadata including the request ID and current timestamp
147
146
final metadata = ResponseMetadata (
148
147
requestId: requestId,
@@ -204,32 +203,30 @@ Future<Response> _handlePut(
204
203
// Ensure the ID in the path matches the ID in the request body (if present)
205
204
// This is a data integrity check, not an authorization check.
206
205
try {
207
- final bodyItemId = modelConfig.getId (itemToUpdate);
208
- if (bodyItemId != id) {
209
- // Throw BadRequestException to be caught by the errorHandler
210
- throw BadRequestException (
211
- 'Bad Request: ID in request body ("$bodyItemId ") does not match ID in path ("$id ").' ,
212
- );
213
- }
206
+ final bodyItemId = modelConfig.getId (itemToUpdate);
207
+ if (bodyItemId != id) {
208
+ // Throw BadRequestException to be caught by the errorHandler
209
+ throw BadRequestException (
210
+ 'Bad Request: ID in request body ("$bodyItemId ") does not match ID in path ("$id ").' ,
211
+ );
212
+ }
214
213
} catch (e) {
215
- // Ignore if getId throws, means ID might not be in the body,
216
- // which is acceptable depending on the model/client.
217
- // Log for debugging if needed.
218
- print ('[ReqID: $requestId ] Warning: Could not get ID from PUT body: $e ' );
214
+ // Ignore if getId throws, means ID might not be in the body,
215
+ // which is acceptable depending on the model/client.
216
+ // Log for debugging if needed.
217
+ print ('[ReqID: $requestId ] Warning: Could not get ID from PUT body: $e ' );
219
218
}
220
219
221
-
222
220
// Determine userId for repository call based on ModelConfig (for data scoping/ownership enforcement)
223
221
String ? userIdForRepoCall;
224
222
// If the model is user-owned, pass the authenticated user's ID to the repository
225
223
// for ownership enforcement. Otherwise, pass null.
226
- if (modelConfig.getOwnerId != null ) {
227
- userIdForRepoCall = authenticatedUser.id;
224
+ if (modelConfig.getOwnerId != null ) {
225
+ userIdForRepoCall = authenticatedUser.id;
228
226
} else {
229
- userIdForRepoCall = null ;
227
+ userIdForRepoCall = null ;
230
228
}
231
229
232
-
233
230
dynamic updatedItem;
234
231
235
232
// Repository exceptions (like NotFoundException, BadRequestException)
@@ -247,7 +244,7 @@ Future<Response> _handlePut(
247
244
case 'category' :
248
245
{
249
246
final repo = context.read <HtDataRepository <Category >>();
250
- updatedItem = await repo.update (
247
+ updatedItem = await repo.update (
251
248
id: id,
252
249
item: itemToUpdate as Category ,
253
250
userId: userIdForRepoCall,
@@ -256,7 +253,7 @@ Future<Response> _handlePut(
256
253
case 'source' :
257
254
{
258
255
final repo = context.read <HtDataRepository <Source >>();
259
- updatedItem = await repo.update (
256
+ updatedItem = await repo.update (
260
257
id: id,
261
258
item: itemToUpdate as Source ,
262
259
userId: userIdForRepoCall,
@@ -265,16 +262,16 @@ Future<Response> _handlePut(
265
262
case 'country' :
266
263
{
267
264
final repo = context.read <HtDataRepository <Country >>();
268
- updatedItem = await repo.update (
265
+ updatedItem = await repo.update (
269
266
id: id,
270
267
item: itemToUpdate as Country ,
271
268
userId: userIdForRepoCall,
272
269
);
273
270
}
274
- case 'user' :
271
+ case 'user' :
275
272
{
276
273
final repo = context.read <HtDataRepository <User >>();
277
- updatedItem = await repo.update (
274
+ updatedItem = await repo.update (
278
275
id: id,
279
276
item: itemToUpdate as User ,
280
277
userId: userIdForRepoCall,
@@ -289,7 +286,7 @@ Future<Response> _handlePut(
289
286
);
290
287
}
291
288
292
- // --- Handler-Level Ownership Check (for PUT) ---
289
+ // --- Handler-Level Ownership Check (for PUT) ---
293
290
// This check is needed if the ModelConfig for PUT requires ownership
294
291
// AND the user is NOT an admin (admins can bypass ownership checks).
295
292
// Note: The repository *might* have already enforced ownership if userId was passed.
@@ -298,9 +295,9 @@ Future<Response> _handlePut(
298
295
// (e.g., if the repo update method allows admins to update any item even if userId is passed).
299
296
if (modelConfig.putPermission.requiresOwnershipCheck &&
300
297
! permissionService.isAdmin (authenticatedUser)) {
301
- // Ensure getOwnerId is provided for models requiring ownership check
298
+ // Ensure getOwnerId is provided for models requiring ownership check
302
299
if (modelConfig.getOwnerId == null ) {
303
- print (
300
+ print (
304
301
'[ReqID: $requestId ] Configuration Error: Model "$modelName " requires '
305
302
'ownership check for PUT but getOwnerId is not provided.' ,
306
303
);
@@ -313,7 +310,7 @@ Future<Response> _handlePut(
313
310
// after the update, or ideally, the update method returns the item with owner ID.
314
311
// Assuming the updatedItem returned by the repo has the owner ID:
315
312
final itemOwnerId = modelConfig.getOwnerId !(updatedItem);
316
- if (itemOwnerId != authenticatedUser.id) {
313
+ if (itemOwnerId != authenticatedUser.id) {
317
314
// This scenario should ideally not happen if the repository correctly
318
315
// enforced ownership during the update call when userId was passed.
319
316
// But as a defense-in-depth, we check here.
@@ -328,7 +325,6 @@ Future<Response> _handlePut(
328
325
}
329
326
}
330
327
331
-
332
328
// Create metadata including the request ID and current timestamp
333
329
final metadata = ResponseMetadata (
334
330
requestId: requestId,
@@ -368,21 +364,21 @@ Future<Response> _handleDelete(
368
364
String ? userIdForRepoCall;
369
365
// If the model is user-owned, pass the authenticated user's ID to the repository
370
366
// for ownership enforcement. Otherwise, pass null.
371
- if (modelConfig.getOwnerId != null ) {
372
- userIdForRepoCall = authenticatedUser.id;
367
+ if (modelConfig.getOwnerId != null ) {
368
+ userIdForRepoCall = authenticatedUser.id;
373
369
} else {
374
- userIdForRepoCall = null ;
370
+ userIdForRepoCall = null ;
375
371
}
376
372
377
373
// --- Handler-Level Ownership Check (for DELETE) ---
378
374
// For DELETE, we need to fetch the item *before* attempting deletion
379
375
// to perform the ownership check if required.
380
376
dynamic itemToDelete;
381
- if (modelConfig.deletePermission.requiresOwnershipCheck &&
377
+ if (modelConfig.deletePermission.requiresOwnershipCheck &&
382
378
! permissionService.isAdmin (authenticatedUser)) {
383
- // Ensure getOwnerId is provided for models requiring ownership check
379
+ // Ensure getOwnerId is provided for models requiring ownership check
384
380
if (modelConfig.getOwnerId == null ) {
385
- print (
381
+ print (
386
382
'[ReqID: $requestId ] Configuration Error: Model "$modelName " requires '
387
383
'ownership check for DELETE but getOwnerId is not provided.' ,
388
384
);
@@ -406,12 +402,12 @@ Future<Response> _handleDelete(
406
402
case 'country' :
407
403
final repo = context.read <HtDataRepository <Country >>();
408
404
itemToDelete = await repo.read (id: id, userId: userIdForRepoCall);
409
- case 'user' :
405
+ case 'user' :
410
406
final repo = context.read <HtDataRepository <User >>();
411
407
itemToDelete = await repo.read (id: id, userId: userIdForRepoCall);
412
408
// Add cases for other models
413
409
default :
414
- print (
410
+ print (
415
411
'[ReqID: $requestId ] Error: Unsupported model type "$modelName " reached _handleDelete ownership check.' ,
416
412
);
417
413
// Throw an exception to be caught by the errorHandler
@@ -431,11 +427,10 @@ Future<Response> _handleDelete(
431
427
);
432
428
}
433
429
}
434
- // If itemToDelete is null here, it means the item wasn't found during the read.
435
- // The subsequent delete call will likely throw NotFoundException, which is correct.
430
+ // If itemToDelete is null here, it means the item wasn't found during the read.
431
+ // The subsequent delete call will likely throw NotFoundException, which is correct.
436
432
}
437
433
438
-
439
434
// Allow repository exceptions (e.g., NotFoundException) to propagate
440
435
// upwards to be handled by the standard error handling mechanism.
441
436
switch (modelName) {
@@ -455,7 +450,7 @@ Future<Response> _handleDelete(
455
450
await context
456
451
.read <HtDataRepository <Country >>()
457
452
.delete (id: id, userId: userIdForRepoCall);
458
- case 'user' :
453
+ case 'user' :
459
454
await context
460
455
.read <HtDataRepository <User >>()
461
456
.delete (id: id, userId: userIdForRepoCall);
@@ -472,7 +467,6 @@ Future<Response> _handleDelete(
472
467
);
473
468
}
474
469
475
-
476
470
// Return 204 No Content for successful deletion (no body, no metadata)
477
471
return Response (statusCode: HttpStatus .noContent);
478
472
}
0 commit comments