Skip to content

Commit

Permalink
fix: Early deploy (#315)
Browse files Browse the repository at this point in the history
# Jira

[Link al issue en Jira](Link%20al%20clickup)

## Descripción

<!-- Ingresa una descripción de la PR aquí -->

## Tasks

<!-- Asegúrate de cumplir todas estas tareas antes de hacer la PR. -->

- \[x] Asignate a tí mismo dentro de la PR.
- \[x] Asegúrate que el nombre de la PR siga el formato de [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/).
- \[x] Añade una breve descripción de la escencia de tus cambios en tu
PR.
- \[x] Agrega el link al issue de Jira.
- \[x] Asegurate que la PR pase todos los chequeos de CI.
- \[x] Ponle las tags correspondientes a tu PR.
  Backend: PRs que modifican lógica relacionada al backend.
  Frontend: PRs que modifican lógica relacionada al frontend.
  Database: PRs que modifican lógica relacionada a la base de datos.
  Wiki: PRs que editan la wiki.
  Nix: PRs que modifican el entorno de desarrollo en Nix.
  CI/CD: PRs relacionadas con la CI/CD pipeline.
  • Loading branch information
ElrohirGT authored Nov 15, 2024
2 parents 824eda8 + 9b733da commit 441b69c
Show file tree
Hide file tree
Showing 36 changed files with 723 additions and 227 deletions.
1 change: 1 addition & 0 deletions database/tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ CREATE MATERIALIZED VIEW md_san.stats
AS
SELECT
p.id,
c.evaluador,
p.fecha_nacimiento,
c.fecha AS fecha_visita,
c.diagnostico,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { describe, expect, test } from "@jest/globals";
import axios from "axios";
import {
createAuthorizationHeader,
createDoctorJWT,
createInvalidJWT,
createPatientJWT,
createTestPatient,
generateUniqueCUI,
LOCAL_API_URL,
} from "../testHelpers.mjs";

const API_URL = `${LOCAL_API_URL}/patient`;

describe("Create Patient Record Integration Tests", () => {
const validHeaders = createAuthorizationHeader(createDoctorJWT());
test("Normal case: Create a new patient record", createTestPatient);

test("Create a new patient record without CUI (should fail)", async () => {
Expand All @@ -17,7 +24,8 @@ describe("Create Patient Record Integration Tests", () => {
birthdate: "1990-01-01",
};

const response = await axios.post(`${LOCAL_API_URL}/patient`, patientData, {
const response = await axios.post(API_URL, patientData, {
headers: validHeaders,
validateStatus: () => true, // So axios doesn't throw an error for status >= 400
});

Expand All @@ -43,18 +51,59 @@ describe("Create Patient Record Integration Tests", () => {
birthdate: "1985-05-05",
};

await axios.post(`${LOCAL_API_URL}/patient`, patientData1);
await axios.post(API_URL, patientData1, {
headers: validHeaders,
});

const response = await axios.post(
`${LOCAL_API_URL}/patient`,
patientData2,
{
validateStatus: () => true, // So axios doesn't throw an error for status >= 400
},
);
const response = await axios.post(API_URL, patientData2, {
headers: validHeaders,
validateStatus: () => true, // So axios doesn't throw an error for status >= 400
});

// Verify the error is as expected
expect(response.status).toBe(409);
expect(response.data.error).toBe("CUI already exists.");
});

test("a patient can't call the endpoint", async () => {
const uniqueCUI = generateUniqueCUI();
const postData = {
cui: uniqueCUI,
names: "Juan",
lastNames: "Pérez",
isWoman: false,
birthdate: "1990-01-01",
};
const specialHeaders = createAuthorizationHeader(createPatientJWT());

const response = await axios.post(API_URL, postData, {
headers: specialHeaders,
validateStatus: () => true,
});

expect(response.status).toBe(401);
expect(response.data).toEqual({
error: "Unauthorized, you're a patient!",
});
});

test("can't be called by a malformed JWT", async () => {
const uniqueCUI = generateUniqueCUI();
const postData = {
cui: uniqueCUI,
names: "Juan",
lastNames: "Pérez",
isWoman: false,
birthdate: "1990-01-01",
};
const specialHeaders = createAuthorizationHeader(createInvalidJWT());

const response = await axios.post(API_URL, postData, {
headers: specialHeaders,
validateStatus: () => true,
});

expect(response.status).toBe(400);
expect(response.data).toEqual({ error: "JWT couldn't be parsed" });
});
});
46 changes: 44 additions & 2 deletions sanitas_backend/src/handlers/CreatePatient/create-patient.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getPgClient, SCHEMA_NAME, transaction } from "db-conn";
import { getPgClient, isDoctor, SCHEMA_NAME, transaction } from "db-conn";
import { logger, withRequest } from "logging";
import { cuiIsValid } from "utils/cui.mjs";
import { createResponse } from "utils/index.mjs";
import { createResponse, decodeJWT } from "utils/index.mjs";

function checkValidInput(patientData) {
const isValidCUI = cuiIsValid(patientData.cui);
Expand Down Expand Up @@ -36,6 +36,24 @@ export const createPatientHandler = async (event, context) => {
.build();
}

logger.info({ headers: event.headers }, "Received headers...");
const jwt = event.headers.Authorization;

logger.info({ jwt }, "Parsing JWT...");
const tokenInfo = decodeJWT(jwt);
if (tokenInfo.error) {
logger.error(
{ err: tokenInfo.error, inputs: { jwt } },
"JWT couldn't be parsed!",
);
return responseBuilder
.setStatusCode(400)
.setBody({ error: "JWT couldn't be parsed" })
.build();
}
const { email } = tokenInfo;
logger.info({ tokenInfo }, "JWT Parsed!");

const patientData = JSON.parse(event.body);
logger.info(process.env, "Environment variables are:");

Expand All @@ -59,6 +77,30 @@ export const createPatientHandler = async (event, context) => {
logger.info({ patientData }, "Data is valid!");

const transactionResult = await transaction(client, logger, async () => {
logger.info("Checking if the user is a doctor...");
const isDoctorResponse = await isDoctor(client, email);
if (isDoctorResponse.error) {
logger.error(
{ isDoctorResponse },
"An error ocurred while checking if the user is doctor!",
);
const response = responseBuilder
.setStatusCode(500)
.setBody(isDoctorResponse)
.build();
return { response };
}

if (!isDoctorResponse) {
logger.error("The user is not a doctor!");
const response = responseBuilder
.setStatusCode(401)
.setBody({ error: "Unauthorized, you're a patient!" })
.build();
return { response };
}
logger.info("The user is a doctor!");

const existingPatientQuery = `
SELECT 1 FROM ${SCHEMA_NAME}.paciente WHERE cui = $1
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe("Get consultations data endpoint tests", () => {
const validDateParams = {
startDate: new Date(),
endDate: new Date(Date.now() + 10_000 * 10_000),
nowDate: new Date(Date.now() + 11_000 * 10_000),
};
let patientId;

Expand Down Expand Up @@ -95,6 +96,7 @@ describe("Get consultations data endpoint tests", () => {
params: {
startDate: new Date(Date.now()),
endDate: new Date(Date.now() - 1000 * 1000),
nowDate: new Date(Date.now() - 2000 * 1000),
},
});

Expand Down
26 changes: 21 additions & 5 deletions sanitas_backend/src/handlers/ExportData/export-data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,19 @@ export const handler = async (event, context) => {
);
const queryStartDate = event.queryStringParameters?.startDate;
const queryEndDate = event.queryStringParameters?.endDate;
const queryNowDate = event.queryStringParameters?.nowDate;

logger.info(
{ queryStartDate, queryEndDate },
{ queryStartDate, queryEndDate, queryNowDate },
"Checking if dates are valid...",
);
if (!(validDate(queryStartDate) && validDate(queryEndDate))) {
if (
!(
validDate(queryStartDate) &&
validDate(queryEndDate) &&
validDate(queryNowDate)
)
) {
logger.error({ queryStartDate, queryEndDate }, "Invalid dates!");
return responseBuilder
.setStatusCode(400)
Expand All @@ -91,7 +98,8 @@ export const handler = async (event, context) => {

const startDate = new Date(queryStartDate);
const endDate = new Date(queryEndDate);
logger.info({ startDate, endDate }, "Dates are valid!");
const nowDate = new Date(queryNowDate);
logger.info({ startDate, endDate, nowDate }, "Dates are valid!");

logger.info("Validating endDate >= startDate");
if (endDate.getTime() < startDate.getTime()) {
Expand Down Expand Up @@ -140,8 +148,16 @@ export const handler = async (event, context) => {
}
logger.info(`${email} is a doctor!`);

const query = `SELECT * FROM ${SCHEMA_NAME}.stats WHERE fecha_visita BETWEEN $1 AND $2`;
const values = [startDate.toISOString(), endDate.toISOString()];
const query = `
SELECT
*, EXTRACT(YEAR FROM AGE($3, st.fecha_nacimiento)) as años_edad
FROM ${SCHEMA_NAME}.stats st
WHERE fecha_visita BETWEEN $1 AND $2`;
const values = [
startDate.toISOString(),
endDate.toISOString(),
nowDate.toISOString(),
];
logger.info({ query, values }, "Querying for information: ");
const result = await client.query(query, values);
logger.info({ rowCount: result.rowCount }, "DB query done!");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { describe, expect, test } from "@jest/globals";
import axios from "axios";
import {
createAuthorizationHeader,
createDoctorJWT,
createInvalidJWT,
createPatientJWT,
generateUniqueCUI,
LOCAL_API_URL,
} from "../testHelpers.mjs";

const API_URL = `${LOCAL_API_URL}/patient/create`;

function generateValidUpdate(cui) {
return {
cui,
names: "Juan",
lastNames: "Pérez",
isWoman: false,
birthdate: "1990-01-01",
phone: "55247856",
insurance: "El Roble",
};
}

describe("Create Patient Record Integration Tests", () => {
const validHeaders = createAuthorizationHeader(createPatientJWT());

test("Normal case: Create a new patient record", async () => {
const patientData = generateValidUpdate(generateUniqueCUI());
const response = await axios.post(API_URL, patientData, {
headers: validHeaders,
});

const expectedResponse = expect.any(Number);

expect(response.status).toBe(200);
expect(response.data).toEqual(expectedResponse);
});

test("Create a new patient record without CUI (should fail)", async () => {
const patientData = generateValidUpdate(generateUniqueCUI());
patientData.cui = undefined;

const response = await axios.post(API_URL, patientData, {
headers: validHeaders,
validateStatus: () => true, // So axios doesn't throw an error for status >= 400
});

// Verify the error is as expected
expect(response.status).toBe(400);
expect(response.data.error).toBe("CUI is empty");
});

test("Create a new patient record with duplicate CUI (should fail)", async () => {
const uniqueCUI = generateUniqueCUI();
const patientData1 = {
cui: uniqueCUI,
names: "Juan",
lastNames: "Pérez",
isWoman: false,
birthdate: "1990-01-01",
phone: "55247856",
insurance: "El Roble",
};
const patientData2 = {
cui: uniqueCUI,
names: "Carlos",
lastNames: "González",
isWoman: false,
birthdate: "1985-05-05",
phone: "55247856",
insurance: "El Roble",
};

await axios.post(API_URL, patientData1, { headers: validHeaders });

const response = await axios.post(API_URL, patientData2, {
headers: validHeaders,
validateStatus: () => true, // So axios doesn't throw an error for status >= 400
});

// Verify the error is as expected
expect(response.status).toBe(409);
expect(response.data.error).toBe("CUI already exists.");
});

test("Can't create a new patient with incomplete data", async () => {
const data = {
cui: generateUniqueCUI(),
names: "Juan",
lastNames: "Pérez",
};

const response = await axios.post(API_URL, data, {
validateStatus: () => true,
headers: validHeaders,
});
expect(response.status).toBe(400);
expect(response.data.error).toBe("Gender (isWoman) is required.");
});

test("a doctor can't call the endpoint", async () => {
const postData = generateValidUpdate(generateUniqueCUI());
const specialHeaders = createAuthorizationHeader(createDoctorJWT());

const response = await axios.post(API_URL, postData, {
headers: specialHeaders,
validateStatus: () => true,
});

console.log(response.data);

expect(response.status).toBe(401);
expect(response.data.error).toEqual("Unauthorized, you're a doctor!");
});

test("can't be called by a malformed JWT", async () => {
const postData = generateValidUpdate(generateUniqueCUI());
const specialHeaders = createAuthorizationHeader(createInvalidJWT());

const response = await axios.post(API_URL, postData, {
headers: specialHeaders,
validateStatus: () => true,
});

expect(response.status).toBe(400);
expect(response.data).toEqual({ error: "JWT couldn't be parsed" });
});
});
Loading

0 comments on commit 441b69c

Please sign in to comment.