Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ VITE_URL_MANUAL_USUARIO=<string> # URL del manual de instrucciones para los usua
VITE_URL_MANUAL_ADMIN=<string> # URL del manual de instrucciones para los administradores
VITE_CANT_LIM_DIAGNOSTICOS=<int> # Cantidad de diagnósticos a partir del cual mostrar la advertencia de espacio
VITE_RECAPTCHA_SITE_KEY=<api-key> # Clave de reCAPTCHA para el sitio
VITE_URL_CONDICIONES=<string> # URL al documento que contiene los términos y condiciones de uso de la aplicación
VITE_URL_CONDICIONES=<string> # URL al documento que contiene los términos y condiciones de uso de la aplicación
VITE_AES_KEY=<string> # Clave AES utilizada para encriptar las credenciales
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ VITE_URL_MANUAL_USUARIO=<string> # URL del manual de instrucciones para los
VITE_URL_MANUAL_ADMIN=<string> # URL del manual de instrucciones para los administradores
VITE_CANT_LIM_DIAGNOSTICOS=<int> # Cantidad de diagnósticos a partir del cual mostrar la advertencia de espacio
VITE_URL_CONDICIONES=<string> # URL al documento que contiene los términos y condiciones de uso de la aplicación
VITE_AES_KEY=<string> # Clave AES utilizada para encriptar las credenciales
```

## Ejecución del frontend sin backend
Expand Down
4 changes: 2 additions & 2 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ export const CAMPOS_BIN = [
"derrame", "tepPrevio", "edema", "disautonomicos", "inmovilidad",
"viajeProlongado", "cirugiaReciente", "otraEnfermedad", "soplos"
];

export const CAMPOS_TXT = ["edad", "presionSis", "presionDias", "frecRes",
"frecCard", "so2", "plaquetas", "hemoglobina", "wbc"];
"frecCard", "so2", "plaquetas", "hemoglobina", "wbc"];
export const AES_KEY = import.meta.env.VITE_CLAVE_AES;
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@mui/x-date-pickers": "^8.5.3",
"babel-jest": "^29.7.0",
"babel-preset-vite": "^1.1.3",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"firebase": "^11.9.1",
"i18next": "^25.5.2",
Expand Down
5 changes: 4 additions & 1 deletion src/components/menu/MenuUsuario.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import CloseIcon from "@mui/icons-material/Close";
import dayjs from "dayjs";
import { Timestamp } from "firebase/firestore";
import { useTranslation } from "react-i18next";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Menú principal para los usuarios. Muestra la cantidad de pacientes y diagnósticos registrados este mes y
Expand Down Expand Up @@ -73,7 +75,8 @@ export default function MenuUsuario() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
8 changes: 5 additions & 3 deletions src/contexts/AuthContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { onAuthStateChanged, signInWithPopup, GoogleAuthProvider } from "firebas
import { verUsuario } from "../firestore/usuarios-collection";
import { cambiarUsuario, verSiEstaRegistrado } from "../firestore/usuarios-collection";
import { FirebaseError } from "firebase/app";
import { CODIGO_ADMIN } from "../../constants";
import { AES_KEY, CODIGO_ADMIN } from "../../constants";
import { useTranslation } from "react-i18next";
import { AES, enc } from "crypto-js";

export const authContext = createContext();

Expand Down Expand Up @@ -332,7 +333,7 @@ export function AuthProvider({ children }) {
const valores = sessionStorage.getItem("session-tokens");

if (valores != null) {
const tokens = JSON.parse(valores);
const tokens = JSON.parse(AES.decrypt(valores, AES_KEY).toString(enc.Utf8));
setTokenDrive(tokens.accessToken);
verificarPermisos(tokens.scopesDrive, scopes);

Expand All @@ -356,7 +357,8 @@ export function AuthProvider({ children }) {
* @param {JSON} tokens - Credenciales OAuth de Google.
*/
const guardarAuthCredsSesion = (tokens) => {
sessionStorage.setItem("session-tokens", JSON.stringify(tokens));
const res = AES.encrypt(JSON.stringify(tokens), AES_KEY).toString();
sessionStorage.setItem("session-tokens", res);
};

/**
Expand Down
20 changes: 11 additions & 9 deletions src/contexts/CredencialesContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { createContext, useState, useContext, useEffect } from "react";
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { API_URL, ENTORNO } from "../../constants";
import { AES_KEY, API_URL, ENTORNO } from "../../constants";
import Cookies from "js-cookie";
import { AES, enc } from "crypto-js";

export const credencialesContext = createContext();

Expand All @@ -23,7 +24,7 @@ export const useCredenciales = () => {
* Proveedor del contexto que permite gestionar las credenciales de Firebase
* de la aplicación.
* @param {JSX.Element} children
* @returns JSX.Element
* @returns {JSX.Element}
*/
export function CredencialesProvider({ children }) {

Expand Down Expand Up @@ -128,22 +129,23 @@ export function CredencialesProvider({ children }) {
* @param {Array} scopes - Scopes de acceso a Google Drive.
*/
const almacenarCredenciales = (firebaseCreds, scopes) => {
Cookies.set("session-credentials", JSON.stringify(firebaseCreds));
const json = AES.encrypt(JSON.stringify(firebaseCreds), AES_KEY).toString();
Cookies.set("session-credentials", json);
Cookies.set("session-drive-scopes", scopes);
};

/**
* Carga las credenciales de los servicios desde las cookies.
* Devuelve el resultado de las operación.
* @returns Boolean
* @returns {Boolean}
*/
const cargarCredsCookies = () => {
const firebaseCreds = Cookies.get("session-credentials");
const driveScopes = Cookies.get("session-drive-scopes");
let res = (firebaseCreds != undefined && firebaseCreds != null);

if (res && (driveScopes != undefined && driveScopes != null)) {
const creds = JSON.parse(firebaseCreds);
const creds = JSON.parse(AES.decrypt(firebaseCreds, AES_KEY).toString(enc.Utf8));

setScopesDrive(driveScopes.split(","));
setCredsInfo((x) => ({ ...x, ...creds }));
Expand All @@ -160,31 +162,31 @@ export function CredencialesProvider({ children }) {

/**
* Obtiene la instancia de Firestore.
* @returns Object
* @returns {Object}
*/
const obtenerInstanciaDB = () => {
return credsInfo.db;
};

/**
* Obtiene la instancia de autenticación de Firebase.
* @returns Object
* @returns {Object}
*/
const obtenerInstanciaAuth = () => {
return credsInfo.auth;
};

/**
* Verificar si las credenciales de Firebase están cargadas.
* @returns Boolean
* @returns {Boolean}
*/
const verSiCredsFirebaseEstancargadas = () => {
return credsInfo.app != null && credsInfo.db != null && credsInfo.auth != null;
};

/**
* Obtiene la clave de reCAPTCHA de las credenciales.
* @returns String
* @returns {String}
*/
const obtenerRecaptcha = () => {
return credsInfo.reCAPTCHA;
Expand Down
7 changes: 6 additions & 1 deletion src/pages/diagnosticos/DiagnosticoPacientePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import ModalSimple from "../../components/modals/ModalSimple";
import CloseIcon from "@mui/icons-material/Close";
import { useTranslation } from "react-i18next";
import { useNavegacion } from "../../contexts/NavegacionContext";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para realizar un diagnóstico de TEP al paciente.
* @returns {JSX.Element}
Expand All @@ -28,12 +31,14 @@ export default function DiagnosticoPacientePage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
}, [auth.tokenDrive]);


/**
* Actualizando los datos de los pacientes cuando son descargados.
*/
Expand Down
6 changes: 4 additions & 2 deletions src/pages/diagnosticos/VerDiagnosticoPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import { peticionApi } from "../../services/Api";
import { ChipDiagnostico, ChipSexo, ChipValidado } from "../../components/tabs/Chips";
import ContLime from "../../components/diagnosticos/ContLime";
import { useTranslation } from "react-i18next";
import { DatosIcono } from "../../components/icons/IconosSidebar";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para ver los datos de un diagnóstico.
Expand Down Expand Up @@ -137,7 +138,8 @@ export default function VerDiagnosticoPage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/diagnosticos/VerDiagnosticosPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import AdvertenciaEspacio from "../../components/menu/AdvertenciaEspacio";
import CloseIcon from "@mui/icons-material/Close";
import { ChipDiagnostico, ChipValidado, ChipSexo } from "../../components/tabs/Chips";
import { useTranslation } from "react-i18next";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para ver los diagnósticos del usuario.
Expand Down Expand Up @@ -131,7 +133,8 @@ export default function VerDiagnosticosPage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
6 changes: 4 additions & 2 deletions src/pages/pacientes/AnadirPacientePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import FormPaciente from "../../components/forms/FormPaciente";
import MenuLayout from "../../components/layout/MenuLayout";
import { useTranslation } from "react-i18next";
import { useNavegacion } from "../../contexts/NavegacionContext";

import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";
/**
* Página para añadir un nuevo paciente al sistema.
* @returns {JSX.Element}
Expand All @@ -26,7 +27,8 @@ export default function AnadirPacientePage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null && drive.token == null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/pacientes/EditarPacientePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { useNavigate, useSearchParams } from "react-router";
import { validarId } from "../../utils/Validadores";
import { useTranslation } from "react-i18next";
import { useNavegacion } from "../../contexts/NavegacionContext";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para editar los datos de un paciente.
Expand All @@ -31,7 +33,8 @@ export default function EditarPacientePage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/pacientes/VerPacientePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import ModalAccion from "../../components/modals/ModalAccion";
import ContComorbilidades from "../../components/diagnosticos/ContComorbilidades";
import { ChipSexo } from "../../components/tabs/Chips";
import { useTranslation } from "react-i18next";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para ver los datos de un paciente.
Expand Down Expand Up @@ -73,7 +75,8 @@ export default function VerPacientePage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/pacientes/VerPacientesPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import customParseFormat from "dayjs/plugin/customParseFormat";
import RefreshIcon from "@mui/icons-material/Refresh";
import CloseIcon from "@mui/icons-material/Close";
import { ChipSexo } from "../../components/tabs/Chips";
import { AES, enc } from "crypto-js";
import { AES_KEY } from "../../../constants";

/**
* Página para ver la lista de pacientes.
Expand Down Expand Up @@ -51,7 +53,8 @@ export default function VerPacientesPage() {
useEffect(() => {
const token = sessionStorage.getItem("session-tokens");
if (token != null) {
drive.setToken(JSON.parse(token).accessToken);
const tokens = JSON.parse(AES.decrypt(token, AES_KEY).toString(enc.Utf8));
drive.setToken(tokens.accessToken);
} else if (auth.tokenDrive != null) {
drive.setToken(auth.tokenDrive);
}
Expand Down