@@ -75,92 +75,63 @@ Future<Response> _handleGet(
7575 User authenticatedUser,
7676 PermissionService permissionService,
7777) async {
78- // Authorization check is handled by authorizationMiddleware before this.
79- // This handler only needs to perform the ownership check if required .
78+ // Authorization and ownership checks are handled by middleware before this.
79+ // This handler's job is to fetch and return the data .
8080
8181 dynamic item;
8282
83- // Determine userId for repository call based on ModelConfig (for data scoping)
84- String ? userIdForRepoCall;
85- // If the model is user-owned, pass the authenticated user's ID to the repository
86- // for filtering. Otherwise, pass null.
87- // Note: This is for data *scoping* by the repository, not the permission check.
88- // We infer user-owned based on the presence of getOwnerId function.
89- if (modelConfig.getOwnerId != null &&
90- ! permissionService.isAdmin (authenticatedUser)) {
91- userIdForRepoCall = authenticatedUser.id;
92- } else {
93- userIdForRepoCall = null ;
94- }
95-
96- // Repository exceptions (like NotFoundException) will propagate up to the
97- // main onRequest try/catch (which is now removed, so they go to errorHandler).
98- switch (modelName) {
99- case 'headline' :
100- final repo = context.read <DataRepository <Headline >>();
101- item = await repo.read (id: id, userId: userIdForRepoCall);
102- case 'topic' :
103- final repo = context.read <DataRepository <Topic >>();
104- item = await repo.read (id: id, userId: userIdForRepoCall);
105- case 'source' :
106- final repo = context.read <DataRepository <Source >>();
107- item = await repo.read (id: id, userId: userIdForRepoCall);
108- case 'country' :
109- final repo = context.read <DataRepository <Country >>();
110- item = await repo.read (id: id, userId: userIdForRepoCall);
111- case 'language' :
112- final repo = context.read <DataRepository <Language >>();
113- item = await repo.read (id: id, userId: userIdForRepoCall);
114- case 'user' : // Handle User model specifically if needed, or rely on generic
115- final repo = context.read <DataRepository <User >>();
116- item = await repo.read (id: id, userId: userIdForRepoCall);
117- case 'user_app_settings' : // New case for UserAppSettings
118- final repo = context.read <DataRepository <UserAppSettings >>();
119- item = await repo.read (id: id, userId: userIdForRepoCall);
120- case 'user_content_preferences' : // New case for UserContentPreferences
121- final repo = context.read <DataRepository <UserContentPreferences >>();
122- item = await repo.read (id: id, userId: userIdForRepoCall);
123- case 'remote_config' : // New case for RemoteConfig (read by admin)
124- final repo = context.read <DataRepository <RemoteConfig >>();
125- item = await repo.read (
126- id: id,
127- userId: userIdForRepoCall,
128- ); // userId should be null for AppConfig
129- case 'dashboard_summary' :
130- final service = context.read <DashboardSummaryService >();
131- item = await service.getSummary ();
132- default :
133- // This case should ideally be caught by middleware, but added for safety
134- // Throw an exception to be caught by the errorHandler
135- throw OperationFailedException (
136- 'Unsupported model type "$modelName " reached handler.' ,
137- );
138- }
83+ // Check if the ownership middleware already fetched the item for a check.
84+ // This avoids a redundant database call.
85+ final fetchedItem = context.read <FetchedItem <dynamic >?>();
13986
140- // --- Handler-Level Ownership Check (for GET item) ---
141- // This check is needed if the ModelConfig for GET item requires ownership
142- // AND the user is NOT an admin (admins can bypass ownership checks).
143- if (modelConfig.getItemPermission.requiresOwnershipCheck &&
144- ! permissionService.isAdmin (authenticatedUser)) {
145- // Ensure getOwnerId is provided for models requiring ownership check
146- if (modelConfig.getOwnerId == null ) {
147- _logger.severe (
148- 'Configuration Error: Model "$modelName " requires '
149- 'ownership check for GET item but getOwnerId is not provided.' ,
150- );
151- // Throw an exception to be caught by the errorHandler
152- throw const OperationFailedException (
153- 'Internal Server Error: Model configuration error.' ,
154- );
155- }
156-
157- final itemOwnerId = modelConfig.getOwnerId !(item);
158- if (itemOwnerId != authenticatedUser.id) {
159- // If the authenticated user is not the owner, deny access.
160- // Throw ForbiddenException to be caught by the errorHandler
161- throw const ForbiddenException (
162- 'You do not have permission to access this specific item.' ,
163- );
87+ if (fetchedItem != null ) {
88+ // If the item was pre-fetched by the middleware, use it directly.
89+ item = fetchedItem.data;
90+ } else {
91+ // If no ownership check was required (e.g., for an admin or public
92+ // resource), the item was not pre-fetched, so we fetch it now.
93+ final userIdForRepoCall =
94+ (modelConfig.getOwnerId != null &&
95+ ! permissionService.isAdmin (authenticatedUser))
96+ ? authenticatedUser.id
97+ : null ;
98+
99+ // Repository exceptions (like NotFoundException) will propagate up.
100+ switch (modelName) {
101+ case 'headline' :
102+ final repo = context.read <DataRepository <Headline >>();
103+ item = await repo.read (id: id, userId: userIdForRepoCall);
104+ case 'topic' :
105+ final repo = context.read <DataRepository <Topic >>();
106+ item = await repo.read (id: id, userId: userIdForRepoCall);
107+ case 'source' :
108+ final repo = context.read <DataRepository <Source >>();
109+ item = await repo.read (id: id, userId: userIdForRepoCall);
110+ case 'country' :
111+ final repo = context.read <DataRepository <Country >>();
112+ item = await repo.read (id: id, userId: userIdForRepoCall);
113+ case 'language' :
114+ final repo = context.read <DataRepository <Language >>();
115+ item = await repo.read (id: id, userId: userIdForRepoCall);
116+ case 'user' :
117+ final repo = context.read <DataRepository <User >>();
118+ item = await repo.read (id: id, userId: userIdForRepoCall);
119+ case 'user_app_settings' :
120+ final repo = context.read <DataRepository <UserAppSettings >>();
121+ item = await repo.read (id: id, userId: userIdForRepoCall);
122+ case 'user_content_preferences' :
123+ final repo = context.read <DataRepository <UserContentPreferences >>();
124+ item = await repo.read (id: id, userId: userIdForRepoCall);
125+ case 'remote_config' :
126+ final repo = context.read <DataRepository <RemoteConfig >>();
127+ item = await repo.read (id: id, userId: userIdForRepoCall);
128+ case 'dashboard_summary' :
129+ final service = context.read <DashboardSummaryService >();
130+ item = await service.getSummary ();
131+ default :
132+ throw OperationFailedException (
133+ 'Unsupported model type "$modelName " reached handler.' ,
134+ );
164135 }
165136 }
166137
0 commit comments