mirror of
https://github.com/documenso/documenso.git
synced 2026-08-21 05:51:53 +10:00
75 lines
2.6 KiB
TypeScript
75 lines
2.6 KiB
TypeScript
import { prisma } from '@documenso/prisma';
|
|
import { seedTeam, seedTeamMember } from '@documenso/prisma/seed/teams';
|
|
import type { Page } from '@playwright/test';
|
|
import { expect, test } from '@playwright/test';
|
|
import { TeamMemberRole, WebhookTriggerEvents } from '@prisma/client';
|
|
|
|
import { apiSignin } from '../fixtures/authentication';
|
|
|
|
/**
|
|
* Calls the procedure the way an attacker would — directly, from the authenticated browser
|
|
* context, bypassing the UI entirely. The settings page is gated on MANAGE_TEAM, so going
|
|
* through the UI would only prove the page is hidden, not that the data is protected.
|
|
*/
|
|
const callGetTeamWebhooks = async (page: Page, teamId: number) =>
|
|
await page.evaluate(async (id) => {
|
|
const response = await fetch('/api/trpc/webhook.getTeamWebhooks', {
|
|
method: 'GET',
|
|
headers: { 'content-type': 'application/json', 'x-team-id': String(id) },
|
|
});
|
|
|
|
return { status: response.status, body: await response.text() };
|
|
}, teamId);
|
|
|
|
test.describe('Webhook secret access', () => {
|
|
test('team managers can read webhook secrets', async ({ page }) => {
|
|
const { owner, team } = await seedTeam();
|
|
|
|
await prisma.webhook.create({
|
|
data: {
|
|
webhookUrl: 'https://example.com/hook',
|
|
eventTriggers: [WebhookTriggerEvents.DOCUMENT_SENT],
|
|
secret: 'super-secret-signing-key',
|
|
enabled: true,
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
},
|
|
});
|
|
|
|
await apiSignin({ page, email: owner.email });
|
|
await page.goto(`/t/${team.url}/settings/webhooks`);
|
|
|
|
const { status, body } = await callGetTeamWebhooks(page, team.id);
|
|
|
|
expect(status).toBe(200);
|
|
// The edit dialog reads the secret straight off these rows, so managers must get it.
|
|
expect(body).toContain('super-secret-signing-key');
|
|
});
|
|
|
|
test('team members without manage permission cannot read webhook secrets', async ({ page }) => {
|
|
const { owner, team } = await seedTeam();
|
|
|
|
await prisma.webhook.create({
|
|
data: {
|
|
webhookUrl: 'https://example.com/hook',
|
|
eventTriggers: [WebhookTriggerEvents.DOCUMENT_SENT],
|
|
secret: 'super-secret-signing-key',
|
|
enabled: true,
|
|
userId: owner.id,
|
|
teamId: team.id,
|
|
},
|
|
});
|
|
|
|
const member = await seedTeamMember({ teamId: team.id, role: TeamMemberRole.MEMBER });
|
|
|
|
await apiSignin({ page, email: member.email });
|
|
await page.goto(`/t/${team.url}/documents`);
|
|
|
|
const { status, body } = await callGetTeamWebhooks(page, team.id);
|
|
|
|
// Whatever the failure mode, the signing key must never appear in the response.
|
|
expect(body).not.toContain('super-secret-signing-key');
|
|
expect(status).not.toBe(200);
|
|
});
|
|
});
|