Skip to content

Commit f891584

Browse files
committed
fix(webapp): stub what the env JWT act-claim test's route actually calls
The test mocked the old preamble, so the route hit real rbac and a logger without `info`, failing with a 403 and an uncaught type error.
1 parent bd357fc commit f891584

1 file changed

Lines changed: 31 additions & 17 deletions

File tree

apps/webapp/test/envJwtActorClaim.test.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
import { beforeEach, describe, expect, it, vi } from "vitest";
22

33
const mocks = vi.hoisted(() => ({
4+
authenticateRequest: vi.fn<(...args: any[]) => Promise<any>>(),
5+
verifyUserActorToken: vi.fn<(...args: any[]) => Promise<any>>(),
6+
isUserActorToken: vi.fn<(value: string) => boolean>(),
47
authenticateUatOrApiRequest: vi.fn<(...args: any[]) => Promise<any>>(),
58
authorizePatEnvironmentAccess: vi.fn<(...args: any[]) => Promise<any>>(),
69
}));
710

8-
vi.mock("~/services/uatRoutePreamble.server", () => ({
9-
authenticateUatOrApiRequest: mocks.authenticateUatOrApiRequest,
11+
vi.mock("@trigger.dev/rbac", async (importOriginal) => ({
12+
...(await importOriginal<Record<string, unknown>>()),
13+
isUserActorToken: mocks.isUserActorToken,
14+
verifyUserActorToken: mocks.verifyUserActorToken,
1015
}));
1116
vi.mock("~/services/environmentVariableApiAccess.server", () => ({
1217
authorizePatEnvironmentAccess: mocks.authorizePatEnvironmentAccess,
1318
}));
1419
vi.mock("~/services/apiAuth.server", () => ({
1520
authenticatedEnvironmentForAuthentication: vi.fn(async () => environment),
1621
branchNameFromRequest: () => undefined,
22+
authenticateRequest: mocks.authenticateRequest,
1723
}));
1824
vi.mock("~/services/logger.server", () => ({
19-
logger: { debug: vi.fn(), error: vi.fn(), warn: vi.fn() },
25+
logger: { debug: vi.fn(), error: vi.fn(), warn: vi.fn(), info: vi.fn() },
2026
}));
27+
vi.mock("~/env.server", () => ({ env: { SESSION_SECRET: "test-session-secret" } }));
28+
vi.mock("~/db.server", () => ({ prisma: {}, $replica: {} }));
2129

2230
import { validateJWT } from "@trigger.dev/core/v3/jwt";
2331
import { action } from "~/routes/api.v1.projects.$projectRef.$env.jwt";
@@ -32,10 +40,10 @@ const environment = {
3240

3341
const params = { projectRef: "proj_abc", env: "prod" };
3442

35-
function request(body: unknown = {}) {
43+
function request(body: unknown = {}, bearer = "tr_pat_test") {
3644
return new Request("https://example.com/api/v1/projects/proj_abc/prod/jwt", {
3745
method: "POST",
38-
headers: { "Content-Type": "application/json" },
46+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${bearer}` },
3947
body: JSON.stringify(body),
4048
});
4149
}
@@ -50,14 +58,18 @@ async function mintedClaims(body?: unknown) {
5058

5159
describe("env JWT exchange — act claim", () => {
5260
beforeEach(() => {
53-
mocks.authenticateUatOrApiRequest.mockReset();
61+
mocks.authenticateRequest.mockReset();
62+
mocks.verifyUserActorToken.mockReset();
63+
mocks.isUserActorToken.mockReset();
64+
mocks.isUserActorToken.mockReturnValue(false);
5465
mocks.authorizePatEnvironmentAccess.mockReset();
5566
mocks.authorizePatEnvironmentAccess.mockResolvedValue(undefined);
5667
});
5768

5869
it("stamps the PAT's user with the personal-access-token client", async () => {
59-
mocks.authenticateUatOrApiRequest.mockResolvedValue({
60-
authenticationResult: { type: "personalAccessToken", result: { userId: "usr_42" } },
70+
mocks.authenticateRequest.mockResolvedValue({
71+
type: "personalAccessToken",
72+
result: { userId: "usr_42" },
6173
});
6274

6375
const claims = await mintedClaims();
@@ -67,9 +79,13 @@ describe("env JWT exchange — act claim", () => {
6779
});
6880

6981
it("passes through a user-actor token's own client", async () => {
70-
mocks.authenticateUatOrApiRequest.mockResolvedValue({
71-
authenticationResult: { type: "personalAccessToken", result: { userId: "usr_7" } },
72-
userActor: { userId: "usr_7", client: "dashboard-agent", cap: ["read:runs"] },
82+
mocks.isUserActorToken.mockReturnValue(true);
83+
mocks.verifyUserActorToken.mockResolvedValue({
84+
userId: "usr_7",
85+
client: "dashboard-agent",
86+
// An agent token always carries the environment it was minted for.
87+
environmentId: environment.id,
88+
cap: ["read:runs"],
7389
});
7490

7591
const claims = await mintedClaims({ claims: { scopes: ["read:runs"] } });
@@ -79,11 +95,9 @@ describe("env JWT exchange — act claim", () => {
7995
});
8096

8197
it("omits act for an org access token (no user)", async () => {
82-
mocks.authenticateUatOrApiRequest.mockResolvedValue({
83-
authenticationResult: {
84-
type: "organizationAccessToken",
85-
result: { organizationId: "org_1" },
86-
},
98+
mocks.authenticateRequest.mockResolvedValue({
99+
type: "organizationAccessToken",
100+
result: { organizationId: "org_1" },
87101
});
88102

89103
const claims = await mintedClaims();
@@ -93,7 +107,7 @@ describe("env JWT exchange — act claim", () => {
93107
});
94108

95109
it("401s without a token", async () => {
96-
mocks.authenticateUatOrApiRequest.mockResolvedValue(undefined);
110+
mocks.authenticateRequest.mockResolvedValue(undefined);
97111

98112
const response = await action({ request: request(), params, context: {} as any });
99113

0 commit comments

Comments
 (0)