mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 23:46:35 +00:00
fix(trips): confine assignee writes to the people on the trip
Holding packing_edit or todo_edit says you may edit this trip's lists, not that any user id you name belongs to it. Both updateCategoryAssignees loops wrote the body's ids straight through, and both end by re-selecting through a JOIN on users — so an id from anywhere on the instance came back with a display name and an avatar attached, in the response and in the WebSocket fan-out to the room. The packing item recipient writes had the same gap. packing already had tripRosterIds for exactly this and used it only for bag members; its doc comment said "assigned to a bag", which is probably why the other three writes grew up without it. The query moves to DatabaseService next to canAccessTrip, which asks the same question as a predicate, and the helper now delegates. Every service that needs it already injects DatabaseService. Off-roster ids drop rather than 400: a copied trip carries assignee ids over before its members exist, and rejecting the whole request would stall the picker there. Guests are unaffected — a guest is a trip_members row, so the roster includes them, which is the point of #1362.
This commit is contained in:
@@ -56,6 +56,25 @@ export class DatabaseService {
|
||||
return isOwner(tripId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user ids a trip may refer to: its members plus the owner. Guests count —
|
||||
* a guest is a credential-less users row joined into trip_members, and #1362
|
||||
* makes it assignable everywhere a real member is.
|
||||
*
|
||||
* This is canAccessTrip's question asked as a set rather than a predicate, so
|
||||
* it lives beside it. Domains that accept user ids in a write body intersect
|
||||
* against it: holding the permission says you may edit the trip, not that any
|
||||
* id you name belongs to it. Runs on the connection rather than delegating to
|
||||
* db/database, because it has no legacy export to stay parity with.
|
||||
*/
|
||||
rosterUserIds(tripId: number | string): Set<number> {
|
||||
const rows = this.all<{ user_id: number }>(
|
||||
'SELECT user_id FROM trip_members WHERE trip_id = ? UNION SELECT user_id FROM trips WHERE id = ?',
|
||||
tripId, tripId,
|
||||
);
|
||||
return new Set(rows.map(r => r.user_id));
|
||||
}
|
||||
|
||||
getPlaceWithTags(placeId: number | string): PlaceWithTags | null {
|
||||
return getPlaceWithTags(placeId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user