Skip to content

Commit

Permalink
Merge pull request #988 from Enterprise-CMCS/main
Browse files Browse the repository at this point in the history
Release to val
  • Loading branch information
13bfrancis authored Jan 9, 2025
2 parents 185e670 + d68c42e commit 7343bbf
Show file tree
Hide file tree
Showing 100 changed files with 70,070 additions and 12,894 deletions.
19 changes: 10 additions & 9 deletions lib/lambda/deleteIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ export const handler: Handler = async (event, __, callback) => {
};
let errorResponse = null;
try {
if (!event.osDomain) throw "process.env.osDomain cannot be undefined";
const { osDomain, indexNamespace = "" } = event;
if (!osDomain) throw "osDomain cannot be undefined";

const indices: Index[] = [
`${event.indexNamespace}main`,
`${event.indexNamespace}changelog`,
`${event.indexNamespace}insights`,
`${event.indexNamespace}types`,
`${event.indexNamespace}subtypes`,
`${event.indexNamespace}legacyinsights`,
`${event.indexNamespace}cpocs`,
`${indexNamespace}main`,
`${indexNamespace}changelog`,
`${indexNamespace}insights`,
`${indexNamespace}types`,
`${indexNamespace}subtypes`,
`${indexNamespace}legacyinsights`,
`${indexNamespace}cpocs`,
];
for (const index of indices) {
await os.deleteIndex(event.osDomain, index);
await os.deleteIndex(osDomain, index);
}
} catch (error: any) {
response.statusCode = 500;
Expand Down
197 changes: 69 additions & 128 deletions lib/lambda/getAttachmentUrl.test.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,36 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { describe, it, expect, vi, afterEach } from "vitest";
import { APIGatewayEvent } from "aws-lambda";
import { handler } from "./getAttachmentUrl";
import { response } from "libs/handler-lib";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { getStateFilter } from "../libs/api/auth/user";
import { getPackage, getPackageChangelog } from "../libs/api/package";

vi.mock("libs/handler-lib", () => ({
response: vi.fn(),
}));

vi.mock("@aws-sdk/client-sts", () => ({
STSClient: vi.fn().mockImplementation(() => ({
send: vi.fn(),
})),
AssumeRoleCommand: vi.fn(),
}));

vi.mock("@aws-sdk/client-s3", () => ({
S3Client: vi.fn().mockImplementation(() => ({
send: vi.fn(),
})),
GetObjectCommand: vi.fn(),
}));
import {
OPENSEARCH_DOMAIN,
getRequestContext,
NOT_FOUND_ITEM_ID,
HI_TEST_ITEM_ID,
TEST_ITEM_ID,
WITHDRAWN_CHANGELOG_ITEM_ID,
GET_ERROR_ITEM_ID,
ATTACHMENT_BUCKET_NAME,
ATTACHMENT_BUCKET_REGION,
} from "mocks";

vi.mock("@aws-sdk/s3-request-presigner", () => ({
getSignedUrl: vi.fn(),
}));

vi.mock("../libs/api/auth/user", () => ({
getStateFilter: vi.fn(),
}));

vi.mock("../libs/api/package", () => ({
getPackage: vi.fn(),
getPackageChangelog: vi.fn(),
}));

describe("Lambda Handler", () => {
beforeEach(() => {
afterEach(() => {
vi.clearAllMocks();
process.env.osDomain = "test-domain"; // Set the environment variable before each test
});

it("should return 400 if event body is missing", async () => {
const event = {} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 400,
body: { message: "Event body required" },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(400);
expect(res.body).toEqual(JSON.stringify({ message: "Event body required" }));
});

it("should return 500 if osDomain is missing", async () => {
Expand All @@ -60,155 +39,117 @@ describe("Lambda Handler", () => {
const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
bucket: ATTACHMENT_BUCKET_NAME,
key: "test-key",
filename: "test-file",
}),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(res).toBeTruthy();
expect(res.statusCode).toEqual(500);
expect(res.body).toEqual(
JSON.stringify({ message: "ERROR: process.env.osDomain must be defined" }),
);

expect(response).toHaveBeenCalledWith({
statusCode: 500,
body: { message: "ERROR: osDomain env variable is required" },
});
process.env.osDomain = OPENSEARCH_DOMAIN;
});

it("should return 404 if no package is found", async () => {
vi.mocked(getPackage).mockResolvedValueOnce(null);

const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
id: NOT_FOUND_ITEM_ID,
bucket: ATTACHMENT_BUCKET_NAME,
key: "test-key",
filename: "test-file",
}),
requestContext: getRequestContext(),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 404,
body: { message: "No record found for the given id" },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(404);
expect(res.body).toEqual(JSON.stringify({ message: "No record found for the given id" }));
});

it("should return 404 if state access is not permitted", async () => {
vi.mocked(getPackage).mockResolvedValueOnce({
_source: { state: "test-state" },
});
vi.mocked(getStateFilter).mockResolvedValueOnce({
terms: { state: ["other-state"] },
});

const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
id: HI_TEST_ITEM_ID,
bucket: ATTACHMENT_BUCKET_NAME,
key: "test-key",
filename: "test-file",
}),
requestContext: getRequestContext(),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 404,
body: { message: "state access not permitted for the given id" },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(403);
expect(res.body).toEqual(
JSON.stringify({ message: "state access not permitted for the given id" }),
);
});

it("should return 500 if attachment details are not found", async () => {
vi.mocked(getPackage).mockResolvedValueOnce({
_source: { state: "test-state" },
});
vi.mocked(getStateFilter).mockResolvedValueOnce({
terms: { state: ["test-state"] },
});
vi.mocked(getPackageChangelog).mockResolvedValueOnce({
hits: {
hits: [
{
_source: {
attachments: [{ bucket: "other-bucket", key: "other-key" }],
},
},
],
},
});

const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
id: TEST_ITEM_ID,
bucket: ATTACHMENT_BUCKET_NAME,
key: "test-key",
filename: "test-file",
}),
requestContext: getRequestContext(),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 500,
body: { message: "Attachment details not found for given record id." },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(500);
expect(res.body).toEqual(
JSON.stringify({ message: "Attachment details not found for given record id." }),
);
});

it("should return 200 with the presigned URL if all checks pass", async () => {
vi.mocked(getPackage).mockResolvedValueOnce({
_source: { state: "test-state" },
});
vi.mocked(getStateFilter).mockResolvedValueOnce({
terms: { state: ["test-state"] },
});
vi.mocked(getPackageChangelog).mockResolvedValueOnce({
hits: {
hits: [
{
_source: {
attachments: [{ bucket: "test-bucket", key: "test-key" }],
},
},
],
},
});
vi.mocked(getSignedUrl).mockResolvedValueOnce("test-presigned-url");
const mockUrl = `https://${ATTACHMENT_BUCKET_NAME}.s3.${ATTACHMENT_BUCKET_REGION}.amazonaws.com/123e4567-e89b-12d3-a456-426614174000`;
vi.mocked(getSignedUrl).mockResolvedValueOnce(mockUrl);

const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
key: "test-key",
filename: "test-file",
id: WITHDRAWN_CHANGELOG_ITEM_ID,
bucket: ATTACHMENT_BUCKET_NAME,
key: "doc001",
filename: "contract_amendment_2024.pdf",
}),
requestContext: getRequestContext(),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 200,
body: { url: "test-presigned-url" },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(200);
expect(res.body).toEqual(JSON.stringify({ url: mockUrl }));
});

it("should handle errors during processing", async () => {
vi.mocked(getPackage).mockRejectedValueOnce(new Error("Test error"));

const event = {
body: JSON.stringify({
id: "test-id",
bucket: "test-bucket",
id: GET_ERROR_ITEM_ID,
bucket: ATTACHMENT_BUCKET_NAME,
key: "test-key",
filename: "test-file",
}),
requestContext: getRequestContext(),
} as APIGatewayEvent;

await handler(event);
const res = await handler(event);

expect(response).toHaveBeenCalledWith({
statusCode: 500,
body: { message: "Internal server error" },
});
expect(res).toBeTruthy();
expect(res.statusCode).toEqual(500);
expect(res.body).toEqual(JSON.stringify({ message: "Internal server error" }));
});
});
27 changes: 10 additions & 17 deletions lib/lambda/getAttachmentUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,31 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

import { getStateFilter } from "../libs/api/auth/user";
import { getPackage, getPackageChangelog } from "../libs/api/package";
import { getDomain } from "libs/utils";

// Handler function to get Seatool data
export const handler = async (event: APIGatewayEvent) => {
if (!process.env.osDomain) {
try {
getDomain();
} catch (error) {
return response({
statusCode: 500,
body: { message: "ERROR: osDomain env variable is required" },
body: { message: `ERROR: ${error?.message || error}` },
});
}

if (!event.body) {
return response({
statusCode: 400,
body: { message: "Event body required" },
});
}
if (!process.env.osDomain) {
return response({
statusCode: 500,
body: { message: "Handler is missing process.env.osDomain env var" },
});
}

try {
const body = JSON.parse(event.body);

const mainResult = await getPackage(body.id);
if (!mainResult) {
if (!mainResult || !mainResult.found) {
return response({
statusCode: 404,
body: { message: "No record found for the given id" },
Expand All @@ -48,7 +46,7 @@ export const handler = async (event: APIGatewayEvent) => {

if (!stateAccessAllowed) {
return response({
statusCode: 404,
statusCode: 403,
body: { message: "state access not permitted for the given id" },
});
}
Expand All @@ -72,12 +70,7 @@ export const handler = async (event: APIGatewayEvent) => {
}

// Now we can generate the presigned url
const url = await generatePresignedUrl(
body.bucket,
body.key,
body.filename,
60,
);
const url = await generatePresignedUrl(body.bucket, body.key, body.filename, 60);

return response<unknown>({
statusCode: 200,
Expand All @@ -104,7 +97,7 @@ async function getClient(bucket: string) {
const assumedCredentials = assumedRoleResponse.Credentials;

if (!assumedCredentials) {
throw new Error("No assumed redentials");
throw new Error("No assumed credentials");
}

// Create S3 client using the assumed role's credentials
Expand Down
Loading

0 comments on commit 7343bbf

Please sign in to comment.