From 7452b33880b0218deb592ee0bca5df45e9e168d5 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 08:09:07 -0300 Subject: [PATCH 01/71] refactor: Update UpdateActivityUsecase to validate and update status_activity --- .../update_activity/app/update_activity_usecase.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index 441be77..e644f48 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -175,6 +175,11 @@ export class UpdateActivityUsecase { }); } + let status_activity: ActivityStatusEnum = body.status_activity; + if (status_activity && !Object.values(ActivityStatusEnum).includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); + } + const activity = await this.activity_repo.get_activity(body.activity_id); if (!activity) { throw new NotfoundError("Activity not found"); @@ -207,8 +212,8 @@ export class UpdateActivityUsecase { courses: courses.length > 0 ? courses : activity.courses, partner_institutions: partner_institutions.length > 0 ? partner_institutions : activity.partner_institutions, criterias: criterias.length > 0 ? criterias : activity.criterias, - status_activity: body.status_activity ? body.status_activity : activity.status_activity, - type_activity: body.type_activity ? body.type_activity : activity.type_activity, + status_activity: status_activity ? status_activity : activity.status_activity, + type_activity: activity.type_activity, created_at: activity.created_at, updated_at: new Date(), applicants: activity.applicants From 4404a85ef2a846a229794a183b39e613f153b727 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 08:14:02 -0300 Subject: [PATCH 02/71] refactor: Update language codes in LanguageMock --- src/core/structure/mocks/LanguageMock.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/structure/mocks/LanguageMock.ts b/src/core/structure/mocks/LanguageMock.ts index 2e9ef9d..ddeeac0 100644 --- a/src/core/structure/mocks/LanguageMock.ts +++ b/src/core/structure/mocks/LanguageMock.ts @@ -13,7 +13,7 @@ export class LanguageMock { new Language({ id: 2, language: "English", - language_code: "en" + language_code: "gb" }), new Language({ id: 3, @@ -38,22 +38,22 @@ export class LanguageMock { new Language({ id: 7, language: "Mandarin", - language_code: "zh" + language_code: "cn" }), new Language({ id: 8, language: "Japanese", - language_code: "ja" + language_code: "jp" }), new Language({ id: 9, language: "Korean", - language_code: "ko" + language_code: "kr" }), new Language({ id: 10, language: "Arabic", - language_code: "ar" + language_code: "sa" }), new Language({ id: 11, @@ -68,12 +68,12 @@ export class LanguageMock { new Language({ id: 13, language: "Swedish", - language_code: "sv" + language_code: "se" }), new Language({ id: 14, language: "Danish", - language_code: "da" + language_code: "dk" }), new Language({ id: 15, From b2c4a3000fc395243d93abacf01936a67de1a949 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 08:35:01 -0300 Subject: [PATCH 03/71] refactor: Update EventBridgeManager to enable rule state --- src/core/helpers/functions/event_bridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/helpers/functions/event_bridge.ts b/src/core/helpers/functions/event_bridge.ts index 6c42d9f..1d198a8 100644 --- a/src/core/helpers/functions/event_bridge.ts +++ b/src/core/helpers/functions/event_bridge.ts @@ -53,7 +53,7 @@ export class EventBridgeManager { await this.event.putRule({ Name: rule_name, ScheduleExpression: "cron(" + date.getMinutes() + " " + date.getHours() + " " + date.getDate() + " " + (date.getMonth() + 1) + " ? " + date.getFullYear() + ")", - State: "ENABLED", + State: "ENABLED" }).promise(); // Add target to the rule From f7661db8bec4c82442d7d97f9bf9eed7712c49f7 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 08:35:12 -0300 Subject: [PATCH 04/71] refactor: Update CreateActivityUsecase to handle time zone offset --- .../create_activity/app/create_activity_usecase.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/modules/create_activity/app/create_activity_usecase.ts b/src/modules/create_activity/app/create_activity_usecase.ts index 39b36e5..18407a6 100644 --- a/src/modules/create_activity/app/create_activity_usecase.ts +++ b/src/modules/create_activity/app/create_activity_usecase.ts @@ -73,7 +73,11 @@ export class CreateActivityUsecase { if (!body.type_activity) { throw new MissingParameter("Type Activity"); } - if (new Date(body.start_date) < new Date()) { + + let time_now: Date = new Date(); + time_now.setHours(time_now.getHours() - 3); + + if (new Date(body.start_date) < time_now) { throw new InvalidParameter("StartDate", "Start Date must be in the future"); } if (new Date(body.start_date) >= new Date(body.end_date)) { @@ -206,10 +210,14 @@ export class CreateActivityUsecase { await this.activity_repo.create_activity(activity).then(async (response) => { if (response && process.env.STAGE !== 'test') { + let start_date = activity.start_date; + start_date.setHours(start_date.getHours() + 3); + let end_date = activity.end_date; + end_date.setHours(end_date.getHours() + 3); await this.event_bridge.create_trigger( "START_ACTIVITY_" + activity.id, "Update_Activity_Event", - activity.start_date, + start_date, { "body": { activity_id: activity.id, @@ -221,7 +229,7 @@ export class CreateActivityUsecase { await this.event_bridge.create_trigger( "END_ACTIVITY_" + activity.id, "Update_Activity_Event", - activity.end_date, + end_date, { "body": { activity_id: activity.id, From 730bfb7ef1220f0eede8d2cc6bb543406f7562c2 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 08:35:19 -0300 Subject: [PATCH 05/71] refactor: Update UpdateActivityUsecase to handle time zone offset and validate status_activity --- .../app/update_activity_usecase.ts | 83 ++++++++++--------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index e644f48..cd83925 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -17,6 +17,7 @@ import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; import { EventBridgeManager } from "../../../core/helpers/functions/event_bridge"; import { ActivityStatusEnum } from "../../../core/helpers/enums/ActivityStatusEnum"; import { IActivityRepo } from "../../../core/repositories/interfaces/IActivityRepo"; +import { time } from "console"; export class UpdateActivityUsecase { public token_auth: TokenAuth; @@ -74,64 +75,64 @@ export class UpdateActivityUsecase { if (body.languages) { if (!Array.isArray(body.languages)) { - throw new InvalidParameter("Languages", "must be an array of ids"); + throw new InvalidParameter("Languages", "must be an array of ids"); } body.languages.forEach((language_id: number) => { - if (!language_id) { - throw new MissingParameter("Language ID"); - } - if (typeof language_id !== 'number') { - throw new InvalidParameter("Language ID", "must be a number"); - } + if (!language_id) { + throw new MissingParameter("Language ID"); + } + if (typeof language_id !== 'number') { + throw new InvalidParameter("Language ID", "must be a number"); + } }) } if (body.courses) { if (!Array.isArray(body.courses)) { - throw new InvalidParameter("Courses", "must be an array of ids"); + throw new InvalidParameter("Courses", "must be an array of ids"); } body.courses.forEach((course_id: number) => { - if (!course_id) { - throw new MissingParameter("Course ID"); - } - if (typeof course_id !== 'number') { - throw new InvalidParameter("Course ID", "must be a number"); - } + if (!course_id) { + throw new MissingParameter("Course ID"); + } + if (typeof course_id !== 'number') { + throw new InvalidParameter("Course ID", "must be a number"); + } }) } if (body.criterias) { if (!Array.isArray(body.criterias)) { - throw new InvalidParameter("Criterias", "must be an array of criterias"); + throw new InvalidParameter("Criterias", "must be an array of criterias"); } body.criterias.forEach((criteria: { id?: number, criteria?: string }) => { - if (criteria.criteria && criteria.id) { - throw new InvalidParameter("Criteria or Criteria ID", "You must provide only the criteria or the criteria id"); - } - if (!criteria.criteria && !criteria.id) { - throw new MissingParameter("Criteria or Criteria ID"); - } - if (criteria.id && typeof criteria.id !== 'number') { - throw new InvalidParameter("Criteria ID", "must be a number"); - } - if (criteria.criteria && typeof criteria.criteria !== 'string') { - throw new InvalidParameter("Criteria", "must be a string"); - } + if (criteria.criteria && criteria.id) { + throw new InvalidParameter("Criteria or Criteria ID", "You must provide only the criteria or the criteria id"); + } + if (!criteria.criteria && !criteria.id) { + throw new MissingParameter("Criteria or Criteria ID"); + } + if (criteria.id && typeof criteria.id !== 'number') { + throw new InvalidParameter("Criteria ID", "must be a number"); + } + if (criteria.criteria && typeof criteria.criteria !== 'string') { + throw new InvalidParameter("Criteria", "must be a string"); + } }) } if (body.partner_institutions) { if (!Array.isArray(body.partner_institutions)) { - throw new InvalidParameter("Partner Institutions", "must be an array of ids"); + throw new InvalidParameter("Partner Institutions", "must be an array of ids"); } body.partner_institutions.forEach((institution: string) => { - if (!institution) { - throw new MissingParameter("Partner Institution"); - } - if (typeof institution !== 'string') { - throw new InvalidParameter("Partner Institution", "must be a string"); - } + if (!institution) { + throw new MissingParameter("Partner Institution"); + } + if (typeof institution !== 'string') { + throw new InvalidParameter("Partner Institution", "must be a string"); + } }) } @@ -185,8 +186,10 @@ export class UpdateActivityUsecase { throw new NotfoundError("Activity not found"); } - if (body.start_date && body.end_date) { - if (new Date(body.start_date) < new Date()) { + if (body.start_date || body.end_date) { + let time_now: Date = new Date(); + time_now.setHours(time_now.getHours() - 3); + if (new Date(body.start_date) < time_now) { throw new InvalidParameter("StartDate", "Start Date must be in the future"); } if (new Date(body.start_date) >= new Date(body.end_date)) { @@ -222,6 +225,8 @@ export class UpdateActivityUsecase { await this.activity_repo.update_activity(activity_update).then(async (response) => { if (response && process.env.STAGE === "prod") { if (activity_update.start_date !== activity.start_date) { + let start_date = activity_update.start_date; + start_date.setHours(start_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( "START_ACTIVITY_" + activity.id, @@ -230,7 +235,7 @@ export class UpdateActivityUsecase { await this.event_bridge.create_trigger( "START_ACTIVITY_" + activity.id, "Update_Activity_Event", - activity_update.start_date, + start_date, { "body": { activity_id: activity.id, @@ -240,6 +245,8 @@ export class UpdateActivityUsecase { ); } if (activity_update.end_date !== activity.end_date) { + let end_date = activity_update.end_date; + end_date.setHours(end_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( "END_ACTIVITY_" + activity.id, @@ -248,7 +255,7 @@ export class UpdateActivityUsecase { await this.event_bridge.create_trigger( "END_ACTIVITY_" + activity.id, "Update_Activity_Event", - activity_update.end_date, + end_date, { "body": { activity_id: activity.id, From 084a168530fa5b8e43f4d78f6d690575412e1aa9 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 09:00:24 -0300 Subject: [PATCH 06/71] refactor: Update UpdateActivityEventPresenter to handle activity status updates and trigger event deletion --- .../app/update_activity_event_presenter.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/update_activity_event/app/update_activity_event_presenter.ts b/src/modules/update_activity_event/app/update_activity_event_presenter.ts index 7aa982b..efa68f5 100644 --- a/src/modules/update_activity_event/app/update_activity_event_presenter.ts +++ b/src/modules/update_activity_event/app/update_activity_event_presenter.ts @@ -1,12 +1,18 @@ import { Repository } from "../../../core/repositories/Repository"; +import { EventBridgeManager } from "../../../core/helpers/functions/event_bridge"; +import { ActivityStatusEnum } from "../../../core/helpers/enums/ActivityStatusEnum"; const repository = new Repository({ activity_repo: true }); export const handler = async (event: any, context: any) => { - const body = event.body; + const event_bridge = new EventBridgeManager(); + const body: { activity_id: string; status: ActivityStatusEnum } = JSON.parse(event.body); + console.log("Activity ID: ", body.activity_id + " Status: " + body.status); const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status); if (resp) { console.log("Activity updated successfully"); + let event_name = body.status === ActivityStatusEnum.ACTIVE ? "START_ACTIVITY_" : "END_ACTIVITY_"; + await event_bridge.delete_trigger(event_name + body.activity_id, "Update_Activity_Event"); } else { console.log("Activity not found"); } From e9d7587b66a73875c5ed26bb5e56b3084dab8fcb Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 09:59:10 -0300 Subject: [PATCH 07/71] refactor: Update UpdateActivityEventPresenter to handle activity status updates and trigger event deletion --- .../app/update_activity_event_presenter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/update_activity_event/app/update_activity_event_presenter.ts b/src/modules/update_activity_event/app/update_activity_event_presenter.ts index efa68f5..1f69877 100644 --- a/src/modules/update_activity_event/app/update_activity_event_presenter.ts +++ b/src/modules/update_activity_event/app/update_activity_event_presenter.ts @@ -6,7 +6,8 @@ const repository = new Repository({ activity_repo: true }); export const handler = async (event: any, context: any) => { const event_bridge = new EventBridgeManager(); - const body: { activity_id: string; status: ActivityStatusEnum } = JSON.parse(event.body); + console.log("Event: ", event); + const body: { activity_id: string; status: ActivityStatusEnum } = event.body; console.log("Activity ID: ", body.activity_id + " Status: " + body.status); const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status); if (resp) { From f349ad6ee3c41fc0170e5950a4d2ed647970b6e9 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 10:22:14 -0300 Subject: [PATCH 08/71] refactor: Update UpdateActivityEventPresenter to handle activity status updates and trigger event deletion --- .../app/update_activity_event_presenter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/update_activity_event/app/update_activity_event_presenter.ts b/src/modules/update_activity_event/app/update_activity_event_presenter.ts index 1f69877..a8b5f5c 100644 --- a/src/modules/update_activity_event/app/update_activity_event_presenter.ts +++ b/src/modules/update_activity_event/app/update_activity_event_presenter.ts @@ -7,12 +7,12 @@ const repository = new Repository({ activity_repo: true }); export const handler = async (event: any, context: any) => { const event_bridge = new EventBridgeManager(); console.log("Event: ", event); - const body: { activity_id: string; status: ActivityStatusEnum } = event.body; - console.log("Activity ID: ", body.activity_id + " Status: " + body.status); - const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status); + const body: { activity_id: string; status_activity: ActivityStatusEnum } = event.body; + console.log("Activity ID: ", body.activity_id + " Status: " + body.status_activity); + const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status_activity); if (resp) { console.log("Activity updated successfully"); - let event_name = body.status === ActivityStatusEnum.ACTIVE ? "START_ACTIVITY_" : "END_ACTIVITY_"; + let event_name = body.status_activity === ActivityStatusEnum.ACTIVE ? "START_ACTIVITY_" : "END_ACTIVITY_"; await event_bridge.delete_trigger(event_name + body.activity_id, "Update_Activity_Event"); } else { console.log("Activity not found"); From 028ce31dad6410a7d91360145e3cc14bf4c5c13f Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 10:52:09 -0300 Subject: [PATCH 09/71] refactor: Update LambdaStack to include new function update_activity_event --- iac/lib/lambda_stack.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 3794fa8..b2a32b3 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -230,6 +230,7 @@ export class LambdaStack extends Construct { this.functions_need_event_bridge_access = [ this.create_activity, this.update_activity, + this.update_activity_event, ] } } From 4004c7bbf34fccc19568cd5cee3d76bbb36f3862 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 14:04:16 -0300 Subject: [PATCH 10/71] refactor: Update UpdateActivityUsecase to validate and update status_activity --- .../update_activity/app/update_activity_usecase.ts | 10 ++++++++-- .../update_activity/app/update_activity.test.ts | 11 +++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index cd83925..8046c7d 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -177,10 +177,16 @@ export class UpdateActivityUsecase { } let status_activity: ActivityStatusEnum = body.status_activity; - if (status_activity && !Object.values(ActivityStatusEnum).includes(body.status_activity)) { - throw new InvalidParameter("Status Activity", "Invalid status activity"); + if (status_activity) { + if (!Object.values(ActivityStatusEnum).includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); + } + if (![ActivityStatusEnum.ENDED, ActivityStatusEnum.CANCELED].includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); + } } + const activity = await this.activity_repo.get_activity(body.activity_id); if (!activity) { throw new NotfoundError("Activity not found"); diff --git a/test/modules/update_activity/app/update_activity.test.ts b/test/modules/update_activity/app/update_activity.test.ts index fef0c8a..165c934 100644 --- a/test/modules/update_activity/app/update_activity.test.ts +++ b/test/modules/update_activity/app/update_activity.test.ts @@ -2,10 +2,9 @@ import { it, describe, expect } from 'vitest'; import { UserMock } from '../../../../src/core/structure/mocks/UserMock'; import { TokenAuth } from '../../../../src/core/helpers/functions/token_auth'; -import { ActivityRepoMock } from "../../../../src/core/repositories/mocks/ActivityRepoMock"; -import { handler } from "../../../../src/modules/update_activity/app/update_activity_presenter"; import { ActivityMock } from '../../../../src/core/structure/mocks/ActivityMock'; -import { a } from 'vitest/dist/suite-ynYMzeLu'; +import { ActivityStatusEnum } from '../../../../src/core/helpers/enums/ActivityStatusEnum'; +import { handler } from "../../../../src/modules/update_activity/app/update_activity_presenter"; describe("Update Activity Presenter", () => { const user_admin = new UserMock().users[0]; @@ -27,7 +26,7 @@ describe("Update Activity Presenter", () => { partner_institutions: [activity.partner_institutions[0].id], criterias: [{ id: activity.criterias[0].id }], courses: [activity.courses[0].course?.id], - status_activity: activity.status_activity, + status_activity: ActivityStatusEnum.ENDED, type_activity: activity.type_activity, start_date: activity.start_date, end_date: activity.end_date, @@ -52,7 +51,7 @@ describe("Update Activity Presenter", () => { partner_institutions: [], criterias: [], courses: [], - status_activity: "ACTIVE", + status_activity: null, type_activity: "PROJECT", start_date: new Date(), end_date: new Date(), @@ -79,7 +78,7 @@ describe("Update Activity Presenter", () => { partner_institutions: [activity.partner_institutions[0].id], criterias: [{ id: activity.criterias[0].id }], courses: [activity.courses[0].course?.id], - status_activity: activity.status_activity, + status_activity: null, type_activity: activity.type_activity, start_date: new Date().getTime() - 1000 * 60 * 60 * 24 * 7, end_date: new Date(), From 7fa30d1b93a230ab69d80269c83784c46ffa5ce1 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Tue, 21 May 2024 14:12:49 -0300 Subject: [PATCH 11/71] refactor: Update UpdateActivityPresenter to set status_activity to null in test --- .../app/update_activity_usecase.ts | 299 ++++++++++-------- .../app/update_activity.test.ts | 2 +- 2 files changed, 165 insertions(+), 136 deletions(-) diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index 8046c7d..5005f8b 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -67,167 +67,196 @@ export class UpdateActivityUsecase { throw new UserNotAllowed(); } - if (body.title && await this.activity_repo.check_activity_by_title(body.title)) { - throw new UniqueConstraintError({ - message: "Activity with this title already exists" - }); - } + let activity: Activity | null; + let activity_update: Activity; + let status_activity: ActivityStatusEnum = body.status_activity; - if (body.languages) { - if (!Array.isArray(body.languages)) { - throw new InvalidParameter("Languages", "must be an array of ids"); + if (!status_activity) { + if (body.title && await this.activity_repo.check_activity_by_title(body.title)) { + throw new UniqueConstraintError({ + message: "Activity with this title already exists" + }); } - body.languages.forEach((language_id: number) => { - if (!language_id) { - throw new MissingParameter("Language ID"); - } - if (typeof language_id !== 'number') { - throw new InvalidParameter("Language ID", "must be a number"); - } - }) - } - if (body.courses) { - if (!Array.isArray(body.courses)) { - throw new InvalidParameter("Courses", "must be an array of ids"); - } - body.courses.forEach((course_id: number) => { - if (!course_id) { - throw new MissingParameter("Course ID"); + if (body.languages) { + if (!Array.isArray(body.languages)) { + throw new InvalidParameter("Languages", "must be an array of ids"); } - if (typeof course_id !== 'number') { - throw new InvalidParameter("Course ID", "must be a number"); - } - }) - } - - if (body.criterias) { - if (!Array.isArray(body.criterias)) { - throw new InvalidParameter("Criterias", "must be an array of criterias"); + body.languages.forEach((language_id: number) => { + if (!language_id) { + throw new MissingParameter("Language ID"); + } + if (typeof language_id !== 'number') { + throw new InvalidParameter("Language ID", "must be a number"); + } + }) } - body.criterias.forEach((criteria: { id?: number, criteria?: string }) => { - if (criteria.criteria && criteria.id) { - throw new InvalidParameter("Criteria or Criteria ID", "You must provide only the criteria or the criteria id"); - } - if (!criteria.criteria && !criteria.id) { - throw new MissingParameter("Criteria or Criteria ID"); - } - if (criteria.id && typeof criteria.id !== 'number') { - throw new InvalidParameter("Criteria ID", "must be a number"); - } - if (criteria.criteria && typeof criteria.criteria !== 'string') { - throw new InvalidParameter("Criteria", "must be a string"); - } - }) - } - if (body.partner_institutions) { - if (!Array.isArray(body.partner_institutions)) { - throw new InvalidParameter("Partner Institutions", "must be an array of ids"); + if (body.courses) { + if (!Array.isArray(body.courses)) { + throw new InvalidParameter("Courses", "must be an array of ids"); + } + body.courses.forEach((course_id: number) => { + if (!course_id) { + throw new MissingParameter("Course ID"); + } + if (typeof course_id !== 'number') { + throw new InvalidParameter("Course ID", "must be a number"); + } + }) } - body.partner_institutions.forEach((institution: string) => { - if (!institution) { - throw new MissingParameter("Partner Institution"); + if (body.criterias) { + if (!Array.isArray(body.criterias)) { + throw new InvalidParameter("Criterias", "must be an array of criterias"); } - if (typeof institution !== 'string') { - throw new InvalidParameter("Partner Institution", "must be a string"); - } - }) - } + body.criterias.forEach((criteria: { id?: number, criteria?: string }) => { + if (criteria.criteria && criteria.id) { + throw new InvalidParameter("Criteria or Criteria ID", "You must provide only the criteria or the criteria id"); + } + if (!criteria.criteria && !criteria.id) { + throw new MissingParameter("Criteria or Criteria ID"); + } + if (criteria.id && typeof criteria.id !== 'number') { + throw new InvalidParameter("Criteria ID", "must be a number"); + } + if (criteria.criteria && typeof criteria.criteria !== 'string') { + throw new InvalidParameter("Criteria", "must be a string"); + } + }) + } - let languages: { id: number }[] = []; - if (body.languages) { - languages = body.languages.map((language_id: number) => { - return { - id: language_id + if (body.partner_institutions) { + if (!Array.isArray(body.partner_institutions)) { + throw new InvalidParameter("Partner Institutions", "must be an array of ids"); } - }); - } - let courses: { id: number, course?: Course }[] = []; - if (body.courses) { - courses = body.courses.map((course_id: number) => { - return { - id: course_id - } - }); - } + body.partner_institutions.forEach((institution: string) => { + if (!institution) { + throw new MissingParameter("Partner Institution"); + } + if (typeof institution !== 'string') { + throw new InvalidParameter("Partner Institution", "must be a string"); + } + }) + } - let criterias: { id: number, criteria?: Criteria }[] = []; - if (body.criterias) { - criterias = body.criterias.map((criteria: { id?: number, criteria?: string }) => { - return { - id: criteria.id || -1, - criteria: criteria.criteria ? new Criteria({ - id: 1, - criteria: criteria.criteria - }) : null - } - }); - } + let languages: { id: number }[] = []; + if (body.languages) { + languages = body.languages.map((language_id: number) => { + return { + id: language_id + } + }); + } - let partner_institutions: { id: string }[] = []; - if (body.partner_institutions) { - partner_institutions = body.partner_institutions.map((institution: string) => { - return { - id: institution - }; - }); - } + let courses: { id: number, course?: Course }[] = []; + if (body.courses) { + courses = body.courses.map((course_id: number) => { + return { + id: course_id + } + }); + } - let status_activity: ActivityStatusEnum = body.status_activity; - if (status_activity) { - if (!Object.values(ActivityStatusEnum).includes(body.status_activity)) { - throw new InvalidParameter("Status Activity", "Invalid status activity"); + let criterias: { id: number, criteria?: Criteria }[] = []; + if (body.criterias) { + criterias = body.criterias.map((criteria: { id?: number, criteria?: string }) => { + return { + id: criteria.id || -1, + criteria: criteria.criteria ? new Criteria({ + id: 1, + criteria: criteria.criteria + }) : null + } + }); } - if (![ActivityStatusEnum.ENDED, ActivityStatusEnum.CANCELED].includes(body.status_activity)) { - throw new InvalidParameter("Status Activity", "Invalid status activity"); + + let partner_institutions: { id: string }[] = []; + if (body.partner_institutions) { + partner_institutions = body.partner_institutions.map((institution: string) => { + return { + id: institution + }; + }); } - } + let status_activity: ActivityStatusEnum = body.status_activity; + if (status_activity) { + if (!Object.values(ActivityStatusEnum).includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); + } + if (![ActivityStatusEnum.ENDED, ActivityStatusEnum.CANCELED].includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); + } + } - const activity = await this.activity_repo.get_activity(body.activity_id); - if (!activity) { - throw new NotfoundError("Activity not found"); - } - if (body.start_date || body.end_date) { - let time_now: Date = new Date(); - time_now.setHours(time_now.getHours() - 3); - if (new Date(body.start_date) < time_now) { - throw new InvalidParameter("StartDate", "Start Date must be in the future"); + activity = await this.activity_repo.get_activity(body.activity_id); + if (!activity) { + throw new NotfoundError("Activity not found"); } - if (new Date(body.start_date) >= new Date(body.end_date)) { - throw new InvalidParameter("StartDate and EndDate", "Start Date must be before End Date"); + + if (body.start_date || body.end_date) { + let time_now: Date = new Date(); + time_now.setHours(time_now.getHours() - 3); + if (new Date(body.start_date) < time_now) { + throw new InvalidParameter("StartDate", "Start Date must be in the future"); + } + if (new Date(body.start_date) >= new Date(body.end_date)) { + throw new InvalidParameter("StartDate and EndDate", "Start Date must be before End Date"); + } + } else if (body.start_date && !body.end_date) { + if (new Date(body.start_date) >= activity.end_date) { + throw new InvalidParameter("StartDate", "Start Date must be before End Date"); + } + } else if (!body.start_date && body.end_date) { + if (activity.start_date >= new Date(body.end_date)) { + throw new InvalidParameter("EndDate", "End Date must be after Start Date"); + } } - } else if (body.start_date && !body.end_date) { - if (new Date(body.start_date) >= activity.end_date) { - throw new InvalidParameter("StartDate", "Start Date must be before End Date"); + activity_update = new Activity({ + id: activity.id, + title: body.title ? body.title : activity.title, + description: body.description ? body.description : activity.description, + start_date: body.start_date ? new Date(body.start_date) : activity.start_date, + end_date: body.end_date ? new Date(body.end_date) : activity.end_date, + languages: languages.length > 0 ? languages : activity.languages, + courses: courses.length > 0 ? courses : activity.courses, + partner_institutions: partner_institutions.length > 0 ? partner_institutions : activity.partner_institutions, + criterias: criterias.length > 0 ? criterias : activity.criterias, + status_activity: activity.status_activity, + type_activity: activity.type_activity, + created_at: activity.created_at, + updated_at: new Date(), + applicants: activity.applicants + }); + } else { + activity = await this.activity_repo.get_activity(body.activity_id); + if (!activity) { + throw new NotfoundError("Activity not found"); } - } else if (!body.start_date && body.end_date) { - if (activity.start_date >= new Date(body.end_date)) { - throw new InvalidParameter("EndDate", "End Date must be after Start Date"); + if (![ActivityStatusEnum.ENDED, ActivityStatusEnum.CANCELED].includes(body.status_activity)) { + throw new InvalidParameter("Status Activity", "Invalid status activity"); } + activity_update = new Activity({ + id: activity.id, + title: activity.title, + description: activity.description, + start_date: activity.start_date, + end_date: activity.end_date, + languages: activity.languages, + courses: activity.courses, + partner_institutions: activity.partner_institutions, + criterias: activity.criterias, + status_activity: body.status_activity, + type_activity: activity.type_activity, + created_at: activity.created_at, + updated_at: new Date(), + applicants: activity.applicants + }); } - const activity_update: Activity = new Activity({ - id: activity.id, - title: body.title ? body.title : activity.title, - description: body.description ? body.description : activity.description, - start_date: body.start_date ? new Date(body.start_date) : activity.start_date, - end_date: body.end_date ? new Date(body.end_date) : activity.end_date, - languages: languages.length > 0 ? languages : activity.languages, - courses: courses.length > 0 ? courses : activity.courses, - partner_institutions: partner_institutions.length > 0 ? partner_institutions : activity.partner_institutions, - criterias: criterias.length > 0 ? criterias : activity.criterias, - status_activity: status_activity ? status_activity : activity.status_activity, - type_activity: activity.type_activity, - created_at: activity.created_at, - updated_at: new Date(), - applicants: activity.applicants - }); - await this.activity_repo.update_activity(activity_update).then(async (response) => { if (response && process.env.STAGE === "prod") { if (activity_update.start_date !== activity.start_date) { diff --git a/test/modules/update_activity/app/update_activity.test.ts b/test/modules/update_activity/app/update_activity.test.ts index 165c934..c453cdf 100644 --- a/test/modules/update_activity/app/update_activity.test.ts +++ b/test/modules/update_activity/app/update_activity.test.ts @@ -132,7 +132,7 @@ describe("Update Activity Presenter", () => { partner_institutions: [activity.partner_institutions[0].id], criterias: [activity.criterias[0].criteria], courses: [{ id: activity.courses[0].id, name: activity.courses[0].name }], - status_activity: activity.status_activity, + status_activity: null, type_activity: activity.type_activity, start_date: new Date(), end_date: new Date(), From aef6116c8dc81df13042540f3a36a8e765b82519 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Thu, 23 May 2024 10:14:30 -0300 Subject: [PATCH 12/71] refactor: Update populate_database.ts to create or update activity status --- populate_database.ts | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/populate_database.ts b/populate_database.ts index 776d7cc..ea7b54f 100644 --- a/populate_database.ts +++ b/populate_database.ts @@ -269,6 +269,39 @@ async function createOrUpdateUser(user: UserEntity): Promise { } } +async function createOrUpdateStatusActivity(status: ActivityStatusEnum) { + try { + let existing = await ActivityStatus.findOne({ where: { id: status } }); + let name: string; + switch (status) { + case ActivityStatusEnum.ACTIVE: + name = "Apply Now"; + break; + case ActivityStatusEnum.CANCELED: + name = "Canceled"; + break; + case ActivityStatusEnum.ENDED: + name = "Ended"; + break; + case ActivityStatusEnum.ON_HOLD: + name = "Under Analysis"; + break; + case ActivityStatusEnum.TO_START: + name = "Coming Soon"; + break; + } + if (!existing) { + await ActivityStatus.create({ name: name }); + console.log(`Activity status ${status} created`); + } else { + await ActivityStatus.update({ name: name }, { where: { id: status } }); + console.log(`Activity status ${status} updated`); + } + } catch (error) { + console.error(`Error creating or updating activity status ${status}:`, error); + } +} + (async () => { try { await handleDatabaseCreation(); @@ -278,7 +311,7 @@ async function createOrUpdateUser(user: UserEntity): Promise { await handleLanguagesCreation(); await handleCountriesCreation(); - + await handleCriteriasCreation(); await createOrUpdateSocialMedia(); From ae27ad4177c4979cc9f2c81030dceaeacee35d7e Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Thu, 23 May 2024 10:43:23 -0300 Subject: [PATCH 13/71] refactor: Update populate_database.ts to create or update activity status --- populate_database.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/populate_database.ts b/populate_database.ts index ea7b54f..270ffaf 100644 --- a/populate_database.ts +++ b/populate_database.ts @@ -314,9 +314,14 @@ async function createOrUpdateStatusActivity(status: ActivityStatusEnum) { await handleCriteriasCreation(); - await createOrUpdateSocialMedia(); + await createOrUpdateSocialMedia(); + + await createOrUpdateStatusActivity(ActivityStatusEnum.ACTIVE); + await createOrUpdateStatusActivity(ActivityStatusEnum.CANCELED); + await createOrUpdateStatusActivity(ActivityStatusEnum.ENDED); + await createOrUpdateStatusActivity(ActivityStatusEnum.ON_HOLD); + await createOrUpdateStatusActivity(ActivityStatusEnum.TO_START); - await createOrUpdateEnumItems(ActivityStatus, activityStatuses, ActivityStatusEnum); await createOrUpdateEnumItems(ActivityType, activityTypes, ActivityTypeEnum); await createOrUpdateEnumItems(UserType, userTypes, UserTypeEnum); From 2565464d6c87a16738dd35b9141a6f28ac4f46e6 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 10:39:36 -0300 Subject: [PATCH 14/71] refactor: Update LambdaStack to include new function get_all_activities_catalog --- iac/lib/iac_stack.ts | 3 +-- iac/lib/lambda_stack.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/iac/lib/iac_stack.ts b/iac/lib/iac_stack.ts index 90555f0..bbf91a5 100644 --- a/iac/lib/iac_stack.ts +++ b/iac/lib/iac_stack.ts @@ -19,8 +19,7 @@ export class IacStack extends cdk.Stack { allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], allowHeaders: ["*"], } - } - ); + }); const bucket = new Bucket(this, "Coil_Bucket", { bucketName: "coil-bucket", diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index b2a32b3..7d07f18 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -21,6 +21,7 @@ export class LambdaStack extends Construct { private update_users_activity: lambda_js.NodejsFunction; private update_activity_event: lambda_js.NodejsFunction; private get_activity_requirements: lambda_js.NodejsFunction; + private get_all_activities_catalog: lambda_js.NodejsFunction; private get_all_activities_enrolled: lambda_js.NodejsFunction; public functions_need_s3_access: lambda.Function[] = []; @@ -222,6 +223,14 @@ export class LambdaStack extends Construct { origins ) + this.get_all_activities_catalog = this.create_lambda( + "get_all_activities_catalog", + environment_variables, + "GET", + restapi_resource, + origins + ) + this.functions_need_s3_access = [ this.create_institution, this.update_institution, From c9b30ae16d4b3d672496d4be4bfe89e97b81fc67 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 10:39:44 -0300 Subject: [PATCH 15/71] refactor: Update ActivityRepo to include get_all_activities_catalog method --- .../database/repositories/ActivityRepo.ts | 31 ++++++++++++++++++- .../repositories/interfaces/IActivityRepo.ts | 3 +- .../repositories/mocks/ActivityRepoMock.ts | 8 +++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 96f55ad..0396f9b 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -354,7 +354,7 @@ export class ActivityRepo implements IActivityRepo { id: activity.id } }); - + await ActivityPartnerInstitution.destroy({ where: { activity_id: activity.id @@ -453,4 +453,33 @@ export class ActivityRepo implements IActivityRepo { } return true; } + + async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { + const response = await ActivityDB.findAll({ + attributes: ["title", "type_id"], + include: [{ + model: ActivityPartnerInstitution, as: 'partner_institutions', include: + [{ + model: Institution, as: 'institution', include: + [{ + model: InstitutionImageDB, as: 'images', limit: 1, order: [['id', 'ASC']], attributes: ['image'] + }] + }] + }], + where: { + status_id: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] + }, + order: [ + ['start_date', 'ASC'] + ] + }); + + let activities = response.map(activity => activity.toJSON()); + + return activities.map(activity => ({ + title: activity.title, + logo: activity.partner_institutions[0].institution.images[0].image, + type_activity: activity.type_id + })); + } } \ No newline at end of file diff --git a/src/core/repositories/interfaces/IActivityRepo.ts b/src/core/repositories/interfaces/IActivityRepo.ts index 67dbc3f..4432011 100644 --- a/src/core/repositories/interfaces/IActivityRepo.ts +++ b/src/core/repositories/interfaces/IActivityRepo.ts @@ -11,10 +11,11 @@ export interface IActivityRepo { check_activity_by_title(title: string): Promise check_activity_enrolled_by_user(user_id: string, activity_id: string): Promise + get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> get_activity(id: string, applicants?: boolean): Promise + get_activities_by_user_id(user_id: string, type: ActivityTypeEnum): Promise get_activity_applicant(activity_id: string, user_id: string): Promise<{ user_id: string, status: boolean } | null> get_activity_applicants(activity_id: string, applicants: string[]): Promise<{ user_id: string, status: boolean }[]> - get_activities_by_user_id(user_id: string, type: ActivityTypeEnum): Promise get_all_activities_by_status(status: ActivityStatusEnum | ActivityStatusEnum[], type: ActivityTypeEnum): Promise assign_user_to_activity(activity_id: string, user_id: string): Promise<{ assign: boolean }> diff --git a/src/core/repositories/mocks/ActivityRepoMock.ts b/src/core/repositories/mocks/ActivityRepoMock.ts index c050781..292503e 100644 --- a/src/core/repositories/mocks/ActivityRepoMock.ts +++ b/src/core/repositories/mocks/ActivityRepoMock.ts @@ -165,4 +165,12 @@ export class ActivityRepoMock implements IActivityRepo { }); } + async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { + return this.activity_mock.activities.map(activity => ({ + title: activity.title, + logo: activity.partner_institutions[0].institution?.images[0] || "", + type_activity: activity.type_activity + })); + } + } From 9a32897f2b78598a2c837747f34ce6012a272a22 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 10:39:51 -0300 Subject: [PATCH 16/71] refactor: Add GetAllActivitiesCatalog feature --- .../get_all_activities_catalog_controller.ts | 45 +++++++++++++++++++ .../get_all_activities_catalog_presenter.ts | 17 +++++++ .../app/get_all_activities_catalog_usecase.ts | 30 +++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts create mode 100644 src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts create mode 100644 src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts new file mode 100644 index 0000000..8eadc49 --- /dev/null +++ b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts @@ -0,0 +1,45 @@ +import { + HttpRequest, + HttpResponse, + OK, + BadRequest, + Unauthorized, + ParameterError, + InternalServerError, +} from "../../../core/helpers/http/http_codes"; +import { + InvalidRequest, + MissingParameter, + UserNotAuthenticated, +} from "../../../core/helpers/errors/ModuleError"; +import { GetAllActivitiesCatalogUsecase } from "./get_all_activities_catalog_usecase"; + + +export class GetAllActivitiesCatalogController { + public usecase: GetAllActivitiesCatalogUsecase; + + constructor(usecase: GetAllActivitiesCatalogUsecase) { + this.usecase = usecase; + } + + public async execute(request: HttpRequest): Promise { + try { + if (!request) { + throw new InvalidRequest(); + } + const response = await this.usecase.execute(); + return new OK(response, "Activities found successfully"); + } catch (error: any) { + if (error instanceof InvalidRequest) { + return new BadRequest(error.message); + } + if (error instanceof UserNotAuthenticated) { + return new Unauthorized(error.message); + } + if (error instanceof MissingParameter) { + return new ParameterError(error.message); + } + return new InternalServerError(error.message); + } + } +} diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts new file mode 100644 index 0000000..9a15606 --- /dev/null +++ b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts @@ -0,0 +1,17 @@ +import { Repository } from "../../../core/repositories/Repository"; +import { HttpRequest } from "../../../core/helpers/http/http_codes"; +import { GetAllActivitiesCatalogUsecase } from "./get_all_activities_catalog_usecase"; +import { GetAllActivitiesCatalogController } from "./get_all_activities_catalog_controller"; + +const repository = new Repository({ user_repo: true, activity_repo: true }); + +const usecase = new GetAllActivitiesCatalogUsecase( + repository.ActivityRepo +); +const controller = new GetAllActivitiesCatalogController(usecase); + +export const handler = async (event: any, context: any) => { + let request = new HttpRequest(event); + let response = await controller.execute(request); + return response.to_json(); +}; diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts new file mode 100644 index 0000000..c936a21 --- /dev/null +++ b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts @@ -0,0 +1,30 @@ +import { TokenAuth } from "../../../core/helpers/functions/token_auth"; +import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; +import { ActivityTypeEnum } from "../../../core/helpers/enums/ActivityTypeEnum"; +import { IActivityRepo } from "../../../core/repositories/interfaces/IActivityRepo"; + + +export class GetAllActivitiesCatalogUsecase { + public token_auth: TokenAuth; + public activity_repo: IActivityRepo; + + constructor(activity_repo: IActivityRepo) { + this.token_auth = new TokenAuth(); + this.activity_repo = activity_repo; + } + + async execute() { + + const activities = await this.activity_repo.get_all_activities_catalog(); + + const projects = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.PROJECT) : null; + const mobilities = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.ACADEMIC_MOBILITY) : null; + + const response = { + projects: projects, + mobilities: mobilities + } + + return response; + } +} From b62985470844c5b425db98e5f6f21a6d3c9b9460 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 10:39:56 -0300 Subject: [PATCH 17/71] refactor: Add unit test for GetAllActivitiesCatalog feature --- .../app/get_all_activities_catalog.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts diff --git a/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts b/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts new file mode 100644 index 0000000..f5d0c05 --- /dev/null +++ b/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts @@ -0,0 +1,19 @@ +import { it, describe, expect } from "vitest"; +import { ActivityMock } from "../../../../src/core/structure/mocks/ActivityMock"; +import { handler } from "../../../../src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter"; + +describe("Get All Activities Catalog", () => { + it("should return all activities", async () => { + const activityMock = new ActivityMock(); + const event = { + headers: { + }, + }; + const response = await handler(event, null); + expect(response.statusCode).toBe(200); + console.log(response.body); + }); + +}); + + From 75cf320616a79f6e8c9cbfa395b17b534acb4bce Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:00:10 -0300 Subject: [PATCH 18/71] refactor: Update GetAllActivitiesCatalogController to handle error cases --- .../app/get_all_activities_catalog_controller.ts | 11 ++--------- .../app/get_all_activities_catalog_usecase.ts | 5 ++--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts index 8eadc49..4410244 100644 --- a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts +++ b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts @@ -27,18 +27,11 @@ export class GetAllActivitiesCatalogController { if (!request) { throw new InvalidRequest(); } + const response = await this.usecase.execute(); return new OK(response, "Activities found successfully"); + } catch (error: any) { - if (error instanceof InvalidRequest) { - return new BadRequest(error.message); - } - if (error instanceof UserNotAuthenticated) { - return new Unauthorized(error.message); - } - if (error instanceof MissingParameter) { - return new ParameterError(error.message); - } return new InternalServerError(error.message); } } diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts index c936a21..70bcf30 100644 --- a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts +++ b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts @@ -14,9 +14,8 @@ export class GetAllActivitiesCatalogUsecase { } async execute() { - const activities = await this.activity_repo.get_all_activities_catalog(); - + const projects = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.PROJECT) : null; const mobilities = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.ACADEMIC_MOBILITY) : null; @@ -24,7 +23,7 @@ export class GetAllActivitiesCatalogUsecase { projects: projects, mobilities: mobilities } - + return response; } } From 8b96159d6e3e3f301bd6d5ef50f914d81c75fcb8 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:04:44 -0300 Subject: [PATCH 19/71] refactor: Include partner institutions in get_all_activities_catalog response --- src/core/repositories/database/repositories/ActivityRepo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 0396f9b..a0ef2c5 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -456,7 +456,7 @@ export class ActivityRepo implements IActivityRepo { async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { const response = await ActivityDB.findAll({ - attributes: ["title", "type_id"], + attributes: ["title", "type_id", "partner_institutions"], include: [{ model: ActivityPartnerInstitution, as: 'partner_institutions', include: [{ From a2f61ed9ea39e4651e4eb241bf44192441b14ef9 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:12:51 -0300 Subject: [PATCH 20/71] refactor: Exclude unnecessary attributes in get_all_activities_catalog response --- src/core/repositories/database/repositories/ActivityRepo.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index a0ef2c5..60d97d7 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -456,7 +456,9 @@ export class ActivityRepo implements IActivityRepo { async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { const response = await ActivityDB.findAll({ - attributes: ["title", "type_id", "partner_institutions"], + attributes: { + exclude: ['description', 'start_date', 'end_date', 'created_at', 'updated_at'] + }, include: [{ model: ActivityPartnerInstitution, as: 'partner_institutions', include: [{ From 23113cdc43f85c65dddaffa5541fb26e618a0cd9 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:27:46 -0300 Subject: [PATCH 21/71] refactor: Update ActivityRepo to include get_all_activities_catalog method --- .../database/repositories/ActivityRepo.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 60d97d7..7db1fd8 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -25,6 +25,7 @@ import { Country, SocialMedia } from "../models/Models"; +import { a } from "vitest/dist/suite-IbNSsUWN"; export class ActivityRepo implements IActivityRepo { @@ -158,8 +159,6 @@ export class ActivityRepo implements IActivityRepo { return null; } - console.log(activities.map((activity) => activity.toJSON())); - return activities.map((activity) => this.ActivityDTO.to_entity(activity.toJSON())); } @@ -460,13 +459,15 @@ export class ActivityRepo implements IActivityRepo { exclude: ['description', 'start_date', 'end_date', 'created_at', 'updated_at'] }, include: [{ - model: ActivityPartnerInstitution, as: 'partner_institutions', include: - [{ - model: Institution, as: 'institution', include: - [{ - model: InstitutionImageDB, as: 'images', limit: 1, order: [['id', 'ASC']], attributes: ['image'] - }] - }] + model: ActivityPartnerInstitution, as: 'partner_institutions', + include: [{ + model: Institution, + as: 'institution', + include: [{ + model: InstitutionImageDB, as: 'images', limit: 1, order: [['id', 'ASC']], attributes: ['image'] + }], + limit: 1 + }] }], where: { status_id: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] @@ -476,11 +477,19 @@ export class ActivityRepo implements IActivityRepo { ] }); - let activities = response.map(activity => activity.toJSON()); + let activities: { + title: string; + partner_institutions: { + institution: { + images: { image: string }[]; + }; + }[]; + type_id: ActivityTypeEnum; + }[] = response.map(activity => activity.toJSON()); return activities.map(activity => ({ title: activity.title, - logo: activity.partner_institutions[0].institution.images[0].image, + logo: activity.partner_institutions.length > 0 ? activity.partner_institutions[0].institution.images[0].image : "", type_activity: activity.type_id })); } From 630486ae3cc6d6d2e415320c9713a35485c34e0b Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:34:32 -0300 Subject: [PATCH 22/71] refactor: Include partner institutions in get_all_activities_catalog response --- src/core/repositories/database/repositories/ActivityRepo.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 7db1fd8..aa4b2b3 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -487,9 +487,13 @@ export class ActivityRepo implements IActivityRepo { type_id: ActivityTypeEnum; }[] = response.map(activity => activity.toJSON()); + activities = activities.map(activity => ( + activity = activity.partner_institutions.length > 0 ? activity : { ...activity, partner_institutions: [{ institution: { images: [{ image: "" }] } }] } + )); + return activities.map(activity => ({ title: activity.title, - logo: activity.partner_institutions.length > 0 ? activity.partner_institutions[0].institution.images[0].image : "", + logo: activity.partner_institutions[0].institution.images[0].image, type_activity: activity.type_id })); } From e6c0ea84b0daa67e4ee86d4ec17385b5c8ccadd2 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:36:38 -0300 Subject: [PATCH 23/71] refactor: Include partner institutions in get_all_activities_catalog response --- .../repositories/database/repositories/ActivityRepo.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index aa4b2b3..e3d01a4 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -464,9 +464,11 @@ export class ActivityRepo implements IActivityRepo { model: Institution, as: 'institution', include: [{ - model: InstitutionImageDB, as: 'images', limit: 1, order: [['id', 'ASC']], attributes: ['image'] - }], - limit: 1 + model: InstitutionImageDB, as: 'images', + limit: 1, + order: [['id', 'ASC']], + attributes: ['image'] + }] }] }], where: { From 0a2091d492ce2838fe51b992671f626ca0b46f50 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:40:10 -0300 Subject: [PATCH 24/71] refactor: Include partner institutions in get_all_activities_catalog response --- .../repositories/database/repositories/ActivityRepo.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index e3d01a4..c5981b6 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -455,9 +455,6 @@ export class ActivityRepo implements IActivityRepo { async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { const response = await ActivityDB.findAll({ - attributes: { - exclude: ['description', 'start_date', 'end_date', 'created_at', 'updated_at'] - }, include: [{ model: ActivityPartnerInstitution, as: 'partner_institutions', include: [{ @@ -466,13 +463,14 @@ export class ActivityRepo implements IActivityRepo { include: [{ model: InstitutionImageDB, as: 'images', limit: 1, - order: [['id', 'ASC']], - attributes: ['image'] + order: [['id', 'ASC']] }] }] }], where: { - status_id: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] + status_id: { + [Op.or]: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] + } }, order: [ ['start_date', 'ASC'] From eac58dc7238aabfa11b825d8c5e730c41b6fd84e Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:47:18 -0300 Subject: [PATCH 25/71] refactor: Include partner institutions in get_all_activities_catalog response --- .../database/repositories/ActivityRepo.ts | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index c5981b6..31f84ca 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -454,7 +454,7 @@ export class ActivityRepo implements IActivityRepo { } async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { - const response = await ActivityDB.findAll({ + const response_project = await ActivityDB.findAll({ include: [{ model: ActivityPartnerInstitution, as: 'partner_institutions', include: [{ @@ -465,19 +465,48 @@ export class ActivityRepo implements IActivityRepo { limit: 1, order: [['id', 'ASC']] }] - }] + }], + limit: 5 }], where: { status_id: { [Op.or]: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] - } + }, + type_id: ActivityTypeEnum.PROJECT + }, + order: [ + ['start_date', 'ASC'] + ] + }); + + const response_mobility = await ActivityDB.findAll({ + include: [{ + model: ActivityPartnerInstitution, as: 'partner_institutions', + include: [{ + model: Institution, + as: 'institution', + include: [{ + model: InstitutionImageDB, as: 'images', + limit: 1, + order: [['id', 'ASC']] + }] + }], + limit: 5 + }], + where: { + status_id: { + [Op.or]: [ActivityStatusEnum.ACTIVE, ActivityStatusEnum.TO_START] + }, + type_id: ActivityTypeEnum.ACADEMIC_MOBILITY }, order: [ ['start_date', 'ASC'] ] }); - let activities: { + let activities = response_project.concat(response_mobility); + + let activities_json: { title: string; partner_institutions: { institution: { @@ -485,13 +514,13 @@ export class ActivityRepo implements IActivityRepo { }; }[]; type_id: ActivityTypeEnum; - }[] = response.map(activity => activity.toJSON()); + }[] = activities.map(activity => activity.toJSON()); - activities = activities.map(activity => ( + activities_json = activities_json.map(activity => ( activity = activity.partner_institutions.length > 0 ? activity : { ...activity, partner_institutions: [{ institution: { images: [{ image: "" }] } }] } )); - return activities.map(activity => ({ + return activities_json.map(activity => ({ title: activity.title, logo: activity.partner_institutions[0].institution.images[0].image, type_activity: activity.type_id From 35550d1fea0bf461b6755e054130408fd932bc5b Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 11:50:26 -0300 Subject: [PATCH 26/71] refactor: Update ActivityRepo to include get_all_activities_catalog method --- .../database/repositories/ActivityRepo.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 31f84ca..8531a78 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -465,8 +465,7 @@ export class ActivityRepo implements IActivityRepo { limit: 1, order: [['id', 'ASC']] }] - }], - limit: 5 + }] }], where: { status_id: { @@ -476,7 +475,8 @@ export class ActivityRepo implements IActivityRepo { }, order: [ ['start_date', 'ASC'] - ] + ], + limit: 5 }); const response_mobility = await ActivityDB.findAll({ @@ -490,8 +490,7 @@ export class ActivityRepo implements IActivityRepo { limit: 1, order: [['id', 'ASC']] }] - }], - limit: 5 + }] }], where: { status_id: { @@ -501,7 +500,8 @@ export class ActivityRepo implements IActivityRepo { }, order: [ ['start_date', 'ASC'] - ] + ], + limit: 5 }); let activities = response_project.concat(response_mobility); From e92ab506aa64b914c4923df4045211a112e72f47 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 22:45:00 -0300 Subject: [PATCH 27/71] chore: Add validation for missing name parameter in CreateModeratorUsecase --- .../create_moderator/app/create_moderator_usecase.ts | 12 +++++++++++- .../create_moderator/app/create_moderator.test.ts | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/modules/create_moderator/app/create_moderator_usecase.ts b/src/modules/create_moderator/app/create_moderator_usecase.ts index c3ee7ee..9c16594 100644 --- a/src/modules/create_moderator/app/create_moderator_usecase.ts +++ b/src/modules/create_moderator/app/create_moderator_usecase.ts @@ -27,6 +27,9 @@ export class CreateModeratorUsecase { if (!headers.Authorization) { throw new MissingParameter("Authorization"); } + if (!body.name) { + throw new MissingParameter("Name"); + } if (!body.email) { throw new MissingParameter("Email"); } @@ -46,15 +49,22 @@ export class CreateModeratorUsecase { throw new UserNotAllowed(); } + if (user_admin.email === body.email) { + throw new UserNotAllowed("Admin can't be a moderator"); + } + const user = await this.database_repo.get_user_by_email(body.email); if (user) { + if (user.user_type === UserTypeEnum.ADMIN) { + throw new UserNotAllowed("Admin can't be a moderator"); + } user.user_type = UserTypeEnum.MODERATOR; this.database_repo.update_user(user); } else { const moderator = new User({ id: randomUUID(), - name: null, + name: body.name, email: body.email, user_type: UserTypeEnum.MODERATOR, created_at: new Date(), diff --git a/test/modules/create_moderator/app/create_moderator.test.ts b/test/modules/create_moderator/app/create_moderator.test.ts index bae7150..fc08837 100644 --- a/test/modules/create_moderator/app/create_moderator.test.ts +++ b/test/modules/create_moderator/app/create_moderator.test.ts @@ -9,6 +9,7 @@ describe("Testing Create Moderator Presenter", () => { const user_admin = new UserMock().users[0]; const user_student = new UserMock().users[1]; const user_moderator = { + name: "Moderator Test", email: "moderador@maua.br" }; From 5a8988bc9ad326a29cccc64f49ec04b07369d3af Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 22:53:13 -0300 Subject: [PATCH 28/71] refactor: Add method to UserRepo to get all moderators --- .../repositories/database/repositories/UserRepo.ts | 14 ++++++++++++++ src/core/repositories/interfaces/IUserRepo.ts | 1 + src/core/repositories/mocks/UserRepoMock.ts | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/src/core/repositories/database/repositories/UserRepo.ts b/src/core/repositories/database/repositories/UserRepo.ts index 894c73e..6d4a262 100644 --- a/src/core/repositories/database/repositories/UserRepo.ts +++ b/src/core/repositories/database/repositories/UserRepo.ts @@ -2,6 +2,7 @@ import { UserDTO } from "../dtos/UserDTO"; import { IUserRepo } from "../../interfaces/IUserRepo"; import { User } from "../../../structure/entities/User"; import { User as UserDB, UserType as UserTypeDB } from "../models/Models"; +import { UserTypeEnum } from "../../../helpers/enums/UserTypeEnum"; export class UserRepo implements IUserRepo { private user_dto: UserDTO = new UserDTO(); @@ -68,4 +69,17 @@ export class UserRepo implements IUserRepo { return user_updated ? true : false; } + + public async get_all_moderators(): Promise { + let moderators_found = await UserDB.findAll({ + where: { + user_type_id: UserTypeEnum.MODERATOR, + }, + include: [ + { model: UserTypeDB, as: 'user_type' } + ] + }); + + return moderators_found.map((moderator) => this.user_dto.to_entity(moderator.toJSON())); + } } diff --git a/src/core/repositories/interfaces/IUserRepo.ts b/src/core/repositories/interfaces/IUserRepo.ts index 2744f92..6212897 100644 --- a/src/core/repositories/interfaces/IUserRepo.ts +++ b/src/core/repositories/interfaces/IUserRepo.ts @@ -5,4 +5,5 @@ export interface IUserRepo { update_user(user: User): Promise; get_user(id: string): Promise; get_user_by_email(email: string): Promise; + get_all_moderators(): Promise; } diff --git a/src/core/repositories/mocks/UserRepoMock.ts b/src/core/repositories/mocks/UserRepoMock.ts index eee3013..39a6d8f 100644 --- a/src/core/repositories/mocks/UserRepoMock.ts +++ b/src/core/repositories/mocks/UserRepoMock.ts @@ -1,6 +1,7 @@ import { IUserRepo } from "../interfaces/IUserRepo"; import { User } from "../../structure/entities/User"; import { UserMock } from "../../structure/mocks/UserMock"; +import { UserTypeEnum } from "../../helpers/enums/UserTypeEnum"; export class UserRepoMock implements IUserRepo { public user_mock: UserMock; @@ -35,4 +36,11 @@ export class UserRepoMock implements IUserRepo { resolve(user || null); }); } + + public get_all_moderators(): Promise { + return new Promise((resolve, reject) => { + const moderators = this.user_mock.users.filter((user) => user.user_type === UserTypeEnum.MODERATOR); + resolve(moderators); + }); + } } \ No newline at end of file From 221e4fabae021d5a3ce713a091cac572af30b6c4 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 22:53:23 -0300 Subject: [PATCH 29/71] refactor: Add GetAllModerators feature --- .../app/get_all_moderators_controller.ts | 57 +++++++++++++++++++ .../app/get_all_moderators_presenter.ts | 17 ++++++ .../app/get_all_moderators_usecase.ts | 46 +++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/modules/get_all_moderators/app/get_all_moderators_controller.ts create mode 100644 src/modules/get_all_moderators/app/get_all_moderators_presenter.ts create mode 100644 src/modules/get_all_moderators/app/get_all_moderators_usecase.ts diff --git a/src/modules/get_all_moderators/app/get_all_moderators_controller.ts b/src/modules/get_all_moderators/app/get_all_moderators_controller.ts new file mode 100644 index 0000000..d2f7555 --- /dev/null +++ b/src/modules/get_all_moderators/app/get_all_moderators_controller.ts @@ -0,0 +1,57 @@ +import { GetAllModeratorsUsecase } from "./get_all_moderators_usecase"; + +import { UniqueConstraintError } from "sequelize"; +import { EntityError } from '../../../core/helpers/errors/EntityError'; +import { BadRequest, ParameterError, InternalServerError } from '../../../core/helpers/http/http_codes'; +import { Conflict, Created, Forbidden, HttpRequest, HttpResponse, Unauthorized, Unprocessable_Entity } from '../../../core/helpers/http/http_codes'; +import { ConflictError, InvalidParameter, InvalidRequest, MissingParameter, UserNotAllowed, UserNotAuthenticated } from '../../../core/helpers/errors/ModuleError'; + + +export class GetAllModeratorsController { + public usecase: GetAllModeratorsUsecase; + + constructor(usecase: GetAllModeratorsUsecase) { + this.usecase = usecase; + } + + public async execute(request: HttpRequest): Promise { + try { + if (!request) { + throw new InvalidRequest(); + } + if (!request.headers) { + throw new InvalidRequest("Headers"); + } + + let response = await this.usecase.execute(request.headers); + return new Created(response, "Moderators found successfully"); + + } catch (error: any) { + if (error instanceof InvalidRequest) { + return new BadRequest(error.message); + } + if (error instanceof UserNotAuthenticated) { + return new Unauthorized(error.message); + } + if (error instanceof UserNotAllowed) { + return new Forbidden(error.message); + } + if (error instanceof ConflictError) { + return new Conflict(error.message); + } + if (error instanceof EntityError) { + return new ParameterError(error.message); + } + if (error instanceof InvalidParameter) { + return new ParameterError(error.message); + } + if (error instanceof UniqueConstraintError) { + return new Unprocessable_Entity(error.message); + } + if (error instanceof MissingParameter) { + return new ParameterError(error.message); + } + return new InternalServerError(error.message); + } + } +} \ No newline at end of file diff --git a/src/modules/get_all_moderators/app/get_all_moderators_presenter.ts b/src/modules/get_all_moderators/app/get_all_moderators_presenter.ts new file mode 100644 index 0000000..b5fc9f6 --- /dev/null +++ b/src/modules/get_all_moderators/app/get_all_moderators_presenter.ts @@ -0,0 +1,17 @@ +import { GetAllModeratorsUsecase } from "./get_all_moderators_usecase"; +import { GetAllModeratorsController } from "./get_all_moderators_controller"; + +import { Repository } from "../../../core/repositories/Repository"; +import { HttpRequest } from "../../../core/helpers/http/http_codes"; + +const repository = new Repository({ user_repo: true }); + +const usecase = new GetAllModeratorsUsecase(repository.UserRepo); +const controller = new GetAllModeratorsController(usecase); + + +export const handler = async (event: any, context: any) => { + let request = new HttpRequest(event); + let response = await controller.execute(request); + return response.to_json(); +} diff --git a/src/modules/get_all_moderators/app/get_all_moderators_usecase.ts b/src/modules/get_all_moderators/app/get_all_moderators_usecase.ts new file mode 100644 index 0000000..d41bc12 --- /dev/null +++ b/src/modules/get_all_moderators/app/get_all_moderators_usecase.ts @@ -0,0 +1,46 @@ +import { randomUUID } from "crypto"; +import { UniqueConstraintError } from "sequelize"; + +import { User } from '../../../core/structure/entities/User'; +import { TokenAuth } from '../../../core/helpers/functions/token_auth'; +import { UserTypeEnum } from '../../../core/helpers/enums/UserTypeEnum'; +import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; +import { InvalidRequest, MissingParameter, UserNotAllowed, UserNotAuthenticated } from '../../../core/helpers/errors/ModuleError'; + + +export class GetAllModeratorsUsecase { + public token_auth: TokenAuth; + public database_repo: IUserRepo; + + constructor(database_repo: IUserRepo) { + this.token_auth = new TokenAuth(); + this.database_repo = database_repo; + } + + public async execute(headers: { [key: string]: any }) { + if (!headers) { + throw new InvalidRequest("Headers"); + } + if (!headers.Authorization) { + throw new MissingParameter("Authorization"); + } + + const user_id = await this.token_auth + .decode_token(headers.Authorization) + .then((response) => { + return response; + }) + .catch((error) => { + throw new UserNotAuthenticated("Invalid or expired token"); + }); + + const user = await this.database_repo.get_user(user_id); + if (!user) { + throw new UserNotAuthenticated(); + } + + const moderators = await this.database_repo.get_all_moderators(); + + return moderators; + } +} \ No newline at end of file From ad48eef900e9d8afe1bee18f586afa603b1d89ab Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 24 May 2024 22:53:58 -0300 Subject: [PATCH 30/71] refactor: Add GetAllModerators feature --- iac/lib/lambda_stack.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 7d07f18..0933da2 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -6,6 +6,7 @@ export class LambdaStack extends Construct { private get_user: lambda_js.NodejsFunction; private auth_user: lambda_js.NodejsFunction; private create_moderator: lambda_js.NodejsFunction; + private get_all_moderators: lambda_js.NodejsFunction; private get_institution: lambda_js.NodejsFunction; private create_institution: lambda_js.NodejsFunction; @@ -231,6 +232,14 @@ export class LambdaStack extends Construct { origins ) + this.get_all_moderators = this.create_lambda( + "get_all_moderators", + environment_variables, + "GET", + restapi_resource, + origins + ) + this.functions_need_s3_access = [ this.create_institution, this.update_institution, From b0fdc88e331b1465734deb3de78b63cd8882b81e Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:02 -0300 Subject: [PATCH 31/71] feat: Add Deleted class to handle HTTP 204 responses --- src/core/helpers/http/http_codes.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/helpers/http/http_codes.ts b/src/core/helpers/http/http_codes.ts index ff2d441..0e3b25b 100644 --- a/src/core/helpers/http/http_codes.ts +++ b/src/core/helpers/http/http_codes.ts @@ -83,6 +83,12 @@ export class Created extends HttpResponse { } } +export class Deleted extends HttpResponse { + constructor(body: { [key: string]: any }, message: string) { + super(204, body, message); + } +} + export class BadRequest extends HttpResponse { constructor(message: string) { super(400, null, message); From 7558c618070f02b06fc6015757edb320ed697165 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:09 -0300 Subject: [PATCH 32/71] feat: Add delete_moderator method to UserRepo --- .../repositories/database/repositories/UserRepo.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/repositories/database/repositories/UserRepo.ts b/src/core/repositories/database/repositories/UserRepo.ts index 6d4a262..bbbe7d7 100644 --- a/src/core/repositories/database/repositories/UserRepo.ts +++ b/src/core/repositories/database/repositories/UserRepo.ts @@ -82,4 +82,15 @@ export class UserRepo implements IUserRepo { return moderators_found.map((moderator) => this.user_dto.to_entity(moderator.toJSON())); } + + public async delete_moderator(id: string): Promise { + let moderator_deleted = await UserDB.destroy({ + where: { + id: id, + user_type_id: UserTypeEnum.MODERATOR, + }, + }); + + return moderator_deleted ? true : false; + } } From 5b00daa23123c962717a4fc416632341d8d7463c Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:14 -0300 Subject: [PATCH 33/71] feat: Implement delete_moderator method in UserRepo --- src/core/repositories/interfaces/IUserRepo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/repositories/interfaces/IUserRepo.ts b/src/core/repositories/interfaces/IUserRepo.ts index 6212897..4c3e5d9 100644 --- a/src/core/repositories/interfaces/IUserRepo.ts +++ b/src/core/repositories/interfaces/IUserRepo.ts @@ -6,4 +6,5 @@ export interface IUserRepo { get_user(id: string): Promise; get_user_by_email(email: string): Promise; get_all_moderators(): Promise; + delete_moderator(id: string): Promise; } From 7734a013769d3848eb526ad14fc9c69a5aab05ae Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:17 -0300 Subject: [PATCH 34/71] Implement delete_moderator method in UserRepo --- src/core/repositories/mocks/UserRepoMock.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/repositories/mocks/UserRepoMock.ts b/src/core/repositories/mocks/UserRepoMock.ts index 39a6d8f..507684a 100644 --- a/src/core/repositories/mocks/UserRepoMock.ts +++ b/src/core/repositories/mocks/UserRepoMock.ts @@ -43,4 +43,12 @@ export class UserRepoMock implements IUserRepo { resolve(moderators); }); } + + public delete_moderator(id: string): Promise { + return new Promise((resolve, reject) => { + const userIndex = this.user_mock.users.findIndex((user) => user.id === id); + this.user_mock.users.splice(userIndex, 1); + resolve(true); + }); + } } \ No newline at end of file From cf62ba2b33c307a588ff6ab3bf97f5288727a0fd Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:21 -0300 Subject: [PATCH 35/71] feat: Implement DeleteModeratorController --- .../app/delete_moderator_controller.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/modules/delete_moderator/app/delete_moderator_controller.ts diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts new file mode 100644 index 0000000..1ec9d94 --- /dev/null +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -0,0 +1,55 @@ +import { + InvalidRequest, + MissingParameter, + UserNotAuthenticated, +} from "../../../core/helpers/errors/ModuleError"; +import { NotFoundError } from "../../../core/helpers/errors/RepoError"; +import { + BadRequest, + Deleted, + HttpRequest, + HttpResponse, + InternalServerError, + NotFound, + OK, + Unauthorized, +} from "../../../core/helpers/http/http_codes"; +import { DeleteModeratorUsecase } from "./delete_moderator_usecase"; + +export class DeleteModeratorController { + public usecase: DeleteModeratorUsecase; + + constructor(usecase: DeleteModeratorUsecase) { + this.usecase = usecase; + } + + public async execute(request: HttpRequest): Promise { + try { + if (!request) { + throw new InvalidRequest(); + } + if (!request.headers) { + throw new InvalidRequest("Headers"); + } + + const queryParams = request.body.queryStringParameters; + + let response = await this.usecase.execute(request.headers, queryParams); + return new Deleted(response, "Moderator deleted successfully"); + } catch (error: any) { + if (error instanceof InvalidRequest) { + return new BadRequest(error.message); + } + if (error instanceof UserNotAuthenticated) { + return new Unauthorized(error.message); + } + if (error instanceof MissingParameter) { + return new NotFound(error.message); + } + if (error instanceof NotFoundError) { + return new NotFound(error.message); + } + return new InternalServerError(error.message); + } + } +} From 2362f651ac410e12128c30821d998c3c456a8a3a Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:26 -0300 Subject: [PATCH 36/71] feat: Add delete_moderator_presenter module --- .../app/delete_moderator_presenter.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/modules/delete_moderator/app/delete_moderator_presenter.ts diff --git a/src/modules/delete_moderator/app/delete_moderator_presenter.ts b/src/modules/delete_moderator/app/delete_moderator_presenter.ts new file mode 100644 index 0000000..ab00e04 --- /dev/null +++ b/src/modules/delete_moderator/app/delete_moderator_presenter.ts @@ -0,0 +1,17 @@ +import { DeleteModeratorController } from "./delete_moderator_controller"; +import { DeleteModeratorUsecase } from "./delete_moderator_usecase"; + +import { Repository } from "../../../core/repositories/Repository"; +import { HttpRequest } from "../../../core/helpers/http/http_codes"; + +const repository = new Repository({user_repo: true}); + +const usecase = new DeleteModeratorUsecase(repository.UserRepo); +const controller = new DeleteModeratorController(usecase); + + +export const handler = async (event: any, context: any) => { + let request = new HttpRequest(event); + let response = await controller.execute(request); + return response.to_json(); +} From fc73709b58cb431f4420db467f2db6b01c0598e7 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 18:22:30 -0300 Subject: [PATCH 37/71] feat: Add DeleteModeratorUsecase --- .../app/delete_moderator_usecase.ts | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/modules/delete_moderator/app/delete_moderator_usecase.ts diff --git a/src/modules/delete_moderator/app/delete_moderator_usecase.ts b/src/modules/delete_moderator/app/delete_moderator_usecase.ts new file mode 100644 index 0000000..a5beb39 --- /dev/null +++ b/src/modules/delete_moderator/app/delete_moderator_usecase.ts @@ -0,0 +1,71 @@ +import { UserTypeEnum } from "../../../core/helpers/enums/UserTypeEnum"; +import { + InvalidRequest, + MissingParameter, + NotfoundError, + UserNotAuthenticated, +} from "../../../core/helpers/errors/ModuleError"; +import { TokenAuth } from "../../../core/helpers/functions/token_auth"; +import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; + +export class DeleteModeratorUsecase { + public token_auth: TokenAuth; + public database_repo: IUserRepo; + + constructor(database_repo: IUserRepo) { + this.token_auth = new TokenAuth(); + this.database_repo = database_repo; + } + + async execute( + headers: { [key: string]: any }, + queryStringParameters: { [key: string]: any } + ) { + if (!headers) { + throw new InvalidRequest("Headers"); + } + if (!headers.Authorization) { + throw new MissingParameter("Authorization"); + } + if (!queryStringParameters) { + throw new InvalidRequest("Body"); + } + if (!queryStringParameters.moderator_id) { + throw new MissingParameter("moderator_id"); + } + + const user_id = await this.token_auth + .decode_token(headers.Authorization) + .then((response) => { + return response; + }) + .catch((error) => { + throw new UserNotAuthenticated("Invalid or expired token"); + }); + + const user = await this.database_repo.get_user(user_id); + if (!user) { + throw new UserNotAuthenticated(); + } + + if (user.user_type !== UserTypeEnum.ADMIN) { + throw new UserNotAuthenticated(); + } + + const moderator = await this.database_repo.get_user( + queryStringParameters.moderator_id + ); + if (!moderator) { + throw new NotfoundError("Moderator"); + } + + if (moderator.user_type !== UserTypeEnum.MODERATOR) { + throw new InvalidRequest("User is not a moderator"); + } + + await this.database_repo.delete_moderator( + queryStringParameters.moderator_id + ); + return { message: "Moderator deleted successfully" }; + } +} From afe69c66e942e77004a9514135a694b6243971d7 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 19:40:25 -0300 Subject: [PATCH 38/71] feat: Add unit tests for Delete Moderator Presenter --- .../app/delete_moderator.test.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/modules/delete_moderator/app/delete_moderator.test.ts diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts new file mode 100644 index 0000000..df0f5ed --- /dev/null +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -0,0 +1,50 @@ +import { it, describe, expect } from 'vitest'; + +import { UserMock } from '../../../../src/core/structure/mocks/UserMock'; +import { TokenAuth } from '../../../../src/core/helpers/functions/token_auth'; +import { handler } from '../../../../src/modules/delete_moderator/app/delete_moderator_presenter'; + +describe("Testing Delete Moderator Presenter", () => { + const user_admin = new UserMock().users[0]; + const user_moderator = new UserMock().users[2]; + + it("should delete a moderator", async () => { + var token = (await new TokenAuth().generate_token(user_admin.id)).toString(); + + var response = await handler({ + headers: { + Authorization: token + }, + body: JSON.stringify({ id: user_moderator.id }) + }, null); + + expect(response.statusCode).toBe(200); + expect(JSON.parse(response.body).message).toBe("Moderator deleted successfully"); + }); + + it("should not delete a moderator with invalid token", async () => { + var response = await handler({ + headers: { + Authorization: "invalid_token" + }, + body: JSON.stringify({ id: user_moderator.id }) + }, null); + + expect(response.statusCode).toBe(401); + expect(JSON.parse(response.body).message).toBe("Invalid or expired token"); + }); + + it("should not delete a moderator with missing parameter id", async () => { + var token = (await new TokenAuth().generate_token(user_admin.id)).toString(); + + var response = await handler({ + headers: { + Authorization: token + }, + body: JSON.stringify({}) + }, null); + + expect(response.statusCode).toBe(400); + expect(JSON.parse(response.body).message).toBe("Missing parameter id"); + }); +}); From ff440c4f1fdc68a48a478d821e2cdf4ee5541e0e Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 19:47:31 -0300 Subject: [PATCH 39/71] feat: Update DeleteModeratorController to handle ParameterError --- .../delete_moderator/app/delete_moderator_controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts index 1ec9d94..519b922 100644 --- a/src/modules/delete_moderator/app/delete_moderator_controller.ts +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -12,6 +12,7 @@ import { InternalServerError, NotFound, OK, + ParameterError, Unauthorized, } from "../../../core/helpers/http/http_codes"; import { DeleteModeratorUsecase } from "./delete_moderator_usecase"; @@ -44,7 +45,7 @@ export class DeleteModeratorController { return new Unauthorized(error.message); } if (error instanceof MissingParameter) { - return new NotFound(error.message); + return new ParameterError(error.message); } if (error instanceof NotFoundError) { return new NotFound(error.message); From b2c673ef9f65ea9675aad460f1e8295247a1405b Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 19:47:52 -0300 Subject: [PATCH 40/71] needs 2 errors to verify --- test/modules/delete_moderator/app/delete_moderator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts index df0f5ed..92bba4d 100644 --- a/test/modules/delete_moderator/app/delete_moderator.test.ts +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -45,6 +45,6 @@ describe("Testing Delete Moderator Presenter", () => { }, null); expect(response.statusCode).toBe(400); - expect(JSON.parse(response.body).message).toBe("Missing parameter id"); + expect(JSON.parse(response.body).message).toBe("Body not found"); }); }); From f0e0d21fbd0279db4ae7f5c4c8f8d2f64b32f080 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 19:53:03 -0300 Subject: [PATCH 41/71] feat: Add delete_moderator lambda function --- iac/lib/lambda_stack.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 0933da2..8f1b96d 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -7,6 +7,7 @@ export class LambdaStack extends Construct { private auth_user: lambda_js.NodejsFunction; private create_moderator: lambda_js.NodejsFunction; private get_all_moderators: lambda_js.NodejsFunction; + private delete_moderator: lambda_js.NodejsFunction; private get_institution: lambda_js.NodejsFunction; private create_institution: lambda_js.NodejsFunction; @@ -106,6 +107,14 @@ export class LambdaStack extends Construct { origins ); + this.delete_moderator = this.create_lambda( + "delete_moderator", + environment_variables, + "DELETE", + restapi_resource, + origins + ); + this.create_activity = this.create_lambda( "create_activity", environment_variables, From dec9b6b9b95499e700c0aff30db8f8016bdb798f Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Sat, 25 May 2024 20:02:11 -0300 Subject: [PATCH 42/71] fix: Correct HTTP method for delete_moderator lambda function --- iac/lib/lambda_stack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 8f1b96d..51dc561 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -110,7 +110,7 @@ export class LambdaStack extends Construct { this.delete_moderator = this.create_lambda( "delete_moderator", environment_variables, - "DELETE", + "GET", restapi_resource, origins ); From 0e7a3d45ab77564943c62e9c3de360ffcfc6179b Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sun, 26 May 2024 11:30:17 -0300 Subject: [PATCH 43/71] refactor: Add validation for maua.br domain in CreateModeratorUsecase --- .../create_moderator/app/create_moderator_usecase.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/create_moderator/app/create_moderator_usecase.ts b/src/modules/create_moderator/app/create_moderator_usecase.ts index 9c16594..cad81a0 100644 --- a/src/modules/create_moderator/app/create_moderator_usecase.ts +++ b/src/modules/create_moderator/app/create_moderator_usecase.ts @@ -5,7 +5,7 @@ import { User } from '../../../core/structure/entities/User'; import { TokenAuth } from '../../../core/helpers/functions/token_auth'; import { UserTypeEnum } from '../../../core/helpers/enums/UserTypeEnum'; import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; -import { InvalidRequest, MissingParameter, UserNotAllowed, UserNotAuthenticated } from '../../../core/helpers/errors/ModuleError'; +import { InvalidParameter, InvalidRequest, MissingParameter, UserNotAllowed, UserNotAuthenticated } from '../../../core/helpers/errors/ModuleError'; export class CreateModeratorUsecase { @@ -53,6 +53,11 @@ export class CreateModeratorUsecase { throw new UserNotAllowed("Admin can't be a moderator"); } + const padrao: RegExp = /@maua\.br$/; + if (!padrao.test(body.email)) { + throw new InvalidParameter("Email", "must be a maua.br domain."); + } + const user = await this.database_repo.get_user_by_email(body.email); if (user) { if (user.user_type === UserTypeEnum.ADMIN) { From 1015edaa56865b8234701743fe73dd033966edbc Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sun, 26 May 2024 11:32:57 -0300 Subject: [PATCH 44/71] refactor: Update GetAllModeratorsController to use OK response code --- .../get_all_moderators/app/get_all_moderators_controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/get_all_moderators/app/get_all_moderators_controller.ts b/src/modules/get_all_moderators/app/get_all_moderators_controller.ts index d2f7555..a2fbeac 100644 --- a/src/modules/get_all_moderators/app/get_all_moderators_controller.ts +++ b/src/modules/get_all_moderators/app/get_all_moderators_controller.ts @@ -2,8 +2,8 @@ import { GetAllModeratorsUsecase } from "./get_all_moderators_usecase"; import { UniqueConstraintError } from "sequelize"; import { EntityError } from '../../../core/helpers/errors/EntityError'; -import { BadRequest, ParameterError, InternalServerError } from '../../../core/helpers/http/http_codes'; -import { Conflict, Created, Forbidden, HttpRequest, HttpResponse, Unauthorized, Unprocessable_Entity } from '../../../core/helpers/http/http_codes'; +import { BadRequest, ParameterError, InternalServerError, OK } from '../../../core/helpers/http/http_codes'; +import { Conflict, Forbidden, HttpRequest, HttpResponse, Unauthorized, Unprocessable_Entity } from '../../../core/helpers/http/http_codes'; import { ConflictError, InvalidParameter, InvalidRequest, MissingParameter, UserNotAllowed, UserNotAuthenticated } from '../../../core/helpers/errors/ModuleError'; @@ -24,7 +24,7 @@ export class GetAllModeratorsController { } let response = await this.usecase.execute(request.headers); - return new Created(response, "Moderators found successfully"); + return new OK(response, "Moderators found successfully"); } catch (error: any) { if (error instanceof InvalidRequest) { From 62f0910bd62e9336853942f7c53c29f63be17ea5 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sun, 26 May 2024 11:44:41 -0300 Subject: [PATCH 45/71] refactor: Update CreateModeratorUsecase to use async/await for updating user --- src/modules/create_moderator/app/create_moderator_usecase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/create_moderator/app/create_moderator_usecase.ts b/src/modules/create_moderator/app/create_moderator_usecase.ts index cad81a0..6d91810 100644 --- a/src/modules/create_moderator/app/create_moderator_usecase.ts +++ b/src/modules/create_moderator/app/create_moderator_usecase.ts @@ -64,7 +64,7 @@ export class CreateModeratorUsecase { throw new UserNotAllowed("Admin can't be a moderator"); } user.user_type = UserTypeEnum.MODERATOR; - this.database_repo.update_user(user); + await this.database_repo.update_user(user); } else { const moderator = new User({ From ec1d98b3ac6d61e64bd7bd513202107df556b539 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 00:00:24 -0300 Subject: [PATCH 46/71] refactor: Remove unused Deleted class from http_codes.ts --- src/core/helpers/http/http_codes.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/core/helpers/http/http_codes.ts b/src/core/helpers/http/http_codes.ts index 0e3b25b..ff2d441 100644 --- a/src/core/helpers/http/http_codes.ts +++ b/src/core/helpers/http/http_codes.ts @@ -83,12 +83,6 @@ export class Created extends HttpResponse { } } -export class Deleted extends HttpResponse { - constructor(body: { [key: string]: any }, message: string) { - super(204, body, message); - } -} - export class BadRequest extends HttpResponse { constructor(message: string) { super(400, null, message); From c0b57261ff9ac5ab964089c67dafe8d8bbbb8e69 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 00:00:31 -0300 Subject: [PATCH 47/71] refactor: Update DeleteModeratorController to use OK class for response --- src/modules/delete_moderator/app/delete_moderator_controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts index 519b922..96f16f3 100644 --- a/src/modules/delete_moderator/app/delete_moderator_controller.ts +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -36,7 +36,7 @@ export class DeleteModeratorController { const queryParams = request.body.queryStringParameters; let response = await this.usecase.execute(request.headers, queryParams); - return new Deleted(response, "Moderator deleted successfully"); + return new OK(response, "Moderator deleted successfully"); } catch (error: any) { if (error instanceof InvalidRequest) { return new BadRequest(error.message); From c460e6da0d0bb0714925df919076d29493d95662 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 00:09:01 -0300 Subject: [PATCH 48/71] refactor: Remove commented out code in delete_moderator.test.ts --- test/modules/delete_moderator/app/delete_moderator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts index 92bba4d..e893acc 100644 --- a/test/modules/delete_moderator/app/delete_moderator.test.ts +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -30,7 +30,7 @@ describe("Testing Delete Moderator Presenter", () => { body: JSON.stringify({ id: user_moderator.id }) }, null); - expect(response.statusCode).toBe(401); + // expect(response.statusCode).toBe(401); expect(JSON.parse(response.body).message).toBe("Invalid or expired token"); }); From 4f2d3a22f9be2b3b925a3d906234fc4d70425511 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 00:09:37 -0300 Subject: [PATCH 49/71] feat: Handle additional errors in DeleteModeratorController --- .../app/delete_moderator_controller.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts index 96f16f3..16a3ae8 100644 --- a/src/modules/delete_moderator/app/delete_moderator_controller.ts +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -1,12 +1,15 @@ import { + InvalidParameter, InvalidRequest, MissingParameter, + NotfoundError, + UserNotAllowed, UserNotAuthenticated, } from "../../../core/helpers/errors/ModuleError"; import { NotFoundError } from "../../../core/helpers/errors/RepoError"; import { BadRequest, - Deleted, + Forbidden, HttpRequest, HttpResponse, InternalServerError, @@ -41,13 +44,19 @@ export class DeleteModeratorController { if (error instanceof InvalidRequest) { return new BadRequest(error.message); } + if (error instanceof InvalidParameter) { + return new ParameterError(error.message); + } if (error instanceof UserNotAuthenticated) { return new Unauthorized(error.message); } + if( error instanceof UserNotAllowed) { + return new Forbidden(error.message); + } if (error instanceof MissingParameter) { return new ParameterError(error.message); } - if (error instanceof NotFoundError) { + if (error instanceof NotfoundError) { return new NotFound(error.message); } return new InternalServerError(error.message); From 9317cfc34d94d3c52a8e4085dc8e9f77786d6f27 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 00:09:52 -0300 Subject: [PATCH 50/71] refactor: Remove commented out code in delete_moderator.test.ts --- test/modules/delete_moderator/app/delete_moderator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts index e893acc..92bba4d 100644 --- a/test/modules/delete_moderator/app/delete_moderator.test.ts +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -30,7 +30,7 @@ describe("Testing Delete Moderator Presenter", () => { body: JSON.stringify({ id: user_moderator.id }) }, null); - // expect(response.statusCode).toBe(401); + expect(response.statusCode).toBe(401); expect(JSON.parse(response.body).message).toBe("Invalid or expired token"); }); From efeac8b33d87cfcf674acef75367340f90ce8e15 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 11:51:18 -0300 Subject: [PATCH 51/71] refactor: Update DeleteModeratorController to handle missing request body --- .../delete_moderator/app/delete_moderator_controller.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts index 16a3ae8..5141592 100644 --- a/src/modules/delete_moderator/app/delete_moderator_controller.ts +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -35,10 +35,13 @@ export class DeleteModeratorController { if (!request.headers) { throw new InvalidRequest("Headers"); } + if (!request.body) { + throw new MissingParameter("Body"); + } - const queryParams = request.body.queryStringParameters; + const body = request.body.body; - let response = await this.usecase.execute(request.headers, queryParams); + let response = await this.usecase.execute(request.headers, body); return new OK(response, "Moderator deleted successfully"); } catch (error: any) { if (error instanceof InvalidRequest) { From 5aa71d3edf68a6f9e0ba2e5b7b00e961a074a628 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 11:51:25 -0300 Subject: [PATCH 52/71] refactor: Update DeleteModeratorUsecase to use request body instead of query string parameters --- .../app/delete_moderator_usecase.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_usecase.ts b/src/modules/delete_moderator/app/delete_moderator_usecase.ts index a5beb39..fb63281 100644 --- a/src/modules/delete_moderator/app/delete_moderator_usecase.ts +++ b/src/modules/delete_moderator/app/delete_moderator_usecase.ts @@ -19,7 +19,7 @@ export class DeleteModeratorUsecase { async execute( headers: { [key: string]: any }, - queryStringParameters: { [key: string]: any } + body: { [key: string]: any } ) { if (!headers) { throw new InvalidRequest("Headers"); @@ -27,11 +27,8 @@ export class DeleteModeratorUsecase { if (!headers.Authorization) { throw new MissingParameter("Authorization"); } - if (!queryStringParameters) { - throw new InvalidRequest("Body"); - } - if (!queryStringParameters.moderator_id) { - throw new MissingParameter("moderator_id"); + if (!body) { + throw new MissingParameter("Body"); } const user_id = await this.token_auth @@ -53,7 +50,7 @@ export class DeleteModeratorUsecase { } const moderator = await this.database_repo.get_user( - queryStringParameters.moderator_id + body.moderator_id ); if (!moderator) { throw new NotfoundError("Moderator"); @@ -64,7 +61,7 @@ export class DeleteModeratorUsecase { } await this.database_repo.delete_moderator( - queryStringParameters.moderator_id + body.moderator_id ); return { message: "Moderator deleted successfully" }; } From 8000daff575b83ddbd034ba97a4b5dabd264b1f4 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 11:51:33 -0300 Subject: [PATCH 53/71] refactor: Remove commented out code in delete_moderator.test.ts --- test/modules/delete_moderator/app/delete_moderator.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts index 92bba4d..b75429d 100644 --- a/test/modules/delete_moderator/app/delete_moderator.test.ts +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -30,7 +30,7 @@ describe("Testing Delete Moderator Presenter", () => { body: JSON.stringify({ id: user_moderator.id }) }, null); - expect(response.statusCode).toBe(401); + // expect(response.statusCode).toBe(401); expect(JSON.parse(response.body).message).toBe("Invalid or expired token"); }); @@ -44,7 +44,7 @@ describe("Testing Delete Moderator Presenter", () => { body: JSON.stringify({}) }, null); - expect(response.statusCode).toBe(400); + // expect(response.statusCode).toBe(400); expect(JSON.parse(response.body).message).toBe("Body not found"); }); }); From c79b2814f6359a1c4d0bf8a7dc2c2d4a2356ba81 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 12:01:22 -0300 Subject: [PATCH 54/71] refactor: Update DeleteModeratorController to throw InvalidRequest instead of MissingParameter for missing request body --- .../delete_moderator/app/delete_moderator_controller.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_controller.ts b/src/modules/delete_moderator/app/delete_moderator_controller.ts index 5141592..4a668de 100644 --- a/src/modules/delete_moderator/app/delete_moderator_controller.ts +++ b/src/modules/delete_moderator/app/delete_moderator_controller.ts @@ -6,7 +6,6 @@ import { UserNotAllowed, UserNotAuthenticated, } from "../../../core/helpers/errors/ModuleError"; -import { NotFoundError } from "../../../core/helpers/errors/RepoError"; import { BadRequest, Forbidden, @@ -36,7 +35,7 @@ export class DeleteModeratorController { throw new InvalidRequest("Headers"); } if (!request.body) { - throw new MissingParameter("Body"); + throw new InvalidRequest("Body"); } const body = request.body.body; @@ -53,7 +52,7 @@ export class DeleteModeratorController { if (error instanceof UserNotAuthenticated) { return new Unauthorized(error.message); } - if( error instanceof UserNotAllowed) { + if (error instanceof UserNotAllowed) { return new Forbidden(error.message); } if (error instanceof MissingParameter) { From ab6e439b4339402d232c85904bc315bbc98bd180 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 12:01:28 -0300 Subject: [PATCH 55/71] refactor: Update DeleteModeratorUsecase to throw InvalidRequest for missing moderator_id parameter --- .../app/delete_moderator_usecase.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/delete_moderator/app/delete_moderator_usecase.ts b/src/modules/delete_moderator/app/delete_moderator_usecase.ts index fb63281..4afc867 100644 --- a/src/modules/delete_moderator/app/delete_moderator_usecase.ts +++ b/src/modules/delete_moderator/app/delete_moderator_usecase.ts @@ -28,7 +28,7 @@ export class DeleteModeratorUsecase { throw new MissingParameter("Authorization"); } if (!body) { - throw new MissingParameter("Body"); + throw new InvalidRequest("Body"); } const user_id = await this.token_auth @@ -49,9 +49,11 @@ export class DeleteModeratorUsecase { throw new UserNotAuthenticated(); } - const moderator = await this.database_repo.get_user( - body.moderator_id - ); + if (!body.moderator_id) { + throw new MissingParameter("moderator_id"); + } + + const moderator = await this.database_repo.get_user(body.moderator_id); if (!moderator) { throw new NotfoundError("Moderator"); } @@ -60,9 +62,7 @@ export class DeleteModeratorUsecase { throw new InvalidRequest("User is not a moderator"); } - await this.database_repo.delete_moderator( - body.moderator_id - ); + await this.database_repo.delete_moderator(body.moderator_id); return { message: "Moderator deleted successfully" }; } } From 3d0b5fcd3b2cbdc304c21f826e9c89002ecdf829 Mon Sep 17 00:00:00 2001 From: LucaPinheiro Date: Mon, 27 May 2024 12:01:43 -0300 Subject: [PATCH 56/71] refactor: Update DeleteModeratorUsecase to throw InvalidRequest for missing moderator_id parameter --- .../delete_moderator/app/delete_moderator.test.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/modules/delete_moderator/app/delete_moderator.test.ts b/test/modules/delete_moderator/app/delete_moderator.test.ts index b75429d..7caed69 100644 --- a/test/modules/delete_moderator/app/delete_moderator.test.ts +++ b/test/modules/delete_moderator/app/delete_moderator.test.ts @@ -1,5 +1,4 @@ import { it, describe, expect } from 'vitest'; - import { UserMock } from '../../../../src/core/structure/mocks/UserMock'; import { TokenAuth } from '../../../../src/core/helpers/functions/token_auth'; import { handler } from '../../../../src/modules/delete_moderator/app/delete_moderator_presenter'; @@ -15,7 +14,7 @@ describe("Testing Delete Moderator Presenter", () => { headers: { Authorization: token }, - body: JSON.stringify({ id: user_moderator.id }) + body: JSON.stringify({ moderator_id: user_moderator.id }) }, null); expect(response.statusCode).toBe(200); @@ -27,24 +26,24 @@ describe("Testing Delete Moderator Presenter", () => { headers: { Authorization: "invalid_token" }, - body: JSON.stringify({ id: user_moderator.id }) + body: JSON.stringify({ moderator_id: user_moderator.id }) }, null); - // expect(response.statusCode).toBe(401); + expect(response.statusCode).toBe(401); expect(JSON.parse(response.body).message).toBe("Invalid or expired token"); }); - it("should not delete a moderator with missing parameter id", async () => { + it("should not delete a moderator with missing parameter moderator_id", async () => { var token = (await new TokenAuth().generate_token(user_admin.id)).toString(); var response = await handler({ headers: { Authorization: token }, - body: JSON.stringify({}) + body: null }, null); - // expect(response.statusCode).toBe(400); + expect(response.statusCode).toBe(400); expect(JSON.parse(response.body).message).toBe("Body not found"); }); }); From 2f0a7794d8e1cdcc1ae3381f6c511d689f31cbac Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 08:48:05 -0300 Subject: [PATCH 57/71] refactor: Update event trigger names for activity start and end --- .../create_activity/app/create_activity_usecase.ts | 4 ++-- .../update_activity/app/update_activity_usecase.ts | 8 ++++---- .../app/update_activity_event_presenter.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/create_activity/app/create_activity_usecase.ts b/src/modules/create_activity/app/create_activity_usecase.ts index 18407a6..1370d80 100644 --- a/src/modules/create_activity/app/create_activity_usecase.ts +++ b/src/modules/create_activity/app/create_activity_usecase.ts @@ -215,7 +215,7 @@ export class CreateActivityUsecase { let end_date = activity.end_date; end_date.setHours(end_date.getHours() + 3); await this.event_bridge.create_trigger( - "START_ACTIVITY_" + activity.id, + "START_" + activity.id.substring(0, 8), "Update_Activity_Event", start_date, { @@ -227,7 +227,7 @@ export class CreateActivityUsecase { ); await this.event_bridge.create_trigger( - "END_ACTIVITY_" + activity.id, + "END_" + activity.id.substring(0, 8), "Update_Activity_Event", end_date, { diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index 5005f8b..7fa4ad5 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -264,11 +264,11 @@ export class UpdateActivityUsecase { start_date.setHours(start_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( - "START_ACTIVITY_" + activity.id, + "START_" + activity.id.substring(0, 8), "Update_Activity_Event" ); await this.event_bridge.create_trigger( - "START_ACTIVITY_" + activity.id, + "START_" + activity.id.substring(0, 8), "Update_Activity_Event", start_date, { @@ -284,11 +284,11 @@ export class UpdateActivityUsecase { end_date.setHours(end_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( - "END_ACTIVITY_" + activity.id, + "END_" + activity.id.substring(0, 8), "Update_Activity_Event" ); await this.event_bridge.create_trigger( - "END_ACTIVITY_" + activity.id, + "END_" + activity.id.substring(0, 8), "Update_Activity_Event", end_date, { diff --git a/src/modules/update_activity_event/app/update_activity_event_presenter.ts b/src/modules/update_activity_event/app/update_activity_event_presenter.ts index a8b5f5c..2fe347d 100644 --- a/src/modules/update_activity_event/app/update_activity_event_presenter.ts +++ b/src/modules/update_activity_event/app/update_activity_event_presenter.ts @@ -12,8 +12,8 @@ export const handler = async (event: any, context: any) => { const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status_activity); if (resp) { console.log("Activity updated successfully"); - let event_name = body.status_activity === ActivityStatusEnum.ACTIVE ? "START_ACTIVITY_" : "END_ACTIVITY_"; - await event_bridge.delete_trigger(event_name + body.activity_id, "Update_Activity_Event"); + let event_name = body.status_activity === ActivityStatusEnum.ACTIVE ? "START_" : "END_"; + await event_bridge.delete_trigger(event_name + body.activity_id.substring(0, 8), "Update_Activity_Event"); } else { console.log("Activity not found"); } From 7b4e308dfb5a15f50dbac8812736f9547d6dd4e2 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 08:54:19 -0300 Subject: [PATCH 58/71] refactor: Update event trigger names for activity start and end --- .../create_activity/app/create_activity_usecase.ts | 4 ++-- .../update_activity/app/update_activity_usecase.ts | 8 ++++---- .../app/update_activity_event_presenter.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/create_activity/app/create_activity_usecase.ts b/src/modules/create_activity/app/create_activity_usecase.ts index 1370d80..5208261 100644 --- a/src/modules/create_activity/app/create_activity_usecase.ts +++ b/src/modules/create_activity/app/create_activity_usecase.ts @@ -215,7 +215,7 @@ export class CreateActivityUsecase { let end_date = activity.end_date; end_date.setHours(end_date.getHours() + 3); await this.event_bridge.create_trigger( - "START_" + activity.id.substring(0, 8), + "START_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event", start_date, { @@ -227,7 +227,7 @@ export class CreateActivityUsecase { ); await this.event_bridge.create_trigger( - "END_" + activity.id.substring(0, 8), + "END_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event", end_date, { diff --git a/src/modules/update_activity/app/update_activity_usecase.ts b/src/modules/update_activity/app/update_activity_usecase.ts index 7fa4ad5..a774ed9 100644 --- a/src/modules/update_activity/app/update_activity_usecase.ts +++ b/src/modules/update_activity/app/update_activity_usecase.ts @@ -264,11 +264,11 @@ export class UpdateActivityUsecase { start_date.setHours(start_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( - "START_" + activity.id.substring(0, 8), + "START_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event" ); await this.event_bridge.create_trigger( - "START_" + activity.id.substring(0, 8), + "START_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event", start_date, { @@ -284,11 +284,11 @@ export class UpdateActivityUsecase { end_date.setHours(end_date.getHours() + 3); // Delete the previous trigger and create a new one await this.event_bridge.delete_trigger( - "END_" + activity.id.substring(0, 8), + "END_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event" ); await this.event_bridge.create_trigger( - "END_" + activity.id.substring(0, 8), + "END_COIL_" + activity.id.substring(0, 8), "Update_Activity_Event", end_date, { diff --git a/src/modules/update_activity_event/app/update_activity_event_presenter.ts b/src/modules/update_activity_event/app/update_activity_event_presenter.ts index 2fe347d..f9aa276 100644 --- a/src/modules/update_activity_event/app/update_activity_event_presenter.ts +++ b/src/modules/update_activity_event/app/update_activity_event_presenter.ts @@ -12,7 +12,7 @@ export const handler = async (event: any, context: any) => { const resp = await repository.ActivityRepo.update_activity_status(body.activity_id, body.status_activity); if (resp) { console.log("Activity updated successfully"); - let event_name = body.status_activity === ActivityStatusEnum.ACTIVE ? "START_" : "END_"; + let event_name = body.status_activity === ActivityStatusEnum.ACTIVE ? "START_COIL_" : "END_COIL_"; await event_bridge.delete_trigger(event_name + body.activity_id.substring(0, 8), "Update_Activity_Event"); } else { console.log("Activity not found"); From ac96aca44eb387a94d1759f2955a49b5306b97fe Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 09:02:52 -0300 Subject: [PATCH 59/71] refactor: Update event trigger names for activity start and end --- src/core/helpers/functions/event_bridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/helpers/functions/event_bridge.ts b/src/core/helpers/functions/event_bridge.ts index 1d198a8..91a3058 100644 --- a/src/core/helpers/functions/event_bridge.ts +++ b/src/core/helpers/functions/event_bridge.ts @@ -46,7 +46,7 @@ export class EventBridgeManager { FunctionName: lambda_function, Principal: "events.amazonaws.com", StatementId: rule_name, - SourceArn: "arn:aws:events:" + this.aws_region + ":" + this.aws_account_id + ":rule/" + rule_name, + SourceArn: "arn:aws:events:" + this.aws_region + ":" + this.aws_account_id + ":rule/*", }).promise(); // Create CloudWatch Events rule From c3c844b416091c74cc160d44dbe20b692179c84d Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 09:21:29 -0300 Subject: [PATCH 60/71] refactor: Update event trigger names for activity start and end --- iac/lib/lambda_stack.ts | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 51dc561..3df031f 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -8,14 +8,14 @@ export class LambdaStack extends Construct { private create_moderator: lambda_js.NodejsFunction; private get_all_moderators: lambda_js.NodejsFunction; private delete_moderator: lambda_js.NodejsFunction; - + private get_institution: lambda_js.NodejsFunction; private create_institution: lambda_js.NodejsFunction; private update_institution: lambda_js.NodejsFunction; private get_all_institutions: lambda_js.NodejsFunction; private get_institution_requirements: lambda_js.NodejsFunction; - private assign_user: lambda_js.NodejsFunction; + private assign_user: lambda_js.NodejsFunction; private get_activity: lambda_js.NodejsFunction; private create_activity: lambda_js.NodejsFunction; private update_activity: lambda_js.NodejsFunction; @@ -27,6 +27,7 @@ export class LambdaStack extends Construct { private get_all_activities_enrolled: lambda_js.NodejsFunction; public functions_need_s3_access: lambda.Function[] = []; + public function_need_event_bridge_access: lambda.Function[] = []; public functions_need_event_bridge_access: lambda.Function[] = []; private create_lambda( @@ -60,9 +61,9 @@ export class LambdaStack extends Construct { restapi_resource.addResource(function_name.replace(/_/g, "-"), { defaultCorsPreflightOptions: { - allowOrigins: origins, - allowMethods: [method], - allowHeaders: ["*"], + allowOrigins: origins, + allowMethods: [method], + allowHeaders: ["*"], } }).addMethod(method, new apigw.LambdaIntegration(function_lambda)); @@ -254,6 +255,25 @@ export class LambdaStack extends Construct { this.update_institution, ] + this.function_need_event_bridge_access = [ + this.create_activity, + this.update_activity, + this.update_activity_event, + ] + + this.functions_need_event_bridge_access.forEach((function_lambda) => { + function_lambda.addToRolePolicy( + new iam.PolicyStatement({ + actions: [ + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "events:DeleteRule", + ], + resources: ["*"], + })) + }); + this.functions_need_event_bridge_access = [ this.create_activity, this.update_activity, From 70ab7906d19e245d72c1ed3c16578db31705ad46 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 09:21:35 -0300 Subject: [PATCH 61/71] refactor: Update event trigger names for activity start and end --- src/core/helpers/functions/event_bridge.ts | 29 +++++----------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/core/helpers/functions/event_bridge.ts b/src/core/helpers/functions/event_bridge.ts index 91a3058..0c5c5be 100644 --- a/src/core/helpers/functions/event_bridge.ts +++ b/src/core/helpers/functions/event_bridge.ts @@ -5,16 +5,12 @@ dotenv.config(); export class EventBridgeManager { - private event: EventBridge; private lambda: Lambda; - private aws_region: string; - private aws_account_id: string; + private event: EventBridge; constructor() { - this.event = new EventBridge(); this.lambda = new Lambda(); - this.aws_region = process.env.AWS_REGION as string; - this.aws_account_id = process.env.AWS_ACCOUNT_ID as string; + this.event = new EventBridge(); } private async get_rule(rule_name: string): Promise { @@ -40,15 +36,6 @@ export class EventBridgeManager { }).promise(); const lambda_arn = lambda_response.Configuration?.FunctionArn as string; - // Add permission - await this.lambda.addPermission({ - Action: "lambda:InvokeFunction", - FunctionName: lambda_function, - Principal: "events.amazonaws.com", - StatementId: rule_name, - SourceArn: "arn:aws:events:" + this.aws_region + ":" + this.aws_account_id + ":rule/*", - }).promise(); - // Create CloudWatch Events rule await this.event.putRule({ Name: rule_name, @@ -77,22 +64,18 @@ export class EventBridgeManager { public async delete_trigger(rule_name: string, lambda_function: string): Promise { const has_rule = await this.get_rule(rule_name); lambda_function = lambda_function + "_Coil"; - + if (has_rule) { - await this.lambda.removePermission({ - FunctionName: lambda_function, - StatementId: rule_name, - }).promise(); - + await this.event.removeTargets({ Rule: rule_name, Ids: [rule_name], }).promise(); - + await this.event.deleteRule({ Name: rule_name, }).promise(); - + return true; } else { return true; From ac7f41f8c2ff6ded2705f21a1670003912e3797e Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Wed, 29 May 2024 09:42:35 -0300 Subject: [PATCH 62/71] refactor: Add EventBridge permission for lambda function --- iac/lib/lambda_stack.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 3df031f..996ded0 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -272,6 +272,11 @@ export class LambdaStack extends Construct { ], resources: ["*"], })) + function_lambda.addPermission("EventBridgePermission", { + principal: new iam.ServicePrincipal("events.amazonaws.com"), + sourceArn: "arn:aws:events:us-east-1:123456789012:rule/*", + action: "lambda:InvokeFunction", + }); }); this.functions_need_event_bridge_access = [ From 936adf0a69cc94af86d9395879e99bdc726fa7cf Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sat, 8 Jun 2024 21:21:43 -0300 Subject: [PATCH 63/71] refactor: Update update_users_activity_usecase to handle conflict errors --- .../database/repositories/ActivityRepo.ts | 14 +++++++++----- .../app/update_users_activity_controller.ts | 5 +++++ .../app/update_users_activity_usecase.ts | 7 ++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 8531a78..9dec53d 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -437,8 +437,10 @@ export class ActivityRepo implements IActivityRepo { } async update_users_activity_status(activity_id: string, users: { user_id: string, status: boolean }[]): Promise { - for (let user of users) { - const response = await ActivityApplication.update({ + let response = true; + + for (const user of users) { + const [affectedCount] = await ActivityApplication.update({ status: user.status }, { where: { @@ -446,11 +448,13 @@ export class ActivityRepo implements IActivityRepo { user_id: user.user_id } }); - if (response[0] === 0) { - return false; + + if (affectedCount === 0) { + response = false; } } - return true; + + return response; } async get_all_activities_catalog(): Promise<{ title: string; logo: string; type_activity: ActivityTypeEnum; }[]> { diff --git a/src/modules/update_users_activity/app/update_users_activity_controller.ts b/src/modules/update_users_activity/app/update_users_activity_controller.ts index 7c7f6ba..eece7d7 100644 --- a/src/modules/update_users_activity/app/update_users_activity_controller.ts +++ b/src/modules/update_users_activity/app/update_users_activity_controller.ts @@ -1,5 +1,6 @@ import { UpdateUsersActivityUsecase } from "./update_users_activity_usecase"; import { + ConflictError, InvalidParameter, InvalidRequest, MissingParameter, @@ -16,6 +17,7 @@ import { OK, ParameterError, Unauthorized, + Unprocessable_Entity, } from "../../../core/helpers/http/http_codes"; import { EntityError } from "../../../core/helpers/errors/EntityError"; @@ -54,6 +56,9 @@ export class UpdateUsersActivityController { if (error instanceof NotfoundError) { return new NotFound(error.message); } + if (error instanceof ConflictError) { + return new Unprocessable_Entity(error.message); + } if (error instanceof EntityError) { return new ParameterError(error.message); } diff --git a/src/modules/update_users_activity/app/update_users_activity_usecase.ts b/src/modules/update_users_activity/app/update_users_activity_usecase.ts index a7f0209..6a82520 100644 --- a/src/modules/update_users_activity/app/update_users_activity_usecase.ts +++ b/src/modules/update_users_activity/app/update_users_activity_usecase.ts @@ -4,7 +4,8 @@ import { NotfoundError, UserNotAllowed, UserNotAuthenticated, - InvalidParameter + InvalidParameter, + ConflictError } from "../../../core/helpers/errors/ModuleError"; import { TokenAuth } from "../../../core/helpers/functions/token_auth"; import { UserTypeEnum } from "../../../core/helpers/enums/UserTypeEnum"; @@ -95,7 +96,7 @@ export class UpdateUsersActivityUsecase { throw new NotfoundError("Applicants not found"); } - applicants_db.forEach((applicant: {user_id: string, status: boolean}) => { + applicants_db.forEach((applicant: { user_id: string, status: boolean }) => { return { user_id: applicant.user_id, status: !applicant.status, @@ -104,7 +105,7 @@ export class UpdateUsersActivityUsecase { const updateStatusResult = await this.activity_repo.update_users_activity_status(body.activity_id, body.applicants); if (!updateStatusResult) { - throw new NotfoundError("Activity not found"); + throw new ConflictError("Error updating activity status"); } return true; From 84bce6ed2e796d75e00cb2db1ef25757c99d9f08 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sat, 8 Jun 2024 21:30:49 -0300 Subject: [PATCH 64/71] refactor: Update update_users_activity_status to use forEach instead of for loop --- .../database/repositories/ActivityRepo.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index 9dec53d..f66ca49 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -439,20 +439,21 @@ export class ActivityRepo implements IActivityRepo { async update_users_activity_status(activity_id: string, users: { user_id: string, status: boolean }[]): Promise { let response = true; - for (const user of users) { - const [affectedCount] = await ActivityApplication.update({ + users.forEach(async user => { + const response_user = await ActivityApplication.update({ status: user.status }, { where: { - activity_id: activity_id, - user_id: user.user_id + [Op.and]: [ + { activity_id: activity_id }, + { user_id: user.user_id } + ] } }); - - if (affectedCount === 0) { + if (response_user[0] === 0) { response = false; } - } + }); return response; } From 7b8bb04be1aae1bc698063e1f39a10b2e97e0fed Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sat, 8 Jun 2024 21:58:48 -0300 Subject: [PATCH 65/71] refactor: Update ActivityRepo and UpdateUsersActivityUsecase to toggle user status --- .../repositories/database/repositories/ActivityRepo.ts | 2 +- .../app/update_users_activity_usecase.ts | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index f66ca49..ea189ff 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -441,7 +441,7 @@ export class ActivityRepo implements IActivityRepo { users.forEach(async user => { const response_user = await ActivityApplication.update({ - status: user.status + status: !user.status }, { where: { [Op.and]: [ diff --git a/src/modules/update_users_activity/app/update_users_activity_usecase.ts b/src/modules/update_users_activity/app/update_users_activity_usecase.ts index 6a82520..c029197 100644 --- a/src/modules/update_users_activity/app/update_users_activity_usecase.ts +++ b/src/modules/update_users_activity/app/update_users_activity_usecase.ts @@ -96,13 +96,6 @@ export class UpdateUsersActivityUsecase { throw new NotfoundError("Applicants not found"); } - applicants_db.forEach((applicant: { user_id: string, status: boolean }) => { - return { - user_id: applicant.user_id, - status: !applicant.status, - }; - }); - const updateStatusResult = await this.activity_repo.update_users_activity_status(body.activity_id, body.applicants); if (!updateStatusResult) { throw new ConflictError("Error updating activity status"); From 01919852c0f7b2c3a4a5bb8a8dcaded690730c1f Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sun, 9 Jun 2024 20:46:09 -0300 Subject: [PATCH 66/71] refactor: Simplify code for toggling user status in ActivityRepo --- src/core/repositories/database/repositories/ActivityRepo.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/repositories/database/repositories/ActivityRepo.ts b/src/core/repositories/database/repositories/ActivityRepo.ts index ea189ff..aa33be3 100644 --- a/src/core/repositories/database/repositories/ActivityRepo.ts +++ b/src/core/repositories/database/repositories/ActivityRepo.ts @@ -444,10 +444,8 @@ export class ActivityRepo implements IActivityRepo { status: !user.status }, { where: { - [Op.and]: [ - { activity_id: activity_id }, - { user_id: user.user_id } - ] + activity_id: activity_id, + user_id: user.user_id } }); if (response_user[0] === 0) { From 7016a1d48b8d8e55a67989f341671ca93732d1a3 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Sun, 9 Jun 2024 21:15:47 -0300 Subject: [PATCH 67/71] refactor: Add EventBridge permission for lambda function --- src/core/helpers/functions/event_bridge.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/helpers/functions/event_bridge.ts b/src/core/helpers/functions/event_bridge.ts index 0c5c5be..2177441 100644 --- a/src/core/helpers/functions/event_bridge.ts +++ b/src/core/helpers/functions/event_bridge.ts @@ -59,6 +59,17 @@ export class EventBridgeManager { }, ], }).promise(); + + // Add permission to Lambda function + await this.lambda.addPermission({ + FunctionName: lambda_function, + StatementId: rule_name, + Action: "lambda:InvokeFunction", + Principal: "events.amazonaws.com", + SourceArn: "arn:aws:events:" + process.env.AWS_REGION + ":" + process.env.AWS_ACCOUNT_ID + ":rule/" + rule_name, + }).promise(); + + return true; } public async delete_trigger(rule_name: string, lambda_function: string): Promise { From ce59cdce9b7da660bc19cd54cee20694723d32e8 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 19 Jul 2024 14:59:12 -0300 Subject: [PATCH 68/71] refactor: Update get_catalog module to use simplified code structure --- .../get_all_activities_catalog_presenter.ts | 17 ----------------- .../app/get_catalog_controller.ts} | 15 +++++---------- .../get_catalog/app/get_catalog_presenter.ts | 18 ++++++++++++++++++ .../app/get_catalog_usecase.ts} | 14 +++++++++----- .../app/get_all_activities_catalog.test.ts | 9 +++------ 5 files changed, 35 insertions(+), 38 deletions(-) delete mode 100644 src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts rename src/modules/{get_all_activities_catalog/app/get_all_activities_catalog_controller.ts => get_catalog/app/get_catalog_controller.ts} (63%) create mode 100644 src/modules/get_catalog/app/get_catalog_presenter.ts rename src/modules/{get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts => get_catalog/app/get_catalog_usecase.ts} (63%) diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts b/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts deleted file mode 100644 index 9a15606..0000000 --- a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Repository } from "../../../core/repositories/Repository"; -import { HttpRequest } from "../../../core/helpers/http/http_codes"; -import { GetAllActivitiesCatalogUsecase } from "./get_all_activities_catalog_usecase"; -import { GetAllActivitiesCatalogController } from "./get_all_activities_catalog_controller"; - -const repository = new Repository({ user_repo: true, activity_repo: true }); - -const usecase = new GetAllActivitiesCatalogUsecase( - repository.ActivityRepo -); -const controller = new GetAllActivitiesCatalogController(usecase); - -export const handler = async (event: any, context: any) => { - let request = new HttpRequest(event); - let response = await controller.execute(request); - return response.to_json(); -}; diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts b/src/modules/get_catalog/app/get_catalog_controller.ts similarity index 63% rename from src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts rename to src/modules/get_catalog/app/get_catalog_controller.ts index 4410244..0468885 100644 --- a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_controller.ts +++ b/src/modules/get_catalog/app/get_catalog_controller.ts @@ -2,23 +2,18 @@ import { HttpRequest, HttpResponse, OK, - BadRequest, - Unauthorized, - ParameterError, InternalServerError, } from "../../../core/helpers/http/http_codes"; import { InvalidRequest, - MissingParameter, - UserNotAuthenticated, } from "../../../core/helpers/errors/ModuleError"; -import { GetAllActivitiesCatalogUsecase } from "./get_all_activities_catalog_usecase"; +import { GetCatalogUsecase } from "./get_catalog_usecase"; -export class GetAllActivitiesCatalogController { - public usecase: GetAllActivitiesCatalogUsecase; +export class GetCatalogController { + public usecase: GetCatalogUsecase; - constructor(usecase: GetAllActivitiesCatalogUsecase) { + constructor(usecase: GetCatalogUsecase) { this.usecase = usecase; } @@ -27,7 +22,7 @@ export class GetAllActivitiesCatalogController { if (!request) { throw new InvalidRequest(); } - + const response = await this.usecase.execute(); return new OK(response, "Activities found successfully"); diff --git a/src/modules/get_catalog/app/get_catalog_presenter.ts b/src/modules/get_catalog/app/get_catalog_presenter.ts new file mode 100644 index 0000000..c55e4a9 --- /dev/null +++ b/src/modules/get_catalog/app/get_catalog_presenter.ts @@ -0,0 +1,18 @@ +import { Repository } from "../../../core/repositories/Repository"; +import { HttpRequest } from "../../../core/helpers/http/http_codes"; +import { GetCatalogUsecase } from "./get_catalog_usecase"; +import { GetCatalogController } from "./get_catalog_controller"; + +const repository = new Repository({ activity_repo: true, institution_repo: true }); + +const usecase = new GetCatalogUsecase( + repository.ActivityRepo, + repository.InstitutionRepo +); +const controller = new GetCatalogController(usecase); + +export const handler = async (event: any, context: any) => { + let request = new HttpRequest(event); + let response = await controller.execute(request); + return response.to_json(); +}; diff --git a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts b/src/modules/get_catalog/app/get_catalog_usecase.ts similarity index 63% rename from src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts rename to src/modules/get_catalog/app/get_catalog_usecase.ts index 70bcf30..c3b1184 100644 --- a/src/modules/get_all_activities_catalog/app/get_all_activities_catalog_usecase.ts +++ b/src/modules/get_catalog/app/get_catalog_usecase.ts @@ -1,27 +1,31 @@ import { TokenAuth } from "../../../core/helpers/functions/token_auth"; -import { IUserRepo } from "../../../core/repositories/interfaces/IUserRepo"; +import { IInstitutionRepo } from "../../../core/repositories/interfaces/IInstitutionRepo"; import { ActivityTypeEnum } from "../../../core/helpers/enums/ActivityTypeEnum"; import { IActivityRepo } from "../../../core/repositories/interfaces/IActivityRepo"; -export class GetAllActivitiesCatalogUsecase { +export class GetCatalogUsecase { public token_auth: TokenAuth; - public activity_repo: IActivityRepo; + public activity_repo: IActivityRepo; + public institution_repo: IInstitutionRepo; - constructor(activity_repo: IActivityRepo) { + constructor(activity_repo: IActivityRepo, institution_repo: IInstitutionRepo) { this.token_auth = new TokenAuth(); this.activity_repo = activity_repo; + this.institution_repo = institution_repo; } async execute() { const activities = await this.activity_repo.get_all_activities_catalog(); + const institutions = await this.institution_repo.get_all_institutions(); const projects = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.PROJECT) : null; const mobilities = activities ? activities.filter((activity) => activity.type_activity === ActivityTypeEnum.ACADEMIC_MOBILITY) : null; const response = { projects: projects, - mobilities: mobilities + mobilities: mobilities, + institutions: institutions } return response; diff --git a/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts b/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts index f5d0c05..17a2f3a 100644 --- a/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts +++ b/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts @@ -1,17 +1,14 @@ import { it, describe, expect } from "vitest"; -import { ActivityMock } from "../../../../src/core/structure/mocks/ActivityMock"; -import { handler } from "../../../../src/modules/get_all_activities_catalog/app/get_all_activities_catalog_presenter"; +import { handler } from "../../../../src/modules/get_catalog/app/get_catalog_presenter"; -describe("Get All Activities Catalog", () => { - it("should return all activities", async () => { - const activityMock = new ActivityMock(); +describe("Get Catalog", () => { + it("should return the catolog for hero page", async () => { const event = { headers: { }, }; const response = await handler(event, null); expect(response.statusCode).toBe(200); - console.log(response.body); }); }); From 1cca407fb3e4f187b6df1528551cced98d0b4e9b Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 19 Jul 2024 15:06:31 -0300 Subject: [PATCH 69/71] refactor: Remove unused test file for get_all_activities_catalog --- .../app/get_all_activities_catalog.test.ts | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts diff --git a/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts b/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts deleted file mode 100644 index 17a2f3a..0000000 --- a/test/modules/get_all_activities_catalog/app/get_all_activities_catalog.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { it, describe, expect } from "vitest"; -import { handler } from "../../../../src/modules/get_catalog/app/get_catalog_presenter"; - -describe("Get Catalog", () => { - it("should return the catolog for hero page", async () => { - const event = { - headers: { - }, - }; - const response = await handler(event, null); - expect(response.statusCode).toBe(200); - }); - -}); - - From 62ed3056c765fb4ce56455ebaae05343fbcd33dc Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 19 Jul 2024 15:06:35 -0300 Subject: [PATCH 70/71] refactor: Add unit test for get_catalog module --- test/modules/get_catalog/app/get_catalog.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/modules/get_catalog/app/get_catalog.test.ts diff --git a/test/modules/get_catalog/app/get_catalog.test.ts b/test/modules/get_catalog/app/get_catalog.test.ts new file mode 100644 index 0000000..17a2f3a --- /dev/null +++ b/test/modules/get_catalog/app/get_catalog.test.ts @@ -0,0 +1,16 @@ +import { it, describe, expect } from "vitest"; +import { handler } from "../../../../src/modules/get_catalog/app/get_catalog_presenter"; + +describe("Get Catalog", () => { + it("should return the catolog for hero page", async () => { + const event = { + headers: { + }, + }; + const response = await handler(event, null); + expect(response.statusCode).toBe(200); + }); + +}); + + From 2081bcc617ac571ba2473110543e44896ee136b8 Mon Sep 17 00:00:00 2001 From: FelipeCarillo Date: Fri, 19 Jul 2024 15:06:41 -0300 Subject: [PATCH 71/71] refactor: Update get_all_activities_catalog to get_catalog --- iac/lib/lambda_stack.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/iac/lib/lambda_stack.ts b/iac/lib/lambda_stack.ts index 996ded0..1f2b1c9 100644 --- a/iac/lib/lambda_stack.ts +++ b/iac/lib/lambda_stack.ts @@ -23,7 +23,7 @@ export class LambdaStack extends Construct { private update_users_activity: lambda_js.NodejsFunction; private update_activity_event: lambda_js.NodejsFunction; private get_activity_requirements: lambda_js.NodejsFunction; - private get_all_activities_catalog: lambda_js.NodejsFunction; + private get_catalog: lambda_js.NodejsFunction; private get_all_activities_enrolled: lambda_js.NodejsFunction; public functions_need_s3_access: lambda.Function[] = []; @@ -234,8 +234,8 @@ export class LambdaStack extends Construct { origins ) - this.get_all_activities_catalog = this.create_lambda( - "get_all_activities_catalog", + this.get_catalog = this.create_lambda( + "get_catalog", environment_variables, "GET", restapi_resource, @@ -255,7 +255,7 @@ export class LambdaStack extends Construct { this.update_institution, ] - this.function_need_event_bridge_access = [ + this.functions_need_event_bridge_access = [ this.create_activity, this.update_activity, this.update_activity_event, @@ -278,11 +278,5 @@ export class LambdaStack extends Construct { action: "lambda:InvokeFunction", }); }); - - this.functions_need_event_bridge_access = [ - this.create_activity, - this.update_activity, - this.update_activity_event, - ] } }