Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/cli/src/cli/dev/dev-server/routes/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { createProxyMiddleware } from "http-proxy-middleware";
import type { DevLogger } from "@/cli/dev/createDevLogger.js";
import type { FunctionManager } from "@/cli/dev/dev-server/function-manager.js";

const LOCAL_DEV_SERVICE_AUTHORIZATION_TOKEN = "Bearer dev";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this approach?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will throw when function code will try to get list of users like this:

await base44.asServiceRole.entities.User.list()

this is because of this validation:

function withAuth<R>(
handler: (
req: Request<R>,
res: Response,
currentUser: UserDocument,
) => Promise<void> | void,
): (req: Request<R>, res: Response) => Promise<void> {
return async (req, res) => {
const currentUserResult = await resolveCurrentUser(db, req);
if (
!currentUserResult.ok &&
(currentUserResult.reason === "missing" ||
currentUserResult.reason === "invalid")
) {
res.status(401).json({ error: "Unauthorized" });
return;
}
if (!currentUserResult.ok) {
res
.status(404)
.json({ error: "Unable to read data for the current user" });
return;
}
await handler(req, res, currentUserResult.user);
};


export function createFunctionRouter(
manager: FunctionManager,
logger: DevLogger,
Expand All @@ -19,14 +21,14 @@ export function createFunctionRouter(
on: {
proxyReq: (proxyReq, req) => {
const xAppId = req.headers["x-app-id"];
const authorization = req.headers.authorization;

if (xAppId) {
proxyReq.setHeader("Base44-App-Id", xAppId as string);
}
if (authorization) {
proxyReq.setHeader("Base44-Service-Authorization", authorization);
}
proxyReq.setHeader(
"Base44-Service-Authorization",
LOCAL_DEV_SERVICE_AUTHORIZATION_TOKEN,
);
proxyReq.setHeader(
"Base44-Api-Url",
`${(req as unknown as Request).protocol}://${req.headers.host}`,
Expand Down
33 changes: 20 additions & 13 deletions packages/cli/tests/cli/dev.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("dev command", () => {
t.expectResult(result).toSucceed();
});

it("forwards the service token header from Authorization to local functions", async () => {
it("sets a local service token header for functions", async () => {
await t.givenLoggedInWithProject(fixture("full-project"));

await writeFile(
Expand All @@ -52,20 +52,27 @@ describe("dev command", () => {
const handle = await t.runLive("dev");
const devServerUrl = await waitForDevServer(handle);

const response = await fetch(
`${devServerUrl}/api/apps/${t.api.appId}/functions/hello`,
{
headers: {
Authorization: "Bearer test-app-token",
"X-App-Id": t.api.appId,
},
},
);
const functionUrl = `${devServerUrl}/api/apps/${t.api.appId}/functions/hello`;
const requestFunction = (headers: Record<string, string>) =>
fetch(functionUrl, { headers });

expect(response.status).toBe(200);
await expect(response.json()).resolves.toEqual({
const anonymousResponse = await requestFunction({
"X-App-Id": t.api.appId,
});
expect(anonymousResponse.status).toBe(200);
await expect(anonymousResponse.json()).resolves.toEqual({
authorization: null,
serviceAuthorization: "Bearer dev",
});

const authenticatedResponse = await requestFunction({
Authorization: "Bearer test-app-token",
"X-App-Id": t.api.appId,
});
expect(authenticatedResponse.status).toBe(200);
await expect(authenticatedResponse.json()).resolves.toEqual({
authorization: "Bearer test-app-token",
serviceAuthorization: "Bearer test-app-token",
serviceAuthorization: "Bearer dev",
});

const result = await handle.stop();
Expand Down
Loading