From 8dd43549549172b66b380046ed8e07b36138120c Mon Sep 17 00:00:00 2001 From: Theresa Kamerman Date: Thu, 27 Jun 2024 14:57:50 -0700 Subject: [PATCH] Fetch and provide auth header when uploading model JAR The Gateway has been updated to (correctly) validate that the user has an active, valid session when hitting restricted endpoints. As a consequence, the E2E tests now provide an `Authorization` header when uploading mission model JARs --- .../jpl/aerie/e2e/utils/GatewayRequests.java | 33 +++++++++++++++++-- .../test/testUtils/MissionModel.ts | 18 +++++++++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/GatewayRequests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/GatewayRequests.java index 2683764cef..7481c22936 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/GatewayRequests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/utils/GatewayRequests.java @@ -16,12 +16,38 @@ public class GatewayRequests implements AutoCloseable { private final APIRequestContext request; + private static String token; - public GatewayRequests(Playwright playwright) { + public GatewayRequests(Playwright playwright) throws IOException { request = playwright.request().newContext( new APIRequest.NewContextOptions() .setBaseURL(BaseURL.GATEWAY.url)); + login(); } + + private void login() throws IOException { + if(token != null) return; + final var response = request.post("/auth/login", RequestOptions.create() + .setHeader("Content-Type", "application/json") + .setData(Json.createObjectBuilder() + .add("username", "AerieE2eTests") + .add("password", "password") + .build() + .toString())); + // Process Response + if(!response.ok()){ + throw new IOException(response.statusText()); + } + try(final var reader = Json.createReader(new StringReader(response.text()))){ + final JsonObject bodyJson = reader.readObject(); + if(!bodyJson.getBoolean("success")){ + System.err.println("Login failed"); + throw new RuntimeException(bodyJson.toString()); + } + token = bodyJson.getString("token"); + } + } + @Override public void close() { request.dispose(); @@ -54,7 +80,9 @@ public int uploadJarFile(String jarPath) throws IOException { "application/java-archive", buffer); - final var response = request.post("/file", RequestOptions.create().setMultipart(FormData.create().set("file", payload))); + final var response = request.post("/file", RequestOptions.create() + .setHeader("Authorization", "Bearer "+token) + .setMultipart(FormData.create().set("file", payload))); // Process Response if(!response.ok()){ @@ -69,5 +97,4 @@ public int uploadJarFile(String jarPath) throws IOException { return bodyJson.getInt("id"); } } - } diff --git a/sequencing-server/test/testUtils/MissionModel.ts b/sequencing-server/test/testUtils/MissionModel.ts index 36dcac047e..4bc08fca72 100644 --- a/sequencing-server/test/testUtils/MissionModel.ts +++ b/sequencing-server/test/testUtils/MissionModel.ts @@ -30,10 +30,14 @@ export async function uploadMissionModel(graphqlClient: GraphQLClient): Promise< const file = await fileFrom(latestBuild.path); formData.set('file', file, 'banananation-latest.jar'); + // Get an authorization token + const authHeader = `Bearer ${await login()}`; + + // Upload File const uploadRes = await fetch(`${process.env['MERLIN_GATEWAY_URL']}/file`, { method: 'POST', body: formData, - headers: { 'x-auth-sso-token': process.env['SSO_TOKEN'] as string }, + headers: { 'Authorization': authHeader }, }); if (!uploadRes.ok) { throw new Error(`Failed to upload mission model: ${uploadRes.statusText}`); @@ -62,6 +66,18 @@ export async function uploadMissionModel(graphqlClient: GraphQLClient): Promise< return (res.insert_mission_model_one as { id: number } as { id: number }).id; } +async function login() { + const response = await fetch(`${process.env['MERLIN_GATEWAY_URL']}/auth/login`, { + method: 'POST', + body: `{"username": "AerieE2ETests", "password": "password"}`, + headers: { 'Content-Type': 'application/json' }, + }); + if (!response.ok) { + throw new Error(`Failed to login: ${response.statusText}`); + } + return (await response.json() as {token: string}).token; +} + export async function removeMissionModel(graphqlClient: GraphQLClient, missionModelId: number): Promise { /* * Remove a mission model