@intlayer/backend 3.0.3 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/controllers/dictionary.controller.cjs +91 -18
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/organization.controller.cjs +140 -12
- package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
- package/dist/cjs/controllers/project.controller.cjs +181 -31
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/controllers/projectAccessKey.controller.cjs +61 -10
- package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
- package/dist/cjs/controllers/sessionAuth.controller.cjs +291 -62
- package/dist/cjs/controllers/sessionAuth.controller.cjs.map +1 -1
- package/dist/cjs/controllers/stripe.controller.cjs +84 -0
- package/dist/cjs/controllers/stripe.controller.cjs.map +1 -0
- package/dist/cjs/controllers/user.controller.cjs +49 -20
- package/dist/cjs/controllers/user.controller.cjs.map +1 -1
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs +182 -0
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs.map +1 -0
- package/dist/cjs/emails/SubscriptionPaymentError.cjs +182 -0
- package/dist/cjs/emails/SubscriptionPaymentError.cjs.map +1 -0
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs +188 -0
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs.map +1 -0
- package/dist/cjs/export.cjs.map +1 -1
- package/dist/cjs/index.cjs +16 -5
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/middlewares/oAuth2.middleware.cjs +10 -0
- package/dist/cjs/middlewares/oAuth2.middleware.cjs.map +1 -1
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs +50 -10
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
- package/dist/cjs/routes/dictionary.routes.cjs +2 -62
- package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
- package/dist/cjs/routes/organization.routes.cjs +1 -25
- package/dist/cjs/routes/organization.routes.cjs.map +1 -1
- package/dist/cjs/routes/project.routes.cjs +10 -85
- package/dist/cjs/routes/project.routes.cjs.map +1 -1
- package/dist/cjs/routes/sessionAuth.routes.cjs +26 -25
- package/dist/cjs/routes/sessionAuth.routes.cjs.map +1 -1
- package/dist/cjs/routes/stripe.routes.cjs +42 -0
- package/dist/cjs/routes/stripe.routes.cjs.map +1 -0
- package/dist/cjs/routes/user.routes.cjs +6 -27
- package/dist/cjs/routes/user.routes.cjs.map +1 -1
- package/dist/cjs/schemas/organization.schema.cjs +5 -0
- package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
- package/dist/cjs/{middlewares/admin.middleware.cjs → schemas/plans.schema.cjs} +32 -20
- package/dist/cjs/schemas/plans.schema.cjs.map +1 -0
- package/dist/cjs/schemas/project.schema.cjs +14 -1
- package/dist/cjs/schemas/project.schema.cjs.map +1 -1
- package/dist/cjs/schemas/user.schema.cjs +5 -1
- package/dist/cjs/schemas/user.schema.cjs.map +1 -1
- package/dist/cjs/services/dictionary.service.cjs.map +1 -1
- package/dist/cjs/services/email.service.cjs +113 -43
- package/dist/cjs/services/email.service.cjs.map +1 -1
- package/dist/cjs/services/oAuth2.service.cjs +16 -8
- package/dist/cjs/services/oAuth2.service.cjs.map +1 -1
- package/dist/cjs/services/organization.service.cjs +63 -8
- package/dist/cjs/services/organization.service.cjs.map +1 -1
- package/dist/cjs/services/project.service.cjs +9 -5
- package/dist/cjs/services/project.service.cjs.map +1 -1
- package/dist/cjs/services/projectAccessKey.service.cjs +42 -10
- package/dist/cjs/services/projectAccessKey.service.cjs.map +1 -1
- package/dist/cjs/services/sessionAuth.service.cjs +9 -11
- package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
- package/dist/cjs/services/subscription.service.cjs +201 -0
- package/dist/cjs/services/subscription.service.cjs.map +1 -0
- package/dist/cjs/services/user.service.cjs +1 -3
- package/dist/cjs/services/user.service.cjs.map +1 -1
- package/dist/cjs/types/dictionary.types.cjs.map +1 -1
- package/dist/cjs/types/organization.types.cjs.map +1 -1
- package/dist/cjs/types/plan.types.cjs +17 -0
- package/dist/cjs/types/plan.types.cjs.map +1 -0
- package/dist/cjs/types/project.types.cjs.map +1 -1
- package/dist/cjs/types/session.types.cjs.map +1 -1
- package/dist/cjs/types/user.types.cjs.map +1 -1
- package/dist/cjs/utils/errors/ErrorHandler.cjs +29 -9
- package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
- package/dist/cjs/utils/errors/ErrorsClass.cjs +17 -3
- package/dist/cjs/utils/errors/ErrorsClass.cjs.map +1 -1
- package/dist/cjs/utils/errors/errorCodes.cjs +321 -9
- package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
- package/dist/cjs/utils/mapper/organization.cjs.map +1 -1
- package/dist/cjs/utils/mapper/project.cjs +19 -3
- package/dist/cjs/utils/mapper/project.cjs.map +1 -1
- package/dist/cjs/utils/mapper/user.cjs.map +1 -1
- package/dist/cjs/utils/plan.cjs +75 -0
- package/dist/cjs/utils/plan.cjs.map +1 -0
- package/dist/cjs/utils/responseData.cjs +8 -0
- package/dist/cjs/utils/responseData.cjs.map +1 -1
- package/dist/cjs/webhooks/stripe.webhook.cjs +133 -0
- package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -0
- package/dist/esm/controllers/dictionary.controller.mjs +91 -18
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs +140 -12
- package/dist/esm/controllers/organization.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +181 -31
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/projectAccessKey.controller.mjs +61 -10
- package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
- package/dist/esm/controllers/sessionAuth.controller.mjs +287 -61
- package/dist/esm/controllers/sessionAuth.controller.mjs.map +1 -1
- package/dist/esm/controllers/stripe.controller.mjs +60 -0
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -0
- package/dist/esm/controllers/user.controller.mjs +49 -20
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs +168 -0
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -0
- package/dist/esm/emails/SubscriptionPaymentError.mjs +168 -0
- package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -0
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs +174 -0
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -0
- package/dist/esm/export.mjs.map +1 -1
- package/dist/esm/index.mjs +19 -7
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/middlewares/oAuth2.middleware.mjs +10 -0
- package/dist/esm/middlewares/oAuth2.middleware.mjs.map +1 -1
- package/dist/esm/middlewares/sessionAuth.middleware.mjs +49 -9
- package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs +2 -62
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/organization.routes.mjs +1 -25
- package/dist/esm/routes/organization.routes.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs +10 -85
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/routes/sessionAuth.routes.mjs +29 -26
- package/dist/esm/routes/sessionAuth.routes.mjs.map +1 -1
- package/dist/esm/routes/stripe.routes.mjs +17 -0
- package/dist/esm/routes/stripe.routes.mjs.map +1 -0
- package/dist/esm/routes/user.routes.mjs +6 -27
- package/dist/esm/routes/user.routes.mjs.map +1 -1
- package/dist/esm/schemas/organization.schema.mjs +5 -0
- package/dist/esm/schemas/organization.schema.mjs.map +1 -1
- package/dist/esm/schemas/plans.schema.mjs +32 -0
- package/dist/esm/schemas/plans.schema.mjs.map +1 -0
- package/dist/esm/schemas/project.schema.mjs +13 -1
- package/dist/esm/schemas/project.schema.mjs.map +1 -1
- package/dist/esm/schemas/user.schema.mjs +5 -1
- package/dist/esm/schemas/user.schema.mjs.map +1 -1
- package/dist/esm/services/dictionary.service.mjs.map +1 -1
- package/dist/esm/services/email.service.mjs +125 -43
- package/dist/esm/services/email.service.mjs.map +1 -1
- package/dist/esm/services/oAuth2.service.mjs +16 -8
- package/dist/esm/services/oAuth2.service.mjs.map +1 -1
- package/dist/esm/services/organization.service.mjs +58 -7
- package/dist/esm/services/organization.service.mjs.map +1 -1
- package/dist/esm/services/project.service.mjs +9 -5
- package/dist/esm/services/project.service.mjs.map +1 -1
- package/dist/esm/services/projectAccessKey.service.mjs +42 -10
- package/dist/esm/services/projectAccessKey.service.mjs.map +1 -1
- package/dist/esm/services/sessionAuth.service.mjs +9 -10
- package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
- package/dist/esm/services/subscription.service.mjs +178 -0
- package/dist/esm/services/subscription.service.mjs.map +1 -0
- package/dist/esm/services/user.service.mjs +1 -3
- package/dist/esm/services/user.service.mjs.map +1 -1
- package/dist/esm/types/plan.types.mjs +1 -0
- package/dist/esm/types/plan.types.mjs.map +1 -0
- package/dist/esm/utils/errors/ErrorHandler.mjs +29 -9
- package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
- package/dist/esm/utils/errors/ErrorsClass.mjs +17 -3
- package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
- package/dist/esm/utils/errors/errorCodes.mjs +321 -9
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/utils/mapper/organization.mjs.map +1 -1
- package/dist/esm/utils/mapper/project.mjs +17 -2
- package/dist/esm/utils/mapper/project.mjs.map +1 -1
- package/dist/esm/utils/mapper/user.mjs.map +1 -1
- package/dist/esm/utils/plan.mjs +50 -0
- package/dist/esm/utils/plan.mjs.map +1 -0
- package/dist/esm/utils/responseData.mjs +8 -0
- package/dist/esm/utils/responseData.mjs.map +1 -1
- package/dist/esm/webhooks/stripe.webhook.mjs +113 -0
- package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -0
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/organization.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts +9 -7
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
- package/dist/types/controllers/sessionAuth.controller.d.ts +28 -9
- package/dist/types/controllers/sessionAuth.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts +17 -0
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -0
- package/dist/types/controllers/user.controller.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -0
- package/dist/types/emails/SubscriptionPaymentError.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -0
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -0
- package/dist/types/export.d.ts +2 -0
- package/dist/types/export.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/middlewares/oAuth2.middleware.d.ts.map +1 -1
- package/dist/types/middlewares/sessionAuth.middleware.d.ts +13 -7
- package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
- package/dist/types/models/dictionary.model.d.ts +1 -1
- package/dist/types/models/oAuth2.model.d.ts +1 -1
- package/dist/types/models/organization.model.d.ts +2 -1
- package/dist/types/models/organization.model.d.ts.map +1 -1
- package/dist/types/models/plan.moddel.d.ts +11 -0
- package/dist/types/models/plan.moddel.d.ts.map +1 -0
- package/dist/types/models/project.model.d.ts +1 -1
- package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
- package/dist/types/routes/organization.routes.d.ts.map +1 -1
- package/dist/types/routes/project.routes.d.ts.map +1 -1
- package/dist/types/routes/sessionAuth.routes.d.ts +15 -2
- package/dist/types/routes/sessionAuth.routes.d.ts.map +1 -1
- package/dist/types/routes/stripe.routes.d.ts +10 -0
- package/dist/types/routes/stripe.routes.d.ts.map +1 -0
- package/dist/types/routes/user.routes.d.ts.map +1 -1
- package/dist/types/schemas/dictionary.schema.d.ts +2 -2
- package/dist/types/schemas/oAuth2.schema.d.ts +2 -2
- package/dist/types/schemas/organization.schema.d.ts +3 -2
- package/dist/types/schemas/organization.schema.d.ts.map +1 -1
- package/dist/types/schemas/plans.schema.d.ts +16 -0
- package/dist/types/schemas/plans.schema.d.ts.map +1 -0
- package/dist/types/schemas/project.schema.d.ts +12 -3
- package/dist/types/schemas/project.schema.d.ts.map +1 -1
- package/dist/types/schemas/user.schema.d.ts +2 -2
- package/dist/types/schemas/user.schema.d.ts.map +1 -1
- package/dist/types/services/dictionary.service.d.ts +9 -9
- package/dist/types/services/dictionary.service.d.ts.map +1 -1
- package/dist/types/services/email.service.d.ts +33 -4
- package/dist/types/services/email.service.d.ts.map +1 -1
- package/dist/types/services/oAuth2.service.d.ts +7 -5
- package/dist/types/services/oAuth2.service.d.ts.map +1 -1
- package/dist/types/services/organization.service.d.ts +27 -6
- package/dist/types/services/organization.service.d.ts.map +1 -1
- package/dist/types/services/plans.service.d.ts +35 -0
- package/dist/types/services/plans.service.d.ts.map +1 -0
- package/dist/types/services/project.service.d.ts +6 -6
- package/dist/types/services/project.service.d.ts.map +1 -1
- package/dist/types/services/projectAccessKey.service.d.ts +4 -4
- package/dist/types/services/projectAccessKey.service.d.ts.map +1 -1
- package/dist/types/services/sessionAuth.service.d.ts +9 -16
- package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
- package/dist/types/services/subscription.service.d.ts +22 -0
- package/dist/types/services/subscription.service.d.ts.map +1 -0
- package/dist/types/services/user.service.d.ts +11 -19
- package/dist/types/services/user.service.d.ts.map +1 -1
- package/dist/types/types/dictionary.types.d.ts +2 -2
- package/dist/types/types/dictionary.types.d.ts.map +1 -1
- package/dist/types/types/organization.types.d.ts +4 -2
- package/dist/types/types/organization.types.d.ts.map +1 -1
- package/dist/types/types/plan.types.d.ts +18 -0
- package/dist/types/types/plan.types.d.ts.map +1 -0
- package/dist/types/types/project.types.d.ts +13 -2
- package/dist/types/types/project.types.d.ts.map +1 -1
- package/dist/types/types/session.types.d.ts +6 -6
- package/dist/types/types/session.types.d.ts.map +1 -1
- package/dist/types/types/user.types.d.ts +2 -1
- package/dist/types/types/user.types.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorHandler.d.ts +5 -3
- package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorsClass.d.ts +4 -1
- package/dist/types/utils/errors/ErrorsClass.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts +313 -1
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/utils/mapper/organization.d.ts +1 -1
- package/dist/types/utils/mapper/organization.d.ts.map +1 -1
- package/dist/types/utils/mapper/project.d.ts +10 -1
- package/dist/types/utils/mapper/project.d.ts.map +1 -1
- package/dist/types/utils/mapper/user.d.ts +1 -1
- package/dist/types/utils/mapper/user.d.ts.map +1 -1
- package/dist/types/utils/plan.d.ts +17 -0
- package/dist/types/utils/plan.d.ts.map +1 -0
- package/dist/types/utils/responseData.d.ts +13 -2
- package/dist/types/utils/responseData.d.ts.map +1 -1
- package/dist/types/webhooks/stripe.d.ts +3 -0
- package/dist/types/webhooks/stripe.d.ts.map +1 -0
- package/dist/types/webhooks/stripe.webhook.d.ts +3 -0
- package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -0
- package/package.json +27 -24
- package/dist/cjs/middlewares/admin.middleware.cjs.map +0 -1
- package/dist/esm/middlewares/admin.middleware.mjs +0 -20
- package/dist/esm/middlewares/admin.middleware.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { sessionAuthRoutes } from '@routes/sessionAuth.routes';\nimport { sendEmail } from '@services/email.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n type OrganizationFilters,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport type { ObjectId } from 'mongoose';\nimport { User } from 'oauth2-server';\nimport * as organizationService from '@/services/organization.service';\nimport type {\n Organization,\n OrganizationCreationData,\n} from '@/types/organization.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<Organization>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithInformation<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n const restrictedFilter: OrganizationFilters = {\n ...filters,\n\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n };\n\n try {\n const organizations = await organizationService.findOrganizations(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<Organization>({\n data: organizations,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<Organization>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithInformation<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n const responseData = formatResponse<Organization>({ data: organization });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<Organization>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithInformation<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user._id\n );\n\n const responseData = formatResponse<Organization>({\n data: newOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<Organization>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithInformation<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization._id,\n organizationFields\n );\n\n const responseData = formatResponse<Organization>({\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\n\nexport type OrganizationMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<Organization>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithInformation<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, isOrganizationAdmin, user } = res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: sessionAuthRoutes.loginEmailPassword.url,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember._id],\n });\n\n const responseData = formatResponse<Organization>({\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: OrganizationMemberByIdOption[];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<Organization>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithInformation<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, isOrganizationAdmin } = res.locals;\n const { membersIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n let existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds?.map((member) => member.userId);\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => {\n const isAdmin =\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false;\n\n return {\n user,\n isAdmin,\n };\n });\n\n existingUsers = userMap;\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n });\n\n const responseData = formatResponse<Organization>({\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteOrganizationResult = ResponseData<Organization>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithInformation,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization._id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization._id)}`);\n\n const responseData = formatResponse<Organization>({\n data: deletedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = { organizationId: ObjectId | string };\nexport type SelectOrganizationResult = ResponseData<Organization>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithInformation<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n sessionAuthService.setOrganizationAuth(res, organization);\n\n const responseData = formatResponse<Organization>({\n data: organization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = (\n _req: Request,\n res: ResponseWithInformation<UnselectOrganizationResult>,\n _next: NextFunction\n): void => {\n try {\n sessionAuthService.clearOrganizationAuth(res);\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { sessionAuthRoutes } from '@routes/sessionAuth.routes';\nimport { sendEmail } from '@services/email.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n type OrganizationFilters,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport { getPLanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { ObjectId } from 'mongoose';\nimport { User } from 'oauth2-server';\nimport * as organizationService from '@/services/organization.service';\nimport type {\n Organization,\n OrganizationCreationData,\n} from '@/types/organization.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<Organization>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithInformation<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user, organizationRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n const restrictedFilter: OrganizationFilters = {\n ...filters,\n\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n };\n\n try {\n const organizations = await organizationService.findOrganizations(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<Organization>({\n data: organizations,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<Organization>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithInformation<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationRights } = res.locals;\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n const responseData = formatResponse<Organization>({ data: organization });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<Organization>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithInformation<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user._id\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization created successfully',\n fr: 'Organisation créée avec succès',\n es: 'Organización creada con éxito',\n }),\n description: t({\n en: 'Your organization has been created successfully',\n fr: 'Votre organisation a été créée avec succès',\n es: 'Su organización ha sido creada con éxito',\n }),\n data: newOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<Organization>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithInformation<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization._id,\n organizationFields\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\n\nexport type OrganizationMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<Organization>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithInformation<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, isOrganizationAdmin, user, organizationRights } =\n res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n if (!organization.plan) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n const planType = getPLanDetails(organization.plan);\n\n if (\n planType.numberOfOrganizationUsers &&\n organization.membersIds.length >= planType.numberOfOrganizationUsers\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_USER_LIMIT_REACHED', {\n organizationId: organization._id,\n });\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: sessionAuthRoutes.loginEmailPassword.url,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember._id],\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: OrganizationMemberByIdOption[];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<Organization>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithInformation<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, organizationRights, isOrganizationAdmin } = res.locals;\n const { membersIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n let existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds?.map((member) => member.userId);\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => {\n const isAdmin =\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false;\n\n return {\n user,\n isAdmin,\n };\n });\n\n existingUsers = userMap;\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteOrganizationResult = ResponseData<Organization>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithInformation,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n try {\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization._id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization._id)}`);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization deleted successfully',\n fr: 'Organisation supprimée avec succès',\n es: 'Organización eliminada con éxito',\n }),\n description: t({\n en: 'Your organization has been deleted successfully',\n fr: 'Votre organisation a été supprimée avec succès',\n es: 'Su organización ha sido eliminada con éxito',\n }),\n data: deletedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = { organizationId: ObjectId | string };\nexport type SelectOrganizationResult = ResponseData<Organization>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithInformation<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n sessionAuthService.setOrganizationAuth(res, organization);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization retrieved successfully',\n fr: 'Organisation récupérée avec succès',\n es: 'Organización recuperada con éxito',\n }),\n description: t({\n en: 'Your organization has been retrieved successfully',\n fr: 'Votre organisation a été récupérée avec succès',\n es: 'Su organización ha sido recuperada con éxito',\n }),\n data: organization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = (\n _req: Request,\n res: ResponseWithInformation<UnselectOrganizationResult>,\n _next: NextFunction\n): void => {\n try {\n sessionAuthService.clearOrganizationAuth(res);\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Organization unselected successfully',\n fr: 'Organisation désélectionnée avec succès',\n es: 'Organización deseleccionada con éxito',\n }),\n description: t({\n en: 'Your organization has been unselected successfully',\n fr: 'Votre organisation a été désélectionnée avec succès',\n es: 'Su organización ha sido deseleccionada con éxito',\n }),\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -43,16 +43,23 @@ var sessionAuthService = __toESM(require('./../services/sessionAuth.service.cjs'
|
|
|
43
43
|
var userService = __toESM(require('./../services/user.service.cjs'), 1);
|
|
44
44
|
var import_errors = require('./../utils/errors/index.cjs');
|
|
45
45
|
var import_getProjectFiltersAndPagination = require('./../utils/filtersAndPagination/getProjectFiltersAndPagination.cjs');
|
|
46
|
+
var import_project = require('./../utils/mapper/project.cjs');
|
|
47
|
+
var import_plan = require('./../utils/plan.cjs');
|
|
46
48
|
var import_responseData = require('./../utils/responseData.cjs');
|
|
49
|
+
var import_express_intlayer = require("express-intlayer");
|
|
47
50
|
const getProjects = async (req, res, _next) => {
|
|
48
|
-
const { user, organization } = res.locals;
|
|
51
|
+
const { user, organization, projectRights } = res.locals;
|
|
49
52
|
const { filters, pageSize, skip, page, getNumberOfPages } = (0, import_getProjectFiltersAndPagination.getProjectFiltersAndPagination)(req);
|
|
50
53
|
if (!user) {
|
|
51
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
54
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
57
|
if (!organization) {
|
|
55
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
58
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!projectRights?.read) {
|
|
62
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_READ");
|
|
56
63
|
return;
|
|
57
64
|
}
|
|
58
65
|
const restrictedFilter = {
|
|
@@ -67,8 +74,13 @@ const getProjects = async (req, res, _next) => {
|
|
|
67
74
|
pageSize
|
|
68
75
|
);
|
|
69
76
|
const totalItems = await projectService.countProjects(filters);
|
|
77
|
+
const formattedProjects = (0, import_project.mapProjectsToAPI)(
|
|
78
|
+
projects,
|
|
79
|
+
user,
|
|
80
|
+
res.locals.isProjectAdmin
|
|
81
|
+
);
|
|
70
82
|
const responseData = (0, import_responseData.formatPaginatedResponse)({
|
|
71
|
-
data:
|
|
83
|
+
data: formattedProjects,
|
|
72
84
|
page,
|
|
73
85
|
pageSize,
|
|
74
86
|
totalPages: getNumberOfPages(totalItems),
|
|
@@ -82,14 +94,14 @@ const getProjects = async (req, res, _next) => {
|
|
|
82
94
|
}
|
|
83
95
|
};
|
|
84
96
|
const addProject = async (req, res, _next) => {
|
|
85
|
-
const { organization, user, isOrganizationAdmin } = res.locals;
|
|
97
|
+
const { organization, user, isOrganizationAdmin, projectRights } = res.locals;
|
|
86
98
|
const projectData = req.body;
|
|
87
99
|
if (!user) {
|
|
88
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
100
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
89
101
|
return;
|
|
90
102
|
}
|
|
91
103
|
if (!organization) {
|
|
92
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
104
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
93
105
|
return;
|
|
94
106
|
}
|
|
95
107
|
if (!isOrganizationAdmin) {
|
|
@@ -98,9 +110,37 @@ const addProject = async (req, res, _next) => {
|
|
|
98
110
|
"USER_IS_NOT_ADMIN_OF_ORGANIZATION"
|
|
99
111
|
);
|
|
100
112
|
}
|
|
113
|
+
if (!projectRights?.admin) {
|
|
114
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_WRITE");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
101
117
|
if (!projectData) {
|
|
102
118
|
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_DATA_NOT_FOUND");
|
|
103
119
|
}
|
|
120
|
+
const { plan } = organization;
|
|
121
|
+
if (!plan) {
|
|
122
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PLAN_NOT_FOUND", {
|
|
123
|
+
organizationId: organization._id
|
|
124
|
+
});
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const planType = (0, import_plan.getPLanDetails)(plan);
|
|
128
|
+
if (planType.numberOfProjects) {
|
|
129
|
+
const projectCount = await projectService.countProjects({
|
|
130
|
+
organizationId: organization._id
|
|
131
|
+
});
|
|
132
|
+
if (projectCount >= planType.numberOfProjects) {
|
|
133
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(
|
|
134
|
+
res,
|
|
135
|
+
"PLAN_PROJECT_LIMIT_REACHED",
|
|
136
|
+
{
|
|
137
|
+
organizationId: organization._id
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
104
144
|
const project = {
|
|
105
145
|
membersIds: [user._id],
|
|
106
146
|
adminsIds: [user._id],
|
|
@@ -110,7 +150,20 @@ const addProject = async (req, res, _next) => {
|
|
|
110
150
|
};
|
|
111
151
|
try {
|
|
112
152
|
const newProject = await projectService.createProject(project);
|
|
113
|
-
const
|
|
153
|
+
const formattedProject = (0, import_project.mapProjectToAPI)(newProject, user, true);
|
|
154
|
+
const responseData = (0, import_responseData.formatResponse)({
|
|
155
|
+
message: (0, import_express_intlayer.t)({
|
|
156
|
+
en: "Project created successfully",
|
|
157
|
+
fr: "Projet cr\xE9\xE9 avec succ\xE8s",
|
|
158
|
+
es: "Proyecto creado con \xE9xito"
|
|
159
|
+
}),
|
|
160
|
+
description: (0, import_express_intlayer.t)({
|
|
161
|
+
en: "Your project has been created successfully",
|
|
162
|
+
fr: "Votre projet a \xE9t\xE9 cr\xE9\xE9 avec succ\xE8s",
|
|
163
|
+
es: "Su proyecto ha sido creado con \xE9xito"
|
|
164
|
+
}),
|
|
165
|
+
data: formattedProject
|
|
166
|
+
});
|
|
114
167
|
res.json(responseData);
|
|
115
168
|
return;
|
|
116
169
|
} catch (error) {
|
|
@@ -119,22 +172,34 @@ const addProject = async (req, res, _next) => {
|
|
|
119
172
|
}
|
|
120
173
|
};
|
|
121
174
|
const updateProject = async (req, res, _next) => {
|
|
122
|
-
const { organization } = res.locals;
|
|
123
|
-
const
|
|
175
|
+
const { organization, projectRights, project, user, isProjectAdmin } = res.locals;
|
|
176
|
+
const projectData = req.body;
|
|
177
|
+
if (!user) {
|
|
178
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
124
181
|
if (!project) {
|
|
125
182
|
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_DATA_NOT_FOUND");
|
|
126
183
|
return;
|
|
127
184
|
}
|
|
128
185
|
if (!organization) {
|
|
129
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
186
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
130
187
|
return;
|
|
131
188
|
}
|
|
132
|
-
if (
|
|
133
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
189
|
+
if (!isProjectAdmin) {
|
|
190
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_ADMIN");
|
|
134
191
|
return;
|
|
135
192
|
}
|
|
136
|
-
if (
|
|
137
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
193
|
+
if (!projectRights?.write) {
|
|
194
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_WRITE");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (String(project._id) !== String(projectData._id)) {
|
|
198
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_ID_MISMATCH");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (String(project.organizationId) !== String(organization._id)) {
|
|
202
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_IN_ORGANIZATION");
|
|
138
203
|
return;
|
|
139
204
|
}
|
|
140
205
|
try {
|
|
@@ -142,7 +207,24 @@ const updateProject = async (req, res, _next) => {
|
|
|
142
207
|
project._id,
|
|
143
208
|
project
|
|
144
209
|
);
|
|
145
|
-
const
|
|
210
|
+
const formattedProject = (0, import_project.mapProjectToAPI)(
|
|
211
|
+
updatedProject,
|
|
212
|
+
user,
|
|
213
|
+
isProjectAdmin
|
|
214
|
+
);
|
|
215
|
+
const responseData = (0, import_responseData.formatResponse)({
|
|
216
|
+
message: (0, import_express_intlayer.t)({
|
|
217
|
+
en: "Project updated successfully",
|
|
218
|
+
fr: "Projet mis \xE0 jour avec succ\xE8s",
|
|
219
|
+
es: "Proyecto actualizado con \xE9xito"
|
|
220
|
+
}),
|
|
221
|
+
description: (0, import_express_intlayer.t)({
|
|
222
|
+
en: "Your project has been updated successfully",
|
|
223
|
+
fr: "Votre projet a \xE9t\xE9 mis \xE0 jour avec succ\xE8s",
|
|
224
|
+
es: "Su proyecto ha sido actualizado con \xE9xito"
|
|
225
|
+
}),
|
|
226
|
+
data: formattedProject
|
|
227
|
+
});
|
|
146
228
|
res.json(responseData);
|
|
147
229
|
return;
|
|
148
230
|
} catch (error) {
|
|
@@ -151,10 +233,14 @@ const updateProject = async (req, res, _next) => {
|
|
|
151
233
|
}
|
|
152
234
|
};
|
|
153
235
|
const updateProjectMembers = async (req, res, _next) => {
|
|
154
|
-
const { project, isProjectAdmin, organization } = res.locals;
|
|
236
|
+
const { user, project, isProjectAdmin, organization, projectRights } = res.locals;
|
|
155
237
|
const { membersIds } = req.body;
|
|
238
|
+
if (!user) {
|
|
239
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
156
242
|
if (!project) {
|
|
157
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
243
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
158
244
|
return;
|
|
159
245
|
}
|
|
160
246
|
if (!isProjectAdmin) {
|
|
@@ -164,8 +250,12 @@ const updateProjectMembers = async (req, res, _next) => {
|
|
|
164
250
|
);
|
|
165
251
|
return;
|
|
166
252
|
}
|
|
253
|
+
if (!projectRights?.admin) {
|
|
254
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_ADMIN");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
167
257
|
if (!organization) {
|
|
168
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
258
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
169
259
|
return;
|
|
170
260
|
}
|
|
171
261
|
if (membersIds?.length === 0) {
|
|
@@ -187,19 +277,19 @@ const updateProjectMembers = async (req, res, _next) => {
|
|
|
187
277
|
).map((member) => member.userId);
|
|
188
278
|
const users = await userService.getUsersByIds(userIdList);
|
|
189
279
|
if (users) {
|
|
190
|
-
const userMap = users.map((
|
|
191
|
-
user,
|
|
280
|
+
const userMap = users.map((user2) => ({
|
|
281
|
+
user: user2,
|
|
192
282
|
isAdmin: membersIds.find(
|
|
193
|
-
(member) => String(member.userId) === String(
|
|
283
|
+
(member) => String(member.userId) === String(user2._id)
|
|
194
284
|
)?.isAdmin ?? false
|
|
195
285
|
}));
|
|
196
286
|
existingUsers.push(...userMap);
|
|
197
287
|
}
|
|
198
288
|
}
|
|
199
289
|
const formattedMembers = existingUsers.map(
|
|
200
|
-
(
|
|
290
|
+
(user2) => user2.user._id
|
|
201
291
|
);
|
|
202
|
-
const formattedAdmin = existingUsers.filter((el) => el.isAdmin).map((
|
|
292
|
+
const formattedAdmin = existingUsers.filter((el) => el.isAdmin).map((user2) => user2.user._id);
|
|
203
293
|
const updatedOrganization = await projectService.updateProjectById(
|
|
204
294
|
project._id,
|
|
205
295
|
{
|
|
@@ -208,8 +298,23 @@ const updateProjectMembers = async (req, res, _next) => {
|
|
|
208
298
|
adminsIds: formattedAdmin
|
|
209
299
|
}
|
|
210
300
|
);
|
|
301
|
+
const formattedProject = (0, import_project.mapProjectToAPI)(
|
|
302
|
+
updatedOrganization,
|
|
303
|
+
user,
|
|
304
|
+
isProjectAdmin
|
|
305
|
+
);
|
|
211
306
|
const responseData = (0, import_responseData.formatResponse)({
|
|
212
|
-
|
|
307
|
+
message: (0, import_express_intlayer.t)({
|
|
308
|
+
en: "Project members updated successfully",
|
|
309
|
+
fr: "Membres du projet mis \xE0 jour avec succ\xE8s",
|
|
310
|
+
es: "Miembros del proyecto actualizados con \xE9xito"
|
|
311
|
+
}),
|
|
312
|
+
description: (0, import_express_intlayer.t)({
|
|
313
|
+
en: "Your project members have been updated successfully",
|
|
314
|
+
fr: "Les membres de votre projet ont \xE9t\xE9 mis \xE0 jour avec succ\xE8s",
|
|
315
|
+
es: "Los miembros de su proyecto han sido actualizados con \xE9xito"
|
|
316
|
+
}),
|
|
317
|
+
data: formattedProject
|
|
213
318
|
});
|
|
214
319
|
res.json(responseData);
|
|
215
320
|
return;
|
|
@@ -218,14 +323,22 @@ const updateProjectMembers = async (req, res, _next) => {
|
|
|
218
323
|
return;
|
|
219
324
|
}
|
|
220
325
|
};
|
|
221
|
-
const deleteProject = async (
|
|
222
|
-
const { organization, project } = res.locals;
|
|
326
|
+
const deleteProject = async (_req, res, _next) => {
|
|
327
|
+
const { user, organization, project, projectRights, isProjectAdmin } = res.locals;
|
|
328
|
+
if (!user) {
|
|
329
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
223
332
|
if (!organization) {
|
|
224
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
333
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
225
334
|
return;
|
|
226
335
|
}
|
|
227
336
|
if (!project) {
|
|
228
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
337
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (!projectRights?.admin) {
|
|
341
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_ADMIN");
|
|
229
342
|
return;
|
|
230
343
|
}
|
|
231
344
|
try {
|
|
@@ -239,13 +352,30 @@ const deleteProject = async (req, res, _next) => {
|
|
|
239
352
|
}
|
|
240
353
|
const deletedProject = await projectService.deleteProjectById(project._id);
|
|
241
354
|
if (!deletedProject) {
|
|
242
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "
|
|
355
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED", {
|
|
243
356
|
projectId: project._id
|
|
244
357
|
});
|
|
245
358
|
return;
|
|
246
359
|
}
|
|
247
360
|
import_logger.logger.info(`Project deleted: ${String(deletedProject._id)}`);
|
|
248
|
-
const
|
|
361
|
+
const formattedProject = (0, import_project.mapProjectToAPI)(
|
|
362
|
+
deletedProject,
|
|
363
|
+
user,
|
|
364
|
+
isProjectAdmin
|
|
365
|
+
);
|
|
366
|
+
const responseData = (0, import_responseData.formatResponse)({
|
|
367
|
+
message: (0, import_express_intlayer.t)({
|
|
368
|
+
en: "Project deleted successfully",
|
|
369
|
+
fr: "Projet supprim\xE9 avec succ\xE8s",
|
|
370
|
+
es: "Proyecto eliminado con \xE9xito"
|
|
371
|
+
}),
|
|
372
|
+
description: (0, import_express_intlayer.t)({
|
|
373
|
+
en: "Your project has been deleted successfully",
|
|
374
|
+
fr: "Votre projet a \xE9t\xE9 supprim\xE9 avec succ\xE8s",
|
|
375
|
+
es: "Su proyecto ha sido eliminado con \xE9xito"
|
|
376
|
+
}),
|
|
377
|
+
data: formattedProject
|
|
378
|
+
});
|
|
249
379
|
res.json(responseData);
|
|
250
380
|
return;
|
|
251
381
|
} catch (error) {
|
|
@@ -263,6 +393,16 @@ const selectProject = async (req, res, _next) => {
|
|
|
263
393
|
const project = await projectService.getProjectById(projectId);
|
|
264
394
|
sessionAuthService.setProjectAuth(res, project);
|
|
265
395
|
const responseData = (0, import_responseData.formatResponse)({
|
|
396
|
+
message: (0, import_express_intlayer.t)({
|
|
397
|
+
en: "Project selected successfully",
|
|
398
|
+
fr: "Projet s\xE9lectionn\xE9 avec succ\xE8s",
|
|
399
|
+
es: "Proyecto seleccionado con \xE9xito"
|
|
400
|
+
}),
|
|
401
|
+
description: (0, import_express_intlayer.t)({
|
|
402
|
+
en: "Your project has been selected successfully",
|
|
403
|
+
fr: "Votre projet a \xE9t\xE9 s\xE9lectionn\xE9 avec succ\xE8s",
|
|
404
|
+
es: "Su proyecto ha sido seleccionado con \xE9xito"
|
|
405
|
+
}),
|
|
266
406
|
data: project
|
|
267
407
|
});
|
|
268
408
|
res.json(responseData);
|
|
@@ -276,6 +416,16 @@ const unselectProject = (_req, res, _next) => {
|
|
|
276
416
|
try {
|
|
277
417
|
sessionAuthService.clearProjectAuth(res);
|
|
278
418
|
const responseData = (0, import_responseData.formatResponse)({
|
|
419
|
+
message: (0, import_express_intlayer.t)({
|
|
420
|
+
en: "Project unselected successfully",
|
|
421
|
+
fr: "Projet d\xE9s\xE9lectionn\xE9 avec succ\xE8s",
|
|
422
|
+
es: "Proyecto deseleccionado con \xE9xito"
|
|
423
|
+
}),
|
|
424
|
+
description: (0, import_express_intlayer.t)({
|
|
425
|
+
en: "Your project has been unselected successfully",
|
|
426
|
+
fr: "Votre projet a \xE9t\xE9 d\xE9s\xE9lectionn\xE9 avec succ\xE8s",
|
|
427
|
+
es: "Su proyecto ha sido deseleccionado con \xE9xito"
|
|
428
|
+
}),
|
|
279
429
|
data: null
|
|
280
430
|
});
|
|
281
431
|
res.json(responseData);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/project.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as projectService from '@services/project.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getProjectFiltersAndPagination,\n type ProjectFilters,\n type ProjectFiltersParams,\n} from '@utils/filtersAndPagination/getProjectFiltersAndPagination';\nimport {\n formatPaginatedResponse,\n type ResponseData,\n type PaginatedResponse,\n formatResponse,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport type { ObjectId } from 'mongoose';\nimport { User } from 'oauth2-server';\nimport type {\n Project,\n ProjectAPI,\n ProjectCreationData,\n ProjectData,\n} from '@/types/project.types';\n\nexport type GetProjectsParams = FiltersAndPagination<ProjectFiltersParams>;\nexport type GetProjectsResult = PaginatedResponse<ProjectAPI>;\n\n/**\n * Retrieves a list of projects based on filters and pagination.\n */\nexport const getProjects = async (\n req: Request<GetProjectsParams>,\n res: ResponseWithInformation<GetProjectsResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, organization } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getProjectFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n const restrictedFilter: ProjectFilters = {\n ...filters,\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n organizationId: String(organization._id),\n };\n\n try {\n const projects = await projectService.findProjects(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await projectService.countProjects(filters);\n\n const responseData = formatPaginatedResponse<ProjectAPI>({\n data: projects,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddProjectBody = ProjectCreationData;\nexport type AddProjectResult = ResponseData<Project>;\n\n/**\n * Adds a new project to the database.\n */\nexport const addProject = async (\n req: Request<any, any, AddProjectBody>,\n res: ResponseWithInformation<AddProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, user, isOrganizationAdmin } = res.locals;\n const projectData = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n }\n\n if (!projectData) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_DATA_NOT_FOUND');\n }\n\n const project: ProjectData = {\n membersIds: [user._id],\n adminsIds: [user._id],\n creatorId: user._id,\n organizationId: organization._id,\n ...projectData,\n };\n\n try {\n const newProject = await projectService.createProject(project);\n\n const responseData = formatResponse<Project>({ data: newProject });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateProjectBody = Partial<Project>;\nexport type UpdateProjectResult = ResponseData<Project>;\n\n/**\n * Updates an existing project in the database.\n */\nexport const updateProject = async (\n req: Request<any, any, UpdateProjectBody>,\n res: ResponseWithInformation<UpdateProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization } = res.locals;\n const project = req.body;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (project.organizationId !== organization._id) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_IN_ORGANIZATION');\n return;\n }\n\n if (typeof project._id === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_ID_NOT_FOUND');\n return;\n }\n\n try {\n const updatedProject = await projectService.updateProjectById(\n project._id,\n project\n );\n\n const responseData = formatResponse<Project>({ data: updatedProject });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\nexport type ProjectMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type UpdateProjectMembersBody = Partial<{\n membersIds: ProjectMemberByIdOption[];\n}>;\nexport type UpdateProjectMembersResult = ResponseData<Project>;\n\n/**\n * Update members to the dictionary in the database.\n */\nexport const updateProjectMembers = async (\n req: Request<any, any, UpdateProjectMembersBody>,\n res: ResponseWithInformation<UpdateProjectMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, isProjectAdmin, organization } = res.locals;\n const { membersIds } = req.body;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_FOUND');\n return;\n }\n\n if (!isProjectAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_PROJECT'\n );\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_MUST_HAVE_MEMBER');\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_MUST_HAVE_ADMIN');\n return;\n }\n\n try {\n const existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds\n ?.filter(\n (member) =>\n // Remove members that are not in the organization\n !organization?.membersIds.includes(member.userId as ObjectId)\n )\n .map((member) => member.userId);\n\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => ({\n user,\n isAdmin:\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false,\n }));\n\n existingUsers.push(...userMap);\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization = await projectService.updateProjectById(\n project._id,\n {\n ...project,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n }\n );\n\n const responseData = formatResponse<Project>({\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteProjectResult = ResponseData<Project>;\n\n/**\n * Deletes a project from the database by its ID.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response confirming the deletion.\n */\nexport const deleteProject = async (\n req: Request,\n res: ResponseWithInformation<DeleteProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, project } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_FOUND');\n return;\n }\n\n try {\n const projectToDelete = await projectService.getProjectById(project._id);\n\n if (projectToDelete.organizationId !== organization._id) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'PROJECT_NOT_IN_ORGANIZATION'\n );\n return;\n }\n\n const deletedProject = await projectService.deleteProjectById(project._id);\n\n if (!deletedProject) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_FOUND', {\n projectId: project._id,\n });\n\n return;\n }\n\n logger.info(`Project deleted: ${String(deletedProject._id)}`);\n\n const responseData = formatResponse<Project>({ data: deletedProject });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectProjectParam = { projectId: ObjectId | string };\nexport type SelectProjectResult = ResponseData<Project>;\n\n/**\n * Select a project.\n */\nexport const selectProject = async (\n req: Request<SelectProjectParam>,\n res: ResponseWithInformation<SelectProjectResult>,\n _next: NextFunction\n) => {\n const { projectId } = req.params;\n\n if (!projectId) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_ID_NOT_FOUND');\n return;\n }\n\n try {\n const project = await projectService.getProjectById(projectId);\n\n sessionAuthService.setProjectAuth(res, project);\n\n const responseData = formatResponse<Project>({\n data: project,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectProjectResult = ResponseData<null>;\n\n/**\n * Unselect a project.\n */\nexport const unselectProject = (\n _req: Request,\n res: ResponseWithInformation<UnselectProjectResult>,\n _next: NextFunction\n) => {\n try {\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/project.controller.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as projectService from '@services/project.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getProjectFiltersAndPagination,\n type ProjectFilters,\n type ProjectFiltersParams,\n} from '@utils/filtersAndPagination/getProjectFiltersAndPagination';\nimport { mapProjectsToAPI, mapProjectToAPI } from '@utils/mapper/project';\nimport { getPLanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n type ResponseData,\n type PaginatedResponse,\n formatResponse,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { ObjectId } from 'mongoose';\nimport { User } from 'oauth2-server';\nimport type {\n Project,\n ProjectAPI,\n ProjectCreationData,\n ProjectData,\n} from '@/types/project.types';\n\nexport type GetProjectsParams = FiltersAndPagination<ProjectFiltersParams>;\nexport type GetProjectsResult = PaginatedResponse<ProjectAPI>;\n\n/**\n * Retrieves a list of projects based on filters and pagination.\n */\nexport const getProjects = async (\n req: Request<GetProjectsParams>,\n res: ResponseWithInformation<GetProjectsResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, organization, projectRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getProjectFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!projectRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_READ');\n return;\n }\n\n const restrictedFilter: ProjectFilters = {\n ...filters,\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n organizationId: String(organization._id),\n };\n\n try {\n const projects = await projectService.findProjects(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await projectService.countProjects(filters);\n\n const formattedProjects = mapProjectsToAPI(\n projects,\n user,\n res.locals.isProjectAdmin\n );\n\n const responseData = formatPaginatedResponse<ProjectAPI>({\n data: formattedProjects,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddProjectBody = ProjectCreationData;\nexport type AddProjectResult = ResponseData<ProjectAPI>;\n\n/**\n * Adds a new project to the database.\n */\nexport const addProject = async (\n req: Request<any, any, AddProjectBody>,\n res: ResponseWithInformation<AddProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, user, isOrganizationAdmin, projectRights } = res.locals;\n const projectData = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n }\n\n if (!projectRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!projectData) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_DATA_NOT_FOUND');\n }\n\n const { plan } = organization;\n\n if (!plan) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n const planType = getPLanDetails(plan);\n\n if (planType.numberOfProjects) {\n const projectCount = await projectService.countProjects({\n organizationId: organization._id,\n });\n\n if (projectCount >= planType.numberOfProjects) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'PLAN_PROJECT_LIMIT_REACHED',\n {\n organizationId: organization._id,\n }\n );\n return;\n }\n\n return;\n }\n\n const project: ProjectData = {\n membersIds: [user._id],\n adminsIds: [user._id],\n creatorId: user._id,\n organizationId: organization._id,\n ...projectData,\n };\n\n try {\n const newProject = await projectService.createProject(project);\n\n const formattedProject = mapProjectToAPI(newProject, user, true);\n\n const responseData = formatResponse<ProjectAPI>({\n message: t({\n en: 'Project created successfully',\n fr: 'Projet créé avec succès',\n es: 'Proyecto creado con éxito',\n }),\n description: t({\n en: 'Your project has been created successfully',\n fr: 'Votre projet a été créé avec succès',\n es: 'Su proyecto ha sido creado con éxito',\n }),\n data: formattedProject,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateProjectBody = Partial<ProjectData> & { _id: string };\nexport type UpdateProjectResult = ResponseData<ProjectAPI>;\n\n/**\n * Updates an existing project in the database.\n */\nexport const updateProject = async (\n req: Request<any, any, UpdateProjectBody>,\n res: ResponseWithInformation<UpdateProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, projectRights, project, user, isProjectAdmin } =\n res.locals;\n const projectData = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isProjectAdmin) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_ADMIN');\n return;\n }\n\n if (!projectRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (String(project._id) !== String(projectData._id)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_ID_MISMATCH');\n return;\n }\n\n if (String(project.organizationId) !== String(organization._id)) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_IN_ORGANIZATION');\n return;\n }\n\n try {\n const updatedProject = await projectService.updateProjectById(\n project._id,\n project\n );\n\n const formattedProject = mapProjectToAPI(\n updatedProject,\n user,\n isProjectAdmin\n );\n\n const responseData = formatResponse<ProjectAPI>({\n message: t({\n en: 'Project updated successfully',\n fr: 'Projet mis à jour avec succès',\n es: 'Proyecto actualizado con éxito',\n }),\n description: t({\n en: 'Your project has been updated successfully',\n fr: 'Votre projet a été mis à jour avec succès',\n es: 'Su proyecto ha sido actualizado con éxito',\n }),\n data: formattedProject,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\nexport type ProjectMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type UpdateProjectMembersBody = Partial<{\n membersIds: ProjectMemberByIdOption[];\n}>;\nexport type UpdateProjectMembersResult = ResponseData<ProjectAPI>;\n\n/**\n * Update members to the dictionary in the database.\n */\nexport const updateProjectMembers = async (\n req: Request<any, any, UpdateProjectMembersBody>,\n res: ResponseWithInformation<UpdateProjectMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, isProjectAdmin, organization, projectRights } =\n res.locals;\n const { membersIds } = req.body;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!isProjectAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_PROJECT'\n );\n return;\n }\n\n if (!projectRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_ADMIN');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_MUST_HAVE_MEMBER');\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_MUST_HAVE_ADMIN');\n return;\n }\n\n try {\n const existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds\n ?.filter(\n (member) =>\n // Remove members that are not in the organization\n !organization?.membersIds.includes(member.userId as ObjectId)\n )\n .map((member) => member.userId);\n\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => ({\n user,\n isAdmin:\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false,\n }));\n\n existingUsers.push(...userMap);\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization = await projectService.updateProjectById(\n project._id,\n {\n ...project,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n }\n );\n\n const formattedProject = mapProjectToAPI(\n updatedOrganization,\n user,\n isProjectAdmin\n );\n\n const responseData = formatResponse<ProjectAPI>({\n message: t({\n en: 'Project members updated successfully',\n fr: 'Membres du projet mis à jour avec succès',\n es: 'Miembros del proyecto actualizados con éxito',\n }),\n description: t({\n en: 'Your project members have been updated successfully',\n fr: 'Les membres de votre projet ont été mis à jour avec succès',\n es: 'Los miembros de su proyecto han sido actualizados con éxito',\n }),\n data: formattedProject,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteProjectResult = ResponseData<ProjectAPI>;\n\n/**\n * Deletes a project from the database by its ID.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response confirming the deletion.\n */\nexport const deleteProject = async (\n _req: Request,\n res: ResponseWithInformation<DeleteProjectResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, organization, project, projectRights, isProjectAdmin } =\n res.locals;\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!projectRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const projectToDelete = await projectService.getProjectById(project._id);\n\n if (projectToDelete.organizationId !== organization._id) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'PROJECT_NOT_IN_ORGANIZATION'\n );\n return;\n }\n\n const deletedProject = await projectService.deleteProjectById(project._id);\n\n if (!deletedProject) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED', {\n projectId: project._id,\n });\n\n return;\n }\n\n logger.info(`Project deleted: ${String(deletedProject._id)}`);\n\n const formattedProject = mapProjectToAPI(\n deletedProject,\n user,\n isProjectAdmin\n );\n\n const responseData = formatResponse<ProjectAPI>({\n message: t({\n en: 'Project deleted successfully',\n fr: 'Projet supprimé avec succès',\n es: 'Proyecto eliminado con éxito',\n }),\n description: t({\n en: 'Your project has been deleted successfully',\n fr: 'Votre projet a été supprimé avec succès',\n es: 'Su proyecto ha sido eliminado con éxito',\n }),\n data: formattedProject,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectProjectParam = { projectId: ObjectId | string };\nexport type SelectProjectResult = ResponseData<Project>;\n\n/**\n * Select a project.\n */\nexport const selectProject = async (\n req: Request<SelectProjectParam>,\n res: ResponseWithInformation<SelectProjectResult>,\n _next: NextFunction\n) => {\n const { projectId } = req.params;\n\n if (!projectId) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_ID_NOT_FOUND');\n return;\n }\n\n try {\n const project = await projectService.getProjectById(projectId);\n\n sessionAuthService.setProjectAuth(res, project);\n\n const responseData = formatResponse<Project>({\n message: t({\n en: 'Project selected successfully',\n fr: 'Projet sélectionné avec succès',\n es: 'Proyecto seleccionado con éxito',\n }),\n description: t({\n en: 'Your project has been selected successfully',\n fr: 'Votre projet a été sélectionné avec succès',\n es: 'Su proyecto ha sido seleccionado con éxito',\n }),\n data: project,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectProjectResult = ResponseData<null>;\n\n/**\n * Unselect a project.\n */\nexport const unselectProject = (\n _req: Request,\n res: ResponseWithInformation<UnselectProjectResult>,\n _next: NextFunction\n) => {\n try {\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Project unselected successfully',\n fr: 'Projet désélectionné avec succès',\n es: 'Proyecto deseleccionado con éxito',\n }),\n description: t({\n en: 'Your project has been unselected successfully',\n fr: 'Votre projet a été désélectionné avec succès',\n es: 'Su proyecto ha sido deseleccionado con éxito',\n }),\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":["user"]}
|