feat: public shopping list links can allow editing
Owner opts in per-list via a new "Allow editing" toggle next to the existing public-link switch. Anonymous writes are scoped to that one list only — the link id is the sole credential, enforced in getShoppingListAccess and the item routes (no session required there now), with an IP rate limit on genuinely anonymous requests. Turning off the public link also revokes editing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,23 @@ describe("getShoppingListAccess", () => {
|
||||
mockMemberFindFirst.mockResolvedValue(undefined);
|
||||
expect(await getShoppingListAccess("list-1", "user-2")).toBeNull();
|
||||
});
|
||||
|
||||
it("grants anonymous editor access via a public-editable link", async () => {
|
||||
mockListFindFirst.mockResolvedValue({ id: "list-1", userId: "user-owner", isPublic: true, publicEditable: true });
|
||||
const access = await getShoppingListAccess("list-1", null);
|
||||
expect(access?.role).toBe("editor");
|
||||
});
|
||||
|
||||
it("grants anonymous viewer access via a public read-only link", async () => {
|
||||
mockListFindFirst.mockResolvedValue({ id: "list-1", userId: "user-owner", isPublic: true, publicEditable: false });
|
||||
const access = await getShoppingListAccess("list-1", null);
|
||||
expect(access?.role).toBe("viewer");
|
||||
});
|
||||
|
||||
it("denies anonymous access when the list isn't public", async () => {
|
||||
mockListFindFirst.mockResolvedValue({ id: "list-1", userId: "user-owner", isPublic: false, publicEditable: false });
|
||||
expect(await getShoppingListAccess("list-1", null)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("canWriteShoppingList", () => {
|
||||
|
||||
Reference in New Issue
Block a user