diff --git a/bootstrapping-lambda/src/middleware/auth-middleware.test.ts b/bootstrapping-lambda/src/middleware/auth-middleware.test.ts index e4906024..396b2937 100644 --- a/bootstrapping-lambda/src/middleware/auth-middleware.test.ts +++ b/bootstrapping-lambda/src/middleware/auth-middleware.test.ts @@ -11,6 +11,7 @@ const mockedGetVerifiedUserEmail = mocked(getVerifiedUserEmail, true); const mockedUserHasPermission = mocked(userHasPermission, true); const mockNextFunction = jest.fn(); +const mockSetHeaderFunction = jest.fn(); describe("auth-middleware", () => { beforeAll(() => { @@ -27,9 +28,14 @@ describe("auth-middleware", () => { status: jest.fn().mockReturnValue({ send: jest.fn(), }), + setHeader: mockSetHeaderFunction, } as unknown) as Response; await getAuthMiddleware()(mockRequest, mockResponse, mockNextFunction); expect(mockResponse.status).toHaveBeenCalledWith(401); + expect(mockSetHeaderFunction).toHaveBeenCalledWith( + "Access-Control-Allow-Credentials", + "true" + ); expect(mockNextFunction).not.toHaveBeenCalled(); }); @@ -42,12 +48,17 @@ describe("auth-middleware", () => { const mockResponse = ({ status: jest.fn(), send: jest.fn(), + setHeader: mockSetHeaderFunction, } as unknown) as Response; await getAuthMiddleware(true)(mockRequest, mockResponse, mockNextFunction); expect(mockResponse.status).not.toHaveBeenCalled(); expect(mockResponse.send).toHaveBeenCalledWith( "console.error('pan-domain auth cookie missing, invalid or expired')" ); + expect(mockSetHeaderFunction).toHaveBeenCalledWith( + "Access-Control-Allow-Credentials", + "true" + ); expect(mockNextFunction).not.toHaveBeenCalled(); }); @@ -62,6 +73,7 @@ describe("auth-middleware", () => { status: jest.fn().mockReturnValue({ send: mockSendFunction, }), + setHeader: mockSetHeaderFunction, } as unknown) as Response; mockedGetVerifiedUserEmail.mockResolvedValueOnce("foo@bar.com"); @@ -72,6 +84,10 @@ describe("auth-middleware", () => { expect(mockSendFunction).toHaveBeenCalledWith( "You do not have permission to use PinBoard" ); + expect(mockSetHeaderFunction).toHaveBeenCalledWith( + "Access-Control-Allow-Credentials", + "true" + ); expect(mockNextFunction).not.toHaveBeenCalled(); expect(mockRequest.userEmail).toBeUndefined(); }); @@ -86,6 +102,7 @@ describe("auth-middleware", () => { const mockResponse = ({ status: jest.fn(), send: mockSendFunction, + setHeader: mockSetHeaderFunction, } as unknown) as Response; mockedGetVerifiedUserEmail.mockResolvedValueOnce("foo@bar.com"); @@ -96,6 +113,10 @@ describe("auth-middleware", () => { expect(mockSendFunction).toHaveBeenCalledWith( "console.log('You do not have permission to use PinBoard')" ); + expect(mockSetHeaderFunction).toHaveBeenCalledWith( + "Access-Control-Allow-Credentials", + "true" + ); expect(mockNextFunction).not.toHaveBeenCalled(); expect(mockRequest.userEmail).toBeUndefined(); }); @@ -110,12 +131,17 @@ describe("auth-middleware", () => { status: jest.fn().mockReturnValue({ send: jest.fn(), }), + setHeader: mockSetHeaderFunction, } as unknown) as Response; mockedGetVerifiedUserEmail.mockResolvedValueOnce("foo@bar.com"); mockedUserHasPermission.mockResolvedValueOnce(true); await getAuthMiddleware()(mockRequest, mockResponse, mockNextFunction); expect(mockRequest.userEmail).toBe("foo@bar.com"); expect(mockResponse.status).not.toHaveBeenCalled(); + expect(mockSetHeaderFunction).toHaveBeenCalledWith( + "Access-Control-Allow-Credentials", + "true" + ); expect(mockNextFunction).toHaveBeenCalledTimes(1); }); }); diff --git a/bootstrapping-lambda/src/middleware/auth-middleware.ts b/bootstrapping-lambda/src/middleware/auth-middleware.ts index b8606fa8..b87182f7 100644 --- a/bootstrapping-lambda/src/middleware/auth-middleware.ts +++ b/bootstrapping-lambda/src/middleware/auth-middleware.ts @@ -16,6 +16,7 @@ export const getAuthMiddleware = (sendErrorAsOk = false) => async ( next: NextFunction ) => { const maybeCookieHeader = request.header("Cookie"); + response.setHeader("Access-Control-Allow-Credentials", "true"); const maybeAuthenticatedEmail = await getVerifiedUserEmail(maybeCookieHeader); if (!maybeAuthenticatedEmail) { diff --git a/bootstrapping-lambda/src/reporting/reportingServiceClient.ts b/bootstrapping-lambda/src/reporting/reportingServiceClient.ts index 85d945da..a5c05ea8 100644 --- a/bootstrapping-lambda/src/reporting/reportingServiceClient.ts +++ b/bootstrapping-lambda/src/reporting/reportingServiceClient.ts @@ -14,27 +14,22 @@ const metricEndpointMap: Record = { [StageMetric.UNIQUE_USERS_PROD]: "PROD", }; -const stageMetricToMetric = { - [StageMetric.UNIQUE_USERS_CODE]: Metric.UNIQUE_USERS, - [StageMetric.UNIQUE_USERS_PROD]: Metric.UNIQUE_USERS, -}; - export const getMetrics = async ( request: GrafanaRequest ): Promise => { const lambda = new AWS.Lambda(standardAwsConfig); const { range, targets } = request; const metricsResponse = await Promise.all( - targets.map((target) => { - console.log(`processing grafana request`, target.target); + targets.map(({ target, data }) => { + console.log(`processing grafana request`, target); return lambda .invoke({ FunctionName: getDatabaseBridgeLambdaFunctionName( - metricEndpointMap[target.target] + data?.stage || metricEndpointMap[target] ), Payload: JSON.stringify({ range, - metric: stageMetricToMetric[target.target], + metric: Metric.UNIQUE_USERS, }), }) .promise(); diff --git a/bootstrapping-lambda/src/server.ts b/bootstrapping-lambda/src/server.ts index 9741ed6f..18f5972c 100644 --- a/bootstrapping-lambda/src/server.ts +++ b/bootstrapping-lambda/src/server.ts @@ -44,7 +44,6 @@ server.use(express.json()); server.use(cors(corsOptions)); server.post("/search", getAuthMiddleware(), (_, response) => { - response.setHeader("Access-Control-Allow-Credentials", "true"); return response.json(Object.values(StageMetric)); }); @@ -52,7 +51,6 @@ server.post( "/query", getAuthMiddleware(), async (request: AuthenticatedRequest, response) => { - response.setHeader("Access-Control-Allow-Credentials", "true"); const { body: metricsQuery }: { body: GrafanaRequest } = request; response.json(await getMetrics(metricsQuery)); } diff --git a/shared/types/grafanaType.ts b/shared/types/grafanaType.ts index 5017c5b0..19d74518 100644 --- a/shared/types/grafanaType.ts +++ b/shared/types/grafanaType.ts @@ -1,3 +1,5 @@ +import { Stage } from "./stage"; + export interface Range { from: string; to: string; @@ -9,15 +11,21 @@ export type TargetType = "timeserie" | "table"; export enum StageMetric { UNIQUE_USERS_CODE = "uniqueUsersCode", UNIQUE_USERS_PROD = "uniqueUsersProd", + UNIQUE_USERS = "uniqueUsers", } export enum Metric { UNIQUE_USERS = "uniqueUsers", } +export interface customData { + stage?: Stage; +} + export interface Target { target: StageMetric; type: TargetType; + data?: customData; } export interface GrafanaRequest {