0% encontró este documento útil (0 votos)
81 vistas50 páginas

Desarrollo de API REST en Node.js

Guía completa
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
81 vistas50 páginas

Desarrollo de API REST en Node.js

Guía completa
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

2024

API REST Cursos y Usuarios

Víctor Vladimir Cortés Arévalo


SENA CEET
3-9-2024
CONTENIDO

INTRODUCCIÓN AL MANUAL DE DESARROLLO DE UNA API REST EN [Link]


2
CAPA DE MODELOS 5
Modelo Curso (`curso_model.js`) 5
Modelo Usuario (`usuario_model.js`) 6
CAPA DE LÓGICA DE NEGOCIO 9
Lógica de Cursos (`curso_logic.js`) 9
Lógica de Usuarios (`usuario_logic.js`) 13
CAPA DE VALIDACIONES DE LOS MODELOS 19
Validaciones para el Modelo Curso (`curso_validation.js`) 19
Validaciones para el Modelo Usuario (`usuario_validation.js`) 22
CAPA DE CONTROLADORES 26
Ejemplo de Controladores 27
Controladores de Cursos (`cursos_controller.js`) 27
Controladores de Usuarios (`usuarios_controller.js`) 33
CAPA DE RUTAS 38
Rutas de Cursos (`cursos_routes.js`) 38
Rutas de Usuarios (`usuarios_routes.js`) 40
Integración de las Rutas en la Aplicación 43
PRUEBAS DE LOS END POINTS 45
Pasos para Probar los Endpoints con Postman 45

Página 1 de 49
INTRODUCCIÓN AL MANUAL DE DESARROLLO DE UNA API REST EN [Link]

En la era digital actual, las aplicaciones web y móviles dependen en gran medida de la capacidad

de comunicarse y compartir datos de manera eficiente. Una de las formas más efectivas de lograr

esto es a través de las APIs (Interfaces de Programación de Aplicaciones). Este manual

se centra en el desarrollo de una API REST (Representational State Transfer) utilizando

[Link], un entorno de ejecución de JavaScript que permite construir aplicaciones escalables y

de alto rendimiento.

¿Qué es una API REST?

Una API REST es un conjunto de reglas y convenciones que permiten la comunicación entre

diferentes sistemas a través de la web. Utiliza los métodos HTTP (GET, POST, PUT, DELETE)

para realizar operaciones sobre los recursos, que se representan en formato JSON o XML. Las

APIs REST son ampliamente utilizadas debido a su simplicidad, flexibilidad y capacidad para

integrarse con diversas plataformas y lenguajes de programación. Al seguir los principios REST,

se logra una arquitectura que es fácil de entender y utilizar, facilitando la interoperabilidad entre

diferentes servicios.

Arquitectura de Software Utilizada

Para el desarrollo de esta API REST, se ha adoptado una arquitectura basada en **MVC

(Modelo-Vista-Controlador)**. Esta arquitectura permite separar las responsabilidades en

diferentes capas, lo que resulta en un código más limpio y mantenible. En este enfoque:

Modelo: Representa la lógica de negocio y la interacción con la base de datos. Aquí se


definen los esquemas y las operaciones CRUD (Crear, Leer, Actualizar, Eliminar).
Vista: En el contexto de una API, la vista se refiere a la representación de los datos que se
envían al cliente. En este caso, se utilizarán formatos como JSON para las respuestas.
Controlador: Actúa como intermediario entre el modelo y la vista. Los controladores
manejan las solicitudes HTTP, realizan las validaciones necesarias y llaman a la lógica de
negocio para procesar los datos.

Página 2 de 49
Estructura General del Proyecto

El proyecto está organizado de manera modular para facilitar su comprensión y mantenimiento.


A continuación, se describe la estructura general del proyecto:

/models: Contiene los modelos de datos, donde se definen los esquemas de las
entidades (por ejemplo, `curso_model.js` y `usuario_model.js`).
/logic: Incluye la lógica de negocio, donde se implementan las funciones que
interactúan con los modelos y realizan las operaciones necesarias (por ejemplo,
`curso_logic.js` y `usuario_logic.js`).
/validations: Contiene los esquemas de validación que aseguran que los datos de
entrada cumplan con las reglas definidas (por ejemplo, `curso_validation.js` y
`usuario_validation.js`).
/controllers: Incluye los controladores que manejan las solicitudes HTTP y responden
a los clientes (por ejemplo, `cursos_controller.js` y `usuarios_controller.js`).
/routes: Define las rutas de la API, donde se mapean las solicitudes a los controladores
correspondientes (por ejemplo, `cursos_routes.js` y `usuarios_routes.js`).
/tests: (opcional) Contiene pruebas automatizadas para verificar el correcto
funcionamiento de la API.

Este manual proporciona una guía paso a paso para el desarrollo de una API REST en [Link],

desde la configuración inicial hasta la implementación de funcionalidades avanzadas. A lo largo

de este documento, se explorarán las mejores prácticas y se ofrecerán ejemplos claros para

facilitar el aprendizaje y la implementación. Al finalizar, los desarrolladores estarán equipados

con las herramientas necesarias para construir y mantener una API REST robusta y eficiente.

Página 3 de 49
Ilustración 1Estructura general del proyecto

Página 4 de 49
CAPA DE MODELOS

La capa de modelos en una aplicación que utiliza una arquitectura de API REST es responsable

de definir la estructura de los datos que se van a almacenar en la base de datos. Esta capa actúa

como una representación de las entidades del dominio de la aplicación y se encarga de la

interacción con la base de datos, permitiendo realizar operaciones como crear, leer, actualizar y

eliminar (CRUD) registros. En el contexto de una API REST desarrollada con [Link] y Mongoose

(una biblioteca de modelado de objetos MongoDB), los modelos se definen utilizando esquemas

que especifican los campos, tipos de datos y validaciones necesarias para cada entidad.

npm install mongoose

Modelo Curso (`curso_model.js`)

El modelo Curso define la estructura de los datos relacionados con los cursos ofrecidos en la

aplicación. Este esquema incluye los siguientes campos:

título: Un campo de tipo `String` que es obligatorio y representa el título del curso.
descripción: Un campo de tipo `String` que es opcional y proporciona una descripción
del curso.
estado: Un campo de tipo `Boolean` que indica si el curso está activo o no, con un valor
predeterminado de `true`.
imagen: Un campo de tipo `String` que es opcional y puede almacenar la URL de una
imagen relacionada con el curso.
alumnos: Un campo de tipo `Number` que cuenta la cantidad de alumnos inscritos en
el curso, con un valor predeterminado de `0`.
calificación: Un campo de tipo `Number` que representa la calificación promedio del
curso, con un valor predeterminado de `0`.

Este modelo permite gestionar la información de los cursos de manera estructurada y facilita la

realización de operaciones CRUD a través de la API.

Página 5 de 49
Curso_model.js
const mongoose = require('mongoose');

const cursoSchema = new [Link]({


titulo: {
type:String,
required: true
},
descripcion: {
type:String,
required:false
},
estado: {
type: Boolean,
default: true
},
imagen: {
type: String,
required: false
},
alumnos: {
type: Number,
default: 0
},
calificacion: {
type: Number,
default: 0
}
});

[Link] = [Link]('Curso', cursoSchema);

Modelo Usuario (`usuario_model.js`)

El modelo Usuario define la estructura de los datos relacionados con los usuarios de la

aplicación. Este esquema incluye los siguientes campos:

email: Un campo de tipo `String` que es obligatorio y almacena la dirección de correo


electrónico del usuario.
nombre: Un campo de tipo `String` que es obligatorio y representa el nombre del
usuario.
password: Un campo de tipo `String` que es obligatorio y almacena la contraseña del
usuario, la cual debe ser gestionada de manera segura.

Página 6 de 49
estado: Un campo de tipo `Boolean` que indica si el usuario está activo o no, con un valor
predeterminado de `true`.
imagen: Un campo de tipo `String` que es opcional y puede almacenar la URL de una
imagen de perfil del usuario.
cursos: Un campo que es un arreglo de identificadores de objetos (`ObjectId`) que
referencia a los cursos que el usuario ha inscrito. Este campo es opcional y permite
establecer una relación entre usuarios y cursos.

Este modelo permite gestionar la información de los usuarios de manera eficiente y establece

relaciones con los cursos, facilitando la administración de inscripciones y la interacción entre las

entidades de la aplicación.

usuario_model.js
const mongoose = require('mongoose');

const usuarioSchema = new [Link]({


email: {
type:String,
required: true
},
nombre: {
type:String,
required:true
},
password: {
type:String,
required: true
},
estado: {
type: Boolean,
default: true
},
imagen: {
type: String,
required: false
},
cursos: [{
type: [Link],
ref: 'Curso', // Referencia al modelo Curso
required:false
}]
});

Página 7 de 49
[Link] = [Link]('Usuario', usuarioSchema);

Página 8 de 49
CAPA DE LÓGICA DE NEGOCIO

La capa de lógica de la API REST es responsable de contener la lógica de negocio y las operaciones

que se realizan sobre los modelos de datos. Esta capa actúa como intermediaria entre la capa de

presentación (controladores) y la capa de datos (modelos). A continuación, se proporciona una

descripción de las funciones clave en los archivos `curso_logic.js` y `usuario_logic.js`, que

manejan la lógica relacionada con cursos y usuarios, respectivamente.

Lógica de Cursos (`curso_logic.js`)

1. crearCurso(body):

Esta función crea un nuevo curso. Primero, verifica si ya existe un curso con el
mismo título. Si no existe, crea un nuevo objeto de curso y lo guarda en la base de
datos.

2. actualizarCurso(id, body):

Permite actualizar los detalles de un curso existente. Busca el curso por su ID y


actualiza los campos especificados en el cuerpo de la solicitud.

3. desactivarCurso(id):

Esta función inactiva un curso cambiando su estado a `false`. Busca el curso por
su ID y actualiza su estado.

4. listarCursosActivos():

Devuelve una lista de todos los cursos que están activos (estado `true`). Utiliza una
consulta a la base de datos para obtener estos cursos.

5. guardarCursos(cursos):

Permite guardar una colección de cursos. Verifica si cada curso ya existe antes de
intentar guardarlo, evitando duplicados.

6. buscarCursoPorId(id):

Busca un curso por su ID. Si no se encuentra, lanza un error indicando que el curso
no fue encontrado.

Página 9 de 49
7. buscarUsuariosPorCurso(id):

Busca usuarios que estén asociados a un curso específico. Utiliza la función de


`populate` para obtener detalles de los cursos relacionados.

const Curso = require('../models/curso_model');


const Usuario = require('../models/usuario_model');

// Función asíncrona para crear cursos


async function crearCurso(body){

// Verificar si ya existe un curso con el mismo título


const cursoExistente = await [Link]({ titulo: [Link] });
if (cursoExistente) {
throw new Error('El curso con este título ya existe');
}

let curso = new Curso({


titulo : [Link],
descripcion : [Link],
estado: [Link],
imagen: [Link],
alumnos : [Link],
calificacion : [Link]
});
return await [Link]();
}

// Función asíncrona para actualizar cursos


async function actualizarCurso(id, body){
let curso = await [Link](id, {
$set: {
titulo: [Link],
descripcion: [Link],
estado: [Link],
imagen: [Link],
alumnos : [Link],
calificacion : [Link]
}
}, {new: true});
return curso;
}

Página 10 de 49
// Función asíncrona para inactivar cursos
async function desactivarCurso(id){
let curso = await [Link](id, {
$set: {
estado: false
}
}, {new: true});
return curso;
}

// Función asíncrona para listar los cursos activos


async function listarCursosActivos(){
let cursos = await [Link]({"estado": true});
return cursos;
}

// Función asíncrona para guardar una colección de cursos


async function guardarCursos(cursos) {
try {
const resultados = [];

for (let cursoData of cursos) {


// Verificar si ya existe un curso con el mismo título
const cursoExistente = await [Link]({ titulo: [Link] });
if (!cursoExistente) {
let nuevoCurso = new Curso(cursoData);
let cursoGuardado = await [Link]();
[Link](cursoGuardado);
} else {
[Link](`El curso con título "${[Link]}" ya existe.`);
}
}

return resultados;
} catch (err) {
[Link]('Error al guardar la colección de cursos:', err);
throw err; // Re-lanza el error para manejarlo en la capa superior si es necesario
}
}

// Función asíncrona para buscar un curso por su ID


async function buscarCursoPorId(id) {
try {
const curso = await [Link](id);

Página 11 de 49
if (!curso) {
throw new Error(`Curso con ID ${id} no encontrado`);
}

return curso;
} catch (err) {
[Link](`Error al buscar el curso por ID: ${[Link]}`);
throw err;
}
}

// Función asíncrona para buscar usuarios asociados a un curso


async function buscarUsuariosPorCurso(id) {
try {
// Buscar usuarios que tengan el curso en su lista de cursos y hacer populate del campo
cursos
const usuarios = await [Link]({ cursos: id }).populate('cursos', 'titulo');

if (!usuarios || [Link] === 0) {


throw new Error(`No se encontraron usuarios asociados al curso con ID ${id}`);
}

// Procesar los resultados para devolver solo los títulos de los cursos
const usuariosConCursos = [Link](usuario => {
return {
_id: usuario._id,
email: [Link],
nombre: [Link],
password: [Link],
estado: [Link],
//cursos: [Link](curso => [Link]), // Solo incluye el título de cada
curso
__v: usuario.__v
};
});

return usuariosConCursos;
} catch (err) {
[Link](`Error al buscar usuarios por curso: ${[Link]}`);
throw err;
}
}

[Link] = {

Página 12 de 49
crearCurso,
actualizarCurso,
desactivarCurso,
listarCursosActivos,
guardarCursos,
buscarCursoPorId,
buscarUsuariosPorCurso
}

Lógica de Usuarios (`usuario_logic.js`)

1. crearUsuario(body):

Crea un nuevo usuario después de verificar que el correo electrónico no esté ya


registrado. Si el correo ya existe, lanza un error.

2. actualizarUsuario(email, body):

Actualiza la información de un usuario existente. Permite agregar nuevos cursos al


array de cursos del usuario y actualiza otros campos según sea necesario.

3. desactivarUsuario(email):

Inactiva un usuario cambiando su estado a `false`. Busca el usuario por su correo


electrónico.

4. listarUsuarioActivos():

Devuelve una lista de todos los usuarios activos. Utiliza `populate` para incluir
información sobre los cursos asociados a cada usuario.

5. agregarCursosAUsuario(email, cursosIds):

Permite agregar uno o varios cursos a un usuario. Filtra los cursos ya existentes
para evitar duplicados.

6. guardarColeccionUsuarios(usuarios):

Guarda una colección de usuarios. Verifica si cada usuario ya existe antes de


intentar guardarlo.

7. listarCursosDeUsuario(usuarioId):

Página 13 de 49
Busca un usuario por su ID y devuelve la lista de cursos asociados a ese usuario,
utilizando `populate` para obtener detalles de los cursos.

const Usuario = require('../models/usuario_model');


const Curso = require('../models/curso_model');

// Función asíncrona para crear un objeto de tipo usuario


async function crearUsuario(body){

// Verificar si el email ya está registrado


const usuarioExistente = await [Link]({ email: [Link] });

if (usuarioExistente) {
throw new Error('El correo electrónico ya está registrado');
}

let usuario = new Usuario({


email : [Link],
nombre : [Link],
password : [Link],
imagen : [Link],
});
return await [Link]();
}

// Función asíncrona para actualizar un usuario y agregar cursos al array de cursos


async function actualizarUsuario(email, body) {
let usuario = await [Link]({"email": email});

if (!usuario) {
throw new Error('Usuario no encontrado');
}

// Verificar si hay cursos para agregar


if ([Link] && [Link] > 0) {
// Filtrar los cursos que ya están en el array para evitar duplicados
const nuevosCursos = [Link](cursoId => ![Link](cursoId));
// Agregar los nuevos cursos al array de cursos del usuario
[Link](...nuevosCursos);
}

// Actualizar los demás campos

Página 14 de 49
[Link] = [Link] || [Link];
[Link] = [Link] || [Link];
[Link] = [Link] !== undefined ? [Link] : [Link];
[Link] = [Link] || [Link];

// Guardar los cambios en la base de datos


await [Link]();

return usuario;
}

//Función asíncrona para inactivar un usuario


async function desactivarUsuario(email){
let usuario = await [Link]({"email": email}, {
$set: {
estado: false
}
}, {new: true});
return usuario;
}

//Función asíncrona para listar todos los usuarios activos


async function listarUsuarioActivos(){

let usuarios = await [Link]({ "estado": true }).populate({


path: 'cursos',
select: 'titulo' // Selecciona solo el campo 'titulo' del curso
});

// Mapea los usuarios para devolver solo los títulos de los cursos
usuarios = [Link](usuario => {
const cursosSoloTitulos = [Link](curso => [Link]);
return {
_id: usuario._id,
email: [Link],
nombre: [Link],
password: [Link],
estado: [Link],
imagen: [Link],
cursos: cursosSoloTitulos, // Reemplaza los cursos con solo los títulos
__v: usuario.__v
};
});

Página 15 de 49
return usuarios;
}

// Agregar uno o varios cursos a un usuario


async function agregarCursosAUsuario(email, cursosIds) {
try {
const usuario = await [Link]({ email });

if (!usuario) {
throw new Error('Usuario no encontrado');
}

// Filtrar los cursos ya existentes para no duplicarlos


const nuevosCursos = [Link](cursoId => ![Link](cursoId));

// Agregar los nuevos cursos al array de cursos del usuario


[Link] = [...[Link], ...nuevosCursos];

await [Link]();

return usuario;
} catch (error) {
throw new Error(`Error al agregar cursos: ${[Link]}`);
}
}

// Función asíncrona para guardar una colección de usuarios


async function guardarColeccionUsuarios(usuarios) {
try {
const resultados = [];

for (let usuarioData of usuarios) {


// Verificar si el email ya está registrado
const usuarioExistente = await [Link]({ email: [Link] });

if (!usuarioExistente) {
let nuevoUsuario = new Usuario({
email: [Link],
nombre: [Link],
password: [Link],
estado: [Link] !== undefined ? [Link] : true,
imagen: [Link] || null,
cursos: [Link] || []

Página 16 de 49
});
let usuarioGuardado = await [Link]();
[Link](usuarioGuardado);
} else {
[Link](`El correo electrónico "${[Link]}" ya está registrado.`);
}
}

return resultados;
} catch (err) {
[Link]('Error al guardar la colección de usuarios:', err);
throw err; // Re-lanza el error para manejarlo en la capa superior si es necesario
}
}

// Función para listar los cursos de un usuario en la capa de lógica


async function listarCursosDeUsuario(usuarioId) {
try {
// Buscar al usuario por su ID y popular el campo 'cursos' con los detalles de los cursos
const usuario = await [Link](usuarioId).populate('cursos');

if (!usuario) {
throw new Error('Usuario no encontrado');
}

// Retornar la lista de cursos


return [Link];
} catch (error) {
throw new Error(`Error al listar los cursos del usuario: ${[Link]}`);
}
}

[Link] = {
agregarCursosAUsuario,
listarCursosDeUsuario,
crearUsuario,
actualizarUsuario,
desactivarUsuario,
listarUsuarioActivos,
guardarColeccionUsuarios

Página 17 de 49
}

La capa de lógica es fundamental para mantener la separación de preocupaciones en la

arquitectura de la API REST. A través de estas funciones, se garantiza que la lógica de negocio se

maneje de manera eficiente y se interactúe correctamente con los modelos de datos. Esto permite

que la aplicación sea más mantenible, escalable y fácil de entender.

Página 18 de 49
CAPA DE VALIDACIONES DE LOS MODELOS

La capa de validaciones es responsable de definir las reglas y restricciones que deben cumplir los

datos antes de ser procesados por la aplicación. Esto ayuda a garantizar la integridad y calidad de

los datos, evitando errores y manteniendo la coherencia de la información almacenada en la base

de datos.

En el contexto de la API REST desarrollada con [Link], se utilizan esquemas de validación

definidos con la biblioteca Joi para validar los datos de entrada antes de interactuar con los

modelos de datos.

npm install joi

Validaciones para el Modelo Curso (`curso_validation.js`)

El esquema de validación para el modelo `Curso` define las siguientes reglas:

título: Debe ser un string, tener al menos 3 caracteres y un máximo de 100 caracteres.
Debe contener solo letras (mayúsculas y minúsculas), números, espacios, y los caracteres
`.`, `#` y `-`. Es un campo requerido.

descripción: Debe ser un string, con un máximo de 500 caracteres. Puede estar vacío.
Debe contener solo letras (mayúsculas y minúsculas), números, espacios, y los caracteres
`.`, `#` y `-`.

estado: Debe ser un valor booleano. Si no se proporciona, se establece como `true` por
defecto.

imagen: Debe ser una URL válida en formato `http` o `https`. Puede estar vacío. Debe
seguir el patrón de una URL válida.

alumnos: Debe ser un número entero, con un valor mínimo de 0. Si no se proporciona,


se establece como 0 por defecto.

Página 19 de 49
calificación: Debe ser un número entre 0 y 5. Si no se proporciona, se establece como 0
por defecto.

Página 20 de 49
Curso_validations.js

// validaciones/[Link]
const Joi = require('@hapi/joi');

//Validaciones para el objeto curso

const cursoSchemaValidation = [Link]({


titulo: [Link]()
.min(3)
.max(100)
.required()
.pattern(/^[A-Za-záéíóúÁÉÍÓÚñÑ0-9 .#-]{3,100}$/)
.messages({
'[Link]': 'El título debe ser un texto',
'[Link]': 'El título no puede estar vacío',
'[Link]': 'El título debe tener al menos 3 caracteres',
'[Link]': 'El título no debe exceder los 100 caracteres',
'[Link]': 'El título es un campo requerido'
}),

descripcion: [Link]()
.max(500)
.optional()
.allow('')
.pattern(/^[A-Za-záéíóúÁÉÍÓÚñÑ0-9 .#-]{3,500}$/)
.messages({
'[Link]': 'La descripción debe ser un texto',
'[Link]': 'La descripción no debe exceder los 500 caracteres'
}),

estado: [Link]()
.default(true)
.messages({
'[Link]': 'El estado debe ser un valor booleano'
}),

imagen: [Link]()
.uri()
.optional()
.allow('')
.pattern(/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-z]{2,}([\/\w \.-]*)*\/?$/)
.messages({
'[Link]': 'La imagen debe ser una URL válida',
'[Link]': 'La imagen debe tener un formato de URL válido'

Página 21 de 49
}),

alumnos: [Link]()
.integer()
.min(0)
.default(0)
.messages({
'[Link]': 'El número de alumnos debe ser un número',
'[Link]': 'El número de alumnos debe ser un entero',
'[Link]': 'El número de alumnos no puede ser negativo'
}),

calificacion: [Link]()
.min(0)
.max(5)
.default(0)
.messages({
'[Link]': 'La calificación debe ser un número',
'[Link]': 'La calificación no puede ser menor que 0',
'[Link]': 'La calificación no puede ser mayor que 5'
})
});

[Link] = { cursoSchemaValidation };

Validaciones para el Modelo Usuario (`usuario_validation.js`)

El esquema de validación para el modelo `Usuario` define las siguientes reglas:

email: Debe ser un string con formato de correo electrónico válido (al menos dos
segmentos de dominio y dominios TLD permitidos: `com`, `net`, `edu`, `co`). Es un
campo requerido.

nombre: Debe ser un string, tener al menos 3 caracteres y un máximo de 30 caracteres.


Debe contener solo letras (mayúsculas y minúsculas) y espacios. Es un campo requerido.

password: Debe ser un string, tener al menos 6 caracteres y un máximo de 30 caracteres.


Debe contener solo letras (mayúsculas y minúsculas), números y caracteres especiales. Es
un campo requerido.

estado: Debe ser un valor booleano. Si no se proporciona, se establece como `true` por
defecto.

imagen: Debe ser una URL válida en formato `http` o `https`. Puede estar vacío. Debe
seguir el patrón de una URL válida.

Página 22 de 49
cursos: Debe ser un array que contiene solo ObjectId válidos de MongoDB (24 caracteres
hexadecimales). Puede estar vacío.

Usuario_validation.js

const Joi = require("@hapi/joi");

// Validaciones para el objeto usuario


const usuarioSchemaValidation = [Link]({

email: [Link]()
.email({ minDomainSegments: 2, tlds: { allow: ['com', 'net', 'edu', 'co'] } })
.required()
.messages({
'[Link]': 'El correo electrónico debe ser un texto',
'[Link]': 'El correo electrónico no puede estar vacío',
'[Link]': 'El correo electrónico debe tener un formato válido',
'[Link]': 'El correo electrónico es un campo requerido'
}),

nombre: [Link]()
.min(3)
.max(30)
.required()
.pattern(/^[A-Za-záéíóúÁÉÍÓÚñÑ ]+$/)
.messages({
'[Link]': 'El nombre debe ser un texto',
'[Link]': 'El nombre no puede estar vacío',
'[Link]': 'El nombre debe tener al menos 3 caracteres',
'[Link]': 'El nombre no debe exceder los 30 caracteres',
'[Link]': 'El nombre solo puede contener letras y espacios',
'[Link]': 'El nombre es un campo requerido'
}),

password: [Link]()
.min(6)
.max(30)
.required()
.pattern(/^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]{6,30}$/)
.messages({
'[Link]': 'La contraseña debe ser un texto',
'[Link]': 'La contraseña no puede estar vacía',
'[Link]': 'La contraseña debe tener al menos 6 caracteres',
'[Link]': 'La contraseña no debe exceder los 30 caracteres',

Página 23 de 49
'[Link]': 'La contraseña solo puede contener letras, números y caracteres
especiales',
'[Link]': 'La contraseña es un campo requerido'
}),

estado: [Link]()
.default(true)
.messages({
'[Link]': 'El estado debe ser un valor booleano'
}),

imagen: [Link]()
.uri()
.optional()
.allow('')
.pattern(/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-z]{2,}([\/\w \.-]*)*\/?$/)
.messages({
'[Link]': 'La imagen debe ser una URL válida',
'[Link]': 'La imagen debe tener un formato de URL válido'
}),

cursos: [Link]()
.items([Link]().pattern(/^[0-9a-fA-F]{24}$/)) // Validación de un array de ObjectId (24
caracteres hexadecimales)
.optional()
.messages({
'[Link]': 'Cursos debe ser un array',
'[Link]': 'Cada curso debe ser un ID de MongoDB válido (24 caracteres
hexadecimales)'
}),
});

[Link] = { usuarioSchemaValidation };

La capa de validaciones es fundamental para garantizar la calidad de los datos en la API REST. Al

definir reglas claras y específicas para cada campo, se evitan errores y se mantiene la integridad

de la información almacenada en la base de datos. Estas validaciones se aplican antes de

interactuar con los modelos de datos, lo que permite una gestión eficiente y segura de los recursos

de la aplicación.

Página 24 de 49
Página 25 de 49
CAPA DE CONTROLADORES

La capa de controladores en una API REST es responsable de recibir las solicitudes del cliente,

interactuar con la lógica de negocio, realizar las validaciones necesarias y devolver las respuestas

adecuadas. Los controladores actúan como intermediarios entre la capa de presentación (como

las rutas) y la lógica de negocio (funciones definidas en la capa de lógica). Esta separación de

responsabilidades permite una mejor organización y mantenimiento del código.

Relación entre Controladores, Lógica, Validaciones y Modelos

1. Controladores:

Reciben las solicitudes HTTP y extraen los datos necesarios del cuerpo de la solicitud

(request body) o de los parámetros de la URL.

Llaman a las funciones de la capa de lógica para realizar operaciones específicas (como

crear, actualizar o listar recursos).

Manejan las respuestas, incluyendo el manejo de errores y la validación de datos.

2. Lógica:

Contiene la lógica de negocio y las operaciones CRUD (Crear, Leer, Actualizar,

Eliminar) sobre los modelos.

Se encarga de interactuar con la base de datos a través de los modelos y aplicar la lógica

necesaria para cumplir con los requisitos de la aplicación.

3. Validaciones:

Se utilizan para validar los datos de entrada antes de que sean procesados por la lógica.

Aseguran que los datos cumplan con las reglas definidas (por ejemplo, formatos, tipos

de datos, etc.) y devuelven mensajes de error claros si no son válidos.

Página 26 de 49
4. Modelos:

Definen la estructura de los datos y las interacciones con la base de datos (como

MongoDB en este caso).

Son utilizados por la lógica para realizar operaciones sobre los datos.

Ejemplo de Controladores

A continuación, se describen las funciones de los controladores para los cursos y usuarios,

mostrando cómo interactúan con la lógica y las validaciones.

Controladores de Cursos (`cursos_controller.js`)

1. listarCursosActivos:

Llama a `[Link]()` para obtener todos los cursos activos.

Devuelve un código de estado 204 si no hay cursos activos, o 200 con la lista de cursos

si los hay.

2. crearCurso:

Valida los datos de entrada usando `cursoSchemaValidation`.

Si la validación falla, devuelve un error 400.

Si la validación es exitosa, llama a `[Link](value)` para crear un nuevo curso

y devuelve el curso creado con un código de estado 201.

3. actualizarCurso:

Valida los datos de entrada y llama a `[Link](id, value)`.

Página 27 de 49
Devuelve un código de estado 404 si el curso no se encuentra, o 200 con el curso

actualizado.

4. desactivarCurso:

Llama a `[Link](id)` para cambiar el estado del curso.

Devuelve un código de estado 404 si el curso no se encuentra, o 200 con el curso

desactivado.

5. guardarColeccionCursos:

Valida cada curso en la colección y llama a `[Link](cursos)` para

guardarlos.

Devuelve un código de estado 201 con los cursos guardados.

6. obtenerCursoPorId:

Llama a `[Link](id)` para obtener un curso específico.

Devuelve un código de estado 404 si no se encuentra el curso, o 200 con el curso.

7. obtenerUsuariosPorCurso:

Llama a `[Link](id)` para obtener usuarios asociados a un

curso.

Devuelve un código de estado 404 si no se encuentran usuarios, o 200 con la lista de

usuarios.

Página 28 de 49
Cursos_controller.js

const logic = require('../logic/curso_logic');


const { cursoSchemaValidation } = require('../validations/curso_validations'); // Importa la
validación

// Controlador para listar los cursos activos


const listarCursosActivos = async (req, res) => {
try {
const cursosActivos = await [Link]();

if ([Link] === 0) {
return [Link](204).send(); // 204 No Content
}

[Link](cursosActivos);
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para crear un curso


const crearCurso = async (req, res) => {
const body = [Link];

const { error, value } = [Link]({


titulo: [Link],
descripcion: [Link],
estado: [Link],
imagen: [Link],
alumnos: [Link],
calificacion: [Link],
curso: [Link]
});

if (error) {
return [Link](400).json({ error: [Link][0].message });
}

try {
const nuevoCurso = await [Link](value);
[Link](201).json(nuevoCurso);
} catch (err) {
if ([Link] === 'El curso con este título ya existe') {
return [Link](409).json({ error: [Link] });

Página 29 de 49
}
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para actualizar un curso


const actualizarCurso = async (req, res) => {
const { id } = [Link];
const body = [Link];

const { error, value } = [Link]({


titulo: [Link],
descripcion: [Link],
estado: [Link],
imagen: [Link],
alumnos: [Link],
calificacion: [Link]
});

if (error) {
return [Link](400).json({ error: [Link][0].message });
}

try {
const cursoActualizado = await [Link](id, value);

if (!cursoActualizado) {
return [Link](404).json({ error: 'Curso no encontrado' });
}

[Link](cursoActualizado);
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para desactivar un curso


const desactivarCurso = async (req, res) => {
const { id } = [Link];

try {
const cursoDesactivado = await [Link](id);

if (!cursoDesactivado) {
return [Link](404).json({ error: 'Curso no encontrado' });

Página 30 de 49
}

[Link](cursoDesactivado);
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para guardar una colección de cursos


const guardarColeccionCursos = async (req, res) => {
const cursos = [Link];

// Validación de cada curso en la colección


for (let curso of cursos) {
const { error } = [Link]({
titulo: [Link],
descripcion: [Link],
estado: [Link],
imagen: [Link],
alumnos: [Link],
calificacion: [Link]
});

if (error) {
return [Link](400).json({ error: `Error en curso "${[Link]}":
${[Link][0].message}` });
}
}

try {
// Guardar la colección de cursos
const resultados = await [Link](cursos);
[Link](201).json({ message: 'Cursos guardados exitosamente', cursos: resultados });
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor al guardar cursos', details:
[Link] });
}
};

// Controlador para buscar un curso por su ID


const obtenerCursoPorId = async (req, res) => {
const { id } = [Link];

try {

Página 31 de 49
const curso = await [Link](id);

if (!curso) {
return [Link](404).json({ error: `Curso con ID ${id} no encontrado` });
}

[Link](curso);
} catch (err) {
[Link](500).json({ error: `Error interno del servidor al buscar el curso: ${[Link]}`
});
}
};

// Controlador para buscar usuarios asociados a un curso


const obtenerUsuariosPorCurso = async (req, res) => {
const { id } = [Link];

try {
const usuarios = await [Link](id);

if (!usuarios || [Link] === 0) {


return [Link](404).json({ error: `No se encontraron usuarios para el curso con ID
${id}` });
}

[Link](usuarios);
} catch (err) {
[Link](500).json({ error: `Error interno del servidor al buscar los usuarios del curso:
${[Link]}` });
}
};

// Exportar los controladores


[Link] = {
listarCursosActivos,
crearCurso,
actualizarCurso,
desactivarCurso,
guardarColeccionCursos,
obtenerCursoPorId,
obtenerUsuariosPorCurso
};

Página 32 de 49
Controladores de Usuarios (`usuarios_controller.js`)

1. listarUsuarioActivos:

Llama a `[Link]()` para obtener todos los usuarios activos.

Devuelve un código de estado 204 si no hay usuarios activos, o 200 con la lista de

usuarios.

2. crearUsuario:

Valida los datos de entrada usando `usuarioSchemaValidation`.

Si la validación falla, devuelve un error 400.

Si la validación es exitosa, llama a `[Link](value)` para crear un nuevo

usuario y devuelve el usuario creado con un código de estado 201.

3. actualizarUsuario:

Valida los datos de entrada y llama a `[Link](email, value)`.

Devuelve un código de estado 404 si el usuario no se encuentra, o 200 con el usuario

actualizado.

4. desactivarUsuario:

Llama a `[Link](email)` para cambiar el estado del usuario.

Devuelve un código de estado 404 si el usuario no se encuentra, o 200 con el usuario

desactivado.

5. agregarCursosAUsuario:

Valida que el cuerpo de la solicitud contenga un array de IDs de cursos y llama a

`[Link](email, cursos)`.

Devuelve un código de estado 200 con el usuario actualizado.

6. listarCursosDeUsuario:

Llama a `[Link](usuarioId)` para obtener los cursos asociados a

un usuario.

Página 33 de 49
Devuelve un código de estado 204 si no hay cursos, o 200 con la lista de cursos.

7. guardarColeccionUsuarios:

Valida cada usuario en la colección y llama a

`[Link](usuariosValidos)` para guardarlos.

Devuelve un código de estado 201 con los usuarios guardados.

const logic = require('../logic/usuario_logic');


const { usuarioSchemaValidation } = require('../validations/usuario_validations');

// Controlador para listar los usuarios activos


const listarUsuarioActivos = async (req, res) => {
try {
const usuarios = await [Link]();
if ([Link] === 0) {
return [Link](204).send(); // No Content
}
[Link](usuarios);
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para crear un nuevo usuario


const crearUsuario = async (req, res) => {

const { error, value } = [Link]([Link]);

if (error) {
return [Link](400).json({ error: [Link][0].message });
}

try {
const nuevoUsuario = await [Link](value);
[Link](201).json({ usuario: nuevoUsuario }); // 201 Created
} catch (err) {
if ([Link] === 'El correo electrónico ya está registrado') {
return [Link](409).json({ error: [Link] }); // 409 Conflict
}
[Link](500).json({ error: 'Error interno del servidor' });
}
};

Página 34 de 49
// Controlador para actualizar un usuario
const actualizarUsuario = async (req, res) => {
const { email } = [Link];
const { error, value } = [Link]([Link]);

if (error) {
return [Link](400).json({ error: [Link][0].message });
}

try {
const usuarioActualizado = await [Link](email, value);
if (!usuarioActualizado) {
return [Link](404).json({ error: 'Usuario no encontrado' });
}
[Link]({ usuario: usuarioActualizado });
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para desactivar un usuario


const desactivarUsuario = async (req, res) => {
const { email } = [Link];

try {
const usuarioDesactivado = await [Link](email);
if (!usuarioDesactivado) {
return [Link](404).json({ error: 'Usuario no encontrado' });
}
[Link]({ usuario: usuarioDesactivado });
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para agregar un curso a un usuario


const agregarCursosAUsuario = async (req, res) => {
const { email } = [Link];
const { cursos } = [Link];

if (![Link](cursos) || [Link] === 0) {


return [Link](400).json({ error: 'Se requiere un array de IDs de cursos' });
}

Página 35 de 49
try {
const usuarioActualizado = await [Link](email, cursos);

[Link]({ usuario: usuarioActualizado });


} catch (error) {
[Link](500).json({ error: [Link] });
}
};

// Controlador para listar los cursos de un usuario


const listarCursosDeUsuario = async (req, res) => {
const { usuarioId } = [Link];

try {
const cursos = await [Link](usuarioId);
if ([Link] === 0) {
return [Link](204).send(); // No Content
}
[Link](cursos);
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor' });
}
};

// Controlador para guardar una colección de usuarios


const guardarColeccionUsuarios = async (req, res) => {
const usuarios = [Link]; // Se espera que el cuerpo de la solicitud contenga un array de
usuarios

// Validar y filtrar usuarios para evitar duplicados por correo electrónico


const emailsUnicos = new Set(); // Usamos un Set para almacenar correos únicos
const usuariosValidos = [];

for (let usuario of usuarios) {


const { error } = [Link](usuario);

if (error) {
return [Link](400).json({ error: [Link][0].message });
}

// Verificar si el correo ya fue encontrado en la colección


if ([Link]([Link])) {
continue; // Si ya existe, lo omitimos para evitar duplicados en la colección
}

Página 36 de 49
// Agregar el correo al Set y el usuario al array de usuarios válidos
[Link]([Link]);
[Link](usuario);
}

try {
const resultados = await [Link](usuariosValidos); // Llama a la
función lógica
[Link](201).json(resultados); // Responde con los usuarios guardados
} catch (err) {
[Link](500).json({ error: 'Error interno del servidor al guardar la colección de usuarios'
});
}
};

// Exportar los controladores


[Link] = {
listarUsuarioActivos,
crearUsuario,
actualizarUsuario,
desactivarUsuario,
agregarCursosAUsuario,
listarCursosDeUsuario,
guardarColeccionUsuarios
};

La capa de controladores es esencial para manejar las interacciones entre el cliente y la lógica de

negocio. Al recibir solicitudes, validar datos y devolver respuestas, los controladores garantizan

que la API funcione de manera eficiente y segura. La colaboración entre controladores, lógica,

validaciones y modelos permite una arquitectura bien estructurada y mantenible para la API

REST.

Página 37 de 49
CAPA DE RUTAS

La capa de rutas en una API REST es fundamental para definir cómo se manejan las solicitudes

HTTP y cómo se mapean a las funciones de los controladores. Esta capa actúa como el punto de

entrada para las solicitudes del cliente y se encarga de dirigir esas solicitudes a los controladores

correspondientes, donde se lleva a cabo la lógica de negocio. Usando [Link], la capa de rutas

se organiza de manera que cada ruta se asocie con un método HTTP específico y una función de

controlador.

Estructura de las Rutas

A continuación, se describen las rutas definidas en los archivos `cursos_routes.js` y

`usuarios_routes.js`.

Rutas de Cursos (`cursos_routes.js`)

1. Listar todos los cursos activos:

Método: `GET`

Ruta: `/`

Controlador: `[Link]`

Descripción: Devuelve una lista de todos los cursos que están activos.

2. Obtener curso por ID:

Método: `GET`

Ruta: `/:id`

Página 38 de 49
Controlador: `[Link]`

Descripción: Devuelve los detalles de un curso específico según su ID.

3. Obtener los usuarios para un curso:

Método: `GET`

Ruta: `/:id/usuarios`

Controlador: `[Link]`

Descripción: Devuelve una lista de usuarios asociados a un curso específico.

4. Crear un curso:

Método: `POST`

Ruta: `/`

Controlador: `[Link]`

Descripción: Crea un nuevo curso en la base de datos.

5. Crear colección de cursos:

Método: `POST`

Ruta: `/coleccion`

Controlador: `[Link]`

Descripción: Permite guardar múltiples cursos en la base de datos.

6. Actualizar curso:

Método: `PUT`

Ruta: `/:id`

Controlador: `[Link]`

Página 39 de 49
Descripción: Actualiza los detalles de un curso específico según su ID.

7. Eliminar curso:

Método: `DELETE`

Ruta: `/:id`

Controlador: `[Link]`

Descripción: Desactiva un curso específico según su ID.

Rutas de Usuarios (`usuarios_routes.js`)

1. Listar usuarios activos:

Método: `GET`

Ruta: `/`

Controlador: `[Link]`

Descripción: Devuelve una lista de todos los usuarios que están activos.

2. Listar cursos del usuario:

Método: `GET`

Ruta: `/:usuarioId/cursos`

Controlador: `[Link]`

Descripción: Devuelve una lista de cursos asociados a un usuario específico.

3. Crear un nuevo usuario:

Método: `POST`

Ruta: `/`

Página 40 de 49
Controlador: `[Link]`

Descripción: Crea un nuevo usuario en la base de datos.

4. Agregar cursos a un usuario:

Método: `POST`

Ruta: `/:email/cursos`

Controlador: `[Link]`

Descripción: Agrega uno o más cursos a un usuario existente.

5. Guardar colección de usuarios:

Método: `POST`

Ruta: `/coleccion`

Controlador: `[Link]`

Descripción: Permite guardar múltiples usuarios en la base de datos.

6. Actualizar un usuario:

Método: `PUT`

Ruta: `/:email`

Controlador: `[Link]`

Descripción: Actualiza los detalles de un usuario específico según su correo

electrónico.

7. Eliminar usuario:

Método: `DELETE`

Ruta: `/:email`

Página 41 de 49
Controlador: `[Link]`

Descripción: Desactiva un usuario específico según su correo electrónico.

Cursos_routes.js
const express = require('express');
const cursoController = require('../controllers/cursos_controller'); // Importa el controlador
const router = [Link](); // Define el enrutador

//Listar todos los cursos activos


[Link]('/', [Link]);

// Obtener curso por Id


[Link]('/:id', [Link]);

//Obtener los usuarios para un curso


[Link]('/:id/usuarios', [Link]);

//Crear un curso
[Link]('/', [Link]);

//Crear Colección de Cursos


[Link]('/coleccion', [Link]);

//Actualizar curso
[Link]('/:id', [Link]);

// Eliminar Curso
[Link]('/:id', [Link]);

[Link] = router;

usuarios_routes.js

const express = require('express');


const usuarioController = require('../controllers/usuarios_controller'); // Importa los
controladores
const router = [Link]();

//Listar usuarios activos


[Link]('/', [Link]);

Página 42 de 49
//Listar cursos del usuario
[Link]('/:usuarioId/cursos', [Link]);

//Crear un usuario sin cursos Usuarios (frontend)


[Link]('/', [Link]);

// Crear un usuario con cursos => Home (frontend)


[Link]('/:email/cursos', [Link]);

// Guardar una colección de usuarios


[Link]('/coleccion', [Link]);

// Actualizar un usuario
[Link]('/:email', [Link]);

// Eliminar usuario
[Link]('/:email', [Link]);

[Link] = router;

Integración de las Rutas en la Aplicación

Para que estas rutas funcionen, deben ser integradas en la aplicación Express. Esto se hace

generalmente en el archivo principal de la aplicación (por ejemplo, `[Link]` o `[Link]`) de la

siguiente manera:

const express = require('express');


const cursosRoutes = require('./routes/cursos_routes');
const usuariosRoutes = require('./routes/usuarios_routes');

const app = express();

[Link]([Link]()); // Middleware para parsear JSON

// Integrar las rutas de cursos


[Link]('/api/cursos', cursosRoutes);

// Integrar las rutas de usuarios


[Link]('/api/usuarios', usuariosRoutes);

Página 43 de 49
// Iniciar el servidor
const PORT = [Link] || 3000;
[Link](PORT, () => {
[Link](`Servidor corriendo en [Link]
});

La capa de rutas es esencial para definir cómo se manejan las solicitudes HTTP en la API REST.

Al organizar las rutas de manera lógica y clara, se facilita la interacción entre el cliente y el

servidor. Las rutas mapean las solicitudes a los controladores correspondientes, que a su vez

interactúan con la lógica de negocio y las validaciones para procesar los datos y devolver

respuestas adecuadas. Esta estructura modular permite un desarrollo más limpio y mantenible.

Página 44 de 49
PRUEBAS DE LOS END POINTS

Probar los endpoints de una API REST es una parte crucial del desarrollo, ya que asegura que la

lógica de negocio y las interacciones con la base de datos funcionen correctamente. **Postman**

es una herramienta popular para realizar pruebas de APIs, ya que permite enviar solicitudes

HTTP y ver las respuestas de manera intuitiva. A continuación, se explican los pasos para probar

los recursos de cursos y usuarios utilizando Postman.

Pasos para Probar los Endpoints con Postman

1. Configuración Inicial

Descargar e instalar Postman: Si aún no lo tienes, descarga Postman desde [su sitio
oficial]([Link]
Iniciar Postman: Abre la aplicación Postman.

2. Probar los Endpoints de Cursos

Listar Cursos Activos

Página 45 de 49
- Método: `GET`
- URL: `[Link]
- Descripción: Obtiene una lista de todos los cursos activos.

Pasos:

1. Selecciona el método `GET`.


2. Ingresa la URL en la barra de dirección.
3. Haz clic en el botón Send.
4. Verifica la respuesta en la sección de resultados.

Crear un Curso

- Método: `POST`
- URL: `[Link]
- Descripción: Crea un nuevo curso.

Pasos:

1. Selecciona el método `POST`.


2. Ingresa la URL.
3. Ve a la pestaña Body y selecciona raw y luego JSON.
4. Ingresa el siguiente JSON en el cuerpo de la solicitud:

{
"titulo": "Curso de Programación",
"descripcion": "Aprende a programar desde cero.",
"estado": true,
"imagen": "[Link]
"alumnos": 0,
"calificacion": 5
}

5. Haz clic en Send.


6. Verifica la respuesta para asegurarte de que el curso se haya creado correctamente.

Obtener Curso por ID

- Método: `GET`

Página 46 de 49
- URL: `[Link] (reemplaza `:id` con el ID del
curso)
- Descripción: Obtiene los detalles de un curso específico.

Pasos:
1. Selecciona el método `GET`.
2. Ingresa la URL con el ID del curso.
3. Haz clic en **Send**.
4. Verifica la respuesta.

Actualizar un Curso

- Método: `PUT`
- URL: `[Link] (reemplaza `:id` con el ID del
curso)
- Descripción: Actualiza los detalles de un curso.

Pasos:
1. Selecciona el método `PUT`.
2. Ingresa la URL con el ID del curso.
3. Ve a la pestaña Body y selecciona raw y luego JSON.
4. Ingresa el JSON con los nuevos datos del curso.
5. Haz clic en Send.
6. Verifica la respuesta.

Desactivar un Curso

- Método: `DELETE`
- URL: `[Link] (reemplaza `:id` con el ID del
curso)
- Descripción: Desactiva un curso específico.

Pasos:
1. Selecciona el método `DELETE`.
2. Ingresa la URL con el ID del curso.
3. Haz clic en Send.
4. Verifica la respuesta.

3. Probar los Endpoints de Usuarios

Página 47 de 49
Listar Usuarios Activos

- Método: `GET`
- URL: `[Link]
- Descripción: Obtiene una lista de todos los usuarios activos.

Pasos:
1. Selecciona el método `GET`.
2. Ingresa la URL.
3. Haz clic en Send.
4. Verifica la respuesta.

Crear un Usuario

- Método: `POST`
- URL: `[Link]
- Descripción: Crea un nuevo usuario.

Pasos:
1. Selecciona el método `POST`.
2. Ingresa la URL.
3. Ve a la pestaña Body y selecciona raw y luego JSON.
4. Ingresa el siguiente JSON en el cuerpo de la solicitud:

{
"email": "usuario@[Link]",
"nombre": "Juan Pérez",
"password": "contraseña123",
"imagen": "[Link]
}

5. Haz clic en Send.


6. Verifica la respuesta.

Actualizar un Usuario

- Método: `PUT`
- URL: `[Link] (reemplaza `:email` con el
correo del usuario)

Página 48 de 49
- Descripción: Actualiza los detalles de un usuario.

Pasos:
1. Selecciona el método `PUT`.
2. Ingresa la URL con el correo del usuario.
3. Ve a la pestaña Body y selecciona raw y luego JSON.
4. Ingresa el JSON con los nuevos datos del usuario.
5. Haz clic en Send.
6. Verifica la respuesta.

Desactivar un Usuario

- Método: `DELETE`
- URL: `[Link] (reemplaza `:email` con el
correo del usuario)
- Descripción: Desactiva un usuario específico.

Pasos:
1. Selecciona el método `DELETE`.
2. Ingresa la URL con el correo del usuario.
3. Haz clic en **Send**.
4. Verifica la respuesta.

4. Verificar Respuestas

En cada prueba, asegúrate de verificar:


Códigos de estado HTTP: Asegúrate de que los códigos de estado devueltos sean los
esperados (200, 201, 204, 400, 404, 409, etc.).
Cuerpo de la respuesta: Revisa que los datos devueltos sean correctos y estén en el
formato esperado.

Postman es una herramienta poderosa para probar y documentar APIs. Al seguir estos pasos,

puedes asegurarte de que los endpoints de tu API REST para cursos y usuarios funcionen

correctamente. Realiza pruebas exhaustivas para detectar errores y asegurarte de que la lógica de

negocio y las interacciones con la base de datos se manejen adecuadamente.

Página 49 de 49

También podría gustarte