Some checks failed
CD / Build and push images (push) Successful in 3m50s
CD / Deploy to Test (push) Successful in 10s
CI / Lint, typecheck, test (push) Successful in 4m13s
CI / Build container images (push) Has been skipped
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 11s
CI / Auth e2e pack (push) Failing after 2m44s
CI / Import/export fidelity gate (push) Has been skipped
The public home page (/) now renders Markdown the Site Admin stores in the new home.content instance setting, through the same sanitizing pipeline as the legal pages; empty falls back to the built-in welcome text. New public GET /home/content, an Admin → Settings editor with live preview, and an e2e test covering default/configured/escaping/ admin-only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
import { INestApplication } from '@nestjs/common';
|
|
import { PrismaClient } from '@prisma/client';
|
|
import request from 'supertest';
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
|
|
import { createTestApp, sessionCookieOf } from '../testing/test-app';
|
|
import { createTestPrisma, hasTestDb, uniqueSuffix } from '../testing/test-db';
|
|
import { UsersService } from '../users/users.service';
|
|
|
|
/**
|
|
* Editable landing page end to end: the home body defaults to unconfigured,
|
|
* a Site Admin sets it through the generic settings PATCH, anonymous visitors
|
|
* read the rendered HTML, and stored Markdown can never smuggle script in.
|
|
*/
|
|
describe.skipIf(!hasTestDb)('landing page (e2e)', () => {
|
|
let app: INestApplication;
|
|
let prisma: PrismaClient;
|
|
let adminCookie: string;
|
|
const suffix = uniqueSuffix();
|
|
const password = 'ein sehr langes testpasswort';
|
|
|
|
const api = () => request(app.getHttpServer());
|
|
|
|
beforeAll(async () => {
|
|
prisma = createTestPrisma();
|
|
await prisma.rateLimit.deleteMany({});
|
|
await prisma.instanceSetting.deleteMany({ where: { key: 'home.content' } });
|
|
app = await createTestApp();
|
|
|
|
const users = app.get(UsersService);
|
|
const admin = await users.createUser({
|
|
username: `home-admin-${suffix}`,
|
|
email: `home-admin-${suffix}@example.org`,
|
|
displayName: 'Home Admin',
|
|
password,
|
|
locale: 'en',
|
|
});
|
|
await users.markEmailVerified(admin.id);
|
|
await prisma.user.update({ where: { id: admin.id }, data: { isSiteAdmin: true } });
|
|
const res = await api()
|
|
.post('/api/v1/auth/login')
|
|
.send({ usernameOrEmail: admin.username, password })
|
|
.expect(200);
|
|
adminCookie = sessionCookieOf(res);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await prisma.user.deleteMany({ where: { username: { contains: suffix } } });
|
|
await prisma.mailOutbox.deleteMany({ where: { toAddress: { contains: suffix } } });
|
|
await prisma.instanceSetting.deleteMany({ where: { key: 'home.content' } });
|
|
await prisma.$disconnect();
|
|
await app.close();
|
|
});
|
|
|
|
it('reports unconfigured content by default, without a session', async () => {
|
|
const res = await api().get('/api/v1/home/content').expect(200);
|
|
expect(res.body).toMatchObject({ configured: false, html: '' });
|
|
});
|
|
|
|
it('renders configured Markdown publicly and escapes script', async () => {
|
|
await api()
|
|
.patch('/api/v1/admin/settings')
|
|
.set('Cookie', adminCookie)
|
|
.send({ 'home.content': '# Welcome\n\nOur **wiki** <script>alert(1)</script>' })
|
|
.expect(200);
|
|
|
|
const res = await api().get('/api/v1/home/content').expect(200);
|
|
expect(res.body.configured).toBe(true);
|
|
expect(res.body.html).toContain('<h1>Welcome</h1>');
|
|
expect(res.body.html).toContain('<strong>wiki</strong>');
|
|
expect(res.body.html).not.toContain('<script>');
|
|
expect(res.body.html).toContain('<script>');
|
|
});
|
|
|
|
it('keeps the setting admin-only', async () => {
|
|
await api()
|
|
.patch('/api/v1/admin/settings')
|
|
.send({ 'home.content': 'anonymous edit' })
|
|
.expect(401);
|
|
});
|
|
});
|