feat(course): Implementar creación de cursos con contenido anidado#46
Merged
Conversation
Frasquito3
approved these changes
Aug 26, 2025
NiconiKimg
added a commit
that referenced
this pull request
Dec 11, 2025
* fix: login no longer returns user data, only the token Additionally, the orm.ts was fixed as it deleted and created the entire database * Create auto-pr.yml * feat(auth): implement full auth flow with login, profile, and middleware (#6) * ref: Move appeal business logic to service layer (#11) Also corrected the entity relationship to link to a Student instead of a Professor * feat: Implement Valibot input validation in Appeal (#12) Also, the appeal creation date is now generated server-side for accuracy and security * feat: Secure Appeal endpoints with auth.middleware.ts (#13) * Feature/appeal creation endpoint (#15) * feat(appeal): update Appeal entity to match frontend form * feat(upload): integrate multer with Cloudinary for file storage * feat(appeal): update validation schema to match frontend form * feat(appeal): implement creation endpoint logic and middlewares * chore(types): extend Express Request type to include user property * fix(auth): align JWT payload type with global Request type * feat(appeal): implement full professor application endpoint * fix(appeal): align entity field name with frontend contract * feat(ci): Add workflow to auto-add new issues to project (#17) * chore(workflow): add automated issue templates * refactor: add services layers * Update auto-pr.yml * chore: Change the feature and bug templates (#21) * chore: configure ESLint with flat config for TypeScript project * style: clean up unused variables and imports reported by ESLint * chore: temporarily disable audit from CI test run * fix: update dependencies and adapt to MikroORM v6 * refactor: Estandarizar el módulo 'student' a la arquitectura de referencia (#28) * feat(student): add validation schemas for create and update * refactor(student): replace manual sanitizer with validation middleware * chore: reorganize course schema file structure * refactor(student): modernize controller logic * fix: resolves instant logout issue after successful login (#32) * feat(appeals): implement user promotion on appeal approval (#34) * refactor(course): standardize controller, service, and secure endpoints (#41) * chore: Add PR template and remove auto-pr workflow (#42) * chore: add PR template and remove auto-pr workflow * fix: Added the pull_request_template.md * fix: sync pnpm-lock.yaml with package.json (#45) * refactor(courseType): Standardize the architecture of courseType module * feat(course): Implementar creación de cursos con contenido anidado (#46) * feat(course): define data model with embeddable content * feat(course): create nested validation schemas for course creation * feat(course): Implement creation of courses with nested content * Feature: Flujo de recuperación de contraseña (#50) * feat: Initial version of the password recovery flow * feat(user): add fields for password recovery * feat(email): create react-email template for password recovery * feat(auth): implement secure password recovery logic * feat(auth): add validation for password recovery endpoints --------- Co-authored-by: NiconiKimg <pedemontenicolas2004@gmail.com> * refactor: Add Professor schema (#48) * refactor: Add Professor schema * fix(professor): correct schema filename and remove unused imports --------- Co-authored-by: NiconiKimg <pedemontenicolas2004@gmail.com> * Refactor/standardize institution module (#51) * feat(institution): add valibot validation schemas * refactor(institution): apply auth and validation middlewares to routes * refactor(institution): align controller with project standards * fix(institution): correct type signature for create method in service and JSDo to entire module * chore(lint): fix unused variable warning in AuthService * refactor(institution): remove unnecessary semicolons * refactor(professor): Estandarizar arquitectura del módulo 'professor' (#53) * refactor(professor): simplify schemas to only support updates * refactor(professor): remove creation route and apply middlewares * refactor(professor): align module with project standards and docs * Refactor: middleware para control de errores global (#56) * feat(shared): add global error handler middleware * refactor(app): integrate global error handler and simplify controllers * refactor(app): integrate global error handler and simplify controllers * feat: add-typedocLibrary * fix: Eliminar vulnerabilidad de JWT Secret por defecto (#58) * feat(config): add .env.example and environment validation * fix(auth): remove default JWT secret fallback * Create typedoc.yml (#64) * Update typedoc.yml (#65) * Update typedoc.yml * Update typedoc.yml * Update typedoc.yml * refactor(student): Remove POST endpoint /api/students Co-authored-by: LucaTvl <LucaTvl@users.noreply.github.com> * feat: Implementación de autorización basada en roles (RBAC) (#78) * feat(auth): add role-based authorization middleware * feat(course-type): protect write endpoints for admins only * feat(appeals): apply role protection to appeal routes * feat(professor): protect write endpoints for admins only * feat(course): apply role protection to course routes * feat(institution): protect write endpoints for admins only * feat(student): apply role protection to student management routes * Feature/add swagger openapi (#77) * feat:add-swagger * feat: add-swagger-openapi --------- Co-authored-by: LucaTvl <155491309+LucaTvl@users.noreply.github.com> * feat: Configuración de rate limiting y cabeceras de seguridad con Helmet (#82) * feat(security): integrate helmet for http header protection * feat(security): implement rate limiting for api and auth endpoints * Refactor: SRP Appeal Service (#90) * feat(professor): Add method to create profile from user Introduces the 'createFromUser' method in ProfessorService. This method encapsulates the business logic for promoting a user to a professor and creating their associated profile, adhering to the Single Responsibility Principle (SRP). It does not flush the EntityManager, allowing the calling service to manage the transaction boundary. * refactor(appeal): Delegate professor creation to ProfessorService Modifies the 'update' method in AppealService to use the new 'ProfessorService.createFromUser'. This refactoring removes professor creation logic from AppealService, improving cohesion and reducing coupling between modules in line with the SRP. * Feature: Setup Database Migrations (#83) * chore(deps): Configuration of migration system from MikroORM * refactor(core): Integrate migration runner on app startup * fix: Added the script migration:create. * fix: Updated the mikro-orm packages versions to march mikro-orm/cli * fix: Added ts-node * feat: Added scripts for migrations and the config path for Ts * fix: Added tsx, enabling migration:create to work succesfully * feat: Created the first migration * fix: Modified the path for the script start:dev and added the script build * docs(migrations): Added the documentation for migration's workflow * fix: Changed the location of the Migration's documentation * fix: Fixed the touting problem in app.ts (#93) * chore: Stop tracking build artifacts in dist folder (#95) * feat: Implementacion de logging estructurado con Pino (#91) * feat(observability): add pino for structured logging * feat(observability): integrate pino-http middleware for request logging * refactor(error): use structured logger in global error handler * refactor(email): replace console logs with structured logger * refactor(auth): delegate generic error handling to global middleware * feat(observability): add request IDs and redact sensitive data in logs * feat(observability): integrate mikro-orm logger with pino * refactor(models): delegate generic error handling to global middleware A bug that existed in app.ts was also fixed, which had to do with the use of serializers. * feat(observability): implement request-scoped logging in all models * refactor(observability): refine pino and pino-http configuration Also fixed some problems in the services of all models * build(scripts): add cross-env and configure NODE_ENV for dev and prod * feat(observability): configure environment-aware logging transports * fix(.gitignore): ignore logs files but no directory * fix(appeal): solved problems with dependencies and existing conflicts * fix: Solved the problems with the routing in app.ts * fix: Solved conflicts with app.ts * fix: deleted tsconfig.buildinfo --------- Co-authored-by: LucaTvl <ltrincavell@frro.utn.edu.ar> Co-authored-by: LucaTvl <155491309+LucaTvl@users.noreply.github.com> * fix(docs): Solved TypeDoc generation strategy for a modular structure (#111) More documentation has also been added. There are some files that have been documented but may not be strictly necessary. However, since they didn’t detract from anything, it was decided to include them, and if they turn out to be unnecessary, they can simply be deleted. * Chore: Externalizar la documentación de Swagger en un yaml (#115) * feat: add swagger configuration in src/docs * docs: add institutions API documentation and docs README * refactor: remove old swagger configuration from shared folder * feat: integrate new swagger configuration in app.ts * feat: update institution routes with new swagger documentation * chore: update eslint configuration * feat(courses): add endpoint to fetch professor's courses (#114) Co-authored-by: LucaTvl <LucaTvl@users.noreply.github.com> * Refactor: Eliminar entidad obsoleta Activity (#116) * refactor: remove activities property from Unit entity * refactor: remove Activity schema and references from course validation * docs: update comment to remove Activity reference in course service * feat: add migration to remove activities field from course units * feat(courses): implement swagger documentation using dedicated yaml file (#118) * feat(courses): implement course creation and retrieval API * hotfix(courses): fix relation persistence on course creation (#121) * Feature: implementar banco de preguntas para el curso (#123) * feat: add question module with CRUD operations * feat: integrate question routes in course router * docs: add question endpoints to swagger documentation * docs: enhance swagger error responses and validation examples * refactor: optimize question service create method * feat: complete question module implementation * fix: update course and professor services imports * fix(): pause migrations and use syncSchema again * wip(): improve controller methods * fix(): use professor id instead of user id and helper creation * Feat: Implementar gestión de contenido de Unidades (#124) * feat: Modified the course, unit and material entities. Modified PUT /api/courses/:id * fix: Deleted an importation not used * feat: modified the update method to accept everything from the front * fix: The edition of the course works * fix: The course image can be edited * refactor: Created a function to be imported in routes for the course update. * fix: Solved the test problem * feat(user): Implement user profile management endpoint * feat: add search method in Course module (#129) * feature: Appeal search with filters endpoint * feature: Appeal search with filters endpoint * Feature/fix : implement mini course endpoints (#132) * wip: build micro endpoints * fix: resolve circular reference between Unit and Question entities * fix: store Question ObjectIds instead of entities in Unit references * feat: implement auto-assignment of unitNumber on unit creation * fix: remove incorrect middlewares from question update routes * chore: update dependencies to fix security vulnerabilities * refactor: modify populate (#133) * create enrollement entity * feat: entity enrollment * Feature/assessment entities (#134) * feat: add assessment entities (Assessment, AssessmentAttempt, AttemptAnswer) * feat: add validation schemas for assessment operations * feat: add assessment service with CRUD and attempt management * feat: add assessment REST API endpoints * feat: integrate assessment routes into application * feat: support questions without unit assignment * chore: regenerate pnpm lockfile to fix CI installation issues * feat: Implementacion de Sistema de Gestión de Instituciones y Solicitudes (#136) * feat: implement institutional affiliation management system * feat: forgot to save this changes * chore: regenerate pnpm lockfile to fix CI installation issues * Create regen-lock.yml (#138) Añade test para resolver reducir problemas en conflicto del lock.yaml * refactor: Clean up routes and schemas for better organization and validation (#139) - Removed TODO comments for validation in auth routes. - Fixed duplicate route definition in course routes. - Reorganized search course schema for clarity and consistency. - Enhanced searchCourses service method with improved query handling and logging. - Updated courseType routes to eliminate duplicate route definitions. Co-authored-by: Frasquito3 <132107743+Frasquito3@users.noreply.github.com> * Update ci.yml * refactor: appeal validation (#140) * feat: Added the endpoints for the landing page * refactor: edit comments (#141) * feat: add virtual properties and fields to entities (#143) * feat: add virtual properties and fields to entities * fix: resolve eslint warnings and audit level for CI * fix: set audit level to high to ignore moderate vulnerabilities * feat: implement full Mercado Pago payment flow * fix: Resolve merge conflicts * fix: Resolve problems with the 2FA from Mercado Pago * feat: Implement Full Assessment and Reporting System * fix: Modified the course.service to return the amount of students * refactor courses service (#148) * feat: implement payment and earning entities with 97/3 revenue split (#149) - Created Payment entity to track Mercado Pago transactions - Created Earning entity with PROFESSOR_SHARE (97%) and PLATFORM_FEE (3%) - Added currency utilities for cents-based calculations - Migrated Course.price to Course.priceInCents for precision - Updated PaymentService to handle webhooks and create payments/earnings/enrollments - Modified EnrollementService to resolve User->Student profiles - Updated app.ts to register payment routes * fix: fixes (#150) * feat: add admin analytics endpoint and professor earnings analytics (#151) * feat: Added protection to the routes (#152) * feat: Implement backend filtering, sorting, and pagination (#153) * fix: fixed the modal for editing course (#154) * Feat/improve course filters (#155) * feat:improve filters options * feat: improve course-filters --------- Co-authored-by: NiconiKimg <pedemontenicolas2004@gmail.com> * bugfix: correct questions endpoints (#156) * feat: Agregado de endpoint para recuperar apelaciones de usuarios autenticados (#157) * feat: add endpoint to retrieve authenticated user appeals * bugfix: fix vulnerabilities * feat: Implementacion de pruebas unitarias y de integración para módulos de autenticación e inscripción (#158) * feat: add endpoint to retrieve authenticated user appeals * bugfix: fix vulnerabilities * feat: Implement unit and integration tests for auth and enrollment modules * bugfix: fix problems * chore: Luca Trincavelli (Leg. 52325) told me to add this * fix: reorder course routes middlewares (#159) * fix: fixed the order of the middlewares in the endpoints (#160) * Feat: ampliar módulo de mails con patrones de diseño (#161) * feat: implement full emails module * bugfix: change correct routes * feat: implement contact module with tickets * feat: Integrate Better Stack for centralized logging with EU region support (#162) * refactor: decouple app definition from server execution and extract security config (#166) * Chore/test infrastructure (#167) * chore: remove migration system and documentation * chore: add test scripts and mongodb-memory-server dependency * chore: configure jest with global setup and teardown * feat: add mikro-orm test configuration * feat: add jest global setup and teardown wrappers * feat: add test database helper functions * feat: add user, student and professor factories * feat: add course and courseType factories * feat: add enrollement factory and factories index * refactor: rewrite auth service unit tests following AAA pattern * refactor: rewrite enrollement service unit tests following AAA pattern * test: add auth service integration tests * ci: update workflow with comprehensive test pipeline * style: format entity files * fix: make jwt.sign test assertion more flexible for CI * fix: verify jwt.sign payload without checking secret parameter * ci: add JWT_SECRET environment variable for tests * feat: Implement secure refresh token rotation and fix tests (#168) * fix: fixed the authmiddleware in institution and professor routes (#169) Co-authored-by: LucaTvl <lucatrincavell@frro.utn.edu.ar> * chore: trigger CI to verify railway removal (#180) --------- Co-authored-by: Franco Zariaga <francozariaga.zariaga@gmail.com> Co-authored-by: carlex74 <r.icardogugliermino@gmail.com> Co-authored-by: Frasquito3 <132107743+Frasquito3@users.noreply.github.com> Co-authored-by: LucaTvl <155491309+LucaTvl@users.noreply.github.com> Co-authored-by: LucaTvl <LucaTvl@users.noreply.github.com> Co-authored-by: LucaTvl <ltrincavell@frro.utn.edu.ar> Co-authored-by: LucaTvl <lucatrincavell@frro.utn.edu.ar>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue Relacionada
Closes #43
Resumen
Este PR introduce la funcionalidad completa del backend para la creación de cursos, permitiendo a los profesores definir una estructura compleja con unidades, materiales de apoyo y actividades desde una única petición a la API.
Cambios Técnicos Implementados
Modelo de Datos con Entidades Embebidas:
Unit,Material, yActivitypara estructurar el contenido del curso.Courseha sido actualizada para incluir un array deUnits, así como campos para la gestión de precios (isFree,price).Validación Anidada con Valibot:
course.schemas.ts.Lógica de Servicio Robusta:
CourseServicepara manejar la creación de entidades con contenido embebido.em.create+em.assign) para satisfacer los requisitos de tipado estricto de MikroORM y manejar correctamente los valores por defecto.Seguridad y Autorización:
CourseControllerutiliza la información delreq.userpara asegurar que solo los usuarios con un perfil deProfessorpuedan crear nuevos cursos.Guía para Pruebas y Revisión
Iniciar el servidor del backend (
pnpm start:dev).Obtener un token JWT válido de un usuario que tenga el rol de
PROFESSOR.Probar el endpoint
POST /api/coursescon un token dePROFESSORválido y un cuerpo JSON complejo.Ejemplo de cuerpo para la petición:
{ "name": "Curso de TypeScript Avanzado", "description": "Un curso para profundizar en los conceptos de TypeScript.", "isFree": false, "price": 49.99, "courseTypeId": "id_del_tipo_de_curso_existente", "units": [ { "unitNumber": 1, "name": "Introducción a los Tipos Avanzados", "detail": "## Genéricos\n\nLos genéricos son una de las herramientas más poderosas...", "materials": [ { "title": "Documentación Oficial de Genéricos", "url": "https://www.typescriptlang.org/docs/handbook/2/generics.html" } ], "activities": [ { "name": "Quiz de Genéricos", "description": "Prueba tus conocimientos sobre genéricos.", "question": "¿Qué palabra clave se usa para definir un tipo genérico?", "options": [ { "text": "any", "isCorrect": false }, { "text": "<T>", "isCorrect": true }, { "text": "generic", "isCorrect": false } ] } ] } ] }Resultado Esperado:
201 Createdcon el objeto del curso recién creado, incluyendo toda la estructura anidada.Verificar Fallos:
401 Unauthorized).STUDENT(esperado:401 Unauthorizedcon el mensaje "The authenticated user is not a professor.").unitNumberque no sea un número (esperado:400 Bad Requestcon detalles del error de validación).