Skip to content
File

Blob: tests/worker/routes/share-resolve.workers.test.ts

typescript93 lines
1import { beforeEach, describe, expect, it } from "vitest";
2 
3import { resetD1Tables } from "@tests/worker/helpers/db";
4import { apiRequest } from "@tests/worker/helpers/request";
5import { seedMembership, seedPage, seedPageShare, seedUser, seedWorkspace } from "@tests/worker/helpers/seeds";
6 
7type ShareResolveResponse = {
8 page_id: string;
9 workspace_id: string;
10 permission: "view" | "edit";
11 token: string;
12 viewer: {
13 access_mode: "member" | "shared";
14 principal_type: "user" | "link";
15 route_kind: "canonical" | "shared";
16 workspace_slug: string | null;
17 workspace_role: "owner" | "admin" | "member" | "guest" | null;
18 };
19};
20 
21describe("GET /share/:token", () => {
22 beforeEach(async () => {
23 await resetD1Tables();
24 });
25 
26 it("returns link-scoped viewer metadata for an anonymous visitor", async () => {
27 const owner = await seedUser();
28 const workspace = await seedWorkspace({ owner_id: owner.id, slug: "demo" });
29 const page = await seedPage({ workspace_id: workspace.id, created_by: owner.id, title: "Alpha" });
30 await seedPageShare({
31 page_id: page.id,
32 created_by: owner.id,
33 grantee_type: "link",
34 grantee_id: null,
35 link_token: "tok-anonymous",
36 permission: "view",
37 });
38 
39 const res = await apiRequest("/api/v1/share/tok-anonymous");
40 expect(res.status).toBe(200);
41 
42 const body = (await res.json()) as ShareResolveResponse;
43 expect(body).toMatchObject({
44 page_id: page.id,
45 permission: "view",
46 token: "tok-anonymous",
47 viewer: {
48 access_mode: "shared",
49 principal_type: "link",
50 route_kind: "shared",
51 workspace_slug: null,
52 workspace_role: null,
53 },
54 });
55 });
56 
57 it("keeps viewer metadata link-scoped even when the caller is a member of the workspace", async () => {
58 const owner = await seedUser();
59 const memberCaller = await seedUser();
60 const workspace = await seedWorkspace({ owner_id: owner.id, slug: "demo" });
61 await seedMembership({ user_id: memberCaller.id, workspace_id: workspace.id, role: "member" });
62 const page = await seedPage({ workspace_id: workspace.id, created_by: owner.id, title: "Alpha" });
63 await seedPageShare({
64 page_id: page.id,
65 created_by: owner.id,
66 grantee_type: "link",
67 grantee_id: null,
68 link_token: "tok-member-visits-share",
69 permission: "view",
70 });
71 
72 const res = await apiRequest("/api/v1/share/tok-member-visits-share", {
73 userId: memberCaller.id,
74 });
75 expect(res.status).toBe(200);
76 
77 const body = (await res.json()) as ShareResolveResponse;
78 expect(body.viewer).toEqual({
79 access_mode: "shared",
80 principal_type: "link",
81 route_kind: "shared",
82 workspace_slug: null,
83 workspace_role: null,
84 });
85 expect(body.permission).toBe("view");
86 });
87 
88 it("returns 404 for unknown tokens", async () => {
89 const res = await apiRequest("/api/v1/share/does-not-exist");
90 expect(res.status).toBe(404);
91 });
92});