Bug: non-admin users cannot share a meal plan (user list is admin-only) #46

Closed
opened 2026-09-27 18:20:49 +00:00 by araemer · 2 comments
Owner

Problem

Non-admin users cannot share a meal plan. The user dropdown in the share dialog stays empty.

Cause

MealPlanShareDialog loads its user list via fetchAllUsers() (src/api/endpoints/UserRestResource.ts), which calls GET /user/all. The backend restricts that endpoint to administrators (requireAdmin in UserResource). For every other role the call returns 403; the dialog only logs the error to the console (Fehler beim Laden der Benutzer) and shows no options.

Fix direction

Spec 001 (shopping lists) introduces a user directory endpoint that any authenticated user may call (POST /user/list-shareable, returning a reduced user summary without email or role). Once that endpoint exists, switch the meal plan share dialog to it. GET /user/all stays admin-only.

Found during the cross-cutting architecture discussion of spec 001.

## Problem Non-admin users cannot share a meal plan. The user dropdown in the share dialog stays empty. ## Cause `MealPlanShareDialog` loads its user list via `fetchAllUsers()` (`src/api/endpoints/UserRestResource.ts`), which calls `GET /user/all`. The backend restricts that endpoint to administrators (`requireAdmin` in `UserResource`). For every other role the call returns 403; the dialog only logs the error to the console (`Fehler beim Laden der Benutzer`) and shows no options. ## Fix direction Spec 001 (shopping lists) introduces a user directory endpoint that any authenticated user may call (`POST /user/list-shareable`, returning a reduced user summary without email or role). Once that endpoint exists, switch the meal plan share dialog to it. `GET /user/all` stays admin-only. Found during the cross-cutting architecture discussion of spec 001.
Author
Owner

Addendum: replace the full UserDto in meal plan shares

MealPlanShareDto.sharedWithUser currently carries the full UserDto, including email and role. Every user a plan is shared with can therefore see the email address of every other recipient.

Spec 001 introduces CompactUserDto (id, user name, first and last name, avatar; no email, no role) and makes it the convention for any DTO that exposes another user (see docs/api-conventions.md, "Other users are exposed as CompactUserDto").

As part of this fix, switch MealPlanShareDto.sharedWithUser from UserDto to CompactUserDto. This is a contract change (api-contract/src/meal-plans.ts) that affects recipe-backend and recipe-app.

## Addendum: replace the full `UserDto` in meal plan shares `MealPlanShareDto.sharedWithUser` currently carries the full `UserDto`, including **email and role**. Every user a plan is shared with can therefore see the email address of every other recipient. Spec 001 introduces `CompactUserDto` (id, user name, first and last name, avatar; no email, no role) and makes it the convention for any DTO that exposes another user (see `docs/api-conventions.md`, "Other users are exposed as CompactUserDto"). As part of this fix, switch `MealPlanShareDto.sharedWithUser` from `UserDto` to `CompactUserDto`. This is a contract change (`api-contract/src/meal-plans.ts`) that affects recipe-backend and recipe-app.
Author
Owner

Update: list-shareable is a GET

During the review of PR #20 the new route became GET /user/list-shareable (reads without a body use GET, docs/adr/2026-09-30-get-reads-and-shallow-nesting.md), not POST as written above. The meal plan share routes themselves (DELETE /meal-plan/:id/share/:shareId, POST /meal-plan/:id/share/save-or-update) also break the new shallow-nesting rule; they are listed in recipe-platform#23 and can move together with this fix.

## Update: `list-shareable` is a GET During the review of PR #20 the new route became `GET /user/list-shareable` (reads without a body use GET, `docs/adr/2026-09-30-get-reads-and-shallow-nesting.md`), not `POST` as written above. The meal plan share routes themselves (`DELETE /meal-plan/:id/share/:shareId`, `POST /meal-plan/:id/share/save-or-update`) also break the new shallow-nesting rule; they are listed in recipe-platform#23 and can move together with this fix.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
araemer/recipe-app#46
No description provided.