import { INestApplication } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; import request from 'supertest'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { PondPermissionCache } from '../permissions/pond-permission-cache'; import { createTestApp } from '../testing/test-app'; import { createTestPrisma, hasTestDb, uniqueSuffix } from '../testing/test-db'; /** * Public read access end to end (issue #56): an anonymous request reads a page * a `public` grant opens, via both the JSON and HTML endpoints; removing the * grant 404s both, and a non-public page never resolves. Requests carry no * session cookie. */ describe.skipIf(!hasTestDb)('public read access (e2e, issue #56)', () => { let app: INestApplication; let prisma: PrismaClient; const suffix = uniqueSuffix(); let ownerId: string; let pondSlug: string; let pondId: string; let pageSlug: string; let privatePondSlug: string; let privatePageSlug: string; let publicGrantId: string; const api = () => request(app.getHttpServer()); async function makePage(pondIdV: string, slug: string, title: string, html: string) { const page = await prisma.page.create({ data: { pondId: pondIdV, slug, title, createdBy: ownerId, sortKey: 'a0', ydocState: new Uint8Array(), contentCache: { create: { plainText: title, markdown: title, html, outline: [] } }, }, }); return page; } beforeAll(async () => { prisma = createTestPrisma(); app = await createTestApp(); const owner = await prisma.user.create({ data: { username: `pub-owner-${suffix}`, email: `pub-owner-${suffix}@example.test`, displayName: 'Pub Owner', }, }); ownerId = owner.id; pondSlug = `pub-pond-${suffix}`; const pond = await prisma.pond.create({ data: { slug: pondSlug, name: 'Public Pond', type: 'SHARED', ownerId }, }); pondId = pond.id; pageSlug = `welcome-${suffix}`; await makePage(pondId, pageSlug, 'Welcome', '
Hello world from a public page.
'); const grant = await prisma.roleGrant.create({ data: { pondId, subjectType: 'PUBLIC', subjectId: null, role: 'READER', scopeType: 'POND', scopeId: null, effect: 'ALLOW', createdBy: ownerId, }, }); publicGrantId = grant.id; privatePondSlug = `priv-pond-${suffix}`; const priv = await prisma.pond.create({ data: { slug: privatePondSlug, name: 'Private Pond', type: 'SHARED', ownerId }, }); privatePageSlug = `secret-${suffix}`; await makePage(priv.id, privatePageSlug, 'Secret', 'Nobody public should read this.
'); }); afterAll(async () => { await prisma.roleGrant.deleteMany({ where: { pond: { ownerId } } }); await prisma.pageContentCache.deleteMany({ where: { page: { pond: { ownerId } } } }); await prisma.page.deleteMany({ where: { pond: { ownerId } } }); await prisma.pond.deleteMany({ where: { ownerId } }); await prisma.user.deleteMany({ where: { id: ownerId } }); await prisma.$disconnect(); await app.close(); }); it('serves a public page as HTML and JSON to an anonymous visitor', async () => { const html = await api().get(`/api/v1/public/${pondSlug}/${pageSlug}`).expect(200); expect(html.headers['content-type']).toContain('text/html'); expect(html.text).toContain(''); expect(html.text).toContain('Welcome'); expect(html.text).toContain('Hello world from a public page.'); expect(html.text).toContain('rel="canonical"'); // No session-dependent content leaked into the crawler document. expect(html.text).not.toContain('dt_session'); const json = await api().get(`/api/v1/public/${pondSlug}/${pageSlug}/content`).expect(200); expect(json.body).toMatchObject({ title: 'Welcome', pondName: 'Public Pond' }); expect((json.body as { html: string }).html).toContain('Hello world'); }); it('never resolves a non-public page for an anonymous visitor', async () => { await api().get(`/api/v1/public/${privatePondSlug}/${privatePageSlug}`).expect(404); await api().get(`/api/v1/public/${privatePondSlug}/${privatePageSlug}/content`).expect(404); await api().get(`/api/v1/public/${pondSlug}/does-not-exist`).expect(404); }); it('serves a page’s comments read-only to an anonymous visitor (issue #133)', async () => { const page = await prisma.page.findFirstOrThrow({ where: { pondId, slug: pageSlug } }); const root = await prisma.comment.create({ data: { pageId: page.id, authorId: ownerId, body: 'A public remark' }, }); await prisma.comment.create({ data: { pageId: page.id, parentId: root.id, authorId: ownerId, body: 'A public reply' }, }); const res = await api().get(`/api/v1/public/${pondSlug}/${pageSlug}/comments`).expect(200); const body = res.body as { threads: { root: { body: string }; replies: { body: string }[] }[]; openCount: number; }; expect(body.openCount).toBe(1); expect(body.threads).toHaveLength(1); const [thread] = body.threads; expect(thread!.root.body).toBe('A public remark'); expect(thread!.replies.map((r) => r.body)).toEqual(['A public reply']); // A non-public page never reveals its comments either. await api().get(`/api/v1/public/${privatePondSlug}/${privatePageSlug}/comments`).expect(404); }); it('expands a page embed to the target’s content, cycle-safe (issue #135)', async () => { const embeddedSlug = `embedded-${suffix}`; const hostSlug = `host-${suffix}`; // The embedded page embeds the host back — the expansion must terminate. await makePage( pondId, embeddedSlug, 'Embedded', `Body of the embedded page.
` + `Before.
` + `Bare body text.
'); await makePage( pondId, hostSlug, 'Bare Host', `Before.
` + `