@intlayer/backend 4.1.4 → 4.1.5
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/project.controller.cjs +51 -12
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs +0 -2
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
- package/dist/cjs/routes/project.routes.cjs +9 -0
- package/dist/cjs/routes/project.routes.cjs.map +1 -1
- package/dist/cjs/schemas/oAuth2.schema.cjs +6 -1
- package/dist/cjs/schemas/oAuth2.schema.cjs.map +1 -1
- package/dist/cjs/schemas/organization.schema.cjs +1 -2
- package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
- package/dist/cjs/schemas/project.schema.cjs +25 -4
- package/dist/cjs/schemas/project.schema.cjs.map +1 -1
- package/dist/cjs/services/sessionAuth.service.cjs +2 -1
- package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
- package/dist/cjs/types/organization.types.cjs.map +1 -1
- package/dist/cjs/types/project.types.cjs.map +1 -1
- package/dist/cjs/utils/AI/embeddings.json +1228 -615
- package/dist/cjs/utils/plan.cjs +1 -1
- package/dist/cjs/utils/plan.cjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +50 -12
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/middlewares/sessionAuth.middleware.mjs +0 -2
- package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs +11 -1
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/schemas/oAuth2.schema.mjs +6 -1
- package/dist/esm/schemas/oAuth2.schema.mjs.map +1 -1
- package/dist/esm/schemas/organization.schema.mjs +1 -2
- package/dist/esm/schemas/organization.schema.mjs.map +1 -1
- package/dist/esm/schemas/project.schema.mjs +25 -4
- package/dist/esm/schemas/project.schema.mjs.map +1 -1
- package/dist/esm/services/sessionAuth.service.mjs +2 -1
- package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
- package/dist/esm/utils/AI/embeddings.json +1228 -615
- package/dist/esm/utils/plan.mjs +1 -1
- package/dist/esm/utils/plan.mjs.map +1 -1
- package/dist/types/controllers/project.controller.d.ts +10 -1
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
- package/dist/types/models/organization.model.d.ts +1 -1
- package/dist/types/routes/project.routes.d.ts +5 -0
- package/dist/types/routes/project.routes.d.ts.map +1 -1
- package/dist/types/schemas/oAuth2.schema.d.ts.map +1 -1
- package/dist/types/schemas/organization.schema.d.ts +1 -1
- package/dist/types/schemas/organization.schema.d.ts.map +1 -1
- package/dist/types/schemas/project.schema.d.ts.map +1 -1
- package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
- package/dist/types/types/organization.types.d.ts +1 -1
- package/dist/types/types/organization.types.d.ts.map +1 -1
- package/dist/types/types/project.types.d.ts +9 -3
- package/dist/types/types/project.types.d.ts.map +1 -1
- package/dist/types/utils/plan.d.ts +1 -1
- package/dist/types/utils/plan.d.ts.map +1 -1
- package/package.json +7 -6
|
@@ -31,6 +31,7 @@ __export(project_controller_exports, {
|
|
|
31
31
|
addProject: () => addProject,
|
|
32
32
|
deleteProject: () => deleteProject,
|
|
33
33
|
getProjects: () => getProjects,
|
|
34
|
+
pushProjectConfiguration: () => pushProjectConfiguration,
|
|
34
35
|
selectProject: () => selectProject,
|
|
35
36
|
unselectProject: () => unselectProject,
|
|
36
37
|
updateProject: () => updateProject,
|
|
@@ -94,7 +95,7 @@ const getProjects = async (req, res, _next) => {
|
|
|
94
95
|
}
|
|
95
96
|
};
|
|
96
97
|
const addProject = async (req, res, _next) => {
|
|
97
|
-
const { organization, user, isOrganizationAdmin
|
|
98
|
+
const { organization, user, isOrganizationAdmin } = res.locals;
|
|
98
99
|
const projectData = req.body;
|
|
99
100
|
if (!user) {
|
|
100
101
|
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
@@ -110,20 +111,10 @@ const addProject = async (req, res, _next) => {
|
|
|
110
111
|
"USER_IS_NOT_ADMIN_OF_ORGANIZATION"
|
|
111
112
|
);
|
|
112
113
|
}
|
|
113
|
-
if (!projectRights?.admin) {
|
|
114
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_RIGHTS_NOT_WRITE");
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
114
|
if (!projectData) {
|
|
118
115
|
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_DATA_NOT_FOUND");
|
|
119
116
|
}
|
|
120
117
|
const { plan } = organization;
|
|
121
|
-
if (!plan) {
|
|
122
|
-
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PLAN_NOT_FOUND", {
|
|
123
|
-
organizationId: organization._id
|
|
124
|
-
});
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
118
|
const planType = (0, import_plan.getPLanDetails)(plan);
|
|
128
119
|
if (planType.numberOfProjects) {
|
|
129
120
|
const projectCount = await projectService.countProjects({
|
|
@@ -139,7 +130,6 @@ const addProject = async (req, res, _next) => {
|
|
|
139
130
|
);
|
|
140
131
|
return;
|
|
141
132
|
}
|
|
142
|
-
return;
|
|
143
133
|
}
|
|
144
134
|
const project = {
|
|
145
135
|
membersIds: [user._id],
|
|
@@ -319,6 +309,54 @@ const updateProjectMembers = async (req, res, _next) => {
|
|
|
319
309
|
return;
|
|
320
310
|
}
|
|
321
311
|
};
|
|
312
|
+
const pushProjectConfiguration = async (req, res, _next) => {
|
|
313
|
+
const { user, project, isProjectAdmin } = res.locals;
|
|
314
|
+
const projectConfiguration = req.body;
|
|
315
|
+
if (!user) {
|
|
316
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (!project) {
|
|
320
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (!isProjectAdmin) {
|
|
324
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(
|
|
325
|
+
res,
|
|
326
|
+
"USER_IS_NOT_ADMIN_OF_PROJECT"
|
|
327
|
+
);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
const projectObject = await projectService.getProjectById(project._id);
|
|
332
|
+
projectObject.configuration = projectConfiguration;
|
|
333
|
+
projectObject.save();
|
|
334
|
+
if (!projectObject.configuration) {
|
|
335
|
+
import_errors.ErrorHandler.handleGenericErrorResponse(res, "PROJECT_UPDATE_FAILED", {
|
|
336
|
+
projectId: project._id
|
|
337
|
+
});
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const responseData = (0, import_responseData.formatResponse)({
|
|
341
|
+
message: (0, import_express_intlayer.t)({
|
|
342
|
+
en: "Project configuration updated successfully",
|
|
343
|
+
fr: "Configuration du projet mise \xE0 jour avec succ\xE8s",
|
|
344
|
+
es: "Configuraci\xF3n del proyecto actualizada con \xE9xito"
|
|
345
|
+
}),
|
|
346
|
+
description: (0, import_express_intlayer.t)({
|
|
347
|
+
en: "Your project configuration has been updated successfully",
|
|
348
|
+
fr: "La configuration du projet a \xE9t\xE9 mise \xE0 jour avec succ\xE8s",
|
|
349
|
+
es: "Su configuraci\xF3n del proyecto ha sido actualizada con \xE9xito"
|
|
350
|
+
}),
|
|
351
|
+
data: projectObject.configuration
|
|
352
|
+
});
|
|
353
|
+
res.json(responseData);
|
|
354
|
+
return;
|
|
355
|
+
} catch (error) {
|
|
356
|
+
import_errors.ErrorHandler.handleAppErrorResponse(res, error);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
322
360
|
const deleteProject = async (_req, res, _next) => {
|
|
323
361
|
const { user, organization, project, projectRights, isProjectAdmin } = res.locals;
|
|
324
362
|
if (!user) {
|
|
@@ -436,6 +474,7 @@ const unselectProject = (_req, res, _next) => {
|
|
|
436
474
|
addProject,
|
|
437
475
|
deleteProject,
|
|
438
476
|
getProjects,
|
|
477
|
+
pushProjectConfiguration,
|
|
439
478
|
selectProject,
|
|
440
479
|
unselectProject,
|
|
441
480
|
updateProject,
|
|
@@ -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 { 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<Project>;\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.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 projectData\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 (String(projectToDelete.organizationId) !== String(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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,oBAAuB;AAEvB,qBAAgC;AAChC,yBAAoC;AACpC,kBAA6B;AAC7B,oBAAuC;AAEvC,4CAIO;AACP,qBAAkD;AAClD,kBAA+B;AAC/B,0BAKO;AAEP,8BAAkB;AAgBX,MAAM,cAAc,OACzB,KACA,KACA,UACkB;AAClB,QAAM,EAAE,MAAM,cAAc,cAAc,IAAI,IAAI;AAClD,QAAM,EAAE,SAAS,UAAU,MAAM,MAAM,iBAAiB,QACtD,sEAA+B,GAAG;AAEpC,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAC/D;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,MAAM;AACxB,+BAAa,2BAA2B,KAAK,yBAAyB;AACtE;AAAA,EACF;AAEA,QAAM,mBAAmC;AAAA,IACvC,GAAG;AAAA,IACH,YAAY,EAAE,KAAK,CAAC,GAAI,QAAQ,cAAc,CAAC,GAAI,OAAO,KAAK,GAAG,CAAC,EAAE;AAAA,IACrE,gBAAgB,OAAO,aAAa,GAAG;AAAA,EACzC;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,eAAe;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,aAAa,MAAM,eAAe,cAAc,OAAO;AAE7D,UAAM,wBAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA,IAAI,OAAO;AAAA,IACb;AAEA,UAAM,mBAAe,6CAAoC;AAAA,MACvD,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,YAAY,iBAAiB,UAAU;AAAA,MACvC;AAAA,IACF,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAQO,MAAM,aAAa,OACxB,KACA,KACA,UACkB;AAClB,QAAM,EAAE,cAAc,MAAM,qBAAqB,cAAc,IAAI,IAAI;AACvE,QAAM,cAAc,IAAI;AAExB,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAC/D;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,qBAAqB;AACxB,+BAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,OAAO;AACzB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,aAAa;AAChB,+BAAa,2BAA2B,KAAK,wBAAwB;AAAA,EACvE;AAEA,QAAM,EAAE,KAAK,IAAI;AAEjB,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAAA,MAC7D,gBAAgB,aAAa;AAAA,IAC/B,CAAC;AACD;AAAA,EACF;AAEA,QAAM,eAAW,4BAAe,IAAI;AAEpC,MAAI,SAAS,kBAAkB;AAC7B,UAAM,eAAe,MAAM,eAAe,cAAc;AAAA,MACtD,gBAAgB,aAAa;AAAA,IAC/B,CAAC;AAED,QAAI,gBAAgB,SAAS,kBAAkB;AAC7C,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,UACE,gBAAgB,aAAa;AAAA,QAC/B;AAAA,MACF;AACA;AAAA,IACF;AAEA;AAAA,EACF;AAEA,QAAM,UAAuB;AAAA,IAC3B,YAAY,CAAC,KAAK,GAAG;AAAA,IACrB,WAAW,CAAC,KAAK,GAAG;AAAA,IACpB,WAAW,KAAK;AAAA,IAChB,gBAAgB,aAAa;AAAA,IAC7B,GAAG;AAAA,EACL;AAEA,MAAI;AACF,UAAM,aAAa,MAAM,eAAe,cAAc,OAAO;AAE7D,UAAM,uBAAmB,gCAAgB,YAAY,MAAM,IAAI;AAE/D,UAAM,mBAAe,oCAA2B;AAAA,MAC9C,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAQO,MAAM,gBAAgB,OAC3B,KACA,KACA,UACkB;AAClB,QAAM,EAAE,cAAc,eAAe,SAAS,MAAM,eAAe,IACjE,IAAI;AACN,QAAM,cAAc,IAAI;AAExB,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAC/D;AAAA,EACF;AAEA,MAAI,CAAC,SAAS;AACZ,+BAAa,2BAA2B,KAAK,wBAAwB;AACrE;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AACnB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,OAAO;AACzB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,cAAc,MAAM,OAAO,aAAa,GAAG,GAAG;AAC/D,+BAAa,2BAA2B,KAAK,6BAA6B;AAC1E;AAAA,EACF;AAEA,MAAI;AACF,UAAM,iBAAiB,MAAM,eAAe;AAAA,MAC1C,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,UAAM,uBAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,mBAAe,oCAA2B;AAAA,MAC9C,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAgBO,MAAM,uBAAuB,OAClC,KACA,KACA,UACkB;AAClB,QAAM,EAAE,MAAM,SAAS,gBAAgB,cAAc,cAAc,IACjE,IAAI;AACN,QAAM,EAAE,WAAW,IAAI,IAAI;AAE3B,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAC/D;AAAA,EACF;AAEA,MAAI,CAAC,SAAS;AACZ,+BAAa,2BAA2B,KAAK,qBAAqB;AAClE;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AACnB,+BAAa;AAAA,MACX;AAAA,MACA;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,OAAO;AACzB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,GAAG;AAC5B,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,YAAY,IAAI,CAAC,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG;AACrD,+BAAa,2BAA2B,KAAK,yBAAyB;AACtE;AAAA,EACF;AAEA,MAAI;AACF,UAAM,gBAAgC,CAAC;AAEvC,QAAI,YAAY;AACd,YAAM,aAAa,YACf;AAAA,QACA,CAAC;AAAA;AAAA,UAEC,CAAC,cAAc,WAAW,SAAS,OAAO,MAAkB;AAAA;AAAA,MAChE,EACC,IAAI,CAAC,WAAW,OAAO,MAAM;AAEhC,YAAM,QAAQ,MAAM,YAAY,cAAc,UAAU;AAExD,UAAI,OAAO;AACT,cAAM,UAA0B,MAAM,IAAI,CAACA,WAAU;AAAA,UACnD,MAAAA;AAAA,UACA,SACE,WAAW;AAAA,YACT,CAAC,WAAW,OAAO,OAAO,MAAM,MAAM,OAAOA,MAAK,GAAG;AAAA,UACvD,GAAG,WAAW;AAAA,QAClB,EAAE;AAEF,sBAAc,KAAK,GAAG,OAAO;AAAA,MAC/B;AAAA,IACF;AAEA,UAAM,mBAA+B,cAAc;AAAA,MACjD,CAACA,UAASA,MAAK,KAAK;AAAA,IACtB;AACA,UAAM,iBAA6B,cAChC,OAAO,CAAC,OAAO,GAAG,OAAO,EACzB,IAAI,CAACA,UAASA,MAAK,KAAK,GAAG;AAE9B,UAAM,sBAAsB,MAAM,eAAe;AAAA,MAC/C,QAAQ;AAAA,MACR;AAAA,QACE,GAAG;AAAA,QACH,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,IACF;AAEA,UAAM,uBAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,mBAAe,oCAA2B;AAAA,MAC9C,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAUO,MAAM,gBAAgB,OAC3B,MACA,KACA,UACkB;AAClB,QAAM,EAAE,MAAM,cAAc,SAAS,eAAe,eAAe,IACjE,IAAI;AAEN,MAAI,CAAC,MAAM;AACT,+BAAa,2BAA2B,KAAK,kBAAkB;AAC/D;AAAA,EACF;AAEA,MAAI,CAAC,cAAc;AACjB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI,CAAC,SAAS;AACZ,+BAAa,2BAA2B,KAAK,qBAAqB;AAClE;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,OAAO;AACzB,+BAAa,2BAA2B,KAAK,0BAA0B;AACvE;AAAA,EACF;AAEA,MAAI;AACF,UAAM,kBAAkB,MAAM,eAAe,eAAe,QAAQ,GAAG;AAEvE,QAAI,OAAO,gBAAgB,cAAc,MAAM,OAAO,aAAa,GAAG,GAAG;AACvE,iCAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,iBAAiB,MAAM,eAAe,kBAAkB,QAAQ,GAAG;AAEzE,QAAI,CAAC,gBAAgB;AACnB,iCAAa,2BAA2B,KAAK,uBAAuB;AAAA,QAClE,WAAW,QAAQ;AAAA,MACrB,CAAC;AAED;AAAA,IACF;AAEA,yBAAO,KAAK,oBAAoB,OAAO,eAAe,GAAG,CAAC,EAAE;AAE5D,UAAM,uBAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,mBAAe,oCAA2B;AAAA,MAC9C,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAQO,MAAM,gBAAgB,OAC3B,KACA,KACA,UACG;AACH,QAAM,EAAE,UAAU,IAAI,IAAI;AAE1B,MAAI,CAAC,WAAW;AACd,+BAAa,2BAA2B,KAAK,sBAAsB;AACnE;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,eAAe,eAAe,SAAS;AAE7D,uBAAmB,eAAe,KAAK,OAAO;AAE9C,UAAM,mBAAe,oCAAwB;AAAA,MAC3C,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;AAOO,MAAM,kBAAkB,CAC7B,MACA,KACA,UACG;AACH,MAAI;AACF,uBAAmB,iBAAiB,GAAG;AAEvC,UAAM,mBAAe,oCAAqB;AAAA,MACxC,aAAS,2BAAE;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,iBAAa,2BAAE;AAAA,QACb,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN,CAAC;AAAA,MACD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,KAAK,YAAY;AACrB;AAAA,EACF,SAAS,OAAO;AACd,+BAAa,uBAAuB,KAAK,KAAiB;AAC1D;AAAA,EACF;AACF;","names":["user"]}
|
|
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 ProjectConfiguration,\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 } = 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 (!projectData) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_DATA_NOT_FOUND');\n }\n\n const { plan } = organization;\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\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<Project>;\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.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 projectData\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 PushProjectConfigurationBody = ProjectConfiguration;\nexport type PushProjectConfigurationResult = ResponseData<ProjectConfiguration>;\n\n/**\n * Pushes a project configuration to the database.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response confirming the deletion.\n */\nexport const pushProjectConfiguration = async (\n req: Request<any, any, PushProjectConfigurationBody>,\n res: ResponseWithInformation<PushProjectConfigurationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, isProjectAdmin } = res.locals;\n const projectConfiguration = 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 try {\n const projectObject = await projectService.getProjectById(project._id);\n projectObject.configuration = projectConfiguration;\n\n projectObject.save();\n\n if (!projectObject.configuration) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_UPDATE_FAILED', {\n projectId: project._id,\n });\n return;\n }\n\n const responseData = formatResponse<ProjectConfiguration>({\n message: t({\n en: 'Project configuration updated successfully',\n fr: 'Configuration du projet mise à jour avec succès',\n es: 'Configuración del proyecto actualizada con éxito',\n }),\n description: t({\n en: 'Your project configuration has been updated successfully',\n fr: 'La configuration du projet a été mise à jour avec succès',\n es: 'Su configuración del proyecto ha sido actualizada con éxito',\n }),\n data: projectObject.configuration,\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 (String(projectToDelete.organizationId) !== String(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"]}
|
|
@@ -62,7 +62,6 @@ const checkOrganization = async (req, res, next) => {
|
|
|
62
62
|
res.locals.organization = null;
|
|
63
63
|
try {
|
|
64
64
|
if (!jwtTokenOrganization || jwtTokenOrganization === "undefined") {
|
|
65
|
-
(0, import_sessionAuth.clearOrganizationAuth)(res);
|
|
66
65
|
return next();
|
|
67
66
|
}
|
|
68
67
|
const organizationData = import_jsonwebtoken.default.verify(
|
|
@@ -89,7 +88,6 @@ const checkProject = async (req, res, next) => {
|
|
|
89
88
|
res.locals.project = null;
|
|
90
89
|
try {
|
|
91
90
|
if (!jwtTokenProject || jwtTokenProject === "undefined") {
|
|
92
|
-
(0, import_sessionAuth.clearProjectAuth)(res);
|
|
93
91
|
return next();
|
|
94
92
|
}
|
|
95
93
|
const decodedTokenProject = import_jsonwebtoken.default.verify(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { OrganizationModel } from '@models/organization.model';\nimport { ProjectModel } from '@models/project.model';\nimport {\n clearOrganizationAuth,\n clearProjectAuth,\n} from '@services/sessionAuth.service';\nimport { getUserBySession as getUserBySessionService } from '@services/user.service';\nimport { Cookies } from '@utils/cookies';\nimport type { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type {\n Organization,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Project, ProjectDocument, Rights } from '@/types/project.types';\nimport type { User } from '@/types/user.types';\n\nexport type ResponseWithInformation<ResBody = any> = Response<\n ResBody,\n {\n user: User | null;\n // Auth Context\n organization: Organization | null;\n project: Project | null;\n authType: 'session' | 'oauth2' | null;\n // Auth Rights - oAuth2 Auth\n organizationRights: Rights | null;\n projectRights: Rights | null;\n dictionaryRights: Rights | null;\n // Auth Rights - Session Auth\n isOrganizationAdmin: boolean | null;\n isProjectAdmin: boolean | null;\n }\n>;\n\nexport const checkUser = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { [Cookies.JWT_AUTH]: sessionToken } = req.cookies;\n\n res.locals.user = null;\n res.locals.authType = null;\n\n try {\n if (sessionToken) {\n const user = await getUserBySessionService(sessionToken);\n\n if (user) {\n res.locals.user = user.toObject();\n res.locals.authType = 'session';\n }\n }\n } catch (error) {\n console.error('Error fetching session:', error);\n }\n\n return next();\n};\n\nexport const checkOrganization = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenOrganization = req.cookies[Cookies.JWT_ORGANIZATION];\n\n res.locals.organization = null;\n\n try {\n if (!jwtTokenOrganization || jwtTokenOrganization === 'undefined') {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { OrganizationModel } from '@models/organization.model';\nimport { ProjectModel } from '@models/project.model';\nimport {\n clearOrganizationAuth,\n clearProjectAuth,\n} from '@services/sessionAuth.service';\nimport { getUserBySession as getUserBySessionService } from '@services/user.service';\nimport { Cookies } from '@utils/cookies';\nimport type { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type {\n Organization,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Project, ProjectDocument, Rights } from '@/types/project.types';\nimport type { User } from '@/types/user.types';\n\nexport type ResponseWithInformation<ResBody = any> = Response<\n ResBody,\n {\n user: User | null;\n // Auth Context\n organization: Organization | null;\n project: Project | null;\n authType: 'session' | 'oauth2' | null;\n // Auth Rights - oAuth2 Auth\n organizationRights: Rights | null;\n projectRights: Rights | null;\n dictionaryRights: Rights | null;\n // Auth Rights - Session Auth\n isOrganizationAdmin: boolean | null;\n isProjectAdmin: boolean | null;\n }\n>;\n\nexport const checkUser = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { [Cookies.JWT_AUTH]: sessionToken } = req.cookies;\n\n res.locals.user = null;\n res.locals.authType = null;\n\n try {\n if (sessionToken) {\n const user = await getUserBySessionService(sessionToken);\n\n if (user) {\n res.locals.user = user.toObject();\n res.locals.authType = 'session';\n }\n }\n } catch (error) {\n console.error('Error fetching session:', error);\n }\n\n return next();\n};\n\nexport const checkOrganization = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenOrganization = req.cookies[Cookies.JWT_ORGANIZATION];\n\n res.locals.organization = null;\n\n try {\n if (!jwtTokenOrganization || jwtTokenOrganization === 'undefined') {\n return next();\n }\n\n const organizationData = jwt.verify(\n jwtTokenOrganization,\n process.env.JWT_TOKEN_SECRET!\n ) as Organization;\n\n if (!organizationData) {\n clearOrganizationAuth(res);\n return next();\n }\n\n const organization: OrganizationDocument | null =\n await OrganizationModel.findById(organizationData._id);\n\n if (!organization) {\n clearOrganizationAuth(res);\n return next();\n }\n\n res.locals.organization = organization.toObject();\n } catch (error) {\n console.error('Error fetching organization:', error);\n }\n\n return next();\n};\n\nexport const checkProject = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenProject = req.cookies[Cookies.JWT_PROJECT];\n res.locals.project = null;\n\n try {\n if (!jwtTokenProject || jwtTokenProject === 'undefined') {\n return next();\n }\n\n const decodedTokenProject = jwt.verify(\n jwtTokenProject,\n process.env.JWT_TOKEN_SECRET!\n ) as Project;\n\n if (!decodedTokenProject) {\n clearProjectAuth(res);\n return next();\n }\n\n const project: ProjectDocument | null = await ProjectModel.findById(\n decodedTokenProject._id\n );\n\n if (\n !project ||\n !res.locals.organization ||\n String(project.organizationId) !== String(res.locals.organization._id)\n ) {\n clearProjectAuth(res);\n return next();\n }\n\n res.locals.project = project.toObject();\n } catch (error) {\n console.error('Error fetching project:', error);\n }\n\n return next();\n};\n\n/**\n * Middleware to check if the user is an admin of the organization or project\n * Sets the following properties in res.locals:\n * - isOrganizationAdmin: boolean\n * - isProjectAdmin: boolean\n */\nexport const checkAdmin = async (\n _req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { organization, project, user, authType } = res.locals;\n\n if (authType !== 'session') {\n return next();\n }\n\n res.locals.organizationRights = {\n read: true,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: true,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: true,\n write: false,\n admin: false,\n };\n\n if (user) {\n if (organization) {\n const isOrganizationAdmin: boolean =\n organization.adminsIds\n .map((id) => String(id))\n .includes(String(user._id)) ?? false;\n\n res.locals.isOrganizationAdmin = isOrganizationAdmin;\n\n res.locals.organizationRights = {\n read: true,\n write: isOrganizationAdmin,\n admin: isOrganizationAdmin,\n };\n }\n\n if (project) {\n const isProjectAdmin: boolean =\n project.adminsIds.map((id) => String(id)).includes(String(user._id)) ??\n false;\n\n res.locals.isProjectAdmin = isProjectAdmin;\n\n res.locals.projectRights = {\n read: true,\n write: isProjectAdmin,\n admin: isProjectAdmin,\n };\n\n res.locals.dictionaryRights = {\n read: true,\n write: true,\n admin: true,\n };\n }\n }\n\n return next();\n};\n"],"mappings":"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","names":["getUserBySessionService","jwt"]}
|
|
@@ -48,6 +48,11 @@ const projectRoutes = {
|
|
|
48
48
|
url: `${process.env.CLIENT_URL}/api/members`,
|
|
49
49
|
method: "PUT"
|
|
50
50
|
},
|
|
51
|
+
pushProjectConfiguration: {
|
|
52
|
+
urlModel: "/configuration",
|
|
53
|
+
url: `${process.env.CLIENT_URL}/api/configuration`,
|
|
54
|
+
method: "PUT"
|
|
55
|
+
},
|
|
51
56
|
deleteProject: {
|
|
52
57
|
urlModel: "/",
|
|
53
58
|
url: baseURL,
|
|
@@ -86,6 +91,10 @@ projectRouter.put(
|
|
|
86
91
|
projectRoutes.updateProjectMembers.urlModel,
|
|
87
92
|
import_project.updateProjectMembers
|
|
88
93
|
);
|
|
94
|
+
projectRouter.put(
|
|
95
|
+
projectRoutes.pushProjectConfiguration.urlModel,
|
|
96
|
+
import_project.pushProjectConfiguration
|
|
97
|
+
);
|
|
89
98
|
projectRouter.delete(projectRoutes.deleteProject.urlModel, import_project.deleteProject);
|
|
90
99
|
projectRouter.post(projectRoutes.addNewAccessKey.urlModel, import_projectAccessKey.addNewAccessKey);
|
|
91
100
|
projectRouter.patch(projectRoutes.refreshAccessKey.urlModel, import_projectAccessKey.refreshAccessKey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/routes/project.routes.ts"],"sourcesContent":["import {\n addProject,\n deleteProject,\n getProjects,\n updateProject,\n selectProject,\n unselectProject,\n updateProjectMembers,\n} from '@controllers/project.controller';\nimport {\n addNewAccessKey,\n deleteAccessKey,\n refreshAccessKey,\n} from '@controllers/projectAccessKey.controller';\nimport { Router } from 'express';\nimport { Routes } from '@/types/Routes';\n\nexport const projectRouter: Router = Router();\n\nconst baseURL = `${process.env.BACKEND_URL}/api/project`;\n\nexport const projectRoutes = {\n getProjects: {\n urlModel: '/',\n url: baseURL,\n method: 'GET',\n },\n addProject: {\n urlModel: '/',\n url: baseURL,\n method: 'POST',\n },\n updateProject: {\n urlModel: '/',\n url: baseURL,\n method: 'PUT',\n },\n updateProjectMembers: {\n urlModel: '/members',\n url: `${process.env.CLIENT_URL}/api/members`,\n method: 'PUT',\n },\n deleteProject: {\n urlModel: '/',\n url: baseURL,\n method: 'DELETE',\n },\n selectProject: {\n urlModel: '/:projectId',\n url: ({ projectId }: { projectId: string }) => `${baseURL}/${projectId}`,\n method: 'PUT',\n },\n unselectProject: {\n urlModel: '/logout',\n url: `${baseURL}/logout`,\n method: 'POST',\n },\n addNewAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'POST',\n },\n refreshAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'PATCH',\n },\n deleteAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'DELETE',\n },\n} satisfies Routes;\n\nprojectRouter.get(projectRoutes.getProjects.urlModel, getProjects);\n\nprojectRouter.post(projectRoutes.addProject.urlModel, addProject);\nprojectRouter.put(projectRoutes.updateProject.urlModel, updateProject);\nprojectRouter.put(\n projectRoutes.updateProjectMembers.urlModel,\n updateProjectMembers\n);\nprojectRouter.delete(projectRoutes.deleteProject.urlModel, deleteProject);\n\nprojectRouter.post(projectRoutes.addNewAccessKey.urlModel, addNewAccessKey);\n\nprojectRouter.patch(projectRoutes.refreshAccessKey.urlModel, refreshAccessKey);\n\nprojectRouter.delete(projectRoutes.deleteAccessKey.urlModel, deleteAccessKey);\n\nprojectRouter.post(projectRoutes.unselectProject.urlModel, unselectProject);\n\nprojectRouter.put(projectRoutes.selectProject.urlModel, selectProject);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../../src/routes/project.routes.ts"],"sourcesContent":["import {\n addProject,\n deleteProject,\n getProjects,\n updateProject,\n selectProject,\n unselectProject,\n updateProjectMembers,\n pushProjectConfiguration,\n} from '@controllers/project.controller';\nimport {\n addNewAccessKey,\n deleteAccessKey,\n refreshAccessKey,\n} from '@controllers/projectAccessKey.controller';\nimport { Router } from 'express';\nimport { Routes } from '@/types/Routes';\n\nexport const projectRouter: Router = Router();\n\nconst baseURL = `${process.env.BACKEND_URL}/api/project`;\n\nexport const projectRoutes = {\n getProjects: {\n urlModel: '/',\n url: baseURL,\n method: 'GET',\n },\n addProject: {\n urlModel: '/',\n url: baseURL,\n method: 'POST',\n },\n updateProject: {\n urlModel: '/',\n url: baseURL,\n method: 'PUT',\n },\n updateProjectMembers: {\n urlModel: '/members',\n url: `${process.env.CLIENT_URL}/api/members`,\n method: 'PUT',\n },\n pushProjectConfiguration: {\n urlModel: '/configuration',\n url: `${process.env.CLIENT_URL}/api/configuration`,\n method: 'PUT',\n },\n deleteProject: {\n urlModel: '/',\n url: baseURL,\n method: 'DELETE',\n },\n selectProject: {\n urlModel: '/:projectId',\n url: ({ projectId }: { projectId: string }) => `${baseURL}/${projectId}`,\n method: 'PUT',\n },\n unselectProject: {\n urlModel: '/logout',\n url: `${baseURL}/logout`,\n method: 'POST',\n },\n addNewAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'POST',\n },\n refreshAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'PATCH',\n },\n deleteAccessKey: {\n urlModel: '/access_key',\n url: `${baseURL}/access_key`,\n method: 'DELETE',\n },\n} satisfies Routes;\n\nprojectRouter.get(projectRoutes.getProjects.urlModel, getProjects);\n\nprojectRouter.post(projectRoutes.addProject.urlModel, addProject);\nprojectRouter.put(projectRoutes.updateProject.urlModel, updateProject);\nprojectRouter.put(\n projectRoutes.updateProjectMembers.urlModel,\n updateProjectMembers\n);\nprojectRouter.put(\n projectRoutes.pushProjectConfiguration.urlModel,\n pushProjectConfiguration\n);\nprojectRouter.delete(projectRoutes.deleteProject.urlModel, deleteProject);\n\nprojectRouter.post(projectRoutes.addNewAccessKey.urlModel, addNewAccessKey);\n\nprojectRouter.patch(projectRoutes.refreshAccessKey.urlModel, refreshAccessKey);\n\nprojectRouter.delete(projectRoutes.deleteAccessKey.urlModel, deleteAccessKey);\n\nprojectRouter.post(projectRoutes.unselectProject.urlModel, unselectProject);\n\nprojectRouter.put(projectRoutes.selectProject.urlModel, selectProject);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBASO;AACP,8BAIO;AACP,qBAAuB;AAGhB,MAAM,oBAAwB,uBAAO;AAE5C,MAAM,UAAU,GAAG,QAAQ,IAAI,WAAW;AAEnC,MAAM,gBAAgB;AAAA,EAC3B,aAAa;AAAA,IACX,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,sBAAsB;AAAA,IACpB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,IAAI,UAAU;AAAA,IAC9B,QAAQ;AAAA,EACV;AAAA,EACA,0BAA0B;AAAA,IACxB,UAAU;AAAA,IACV,KAAK,GAAG,QAAQ,IAAI,UAAU;AAAA,IAC9B,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,KAAK,CAAC,EAAE,UAAU,MAA6B,GAAG,OAAO,IAAI,SAAS;AAAA,IACtE,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,OAAO;AAAA,IACf,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,OAAO;AAAA,IACf,QAAQ;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,IAChB,UAAU;AAAA,IACV,KAAK,GAAG,OAAO;AAAA,IACf,QAAQ;AAAA,EACV;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,KAAK,GAAG,OAAO;AAAA,IACf,QAAQ;AAAA,EACV;AACF;AAEA,cAAc,IAAI,cAAc,YAAY,UAAU,0BAAW;AAEjE,cAAc,KAAK,cAAc,WAAW,UAAU,yBAAU;AAChE,cAAc,IAAI,cAAc,cAAc,UAAU,4BAAa;AACrE,cAAc;AAAA,EACZ,cAAc,qBAAqB;AAAA,EACnC;AACF;AACA,cAAc;AAAA,EACZ,cAAc,yBAAyB;AAAA,EACvC;AACF;AACA,cAAc,OAAO,cAAc,cAAc,UAAU,4BAAa;AAExE,cAAc,KAAK,cAAc,gBAAgB,UAAU,uCAAe;AAE1E,cAAc,MAAM,cAAc,iBAAiB,UAAU,wCAAgB;AAE7E,cAAc,OAAO,cAAc,gBAAgB,UAAU,uCAAe;AAE5E,cAAc,KAAK,cAAc,gBAAgB,UAAU,8BAAe;AAE1E,cAAc,IAAI,cAAc,cAAc,UAAU,4BAAa;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/schemas/oAuth2.schema.ts"],"sourcesContent":["import { Schema } from 'mongoose';\nimport { Token as TokenType, Client, User } from 'oauth2-server';\n\nexport type Token = Omit<TokenType, 'client' | 'user'> & {\n clientId: Client['id'];\n userId: User['_id'];\n};\n\nexport const accessTokenSchema = new Schema<Token>(\n {\n accessToken: {\n type: String,\n required: true,\n },\n accessTokenExpiresAt: {\n type: Date,\n },\n clientId: {\n type: String,\n ref: 'Project',\n required: true,\n },\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n expireAfterSeconds: 60 * 60 * 24 * 10, // 10 Days\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAuB;AAQhB,MAAM,oBAAoB,IAAI;AAAA,EACnC;AAAA,IACE,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA,sBAAsB;AAAA,MACpB,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,MACN,MAAM,uBAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../../src/schemas/oAuth2.schema.ts"],"sourcesContent":["import { Schema } from 'mongoose';\nimport { Token as TokenType, Client, User } from 'oauth2-server';\n\nexport type Token = Omit<TokenType, 'client' | 'user'> & {\n clientId: Client['id'];\n userId: User['_id'];\n};\n\nexport const accessTokenSchema = new Schema<Token>(\n {\n accessToken: {\n type: String,\n required: true,\n },\n accessTokenExpiresAt: {\n type: Date,\n },\n clientId: {\n type: String,\n ref: 'Project',\n required: true,\n },\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n }\n);\n\naccessTokenSchema.index(\n { createdAt: 1 },\n {\n expireAfterSeconds: 60 * 60 * 24 * 10, // 10 Days\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAuB;AAQhB,MAAM,oBAAoB,IAAI;AAAA,EACnC;AAAA,IACE,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA,sBAAsB;AAAA,MACpB,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,MACN,MAAM,uBAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,EACd;AACF;AAEA,kBAAkB;AAAA,EAChB,EAAE,WAAW,EAAE;AAAA,EACf;AAAA,IACE,oBAAoB,KAAK,KAAK,KAAK;AAAA;AAAA,EACrC;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/schemas/organization.schema.ts"],"sourcesContent":["import {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateOrganization';\nimport { Schema } from 'mongoose';\nimport { planSchema } from './plans.schema';\nimport type { Organization } from '@/types/organization.types';\n\nexport const organizationSchema = new Schema<Organization>(\n {\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n plan: {\n type: planSchema,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/schemas/organization.schema.ts"],"sourcesContent":["import {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateOrganization';\nimport { Schema } from 'mongoose';\nimport { planSchema } from './plans.schema';\nimport type { Organization } from '@/types/organization.types';\n\nexport const organizationSchema = new Schema<Organization>(\n {\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n plan: {\n type: planSchema,\n },\n },\n {\n timestamps: true,\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAIO;AACP,sBAAuB;AACvB,mBAA2B;AAGpB,MAAM,qBAAqB,IAAI;AAAA,EACpC;AAAA,IACE,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,YAAY;AAAA,MACV,MAAM,CAAC,uBAAO,MAAM,QAAQ;AAAA,MAC5B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,MAAM,CAAC,uBAAO,MAAM,QAAQ;AAAA,MAC5B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,MAAM,uBAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,EACd;AACF;","names":[]}
|
|
@@ -49,6 +49,30 @@ const oAuth2AccessSchema = new import_mongoose.Schema(
|
|
|
49
49
|
timestamps: true
|
|
50
50
|
}
|
|
51
51
|
);
|
|
52
|
+
const projectConfigSchema = new import_mongoose.Schema(
|
|
53
|
+
{
|
|
54
|
+
internationalization: {
|
|
55
|
+
locales: {
|
|
56
|
+
type: [String],
|
|
57
|
+
enum: Object.values(import_intlayer.Locales),
|
|
58
|
+
required: true
|
|
59
|
+
},
|
|
60
|
+
defaultLocale: {
|
|
61
|
+
type: String,
|
|
62
|
+
enum: Object.values(import_intlayer.Locales)
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
editor: {
|
|
66
|
+
applicationURL: {
|
|
67
|
+
type: String
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
_id: false
|
|
73
|
+
// Prevents the generation of an _id field for this subdocument
|
|
74
|
+
}
|
|
75
|
+
);
|
|
52
76
|
const projectSchema = new import_mongoose.Schema(
|
|
53
77
|
{
|
|
54
78
|
organizationId: {
|
|
@@ -62,10 +86,7 @@ const projectSchema = new import_mongoose.Schema(
|
|
|
62
86
|
minlength: import_validateProject.NAME_MIN_LENGTH,
|
|
63
87
|
maxlength: import_validateProject.NAME_MAX_LENGTH
|
|
64
88
|
},
|
|
65
|
-
|
|
66
|
-
type: [String],
|
|
67
|
-
enum: Object.values(import_intlayer.Locales)
|
|
68
|
-
},
|
|
89
|
+
configuration: projectConfigSchema,
|
|
69
90
|
oAuth2Access: [oAuth2AccessSchema],
|
|
70
91
|
membersIds: {
|
|
71
92
|
type: [import_mongoose.Schema.Types.ObjectId],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/schemas/project.schema.ts"],"sourcesContent":["import {\n NAME_MIN_LENGTH,\n NAME_MAX_LENGTH,\n MEMBERS_MIN_LENGTH,\n} from '@utils/validation/validateProject';\nimport { Locales } from 'intlayer';\nimport { Schema } from 'mongoose';\nimport { Project, Rights, TokenRights } from '@/types/project.types';\n\nconst RightsSchema = new Schema<Rights>({\n read: { type: Boolean, required: true },\n write: { type: Boolean, required: true },\n admin: { type: Boolean, required: true },\n});\n\nexport const TokenRightsSchema = new Schema<TokenRights>({\n dictionary: { type: RightsSchema, required: true },\n project: { type: RightsSchema, required: true },\n organization: { type: RightsSchema, required: true },\n});\n\n// Define the oAuth2Access subdocument schema with timestamps\nconst oAuth2AccessSchema = new Schema(\n {\n clientId: { type: String, required: true, unique: true },\n clientSecret: { type: String, required: true },\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n name: { type: String, required: true },\n expiresAt: { type: Date },\n accessToken: { type: [String], required: true },\n rights: { type: TokenRightsSchema, required: true },\n },\n {\n timestamps: true,\n }\n);\n\nexport const projectSchema = new Schema<Project>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n
|
|
1
|
+
{"version":3,"sources":["../../../src/schemas/project.schema.ts"],"sourcesContent":["import {\n NAME_MIN_LENGTH,\n NAME_MAX_LENGTH,\n MEMBERS_MIN_LENGTH,\n} from '@utils/validation/validateProject';\nimport { Locales } from 'intlayer';\nimport { Schema } from 'mongoose';\nimport { Project, Rights, TokenRights } from '@/types/project.types';\n\nconst RightsSchema = new Schema<Rights>({\n read: { type: Boolean, required: true },\n write: { type: Boolean, required: true },\n admin: { type: Boolean, required: true },\n});\n\nexport const TokenRightsSchema = new Schema<TokenRights>({\n dictionary: { type: RightsSchema, required: true },\n project: { type: RightsSchema, required: true },\n organization: { type: RightsSchema, required: true },\n});\n\n// Define the oAuth2Access subdocument schema with timestamps\nconst oAuth2AccessSchema = new Schema(\n {\n clientId: { type: String, required: true, unique: true },\n clientSecret: { type: String, required: true },\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n name: { type: String, required: true },\n expiresAt: { type: Date },\n accessToken: { type: [String], required: true },\n rights: { type: TokenRightsSchema, required: true },\n },\n {\n timestamps: true,\n }\n);\n\nconst projectConfigSchema = new Schema<Project['configuration']>(\n {\n internationalization: {\n locales: {\n type: [String],\n enum: Object.values(Locales),\n required: true,\n },\n defaultLocale: {\n type: String,\n enum: Object.values(Locales),\n },\n },\n editor: {\n applicationURL: {\n type: String,\n },\n },\n },\n {\n _id: false, // Prevents the generation of an _id field for this subdocument\n }\n);\n\nexport const projectSchema = new Schema<Project>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n configuration: projectConfigSchema,\n oAuth2Access: [oAuth2AccessSchema],\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAIO;AACP,sBAAwB;AACxB,sBAAuB;AAGvB,MAAM,eAAe,IAAI,uBAAe;AAAA,EACtC,MAAM,EAAE,MAAM,SAAS,UAAU,KAAK;AAAA,EACtC,OAAO,EAAE,MAAM,SAAS,UAAU,KAAK;AAAA,EACvC,OAAO,EAAE,MAAM,SAAS,UAAU,KAAK;AACzC,CAAC;AAEM,MAAM,oBAAoB,IAAI,uBAAoB;AAAA,EACvD,YAAY,EAAE,MAAM,cAAc,UAAU,KAAK;AAAA,EACjD,SAAS,EAAE,MAAM,cAAc,UAAU,KAAK;AAAA,EAC9C,cAAc,EAAE,MAAM,cAAc,UAAU,KAAK;AACrD,CAAC;AAGD,MAAM,qBAAqB,IAAI;AAAA,EAC7B;AAAA,IACE,UAAU,EAAE,MAAM,QAAQ,UAAU,MAAM,QAAQ,KAAK;AAAA,IACvD,cAAc,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC7C,QAAQ,EAAE,MAAM,uBAAO,MAAM,UAAU,KAAK,QAAQ,UAAU,KAAK;AAAA,IACnE,MAAM,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IACrC,WAAW,EAAE,MAAM,KAAK;AAAA,IACxB,aAAa,EAAE,MAAM,CAAC,MAAM,GAAG,UAAU,KAAK;AAAA,IAC9C,QAAQ,EAAE,MAAM,mBAAmB,UAAU,KAAK;AAAA,EACpD;AAAA,EACA;AAAA,IACE,YAAY;AAAA,EACd;AACF;AAEA,MAAM,sBAAsB,IAAI;AAAA,EAC9B;AAAA,IACE,sBAAsB;AAAA,MACpB,SAAS;AAAA,QACP,MAAM,CAAC,MAAM;AAAA,QACb,MAAM,OAAO,OAAO,uBAAO;AAAA,QAC3B,UAAU;AAAA,MACZ;AAAA,MACA,eAAe;AAAA,QACb,MAAM;AAAA,QACN,MAAM,OAAO,OAAO,uBAAO;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,gBAAgB;AAAA,QACd,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,KAAK;AAAA;AAAA,EACP;AACF;AAEO,MAAM,gBAAgB,IAAI;AAAA,EAC/B;AAAA,IACE,gBAAgB;AAAA,MACd,MAAM,uBAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,eAAe;AAAA,IACf,cAAc,CAAC,kBAAkB;AAAA,IACjC,YAAY;AAAA,MACV,MAAM,CAAC,uBAAO,MAAM,QAAQ;AAAA,MAC5B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,MAAM,CAAC,uBAAO,MAAM,QAAQ;AAAA,MAC5B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,MAAM,uBAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA;AAAA,IACE,YAAY;AAAA,EACd;AACF;","names":[]}
|
|
@@ -53,6 +53,7 @@ module.exports = __toCommonJS(sessionAuth_service_exports);
|
|
|
53
53
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
54
54
|
var import_logger = require('./../logger/index.cjs');
|
|
55
55
|
var import_cookies = require('./../utils/cookies.cjs');
|
|
56
|
+
var import_ensureMongoDocumentToObject = require('./../utils/ensureMongoDocumentToObject.cjs');
|
|
56
57
|
var import_errors = require('./../utils/errors/index.cjs');
|
|
57
58
|
var import_user = require('./../utils/mapper/user.cjs');
|
|
58
59
|
var import_bcrypt = require("bcrypt");
|
|
@@ -208,7 +209,7 @@ const getUserProvider = async (userId, provider, providerAccountId) => {
|
|
|
208
209
|
return userProvider ?? null;
|
|
209
210
|
};
|
|
210
211
|
const formatUserProviderUpdate = (provider, user, providerUpdate) => {
|
|
211
|
-
const userProvider = user.provider
|
|
212
|
+
const userProvider = (0, import_ensureMongoDocumentToObject.ensureMongoDocumentToObject)(user.provider ?? []);
|
|
212
213
|
const userProviderToUpdate = userProvider?.find(
|
|
213
214
|
(providerEl) => providerEl.provider === provider
|
|
214
215
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { logger } from '@logger';\nimport { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hash, genSalt, compare } from 'bcrypt';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { Document, ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\n// eslint-disable-next-line import/no-cycle\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n SessionProviders,\n EmailPasswordSessionProvider,\n GoogleSessionProvider,\n GithubSessionProvider,\n Session,\n} from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<UserDocument> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<UserDocument> => {\n const session = undefined;\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession: UserDocument = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (!emailAndPasswordProvider.secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_DEFINED', { userId });\n }\n\n if (\n !crypto.timingSafeEqual(\n Buffer.from(emailAndPasswordProvider.secret),\n Buffer.from(secret)\n )\n ) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = (\n user.provider as unknown as Document\n ).toObject();\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: UserDocument = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<UserDocument>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: UserDocument = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":["import_user","uuidv4","jwt","crypto"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { logger } from '@logger';\nimport { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hash, genSalt, compare } from 'bcrypt';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\n// eslint-disable-next-line import/no-cycle\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n SessionProviders,\n EmailPasswordSessionProvider,\n GoogleSessionProvider,\n GithubSessionProvider,\n Session,\n} from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<UserDocument> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<UserDocument> => {\n const session = undefined;\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession: UserDocument = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (!emailAndPasswordProvider.secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_DEFINED', { userId });\n }\n\n if (\n !crypto.timingSafeEqual(\n Buffer.from(emailAndPasswordProvider.secret),\n Buffer.from(secret)\n )\n ) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = ensureMongoDocumentToObject<\n SessionProviders[]\n >(user.provider ?? []);\n\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: UserDocument = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<UserDocument>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: UserDocument = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":["import_user","uuidv4","jwt","crypto"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/types/organization.types.ts"],"sourcesContent":["import type { ObjectId, Document } from 'mongoose';\nimport { Plan } from './plan.types';\nimport type { User } from './user.types';\n\nexport type OrganizationCreationData = {\n name: Organization['name'];\n};\n\nexport type OrganizationData = {\n name: string;\n membersIds: User['_id'][];\n adminsIds: User['_id'][];\n};\n\nexport type Organization = OrganizationData & {\n _id: ObjectId;\n creatorId: User['_id'];\n plan
|
|
1
|
+
{"version":3,"sources":["../../../src/types/organization.types.ts"],"sourcesContent":["import type { ObjectId, Document } from 'mongoose';\nimport { Plan } from './plan.types';\nimport type { User } from './user.types';\n\nexport type OrganizationCreationData = {\n name: Organization['name'];\n};\n\nexport type OrganizationData = {\n name: string;\n membersIds: User['_id'][];\n adminsIds: User['_id'][];\n};\n\nexport type Organization = OrganizationData & {\n _id: ObjectId;\n creatorId: User['_id'];\n plan?: Plan;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type OrganizationAPI = Omit<Organization, 'adminsIds'> & {\n adminsIds?: User['_id'][];\n};\n\nexport type OrganizationDocument = Document<unknown, {}, Organization> &\n Organization;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/types/project.types.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/types/project.types.ts"],"sourcesContent":["import { IntlayerConfig } from '@intlayer/config';\nimport type { Model, ObjectId, Document } from 'mongoose';\nimport type { Organization } from './organization.types';\nimport type { User } from './user.types';\n\nexport type ProjectCreationData = {\n name: Project['name'];\n};\n\ntype ProjectConfigInternationalization = Pick<\n IntlayerConfig['internationalization'],\n 'locales' | 'defaultLocale'\n>;\n\ntype ProjectConfigEditor = Pick<IntlayerConfig['editor'], 'applicationURL'>;\n\nexport type ProjectConfiguration = {\n internationalization: ProjectConfigInternationalization;\n editor: ProjectConfigEditor;\n};\n\nexport type ProjectData = {\n organizationId: Organization['_id'];\n name: string;\n membersIds: User['_id'][];\n adminsIds: User['_id'][];\n creatorId: User['_id'];\n configuration?: ProjectConfiguration;\n};\n\nexport type Rights = {\n read: boolean;\n write: boolean;\n admin: boolean;\n};\n\nexport type TokenRights = {\n dictionary: Rights;\n project: Rights;\n organization: Rights;\n};\n\nexport type AccessKeyData = {\n name: string;\n rights: TokenRights;\n expiresAt?: Date;\n};\n\nexport type OAuth2AccessData = AccessKeyData & {\n clientId: string;\n clientSecret: string;\n accessToken: string[];\n userId: User['_id'];\n};\n\nexport type OAuth2Access = OAuth2AccessData & {\n _id: ObjectId;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type Project = ProjectData & {\n _id: ObjectId;\n createdAt: number;\n updatedAt: number;\n oAuth2Access: OAuth2Access[];\n};\n\nexport type ProjectAPI = Omit<Project, 'adminsIds'> & {\n adminsIds?: User['_id'][];\n};\n\nexport type ProjectDocument = Document<unknown, {}, Project> & Project;\n\nexport type ProjectModelType = Model<Project>;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|