Skip to content

Servicio de Gestión y Validación de Usuarios para Laab2 y LaabPro

Este servicio consta de funciones para gestionar la validación, creación y asociación de usuarios a cursos o productos, integrándose con los sistemas externos Laab2 y LaabPro.


Archivo

src/api/laab-connection/services/laab-connection.ts


Funcionalidad General del Servicio

El servicio está diseñado para:

  • Validar fechas y condiciones de compra en órdenes.
  • Separar nombres y apellidos de datos de usuario.
  • Construir cuerpos de solicitud para APIs externas.
  • Consultar productos, usuarios y órdenes en base de datos Strapi.
  • Interactuar con APIs de Laab2 y LaabPro para registrar usuarios, obtener cursos y matricular usuarios en cursos.
  • Generar tokens JWT para LaabPro.
  • Gestionar accesos y enrolamientos de usuarios.

Laab Connection Service


Funciones comunes

Método: checkDateValidation

Valida si la fecha proporcionada ya ha pasado.


Método: checkValidations

Verifica que la fecha de inicio sea válida, que el contrato esté firmado (si aplica) y que el pago haya sido exitoso.


Método: separateNameSurnames

Separa el nombre completo en nombre y apellidos.


Método: buildBody

Construye un FormData con los datos del usuario y la compra.


Método: getProductBySKU

Obtiene un producto desde Strapi según su SKU.


Método: getLastOrderByEmailProductSKU

Busca la última orden completada por un usuario para un SKU dado.


Método: getUserByEmail

Busca un usuario en Strapi a partir del email.


Funciones Laab2


Método: checkLaab2UserExists

Comprueba si el usuario existe en la plataforma Laab2.

async checkLaab2UserExists(userData: userData) {
const body = new FormData();
body.append('email', userData.email);
body.append('token', process.env.LAAB_ENCRYPTED_TOKEN || '');
body.append('origen', 'AE');
const data = await laab2HttpClient.postLaab2<{
status: string;
idUser?: string;
}>('usuario/existeAlumno', body, {});
return data;
}

Método: getIdCourseByIdGroup

Obtiene el ID del curso vinculado a un grupo de Laab2.

async getIdCourseByIdGroup(groupId: string): Promise<{
status?: number;
response?: { idCurso: string };
code?: string;
error?: string;
}> {
const data = await laab2HttpClient.get<{
status: number;
response: { idCurso: string };
code: string;
error: string;
}>(`idcursogrp/${groupId}`);
if (data.code === CODES.ko) {
return { status: 400, error: data.error };
} else {
return data;
}
}

Método: checkLaab2UserCourses

Lista los cursos en los que está inscrito un usuario en Laab2.

async checkLaab2UserCourses(userId: string) {
const body = new FormData();
body.append('token', process.env.LAAB_ENCRYPTED_TOKEN || '');
body.append('idLaab2', userId);
const data = await laab2HttpClient.postLaab2<{
status: number;
ListaCursos: { id: string }[];
}>('getusercourses', body, {});
return data;
}

Método: unimedLaab2ApiCall

Realiza la llamada para inscribir al usuario en un curso de Laab2.

async unimedLaab2ApiCall(
name: string,
surnames: string,
userData: userData,
price: number,
discountPercentage: number,
groupId: string,
sku: string,
) {
const headers = {
'Content-Type': 'multipart/form-data',
Authorization: `Laab-oauthtoken ${process.env.LAAB_REGISTER_TOKEN}`,
};
const body = this.buildBody(
name,
surnames,
userData,
price,
discountPercentage,
);
const data = await laab2HttpClient.postLaab2<{
status: string;
message: string;
link: string;
}>(`laab2/registro/3/${groupId}/${sku}/vertical`, body, headers);
return data;
}

Método: manageUserLaab2

Flujo completo de gestión del usuario en Laab2: comprobar existencia, registrar si es necesario y verificar acceso.

async manageUserLaab2(
userData: userData,
name: string,
surnames: string,
groupId: string,
price: number,
discountPercentage: number,
sku: string,
) {
const groupCourseData = await this.getIdCourseByIdGroup(groupId);
if (groupCourseData.status === 400) return groupCourseData;
const courseId = groupCourseData.response.idCurso;
const userExistsData = await this.checkLaab2UserExists(userData);
if (userExistsData.status === CODES.ok) {
const userId = userExistsData.idUser;
const userCourseData = await this.checkLaab2UserCourses(userId);
if (userCourseData.status !== 1002) {
return { status: 500, message: ERROR_CHECKING_ASSOCIATED_COURSES };
}
const isRegistered = userCourseData.ListaCursos.some(
(course) => course.id === courseId,
);
if (isRegistered) {
return {
status: 200,
access_link: `${process.env.LAAB2_URL}laab2/action/accesoAdministrativoAction.php?action=alumno&id_curso=${courseId}&id_usr=${userId}`,
};
}
}
const unimedResponse = await this.unimedLaab2ApiCall(
name,
surnames,
userData,
price,
discountPercentage,
groupId,
sku,
);
if (Array.isArray(unimedResponse)) {
return { status: 500, message: ERROR_REGISTERING_NEW_USER };
}
return { status: 200, access_link: unimedResponse.link };
}

Funciones LaabPro


Método: getRegisteredLaabproUserId

Consulta el ID de usuario en LaabPro por email.

async getRegisteredLaabproUserId(
userData: userData,
): Promise<number | false> {
const laabproUserData = await laabproClient.getLaabpro<{
status: number;
code?: number;
body?: { id: number }[];
}>('local_contentdata_get_users', [
{ name: 'text', value: userData.email },
{ name: 'roleid', value: '3' },
{ name: 'usertoken', value: process.env.LAABPRO_USER_TOKEN },
]);
if (laabproUserData.body.length > 0) {
const userId = laabproUserData.body[0].id;
return userId;
}
return false;
}

Método: createLaabproUser

Crea un nuevo usuario en LaabPro.

async createLaabproUser(
userData: userData,
name: string,
surnames: string,
): Promise<{ status: number; code?: number; body?: { id: number } }> {
const laabproSurnames = surnames || '-';
const laabproUserData = await laabproClient.getLaabpro<{
status: number;
code?: number;
body?: { id: number };
}>('local_servicerefactor_user_create_users', [
{ name: 'firstname', value: name },
{ name: 'lastname', value: laabproSurnames },
{ name: 'dni', value: userData.identificationNumber },
{ name: 'email', value: userData.email },
{ name: 'country', value: userData.mailingAddress.country },
{ name: 'city', value: 'Ciudad' },
{ name: 'roleid', value: '3' },
]);
return laabproUserData;
}

Método: enrolUserInCourse

Matricula al usuario en un curso LaabPro y genera un token de acceso.

async enrolUserInCourse(
email: string,
userId: number,
courseId: number,
groupId: number,
vertical: string,
): Promise<{ status: number; access_link?: string; message?: string }> {
const enrollmentStatus = await laabproClient.getLaabpro<{
status: number;
code: number;
message: string;
body?: [];
}>('local_servicerefactor_enrol_course_group_user', [
{ name: 'userid', value: String(userId) },
{ name: 'courseid', value: String(courseId) },
{ name: 'groupid', value: String(groupId) },
{ name: 'usertoken', value: process.env.LAABPRO_USER_TOKEN },
]);
if (enrollmentStatus.status === 200 || enrollmentStatus.code === 6) {
const studentAccessStatus = await this.laabproGenerateAccessStudent(
email,
vertical,
);
if (studentAccessStatus.status !== 200) {
return studentAccessStatus;
}
return {
status: 200,
access_link: `${process.env.LAABPRO_URL}?token=${encodeURI(btoa(studentAccessStatus.accesstoken))}`,
};
} else {
return {
status: enrollmentStatus.status,
message: enrollmentStatus.message,
};
}
}

Método: craftLaabproJWT

Genera un JWT firmado con clave privada específica de vertical.

craftLaabproJWT(vertical: string): string {
const jwt = require('jsonwebtoken');
const fileSystem = require('graceful-fs');
const verticalDirectory = VERTICALS_DIRECTORIES[vertical];
const PEMROUTE = 'keys/' + verticalDirectory + '/private.pem';
const privateKeyBuffer = fileSystem.readFileSync(PEMROUTE);
const now = Math.floor(Date.now() / 1000);
const expires = now + 300;
const laabproJWT = jwt.sign(
{
kid: process.env.LAABPRO_KID,
aud: LAABPROAUD,
iat: now,
exp: expires,
},
privateKeyBuffer,
{
algorithm: 'RS256',
},
);
return laabproJWT;
}

Método: laabproGenerateAccessStudent

Usa el JWT para obtener el token de acceso para el alumno.

async laabproGenerateAccessStudent(
email: string,
vertical: string,
): Promise<{ status: number; message?: string; accesstoken?: string }> {
const encryptedToken = encodeURI(btoa(this.craftLaabproJWT(vertical)));
const tokenStatus = await laabproClient.getLaabpro<{
status: number;
code: number;
message: string;
body?: { accesstoken: string };
}>('local_servicerefactor_generate_access_student_external', [
{ name: 'token', value: encryptedToken },
{ name: 'email', value: email },
]);
if (tokenStatus.status !== 200) {
return tokenStatus;
}
return {
status: tokenStatus.status,
accesstoken: tokenStatus.body.accesstoken,
};
}

Método: manageUserLaabpro

Orquesta la creación o recuperación de usuario, inscripción y acceso para LaabPro.

async manageUserLaabpro(
userData: userData,
name: string,
surnames: string,
courseId: number,
groupId: number,
vertical: string,
): Promise<{ status: number; message?: string; access_link?: string }> {
const laabproUserData = await this.createLaabproUser(
userData,
name,
surnames,
);
if (laabproUserData.status === 400) {
if (laabproUserData.code === 6) {
const userId = await this.getRegisteredLaabproUserId(userData);
if (!userId) {
return {
status: laabproUserData.status,
message: ERROR_TRYING_GET_USER_ID,
};
}
const enrollmentStatus = await this.enrolUserInCourse(
userData.email,
userId,
courseId,
groupId,
vertical,
);
return enrollmentStatus;
} else {
return {
status: laabproUserData.status,
message: ERROR_CREATING_USER,
};
}
} else {
const userId = laabproUserData.body.id;
const enrollmentStatus = await this.enrolUserInCourse(
userData.email,
userId,
courseId,
groupId,
vertical,
);
return enrollmentStatus;
}
}

Función de gestión global


Método: manageAccessLaab2Laabpro

Decide si la gestión del acceso debe hacerse con Laab2 o LaabPro y ejecuta la lógica correspondiente.

async manageAccessLaab2Laabpro(
userData: userData,
name: string,
surnames: string,
groupId: string,
price: number,
discountPercentage: number,
sku: string,
courseId?: number,
vertical?: string,
) {
if (courseId) {
const userStatus = await this.manageUserLaabpro(
userData,
name,
surnames,
courseId,
Number(groupId),
vertical,
);
return userStatus;
}
const userStatus = await this.manageUserLaab2(
userData,
name,
surnames,
groupId,
price,
discountPercentage,
sku,
);
return userStatus;
}