@intlayer/backend 5.1.5 → 5.1.7
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/ai.controller.cjs +61 -43
- package/dist/cjs/controllers/ai.controller.cjs.map +1 -1
- package/dist/cjs/controllers/dictionary.controller.cjs +1 -1
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/organization.controller.cjs +17 -1
- package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
- package/dist/cjs/controllers/project.controller.cjs +1 -0
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/controllers/sessionAuth.controller.cjs +6 -12
- package/dist/cjs/controllers/sessionAuth.controller.cjs.map +1 -1
- package/dist/cjs/controllers/stripe.controller.cjs +31 -10
- package/dist/cjs/controllers/stripe.controller.cjs.map +1 -1
- package/dist/cjs/controllers/tag.controller.cjs +0 -7
- package/dist/cjs/controllers/tag.controller.cjs.map +1 -1
- package/dist/cjs/controllers/user.controller.cjs +1 -1
- package/dist/cjs/controllers/user.controller.cjs.map +1 -1
- package/dist/cjs/emails/InviteUserEmail.cjs +3 -3
- package/dist/cjs/emails/InviteUserEmail.cjs.map +1 -1
- package/dist/cjs/emails/PasswordChangeConfirmation.cjs +3 -3
- package/dist/cjs/emails/PasswordChangeConfirmation.cjs.map +1 -1
- package/dist/cjs/emails/ResetUserPassword.cjs +3 -3
- package/dist/cjs/emails/ResetUserPassword.cjs.map +1 -1
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs +19 -3
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs.map +1 -1
- package/dist/cjs/emails/SubscriptionPaymentError.cjs +19 -3
- package/dist/cjs/emails/SubscriptionPaymentError.cjs.map +1 -1
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs +19 -3
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs.map +1 -1
- package/dist/cjs/emails/ValidateUserEmail.cjs +3 -3
- package/dist/cjs/emails/ValidateUserEmail.cjs.map +1 -1
- package/dist/cjs/emails/Welcome.cjs +3 -3
- package/dist/cjs/emails/Welcome.cjs.map +1 -1
- package/dist/cjs/export.cjs +10 -10
- package/dist/cjs/export.cjs.map +1 -1
- package/dist/cjs/routes/ai.routes.cjs +21 -15
- package/dist/cjs/routes/ai.routes.cjs.map +1 -1
- package/dist/cjs/routes/dictionary.routes.cjs +15 -12
- package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
- package/dist/cjs/routes/event-listener.routes.cjs +4 -4
- package/dist/cjs/routes/event-listener.routes.cjs.map +1 -1
- package/dist/cjs/routes/organization.routes.cjs +15 -15
- package/dist/cjs/routes/organization.routes.cjs.map +1 -1
- package/dist/cjs/routes/project.routes.cjs +30 -18
- package/dist/cjs/routes/project.routes.cjs.map +1 -1
- package/dist/cjs/routes/sessionAuth.routes.cjs +38 -35
- package/dist/cjs/routes/sessionAuth.routes.cjs.map +1 -1
- package/dist/cjs/routes/stripe.routes.cjs +23 -11
- package/dist/cjs/routes/stripe.routes.cjs.map +1 -1
- package/dist/cjs/routes/tags.routes.cjs +11 -11
- package/dist/cjs/routes/tags.routes.cjs.map +1 -1
- package/dist/cjs/routes/user.routes.cjs +13 -13
- package/dist/cjs/routes/user.routes.cjs.map +1 -1
- package/dist/cjs/schemas/project.schema.cjs +2 -2
- package/dist/cjs/schemas/project.schema.cjs.map +1 -1
- package/dist/cjs/services/dictionary.service.cjs +0 -6
- package/dist/cjs/services/dictionary.service.cjs.map +1 -1
- package/dist/cjs/services/email.service.cjs +1 -1
- package/dist/cjs/services/email.service.cjs.map +1 -1
- package/dist/cjs/services/subscription.service.cjs +81 -2
- package/dist/cjs/services/subscription.service.cjs.map +1 -1
- package/dist/cjs/utils/AI/{askDocQuestion.cjs → askDocQuestion/askDocQuestion.cjs} +1 -1
- package/dist/cjs/utils/AI/askDocQuestion/askDocQuestion.cjs.map +1 -0
- package/dist/{esm/utils/AI → cjs/utils/AI/askDocQuestion}/embeddings.json +4288 -4288
- package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/index.cjs +5 -3
- package/dist/cjs/utils/AI/auditDictionary/index.cjs.map +1 -0
- package/dist/cjs/utils/{auditDictionaryField → AI/auditDictionaryField}/index.cjs +5 -3
- package/dist/cjs/utils/AI/auditDictionaryField/index.cjs.map +1 -0
- package/dist/cjs/utils/{auditDictionaryMetadata → AI/auditDictionaryMetadata}/index.cjs +5 -3
- package/dist/cjs/utils/AI/auditDictionaryMetadata/index.cjs.map +1 -0
- package/dist/cjs/utils/AI/autocomplete/PROMPT.md +13 -0
- package/dist/cjs/utils/AI/autocomplete/index.cjs +73 -0
- package/dist/cjs/utils/AI/autocomplete/index.cjs.map +1 -0
- package/dist/cjs/utils/auditTag/index.cjs +4 -2
- package/dist/cjs/utils/auditTag/index.cjs.map +1 -1
- package/dist/cjs/utils/errors/errorCodes.cjs +26 -0
- package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
- package/dist/cjs/utils/mongoDB/connectDB.cjs +10 -0
- package/dist/cjs/utils/mongoDB/connectDB.cjs.map +1 -1
- package/dist/cjs/webhooks/stripe.webhook.cjs +42 -0
- package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -1
- package/dist/esm/controllers/ai.controller.mjs +59 -42
- package/dist/esm/controllers/ai.controller.mjs.map +1 -1
- package/dist/esm/controllers/dictionary.controller.mjs +1 -1
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs +18 -2
- package/dist/esm/controllers/organization.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +1 -0
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/sessionAuth.controller.mjs +6 -12
- package/dist/esm/controllers/sessionAuth.controller.mjs.map +1 -1
- package/dist/esm/controllers/stripe.controller.mjs +30 -10
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -1
- package/dist/esm/controllers/tag.controller.mjs +0 -7
- package/dist/esm/controllers/tag.controller.mjs.map +1 -1
- package/dist/esm/controllers/user.controller.mjs +2 -2
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/emails/InviteUserEmail.mjs +3 -3
- package/dist/esm/emails/InviteUserEmail.mjs.map +1 -1
- package/dist/esm/emails/PasswordChangeConfirmation.mjs +3 -3
- package/dist/esm/emails/PasswordChangeConfirmation.mjs.map +1 -1
- package/dist/esm/emails/ResetUserPassword.mjs +3 -3
- package/dist/esm/emails/ResetUserPassword.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs +19 -3
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentError.mjs +19 -3
- package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs +19 -3
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -1
- package/dist/esm/emails/ValidateUserEmail.mjs +3 -3
- package/dist/esm/emails/ValidateUserEmail.mjs.map +1 -1
- package/dist/esm/emails/Welcome.mjs +3 -3
- package/dist/esm/emails/Welcome.mjs.map +1 -1
- package/dist/esm/export.mjs +10 -10
- package/dist/esm/export.mjs.map +1 -1
- package/dist/esm/routes/ai.routes.mjs +22 -15
- package/dist/esm/routes/ai.routes.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs +14 -11
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/event-listener.routes.mjs +4 -4
- package/dist/esm/routes/event-listener.routes.mjs.map +1 -1
- package/dist/esm/routes/organization.routes.mjs +13 -13
- package/dist/esm/routes/organization.routes.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs +28 -16
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/routes/sessionAuth.routes.mjs +37 -34
- package/dist/esm/routes/sessionAuth.routes.mjs.map +1 -1
- package/dist/esm/routes/stripe.routes.mjs +22 -9
- package/dist/esm/routes/stripe.routes.mjs.map +1 -1
- package/dist/esm/routes/tags.routes.mjs +9 -9
- package/dist/esm/routes/tags.routes.mjs.map +1 -1
- package/dist/esm/routes/user.routes.mjs +11 -11
- package/dist/esm/routes/user.routes.mjs.map +1 -1
- package/dist/esm/schemas/project.schema.mjs +2 -2
- package/dist/esm/schemas/project.schema.mjs.map +1 -1
- package/dist/esm/services/dictionary.service.mjs +0 -6
- package/dist/esm/services/dictionary.service.mjs.map +1 -1
- package/dist/esm/services/email.service.mjs +1 -1
- package/dist/esm/services/email.service.mjs.map +1 -1
- package/dist/esm/services/subscription.service.mjs +78 -1
- package/dist/esm/services/subscription.service.mjs.map +1 -1
- package/dist/esm/utils/AI/{askDocQuestion.mjs → askDocQuestion/askDocQuestion.mjs} +1 -1
- package/dist/esm/utils/AI/askDocQuestion/askDocQuestion.mjs.map +1 -0
- package/dist/{cjs/utils/AI → esm/utils/AI/askDocQuestion}/embeddings.json +4288 -4288
- package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/index.mjs +5 -3
- package/dist/esm/utils/AI/auditDictionary/index.mjs.map +1 -0
- package/dist/esm/utils/{auditDictionaryField → AI/auditDictionaryField}/index.mjs +5 -3
- package/dist/esm/utils/AI/auditDictionaryField/index.mjs.map +1 -0
- package/dist/esm/utils/{auditDictionaryMetadata → AI/auditDictionaryMetadata}/index.mjs +5 -3
- package/dist/esm/utils/AI/auditDictionaryMetadata/index.mjs.map +1 -0
- package/dist/esm/utils/AI/autocomplete/PROMPT.md +13 -0
- package/dist/esm/utils/AI/autocomplete/index.mjs +48 -0
- package/dist/esm/utils/AI/autocomplete/index.mjs.map +1 -0
- package/dist/esm/utils/auditTag/index.mjs +4 -2
- package/dist/esm/utils/auditTag/index.mjs.map +1 -1
- package/dist/esm/utils/errors/errorCodes.mjs +26 -0
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/utils/mongoDB/connectDB.mjs +10 -0
- package/dist/esm/utils/mongoDB/connectDB.mjs.map +1 -1
- package/dist/esm/webhooks/stripe.webhook.mjs +32 -0
- package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -1
- package/dist/types/controllers/ai.controller.d.ts +17 -2
- package/dist/types/controllers/ai.controller.d.ts.map +1 -1
- package/dist/types/controllers/organization.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/sessionAuth.controller.d.ts +4 -3
- package/dist/types/controllers/sessionAuth.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts +15 -7
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -1
- package/dist/types/controllers/tag.controller.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +4 -3
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentError.d.ts +4 -3
- package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +4 -3
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -1
- package/dist/types/export.d.ts +5 -5
- package/dist/types/export.d.ts.map +1 -1
- package/dist/types/routes/ai.routes.d.ts +6 -1
- package/dist/types/routes/ai.routes.d.ts.map +1 -1
- package/dist/types/routes/dictionary.routes.d.ts +4 -4
- package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
- package/dist/types/routes/event-listener.routes.d.ts +1 -1
- package/dist/types/routes/event-listener.routes.d.ts.map +1 -1
- package/dist/types/routes/organization.routes.d.ts +5 -5
- package/dist/types/routes/organization.routes.d.ts.map +1 -1
- package/dist/types/routes/project.routes.d.ts +5 -5
- package/dist/types/routes/project.routes.d.ts.map +1 -1
- package/dist/types/routes/sessionAuth.routes.d.ts +4 -7
- package/dist/types/routes/sessionAuth.routes.d.ts.map +1 -1
- package/dist/types/routes/stripe.routes.d.ts +6 -1
- package/dist/types/routes/stripe.routes.d.ts.map +1 -1
- package/dist/types/routes/tags.routes.d.ts +3 -3
- package/dist/types/routes/tags.routes.d.ts.map +1 -1
- package/dist/types/routes/user.routes.d.ts +4 -4
- package/dist/types/routes/user.routes.d.ts.map +1 -1
- package/dist/types/services/dictionary.service.d.ts.map +1 -1
- package/dist/types/services/subscription.service.d.ts +9 -0
- package/dist/types/services/subscription.service.d.ts.map +1 -1
- package/dist/types/utils/AI/askDocQuestion/askDocQuestion.d.ts.map +1 -0
- package/dist/types/utils/{auditDictionary → AI/auditDictionary}/index.d.ts +8 -5
- package/dist/types/utils/AI/auditDictionary/index.d.ts.map +1 -0
- package/dist/types/utils/{auditDictionaryField → AI/auditDictionaryField}/index.d.ts +8 -5
- package/dist/types/utils/AI/auditDictionaryField/index.d.ts.map +1 -0
- package/dist/types/utils/{auditDictionaryMetadata → AI/auditDictionaryMetadata}/index.d.ts +8 -5
- package/dist/types/utils/AI/auditDictionaryMetadata/index.d.ts.map +1 -0
- package/dist/types/utils/AI/autocomplete/index.d.ts +22 -0
- package/dist/types/utils/AI/autocomplete/index.d.ts.map +1 -0
- package/dist/types/utils/auditTag/index.d.ts +7 -4
- package/dist/types/utils/auditTag/index.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts +26 -0
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/utils/mongoDB/connectDB.d.ts.map +1 -1
- package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -1
- package/package.json +10 -9
- package/dist/cjs/utils/AI/askDocQuestion.cjs.map +0 -1
- package/dist/cjs/utils/auditDictionary/index.cjs.map +0 -1
- package/dist/cjs/utils/auditDictionaryField/index.cjs.map +0 -1
- package/dist/cjs/utils/auditDictionaryMetadata/index.cjs.map +0 -1
- package/dist/esm/utils/AI/askDocQuestion.mjs.map +0 -1
- package/dist/esm/utils/auditDictionary/index.mjs.map +0 -1
- package/dist/esm/utils/auditDictionaryField/index.mjs.map +0 -1
- package/dist/esm/utils/auditDictionaryMetadata/index.mjs.map +0 -1
- package/dist/types/utils/AI/askDocQuestion.d.ts.map +0 -1
- package/dist/types/utils/auditDictionary/index.d.ts.map +0 -1
- package/dist/types/utils/auditDictionaryField/index.d.ts.map +0 -1
- package/dist/types/utils/auditDictionaryMetadata/index.d.ts.map +0 -1
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/CJS_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/JSON_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/JSX_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/MJS_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/PROMPT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/TSX_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionary → AI/auditDictionary}/TS_FORMAT.md +0 -0
- /package/dist/cjs/utils/{auditDictionaryField → AI/auditDictionaryField}/PROMPT.md +0 -0
- /package/dist/cjs/utils/{auditDictionaryMetadata → AI/auditDictionaryMetadata}/PROMPT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/CJS_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/JSON_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/JSX_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/MJS_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/PROMPT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/TSX_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionary → AI/auditDictionary}/TS_FORMAT.md +0 -0
- /package/dist/esm/utils/{auditDictionaryField → AI/auditDictionaryField}/PROMPT.md +0 -0
- /package/dist/esm/utils/{auditDictionaryMetadata → AI/auditDictionaryMetadata}/PROMPT.md +0 -0
- /package/dist/types/utils/AI/{askDocQuestion.d.ts → askDocQuestion/askDocQuestion.d.ts} +0 -0
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
import { getDictionariesByTags } from "./../services/dictionary.service.mjs";
|
|
2
2
|
import { getTagsByKeys } from "./../services/tag.service.mjs";
|
|
3
3
|
import * as tagService from "./../services/tag.service.mjs";
|
|
4
|
-
import * as askDocQuestionUtil from "./../utils/AI/askDocQuestion.mjs";
|
|
5
|
-
import * as auditContentDeclarationUtil from "./../utils/auditDictionary/index.mjs";
|
|
6
|
-
import * as auditContentDeclarationFieldUtil from "./../utils/auditDictionaryField/index.mjs";
|
|
7
|
-
import * as auditContentDeclarationMetadataUtil from "./../utils/auditDictionaryMetadata/index.mjs";
|
|
4
|
+
import * as askDocQuestionUtil from "./../utils/AI/askDocQuestion/askDocQuestion.mjs";
|
|
5
|
+
import * as auditContentDeclarationUtil from "./../utils/AI/auditDictionary/index.mjs";
|
|
6
|
+
import * as auditContentDeclarationFieldUtil from "./../utils/AI/auditDictionaryField/index.mjs";
|
|
7
|
+
import * as auditContentDeclarationMetadataUtil from "./../utils/AI/auditDictionaryMetadata/index.mjs";
|
|
8
|
+
import * as autocompleteUtil from "./../utils/AI/autocomplete/index.mjs";
|
|
8
9
|
import * as auditTagUtil from "./../utils/auditTag/index.mjs";
|
|
9
10
|
import { ErrorHandler } from "./../utils/errors/index.mjs";
|
|
10
11
|
import { formatResponse } from "./../utils/responseData.mjs";
|
|
11
12
|
const auditContentDeclaration = async (req, res, _next) => {
|
|
12
|
-
const { user, project } = res.locals;
|
|
13
|
+
const { user, project, organization } = res.locals;
|
|
13
14
|
const {
|
|
14
15
|
fileContent,
|
|
15
16
|
filePath,
|
|
16
17
|
openAiApiKey,
|
|
17
18
|
customPrompt,
|
|
18
19
|
model,
|
|
20
|
+
temperature,
|
|
19
21
|
locales,
|
|
20
22
|
defaultLocale,
|
|
21
23
|
tagsKeys
|
|
22
24
|
} = req.body;
|
|
23
25
|
if (!openAiApiKey) {
|
|
24
|
-
if (!user) {
|
|
25
|
-
ErrorHandler.handleGenericErrorResponse(res, "
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (!project) {
|
|
29
|
-
ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
26
|
+
if (!user || !project || !organization) {
|
|
27
|
+
ErrorHandler.handleGenericErrorResponse(res, "AI_ACCESS_DENIED");
|
|
30
28
|
return;
|
|
31
29
|
}
|
|
32
30
|
}
|
|
@@ -39,7 +37,8 @@ const auditContentDeclaration = async (req, res, _next) => {
|
|
|
39
37
|
fileContent,
|
|
40
38
|
filePath,
|
|
41
39
|
model,
|
|
42
|
-
|
|
40
|
+
temperature,
|
|
41
|
+
openAiApiKey,
|
|
43
42
|
customPrompt,
|
|
44
43
|
locales,
|
|
45
44
|
defaultLocale,
|
|
@@ -60,23 +59,20 @@ const auditContentDeclaration = async (req, res, _next) => {
|
|
|
60
59
|
}
|
|
61
60
|
};
|
|
62
61
|
const auditContentDeclarationField = async (req, res, _next) => {
|
|
63
|
-
const { user, project } = res.locals;
|
|
62
|
+
const { user, project, organization } = res.locals;
|
|
64
63
|
const {
|
|
65
64
|
fileContent,
|
|
66
65
|
openAiApiKey,
|
|
67
66
|
customPrompt,
|
|
68
67
|
model,
|
|
68
|
+
temperature,
|
|
69
69
|
locales,
|
|
70
70
|
tagsKeys,
|
|
71
71
|
keyPath
|
|
72
72
|
} = req.body;
|
|
73
73
|
if (!openAiApiKey) {
|
|
74
|
-
if (!user) {
|
|
75
|
-
ErrorHandler.handleGenericErrorResponse(res, "
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if (!project) {
|
|
79
|
-
ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
74
|
+
if (!user || !project || !organization) {
|
|
75
|
+
ErrorHandler.handleGenericErrorResponse(res, "AI_ACCESS_DENIED");
|
|
80
76
|
return;
|
|
81
77
|
}
|
|
82
78
|
}
|
|
@@ -88,7 +84,8 @@ const auditContentDeclarationField = async (req, res, _next) => {
|
|
|
88
84
|
const auditResponse = await auditContentDeclarationFieldUtil.auditDictionaryField({
|
|
89
85
|
fileContent,
|
|
90
86
|
model,
|
|
91
|
-
|
|
87
|
+
temperature,
|
|
88
|
+
openAiApiKey,
|
|
92
89
|
customPrompt,
|
|
93
90
|
locales,
|
|
94
91
|
tags,
|
|
@@ -110,18 +107,10 @@ const auditContentDeclarationField = async (req, res, _next) => {
|
|
|
110
107
|
};
|
|
111
108
|
const auditContentDeclarationMetadata = async (req, res, _next) => {
|
|
112
109
|
const { user, organization, project } = res.locals;
|
|
113
|
-
const { fileContent, openAiApiKey, customPrompt, model } = req.body;
|
|
110
|
+
const { fileContent, openAiApiKey, customPrompt, model, temperature } = req.body;
|
|
114
111
|
if (!openAiApiKey) {
|
|
115
|
-
if (!user) {
|
|
116
|
-
ErrorHandler.handleGenericErrorResponse(res, "
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (!organization) {
|
|
120
|
-
ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (!project) {
|
|
124
|
-
ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
112
|
+
if (!user || !project || !organization) {
|
|
113
|
+
ErrorHandler.handleGenericErrorResponse(res, "AI_ACCESS_DENIED");
|
|
125
114
|
return;
|
|
126
115
|
}
|
|
127
116
|
}
|
|
@@ -136,7 +125,8 @@ const auditContentDeclarationMetadata = async (req, res, _next) => {
|
|
|
136
125
|
const auditResponse = await auditContentDeclarationMetadataUtil.auditDictionaryMetadata({
|
|
137
126
|
fileContent,
|
|
138
127
|
model,
|
|
139
|
-
openAiApiKey
|
|
128
|
+
openAiApiKey,
|
|
129
|
+
temperature,
|
|
140
130
|
customPrompt,
|
|
141
131
|
tags
|
|
142
132
|
});
|
|
@@ -155,15 +145,11 @@ const auditContentDeclarationMetadata = async (req, res, _next) => {
|
|
|
155
145
|
}
|
|
156
146
|
};
|
|
157
147
|
const auditTag = async (req, res, _next) => {
|
|
158
|
-
const { user, project } = res.locals;
|
|
159
|
-
const { openAiApiKey, customPrompt, model, tag } = req.body;
|
|
148
|
+
const { user, project, organization } = res.locals;
|
|
149
|
+
const { openAiApiKey, customPrompt, model, temperature, tag } = req.body;
|
|
160
150
|
if (!openAiApiKey) {
|
|
161
|
-
if (!user) {
|
|
162
|
-
ErrorHandler.handleGenericErrorResponse(res, "
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (!project) {
|
|
166
|
-
ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
|
|
151
|
+
if (!user || !project || !organization) {
|
|
152
|
+
ErrorHandler.handleGenericErrorResponse(res, "AI_ACCESS_DENIED");
|
|
167
153
|
return;
|
|
168
154
|
}
|
|
169
155
|
}
|
|
@@ -174,7 +160,8 @@ const auditTag = async (req, res, _next) => {
|
|
|
174
160
|
}
|
|
175
161
|
const auditResponse = await auditTagUtil.auditTag({
|
|
176
162
|
model,
|
|
177
|
-
openAiApiKey
|
|
163
|
+
openAiApiKey,
|
|
164
|
+
temperature,
|
|
178
165
|
customPrompt,
|
|
179
166
|
dictionaries,
|
|
180
167
|
tag
|
|
@@ -206,11 +193,41 @@ const askDocQuestion = async (req, res) => {
|
|
|
206
193
|
return;
|
|
207
194
|
}
|
|
208
195
|
};
|
|
196
|
+
const autocomplete = async (req, res) => {
|
|
197
|
+
try {
|
|
198
|
+
const { text, model, openAiApiKey, customPrompt, temperature } = req.body;
|
|
199
|
+
const { user, project, organization } = res.locals;
|
|
200
|
+
if (!openAiApiKey) {
|
|
201
|
+
if (!user || !project || !organization) {
|
|
202
|
+
ErrorHandler.handleGenericErrorResponse(res, "AI_ACCESS_DENIED");
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const response = await autocompleteUtil.autocomplete({
|
|
207
|
+
text,
|
|
208
|
+
model,
|
|
209
|
+
openAiApiKey,
|
|
210
|
+
temperature,
|
|
211
|
+
customPrompt
|
|
212
|
+
}) ?? {
|
|
213
|
+
autocompletion: "",
|
|
214
|
+
tokenUsed: 0
|
|
215
|
+
};
|
|
216
|
+
const responseData = formatResponse({
|
|
217
|
+
data: response
|
|
218
|
+
});
|
|
219
|
+
res.json(responseData);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
ErrorHandler.handleAppErrorResponse(res, error);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
209
225
|
export {
|
|
210
226
|
askDocQuestion,
|
|
211
227
|
auditContentDeclaration,
|
|
212
228
|
auditContentDeclarationField,
|
|
213
229
|
auditContentDeclarationMetadata,
|
|
214
|
-
auditTag
|
|
230
|
+
auditTag,
|
|
231
|
+
autocomplete
|
|
215
232
|
};
|
|
216
233
|
//# sourceMappingURL=ai.controller.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/ai.controller.ts"],"sourcesContent":["import { type KeyPath } from '@intlayer/core';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { getDictionariesByTags } from '@services/dictionary.service';\nimport { getTagsByKeys } from '@services/tag.service';\nimport * as tagService from '@services/tag.service';\nimport * as askDocQuestionUtil from '@utils/AI/askDocQuestion';\nimport * as auditContentDeclarationUtil from '@utils/auditDictionary';\nimport * as auditContentDeclarationFieldUtil from '@utils/auditDictionaryField';\nimport * as auditContentDeclarationMetadataUtil from '@utils/auditDictionaryMetadata';\nimport * as auditTagUtil from '@utils/auditTag';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport type { Locales } from 'intlayer';\nimport type { Dictionary } from '@/types/dictionary.types';\nimport type { Tag } from '@/types/tag.types';\n\nexport type AuditContentDeclarationBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n locales: Locales[];\n defaultLocale: Locales;\n fileContent: string;\n filePath?: string;\n model?: string;\n tagsKeys?: string[];\n};\nexport type AuditContentDeclarationResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclaration = async (\n req: Request<AuditContentDeclarationBody>,\n res: ResponseWithInformation<AuditContentDeclarationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project } = res.locals;\n const {\n fileContent,\n filePath,\n openAiApiKey,\n customPrompt,\n model,\n locales,\n defaultLocale,\n tagsKeys,\n } = req.body;\n\n if (!openAiApiKey) {\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n }\n\n try {\n let tags: Tag[] = [];\n\n if (project?.organizationId) {\n tags = await getTagsByKeys(tagsKeys, project.organizationId);\n }\n\n const auditResponse = await auditContentDeclarationUtil.auditDictionary({\n fileContent,\n filePath,\n model,\n openAiApiKey: openAiApiKey ?? process.env.OPENAI_API_KEY,\n customPrompt,\n locales,\n defaultLocale,\n tags,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditContentDeclarationFieldBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n locales: Locales[];\n fileContent: string;\n filePath?: string;\n model?: string;\n tagsKeys?: string[];\n keyPath: KeyPath[];\n};\nexport type AuditContentDeclarationFieldResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclarationField = async (\n req: Request<AuditContentDeclarationFieldBody>,\n res: ResponseWithInformation<AuditContentDeclarationFieldResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project } = res.locals;\n const {\n fileContent,\n openAiApiKey,\n customPrompt,\n model,\n locales,\n tagsKeys,\n keyPath,\n } = req.body;\n\n if (!openAiApiKey) {\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n }\n\n try {\n let tags: Tag[] = [];\n\n if (project?.organizationId) {\n tags = await getTagsByKeys(tagsKeys, project.organizationId);\n }\n\n const auditResponse =\n await auditContentDeclarationFieldUtil.auditDictionaryField({\n fileContent,\n model,\n openAiApiKey: openAiApiKey ?? process.env.OPENAI_API_KEY,\n customPrompt,\n locales,\n tags,\n keyPath,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditContentDeclarationMetadataBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n fileContent: string;\n model?: string;\n};\nexport type AuditContentDeclarationMetadataResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclarationMetadata = async (\n req: Request<AuditContentDeclarationMetadataBody>,\n res: ResponseWithInformation<AuditContentDeclarationMetadataResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, organization, project } = res.locals;\n const { fileContent, openAiApiKey, customPrompt, model } = req.body;\n\n if (!openAiApiKey) {\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n }\n\n try {\n const tags: Tag[] = await tagService.findTags(\n {\n organizationId: organization?._id,\n },\n 0,\n 1000\n );\n\n const auditResponse =\n await auditContentDeclarationMetadataUtil.auditDictionaryMetadata({\n fileContent,\n model,\n openAiApiKey: openAiApiKey ?? process.env.OPENAI_API_KEY,\n customPrompt,\n tags,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditTagBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n filePath?: string;\n model?: string;\n tag: Tag;\n};\nexport type AuditTagResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditTag = async (\n req: Request<undefined, undefined, AuditTagBody>,\n res: ResponseWithInformation<AuditTagResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project } = res.locals;\n const { openAiApiKey, customPrompt, model, tag } = req.body;\n\n if (!openAiApiKey) {\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n }\n\n try {\n let dictionaries: Dictionary[] = [];\n if (project?.organizationId) {\n dictionaries = await getDictionariesByTags([tag.key], project._id);\n }\n\n const auditResponse = await auditTagUtil.auditTag({\n model,\n openAiApiKey: openAiApiKey ?? process.env.OPENAI_API_KEY!,\n customPrompt,\n dictionaries,\n tag,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AskDocQuestionBody = {\n messages: askDocQuestionUtil.ChatCompletionRequestMessage[];\n};\nexport type AskDocQuestionResult =\n ResponseData<askDocQuestionUtil.AskDocQuestionResult>;\n\nexport const askDocQuestion = async (\n req: Request<undefined, undefined, AskDocQuestionBody>,\n res: ResponseWithInformation<AskDocQuestionResult>\n) => {\n const { messages } = req.body;\n try {\n const response = await askDocQuestionUtil.askDocQuestion(messages);\n\n const responseData =\n formatResponse<askDocQuestionUtil.AskDocQuestionResult>({\n data: response,\n });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/ai.controller.ts"],"sourcesContent":["import { type KeyPath } from '@intlayer/core';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { getDictionariesByTags } from '@services/dictionary.service';\nimport { getTagsByKeys } from '@services/tag.service';\nimport * as tagService from '@services/tag.service';\nimport * as askDocQuestionUtil from '@utils/AI/askDocQuestion/askDocQuestion';\nimport * as auditContentDeclarationUtil from '@utils/AI/auditDictionary';\nimport * as auditContentDeclarationFieldUtil from '@utils/AI/auditDictionaryField';\nimport * as auditContentDeclarationMetadataUtil from '@utils/AI/auditDictionaryMetadata';\nimport * as autocompleteUtil from '@utils/AI/autocomplete';\nimport * as auditTagUtil from '@utils/auditTag';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport { formatResponse, type ResponseData } from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport type { Locales } from 'intlayer';\nimport type { Dictionary } from '@/types/dictionary.types';\nimport type { Tag } from '@/types/tag.types';\n\nexport type AuditContentDeclarationBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n locales: Locales[];\n defaultLocale: Locales;\n fileContent: string;\n filePath?: string;\n model?: string;\n temperature?: number;\n tagsKeys?: string[];\n};\nexport type AuditContentDeclarationResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclaration = async (\n req: Request<AuditContentDeclarationBody>,\n res: ResponseWithInformation<AuditContentDeclarationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, organization } = res.locals;\n const {\n fileContent,\n filePath,\n openAiApiKey,\n customPrompt,\n model,\n temperature,\n locales,\n defaultLocale,\n tagsKeys,\n } = req.body;\n\n if (!openAiApiKey) {\n if (!user || !project || !organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'AI_ACCESS_DENIED');\n return;\n }\n }\n\n try {\n let tags: Tag[] = [];\n\n if (project?.organizationId) {\n tags = await getTagsByKeys(tagsKeys, project.organizationId);\n }\n\n const auditResponse = await auditContentDeclarationUtil.auditDictionary({\n fileContent,\n filePath,\n model,\n temperature,\n openAiApiKey,\n customPrompt,\n locales,\n defaultLocale,\n tags,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditContentDeclarationFieldBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n locales: Locales[];\n fileContent: string;\n filePath?: string;\n model?: string;\n temperature?: number;\n tagsKeys?: string[];\n keyPath: KeyPath[];\n};\nexport type AuditContentDeclarationFieldResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclarationField = async (\n req: Request<AuditContentDeclarationFieldBody>,\n res: ResponseWithInformation<AuditContentDeclarationFieldResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, organization } = res.locals;\n const {\n fileContent,\n openAiApiKey,\n customPrompt,\n model,\n temperature,\n locales,\n tagsKeys,\n keyPath,\n } = req.body;\n\n if (!openAiApiKey) {\n if (!user || !project || !organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'AI_ACCESS_DENIED');\n return;\n }\n }\n\n try {\n let tags: Tag[] = [];\n\n if (project?.organizationId) {\n tags = await getTagsByKeys(tagsKeys, project.organizationId);\n }\n\n const auditResponse =\n await auditContentDeclarationFieldUtil.auditDictionaryField({\n fileContent,\n model,\n temperature,\n openAiApiKey,\n customPrompt,\n locales,\n tags,\n keyPath,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditContentDeclarationMetadataBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n fileContent: string;\n model?: string;\n temperature?: number;\n};\nexport type AuditContentDeclarationMetadataResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditContentDeclarationMetadata = async (\n req: Request<AuditContentDeclarationMetadataBody>,\n res: ResponseWithInformation<AuditContentDeclarationMetadataResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, organization, project } = res.locals;\n const { fileContent, openAiApiKey, customPrompt, model, temperature } =\n req.body;\n\n if (!openAiApiKey) {\n if (!user || !project || !organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'AI_ACCESS_DENIED');\n return;\n }\n }\n\n try {\n const tags: Tag[] = await tagService.findTags(\n {\n organizationId: organization?._id,\n },\n 0,\n 1000\n );\n\n const auditResponse =\n await auditContentDeclarationMetadataUtil.auditDictionaryMetadata({\n fileContent,\n model,\n openAiApiKey,\n temperature,\n customPrompt,\n tags,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AuditTagBody = {\n openAiApiKey?: string;\n customPrompt?: string;\n filePath?: string;\n model?: string;\n temperature?: number;\n tag: Tag;\n};\nexport type AuditTagResult =\n ResponseData<auditContentDeclarationUtil.AuditFileResultData>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const auditTag = async (\n req: Request<undefined, undefined, AuditTagBody>,\n res: ResponseWithInformation<AuditTagResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, organization } = res.locals;\n const { openAiApiKey, customPrompt, model, temperature, tag } = req.body;\n\n if (!openAiApiKey) {\n if (!user || !project || !organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'AI_ACCESS_DENIED');\n return;\n }\n }\n\n try {\n let dictionaries: Dictionary[] = [];\n if (project?.organizationId) {\n dictionaries = await getDictionariesByTags([tag.key], project._id);\n }\n\n const auditResponse = await auditTagUtil.auditTag({\n model,\n openAiApiKey,\n temperature,\n customPrompt,\n dictionaries,\n tag,\n });\n\n if (!auditResponse) {\n ErrorHandler.handleGenericErrorResponse(res, 'AUDIT_FAILED');\n return;\n }\n\n const responseData =\n formatResponse<auditContentDeclarationUtil.AuditFileResultData>({\n data: auditResponse,\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 AskDocQuestionBody = {\n messages: askDocQuestionUtil.ChatCompletionRequestMessage[];\n};\nexport type AskDocQuestionResult =\n ResponseData<askDocQuestionUtil.AskDocQuestionResult>;\n\nexport const askDocQuestion = async (\n req: Request<undefined, undefined, AskDocQuestionBody>,\n res: ResponseWithInformation<AskDocQuestionResult>\n) => {\n const { messages } = req.body;\n try {\n const response = await askDocQuestionUtil.askDocQuestion(messages);\n\n const responseData =\n formatResponse<askDocQuestionUtil.AskDocQuestionResult>({\n data: response,\n });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AutocompleteBody = {\n text: string;\n model?: string;\n temperature?: number;\n openAiApiKey?: string;\n customPrompt?: string;\n};\n\nexport type AutocompleteResponse = ResponseData<{\n autocompletion: string;\n}>;\n\nexport const autocomplete = async (\n req: Request<undefined, undefined, AutocompleteBody>,\n res: ResponseWithInformation<AutocompleteResponse>\n) => {\n try {\n const { text, model, openAiApiKey, customPrompt, temperature } = req.body;\n const { user, project, organization } = res.locals;\n\n if (!openAiApiKey) {\n if (!user || !project || !organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'AI_ACCESS_DENIED');\n return;\n }\n }\n\n const response = (await autocompleteUtil.autocomplete({\n text,\n model,\n openAiApiKey,\n temperature,\n customPrompt,\n })) ?? {\n autocompletion: '',\n tokenUsed: 0,\n };\n\n const responseData =\n formatResponse<autocompleteUtil.AutocompleteFileResultData>({\n data: response,\n });\n\n res.json(responseData);\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -129,7 +129,7 @@ const addDictionary = async (req, res, _next) => {
|
|
|
129
129
|
ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
|
-
if (!dictionaryData.projectIds
|
|
132
|
+
if (!dictionaryData.projectIds?.includes(String(project._id))) {
|
|
133
133
|
ErrorHandler.handleGenericErrorResponse(res, "DICTIONARY_PROJECT_MISMATCH");
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\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 * as eventListener from '@/controllers/event-listener';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n filters,\n skip,\n pageSize\n );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id)\n );\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\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 GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\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 GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\n );\n\n if (!dictionary.projectIds.map(String).includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, project._id, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\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 AddDictionaryBody = { dictionary: DictionaryCreationData };\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionary;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: new Map([\n ['v1', { content: dictionaryData.content ?? ({} as ContentNode) }],\n ]),\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: mapDictionaryToAPI(newDictionary, project._id),\n status: 'ADDED',\n },\n ]);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project._id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const newDictionariesResult: DictionaryAPI[] = [];\n const updatedDictionariesResult: DictionaryAPI[] = [];\n const errorResult: PushDictionariesResultData['error'] = [];\n\n for (const dictionaryDataEl of newDictionaries) {\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project._id)],\n creatorId: user._id,\n content: new Map([\n ['v1', { content: dictionaryDataEl.content ?? ({} as ContentNode) }],\n ]),\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(\n mapDictionaryToAPI(newDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project._id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const versionList = [...(existingDictionaryDB.content.keys() ?? [])];\n const lastVersion = versionList[versionList.length - 1];\n\n const lastContent =\n (existingDictionaryDB.content.get(lastVersion)\n ?.content as DictionaryAPI['content']) ?? null;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n newContent = {\n ...newContent,\n [newContentVersion]: {\n content: dictionaryDataEl.content,\n },\n };\n }\n\n const dictionary: DictionaryData = {\n ...ensureMongoDocumentToObject(existingDictionaryDB),\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project._id)],\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const updatedDictionary =\n await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project._id\n );\n updatedDictionariesResult.push(\n mapDictionaryToAPI(updatedDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const result: PushDictionariesResultData = {\n newDictionaries: newDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n updatedDictionaries: updatedDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n error: errorResult,\n };\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n eventListener.sendDictionaryUpdate([\n ...newDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'ADDED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ...updatedDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'UPDATED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\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 UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'UPDATED',\n },\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 DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project._id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary._id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'DELETED',\n },\n ]);\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/dictionary.controller.ts"],"sourcesContent":["import type {\n ContentNode,\n Dictionary as LocalDictionary,\n} from '@intlayer/core';\nimport { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport * as dictionaryService from '@services/dictionary.service';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport {\n type DictionaryFiltersParams,\n getDictionaryFiltersAndPagination,\n} from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport { mapDictionaryToAPI } from '@utils/mapper/dictionary';\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 * as eventListener from '@/controllers/event-listener';\nimport type {\n Dictionary,\n DictionaryAPI,\n DictionaryCreationData,\n DictionaryData,\n VersionedContent,\n} from '@/types/dictionary.types';\n\nexport type GetDictionariesParams =\n FiltersAndPagination<DictionaryFiltersParams>;\nexport type GetDictionariesResult = PaginatedResponse<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaries = async (\n req: Request<GetDictionariesParams>,\n res: ResponseWithInformation<GetDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user, project, dictionaryRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getDictionaryFiltersAndPagination(req);\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionaries = await dictionaryService.findDictionaries(\n filters,\n skip,\n pageSize\n );\n const totalItems = await dictionaryService.countDictionaries(filters);\n\n const dictionariesAPI = dictionaries.map((el) =>\n mapDictionaryToAPI(el, project._id)\n );\n\n const responseData = formatPaginatedResponse<DictionaryAPI>({\n data: dictionariesAPI,\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 GetDictionariesKeysResult = ResponseData<string[]>;\n\n/**\n * Retrieves a list of dictionaries keys based on filters and pagination.\n */\nexport const getDictionariesKeys = async (\n _req: Request,\n res: ResponseWithInformation<GetDictionariesKeysResult>,\n _next: NextFunction\n) => {\n const { project, dictionaryRights } = res.locals;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionariesKeys = await dictionaryService.getDictionariesKeys(\n project._id\n );\n\n const responseData = formatResponse<string[]>({\n data: dictionariesKeys,\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 GetDictionaryParams = { dictionaryKey: string };\nexport type GetDictionaryQuery = { version?: string };\nexport type GetDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Retrieves a list of dictionaries based on filters and pagination.\n */\nexport const getDictionaryByKey = async (\n req: Request<GetDictionaryParams, any, any, GetDictionaryQuery>,\n res: ResponseWithInformation<GetDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const { dictionaryKey } = req.params;\n const version = req.query.version;\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n if (!dictionaryRights?.read) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_READ');\n return;\n }\n\n try {\n const dictionary = await dictionaryService.getDictionaryByKey(\n dictionaryKey,\n project._id\n );\n\n if (!dictionary.projectIds.map(String).includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const apiResult = mapDictionaryToAPI(dictionary, project._id, version);\n\n const responseData = formatResponse<DictionaryAPI>({\n data: apiResult,\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 AddDictionaryBody = { dictionary: DictionaryCreationData };\nexport type AddDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Adds a new dictionary to the database.\n */\nexport const addDictionary = async (\n req: Request<any, any, AddDictionaryBody>,\n res: ResponseWithInformation<AddDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionary;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n const dictionary: DictionaryData = {\n key: dictionaryData.key,\n title: dictionaryData.title,\n description: dictionaryData.description,\n content: new Map([\n ['v1', { content: dictionaryData.content ?? ({} as ContentNode) }],\n ]),\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryData.filePath ?? '',\n },\n projectIds: dictionaryData.projectIds ?? [String(project._id)],\n };\n\n try {\n const newDictionary = await dictionaryService.createDictionary(dictionary);\n\n const apiResult = mapDictionaryToAPI(newDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary created successfully',\n fr: 'Dictionnaire créé avec succès',\n es: 'Diccionario creado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been created successfully',\n fr: 'Votre dictionnaire a été créé avec succès',\n es: 'Su diccionario ha sido creado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: mapDictionaryToAPI(newDictionary, project._id),\n status: 'ADDED',\n },\n ]);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type PushDictionariesBody = {\n dictionaries: LocalDictionary[];\n};\ntype PushDictionariesResultData = {\n newDictionaries: string[];\n updatedDictionaries: string[];\n error: { dictionaryId: string; message: string }[];\n};\nexport type PushDictionariesResult = ResponseData<PushDictionariesResultData>;\n\n/**\n * Check each dictionaries, add the new ones and update the existing ones.\n * @param req - Express request object.\n * @param res - Express response object.\n * @returns Response containing the created dictionary.\n */\nexport const pushDictionaries = async (\n req: Request<any, any, PushDictionariesBody>,\n res: ResponseWithInformation<PushDictionariesResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, user, dictionaryRights } = res.locals;\n const dictionaryData = req.body.dictionaries;\n const dictionariesKeys = dictionaryData.map((dictionary) => dictionary.key);\n\n if (\n typeof dictionaryData === 'object' &&\n Array.isArray(dictionaryData) &&\n dictionaryData.length === 0\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARIES_NOT_PROVIDED');\n return;\n } else if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const { existingDictionariesKey, newDictionariesKey } =\n await dictionaryService.getExistingDictionaryKey(\n dictionariesKeys,\n project._id\n );\n\n const existingDictionaries = dictionaryData.filter((dictionary) =>\n existingDictionariesKey.includes(dictionary.key)\n );\n const newDictionaries = dictionaryData.filter((dictionary) =>\n newDictionariesKey.includes(dictionary.key)\n );\n\n const newDictionariesResult: DictionaryAPI[] = [];\n const updatedDictionariesResult: DictionaryAPI[] = [];\n const errorResult: PushDictionariesResultData['error'] = [];\n\n for (const dictionaryDataEl of newDictionaries) {\n const dictionary: DictionaryData = {\n title: dictionaryDataEl.title,\n description: dictionaryDataEl.description,\n projectIds: [String(project._id)],\n creatorId: user._id,\n content: new Map([\n ['v1', { content: dictionaryDataEl.content ?? ({} as ContentNode) }],\n ]),\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const newDictionary =\n await dictionaryService.createDictionary(dictionary);\n newDictionariesResult.push(\n mapDictionaryToAPI(newDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n\n if (existingDictionariesKey.length >= 0) {\n const existingDictionariesDB =\n await dictionaryService.getDictionariesByKeys(\n existingDictionariesKey,\n project._id\n );\n\n for (const dictionaryDataEl of existingDictionaries) {\n const existingDictionaryDB = existingDictionariesDB.find(\n (dictionaryDB) => dictionaryDB.key === dictionaryDataEl.key\n )!;\n\n const versionList = [...(existingDictionaryDB.content.keys() ?? [])];\n const lastVersion = versionList[versionList.length - 1];\n\n const lastContent =\n (existingDictionaryDB.content.get(lastVersion)\n ?.content as DictionaryAPI['content']) ?? null;\n\n const isSameContent =\n JSON.stringify(lastContent) ===\n JSON.stringify(dictionaryDataEl.content);\n\n let newContent: VersionedContent = existingDictionaryDB.content;\n\n if (!isSameContent) {\n const newContentVersion =\n dictionaryService.incrementVersion(existingDictionaryDB);\n\n newContent = {\n ...newContent,\n [newContentVersion]: {\n content: dictionaryDataEl.content,\n },\n };\n }\n\n const dictionary: DictionaryData = {\n ...ensureMongoDocumentToObject(existingDictionaryDB),\n ...dictionaryDataEl,\n content: newContent,\n projectIds: [String(project._id)],\n creatorId: user._id,\n filePath: {\n [String(project._id)]: dictionaryDataEl.filePath ?? '',\n },\n key: dictionaryDataEl.key,\n };\n\n try {\n const updatedDictionary =\n await dictionaryService.updateDictionaryByKey(\n dictionaryDataEl.key,\n dictionary,\n project._id\n );\n updatedDictionariesResult.push(\n mapDictionaryToAPI(updatedDictionary, project._id)\n );\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n }\n }\n\n const result: PushDictionariesResultData = {\n newDictionaries: newDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n updatedDictionaries: updatedDictionariesResult.map(\n (dictionary) => dictionary.key\n ),\n error: errorResult,\n };\n\n const responseData = formatResponse<PushDictionariesResultData>({\n message: t({\n en: 'Dictionaries updated successfully',\n fr: 'Dictionnaires mis à jour avec succès',\n es: 'Diccionarios actualizados con éxito',\n }),\n description: t({\n en: 'Your dictionaries have been updated successfully',\n fr: 'Vos dictionnaires ont été mis à jour avec succès',\n es: 'Sus diccionarios han sido actualizados con éxito',\n }),\n data: result,\n });\n\n eventListener.sendDictionaryUpdate([\n ...newDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'ADDED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\n ...updatedDictionariesResult.map(\n (dictionary) =>\n ({\n dictionary,\n status: 'UPDATED',\n }) as eventListener.SendDictionaryUpdateArg\n ),\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 UpdateDictionaryParam = { dictionaryId: string };\nexport type UpdateDictionaryBody = Partial<Dictionary>;\nexport type UpdateDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Updates an existing dictionary in the database.\n */\nexport const updateDictionary = async (\n req: Request<UpdateDictionaryParam, any, UpdateDictionaryBody>,\n res: ResponseWithInformation<UpdateDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { dictionaryId } = req.params;\n const { project, dictionaryRights } = res.locals;\n const dictionaryData = req.body;\n\n if (!dictionaryData) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_DATA_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryData.projectIds?.includes(String(project._id))) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_PROJECT_MISMATCH');\n return;\n }\n\n if (typeof dictionaryId === 'undefined') {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!dictionaryRights?.write) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_WRITE');\n return;\n }\n\n try {\n const updatedDictionary = await dictionaryService.updateDictionaryById(\n dictionaryId,\n dictionaryData\n );\n\n const apiResult = mapDictionaryToAPI(updatedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary updated successfully',\n fr: 'Dictionnaire mis à jour avec succès',\n es: 'Diccionario actualizado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been updated successfully',\n fr: 'Votre dictionnaire a été mis à jour avec succès',\n es: 'Su diccionario ha sido actualizado con éxito',\n }),\n data: apiResult,\n });\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'UPDATED',\n },\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 DeleteDictionaryParam = { dictionaryId: string };\nexport type DeleteDictionaryResult = ResponseData<DictionaryAPI>;\n\n/**\n * Deletes a dictionary from the database by its ID.\n */\nexport const deleteDictionary = async (\n req: Request<DeleteDictionaryParam>,\n res: ResponseWithInformation<DeleteDictionaryResult>,\n _next: NextFunction\n): Promise<void> => {\n const { project, dictionaryRights } = res.locals;\n const { dictionaryId } = req.params as Partial<DeleteDictionaryParam>;\n\n if (!dictionaryId) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_ID_NOT_FOUND');\n return;\n }\n\n if (!project) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECT_NOT_DEFINED');\n return;\n }\n\n if (!dictionaryRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_RIGHTS_NOT_ADMIN');\n return;\n }\n\n try {\n const dictionaryToDelete =\n await dictionaryService.getDictionaryById(dictionaryId);\n\n if (!dictionaryToDelete.projectIds.includes(project._id)) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'DICTIONARY_PROJECT_MISMATCH'\n );\n return;\n }\n\n const deletedDictionary =\n await dictionaryService.deleteDictionaryById(dictionaryId);\n\n if (!deletedDictionary) {\n ErrorHandler.handleGenericErrorResponse(res, 'DICTIONARY_NOT_FOUND', {\n dictionaryId,\n });\n return;\n }\n\n logger.info(`Dictionary deleted: ${String(deletedDictionary._id)}`);\n\n const apiResult = mapDictionaryToAPI(deletedDictionary, project._id);\n\n const responseData = formatResponse<DictionaryAPI>({\n message: t({\n en: 'Dictionary deleted successfully',\n fr: 'Dictionnaire supprimé avec succès',\n es: 'Diccionario eliminado con éxito',\n }),\n description: t({\n en: 'Your dictionary has been deleted successfully',\n fr: 'Votre dictionnaire a été supprimé avec succès',\n es: 'Su diccionario ha sido eliminado con éxito',\n }),\n data: apiResult,\n });\n\n res.json(responseData);\n\n eventListener.sendDictionaryUpdate([\n {\n dictionary: apiResult,\n status: 'DELETED',\n },\n ]);\n\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { logger } from "./../logger/index.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { getSessionAuthRoutes } from "./../routes/sessionAuth.routes.mjs";
|
|
3
3
|
import { sendEmail } from "./../services/email.service.mjs";
|
|
4
|
+
import * as projectService from "./../services/project.service.mjs";
|
|
4
5
|
import * as sessionAuthService from "./../services/sessionAuth.service.mjs";
|
|
5
6
|
import * as userService from "./../services/user.service.mjs";
|
|
6
7
|
import { ErrorHandler } from "./../utils/errors/index.mjs";
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
formatResponse
|
|
14
15
|
} from "./../utils/responseData.mjs";
|
|
15
16
|
import { t } from "express-intlayer";
|
|
17
|
+
import { Stripe } from "stripe";
|
|
16
18
|
import * as organizationService from "./../services/organization.service.mjs";
|
|
17
19
|
const getOrganizations = async (req, res, _next) => {
|
|
18
20
|
const { user, organizationRights } = res.locals;
|
|
@@ -219,7 +221,7 @@ const addOrganizationMember = async (req, res, _next) => {
|
|
|
219
221
|
invitedByUsername: user.name,
|
|
220
222
|
invitedByEmail: user.email,
|
|
221
223
|
organizationName: organization.name,
|
|
222
|
-
inviteLink:
|
|
224
|
+
inviteLink: getSessionAuthRoutes().loginEmailPassword.url,
|
|
223
225
|
inviteFromIp: req.ip ?? "",
|
|
224
226
|
inviteFromLocation: req.hostname
|
|
225
227
|
});
|
|
@@ -330,6 +332,7 @@ const updateOrganizationMembers = async (req, res, _next) => {
|
|
|
330
332
|
}
|
|
331
333
|
};
|
|
332
334
|
const deleteOrganization = async (_req, res, _next) => {
|
|
335
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
333
336
|
const { isOrganizationAdmin, organization, organizationRights } = res.locals;
|
|
334
337
|
if (!organization) {
|
|
335
338
|
ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
|
|
@@ -349,7 +352,19 @@ const deleteOrganization = async (_req, res, _next) => {
|
|
|
349
352
|
);
|
|
350
353
|
return;
|
|
351
354
|
}
|
|
355
|
+
const projects = await projectService.findProjects({
|
|
356
|
+
organizationId: organization._id
|
|
357
|
+
});
|
|
358
|
+
if (projects.length > 0) {
|
|
359
|
+
ErrorHandler.handleGenericErrorResponse(res, "PROJECTS_EXIST", {
|
|
360
|
+
organizationId: organization._id
|
|
361
|
+
});
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
352
364
|
try {
|
|
365
|
+
if (organization.plan?.subscriptionId) {
|
|
366
|
+
await stripe.subscriptions.cancel(organization.plan.subscriptionId);
|
|
367
|
+
}
|
|
353
368
|
const deletedOrganization = await organizationService.deleteOrganizationById(organization._id);
|
|
354
369
|
if (!deletedOrganization) {
|
|
355
370
|
ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_FOUND", {
|
|
@@ -371,6 +386,7 @@ const deleteOrganization = async (_req, res, _next) => {
|
|
|
371
386
|
}),
|
|
372
387
|
data: deletedOrganization
|
|
373
388
|
});
|
|
389
|
+
sessionAuthService.clearOrganizationAuth(res);
|
|
374
390
|
res.json(responseData);
|
|
375
391
|
return;
|
|
376
392
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { sessionAuthRoutes } from '@routes/sessionAuth.routes';\nimport { sendEmail } from '@services/email.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n type OrganizationFilters,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport { getPLanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { ObjectId } from 'mongoose';\nimport type { User } from 'oauth2-server';\nimport * as organizationService from '@/services/organization.service';\nimport type {\n Organization,\n OrganizationCreationData,\n} from '@/types/organization.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<Organization>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithInformation<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user, organizationRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n const restrictedFilter: OrganizationFilters = {\n ...filters,\n\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n };\n\n try {\n const organizations = await organizationService.findOrganizations(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<Organization>({\n data: organizations,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<Organization>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithInformation<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationRights } = res.locals;\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n const responseData = formatResponse<Organization>({ data: organization });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<Organization>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithInformation<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user._id\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization created successfully',\n fr: 'Organisation créée avec succès',\n es: 'Organización creada con éxito',\n }),\n description: t({\n en: 'Your organization has been created successfully',\n fr: 'Votre organisation a été créée avec succès',\n es: 'Su organización ha sido creada con éxito',\n }),\n data: newOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<Organization>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithInformation<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization._id,\n organizationFields\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\n\nexport type OrganizationMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<Organization>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithInformation<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, isOrganizationAdmin, user, organizationRights } =\n res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n if (!organization.plan) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n const planType = getPLanDetails(organization.plan);\n\n if (\n planType.numberOfOrganizationUsers &&\n organization.membersIds.length >= planType.numberOfOrganizationUsers\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_USER_LIMIT_REACHED', {\n organizationId: organization._id,\n });\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: sessionAuthRoutes.loginEmailPassword.url,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember._id],\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: OrganizationMemberByIdOption[];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<Organization>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithInformation<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, organizationRights, isOrganizationAdmin } = res.locals;\n const { membersIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n let existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds?.map((member) => member.userId);\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => {\n const isAdmin =\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false;\n\n return {\n user,\n isAdmin,\n };\n });\n\n existingUsers = userMap;\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteOrganizationResult = ResponseData<Organization>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithInformation,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n try {\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization._id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization._id)}`);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization deleted successfully',\n fr: 'Organisation supprimée avec succès',\n es: 'Organización eliminada con éxito',\n }),\n description: t({\n en: 'Your organization has been deleted successfully',\n fr: 'Votre organisation a été supprimée avec succès',\n es: 'Su organización ha sido eliminada con éxito',\n }),\n data: deletedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = { organizationId: ObjectId | string };\nexport type SelectOrganizationResult = ResponseData<Organization>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithInformation<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n sessionAuthService.setOrganizationAuth(res, organization);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization retrieved successfully',\n fr: 'Organisation récupérée avec succès',\n es: 'Organización recuperada con éxito',\n }),\n description: t({\n en: 'Your organization has been retrieved successfully',\n fr: 'Votre organisation a été récupérée avec succès',\n es: 'Su organización ha sido recuperada con éxito',\n }),\n data: organization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = (\n _req: Request,\n res: ResponseWithInformation<UnselectOrganizationResult>,\n _next: NextFunction\n): void => {\n try {\n sessionAuthService.clearOrganizationAuth(res);\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Organization unselected successfully',\n fr: 'Organisation désélectionnée avec succès',\n es: 'Organización deseleccionada con éxito',\n }),\n description: t({\n en: 'Your organization has been unselected successfully',\n fr: 'Votre organisation a été désélectionnée avec succès',\n es: 'Su organización ha sido deseleccionada con éxito',\n }),\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/controllers/organization.controller.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport { getSessionAuthRoutes } from '@routes/sessionAuth.routes';\nimport { sendEmail } from '@services/email.service';\nimport * as projectService from '@services/project.service';\nimport * as sessionAuthService from '@services/sessionAuth.service';\nimport * as userService from '@services/user.service';\nimport { type AppError, ErrorHandler } from '@utils/errors';\nimport type { FiltersAndPagination } from '@utils/filtersAndPagination/getFiltersAndPaginationFromBody';\nimport {\n getOrganizationFiltersAndPagination,\n type OrganizationFiltersParams,\n type OrganizationFilters,\n} from '@utils/filtersAndPagination/getOrganizationFiltersAndPagination';\nimport { getPLanDetails } from '@utils/plan';\nimport {\n formatPaginatedResponse,\n formatResponse,\n type PaginatedResponse,\n type ResponseData,\n} from '@utils/responseData';\nimport type { NextFunction, Request } from 'express';\nimport { t } from 'express-intlayer';\nimport type { ObjectId } from 'mongoose';\nimport type { User } from 'oauth2-server';\nimport { Stripe } from 'stripe';\nimport * as organizationService from '@/services/organization.service';\nimport type {\n Organization,\n OrganizationCreationData,\n} from '@/types/organization.types';\n\nexport type GetOrganizationsParams =\n FiltersAndPagination<OrganizationFiltersParams>;\nexport type GetOrganizationsResult = PaginatedResponse<Organization>;\n\n/**\n * Retrieves a list of organizations based on filters and pagination.\n */\nexport const getOrganizations = async (\n req: Request<GetOrganizationsParams>,\n res: ResponseWithInformation<GetOrganizationsResult>,\n _next: NextFunction\n) => {\n const { user, organizationRights } = res.locals;\n const { filters, pageSize, skip, page, getNumberOfPages } =\n getOrganizationFiltersAndPagination(req);\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n const restrictedFilter: OrganizationFilters = {\n ...filters,\n\n membersIds: { $in: [...(filters.membersIds ?? []), String(user._id)] },\n };\n\n try {\n const organizations = await organizationService.findOrganizations(\n restrictedFilter,\n skip,\n pageSize\n );\n const totalItems = await organizationService.countOrganizations(filters);\n\n const responseData = formatPaginatedResponse<Organization>({\n data: organizations,\n page,\n pageSize,\n totalPages: getNumberOfPages(totalItems),\n totalItems,\n });\n\n res.status(200).json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type GetOrganizationParam = { organizationId: string };\nexport type GetOrganizationResult = ResponseData<Organization>;\n\n/**\n * Retrieves an organization by its ID.\n */\nexport const getOrganization = async (\n req: Request<GetOrganizationParam, any, any>,\n res: ResponseWithInformation<GetOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationRights } = res.locals;\n const { organizationId } = req.params as Partial<GetOrganizationParam>;\n\n if (!organizationRights?.read) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_READ'\n );\n return;\n }\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n const responseData = formatResponse<Organization>({ data: organization });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type AddOrganizationBody = OrganizationCreationData;\nexport type AddOrganizationResult = ResponseData<Organization>;\n\n/**\n * Adds a new organization to the database.\n */\nexport const addOrganization = async (\n req: Request<any, any, AddOrganizationBody>,\n res: ResponseWithInformation<AddOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { user } = res.locals;\n const organization = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n try {\n const newOrganization = await organizationService.createOrganization(\n organization,\n user._id\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization created successfully',\n fr: 'Organisation créée avec succès',\n es: 'Organización creada con éxito',\n }),\n description: t({\n en: 'Your organization has been created successfully',\n fr: 'Votre organisation a été créée avec succès',\n es: 'Su organización ha sido creada con éxito',\n }),\n data: newOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationBody = Partial<Organization>;\nexport type UpdateOrganizationResult = ResponseData<Organization>;\n\n/**\n * Updates an existing organization in the database.\n */\nexport const updateOrganization = async (\n req: Request<undefined, undefined, UpdateOrganizationBody>,\n res: ResponseWithInformation<UpdateOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n const organizationFields = req.body;\n\n if (!organizationFields) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_DATA_NOT_FOUND');\n return;\n }\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n try {\n const updatedOrganization =\n await organizationService.updateOrganizationById(\n organization._id,\n organizationFields\n );\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\ntype UserAndAdmin = { user: User; isAdmin: boolean };\n\nexport type OrganizationMemberByIdOption = {\n userId: string | ObjectId;\n isAdmin?: boolean;\n};\n\nexport type AddOrganizationMemberBody = {\n userEmail: string;\n};\nexport type AddOrganizationMemberResult = ResponseData<Organization>;\n\n/**\n * Add member to the organization in the database.\n */\nexport const addOrganizationMember = async (\n req: Request<any, any, AddOrganizationMemberBody>,\n res: ResponseWithInformation<AddOrganizationMemberResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, isOrganizationAdmin, user, organizationRights } =\n res.locals;\n const { userEmail } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!user) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n if (!organization.plan) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n const planType = getPLanDetails(organization.plan);\n\n if (\n planType.numberOfOrganizationUsers &&\n organization.membersIds.length >= planType.numberOfOrganizationUsers\n ) {\n ErrorHandler.handleGenericErrorResponse(res, 'PLAN_USER_LIMIT_REACHED', {\n organizationId: organization._id,\n });\n return;\n }\n\n try {\n let newMember = await userService.getUserByEmail(userEmail);\n\n if (!newMember) {\n // Create user if not found\n const newUser = await userService.createUser({ email: userEmail });\n if (!newUser) {\n ErrorHandler.handleGenericErrorResponse(res, 'USER_CREATION_FAILED', {\n email: userEmail,\n });\n return;\n }\n\n newMember = newUser;\n }\n\n await sendEmail({\n type: 'invite',\n to: userEmail,\n username: newMember.email.slice(0, newMember.email.indexOf('@')),\n invitedByUsername: user.name,\n invitedByEmail: user.email,\n organizationName: organization.name,\n inviteLink: getSessionAuthRoutes().loginEmailPassword.url,\n inviteFromIp: req.ip ?? '',\n inviteFromLocation: req.hostname,\n });\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: [...organization.membersIds, newMember._id],\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UpdateOrganizationMembersBody = Partial<{\n membersIds: OrganizationMemberByIdOption[];\n}>;\nexport type UpdateOrganizationMembersResult = ResponseData<Organization>;\n\n/**\n * Update members to the organization in the database.\n */\nexport const updateOrganizationMembers = async (\n req: Request<any, any, UpdateOrganizationMembersBody>,\n res: ResponseWithInformation<UpdateOrganizationMembersResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organization, organizationRights, isOrganizationAdmin } = res.locals;\n const { membersIds } = req.body;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.write) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_WRITE'\n );\n return;\n }\n\n if (membersIds?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_MEMBER'\n );\n return;\n }\n\n if (membersIds?.map((el) => el.isAdmin)?.length === 0) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_MUST_HAVE_ADMIN'\n );\n return;\n }\n\n try {\n let existingUsers: UserAndAdmin[] = [];\n\n if (membersIds) {\n const userIdList = membersIds?.map((member) => member.userId);\n const users = await userService.getUsersByIds(userIdList);\n\n if (users) {\n const userMap: UserAndAdmin[] = users.map((user) => {\n const isAdmin =\n membersIds.find(\n (member) => String(member.userId) === String(user._id)\n )?.isAdmin ?? false;\n\n return {\n user,\n isAdmin,\n };\n });\n\n existingUsers = userMap;\n }\n }\n\n const formattedMembers: ObjectId[] = existingUsers.map(\n (user) => user.user._id\n );\n const formattedAdmin: ObjectId[] = existingUsers\n .filter((el) => el.isAdmin)\n .map((user) => user.user._id);\n\n const updatedOrganization =\n await organizationService.updateOrganizationById(organization._id, {\n ...organization,\n membersIds: formattedMembers,\n adminsIds: formattedAdmin,\n });\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization updated successfully',\n fr: 'Organisation mise à jour avec succès',\n es: 'Organización actualizada con éxito',\n }),\n description: t({\n en: 'Your organization has been updated successfully',\n fr: 'Votre organisation a été mise à jour avec succès',\n es: 'Su organización ha sido actualizada con éxito',\n }),\n data: updatedOrganization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type DeleteOrganizationResult = ResponseData<Organization>;\n\n/**\n * Deletes an organization from the database by its ID.\n */\nexport const deleteOrganization = async (\n _req: Request,\n res: ResponseWithInformation,\n _next: NextFunction\n): Promise<void> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const { isOrganizationAdmin, organization, organizationRights } = res.locals;\n\n if (!organization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_DEFINED');\n return;\n }\n\n if (!isOrganizationAdmin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'USER_IS_NOT_ADMIN_OF_ORGANIZATION'\n );\n return;\n }\n\n if (!organizationRights?.admin) {\n ErrorHandler.handleGenericErrorResponse(\n res,\n 'ORGANIZATION_RIGHTS_NOT_ADMIN'\n );\n return;\n }\n\n const projects = await projectService.findProjects({\n organizationId: organization._id,\n });\n\n if (projects.length > 0) {\n ErrorHandler.handleGenericErrorResponse(res, 'PROJECTS_EXIST', {\n organizationId: organization._id,\n });\n return;\n }\n\n try {\n // Cancel the subscription on Stripe if it exists\n if (organization.plan?.subscriptionId) {\n await stripe.subscriptions.cancel(organization.plan.subscriptionId);\n }\n\n const deletedOrganization =\n await organizationService.deleteOrganizationById(organization._id);\n\n if (!deletedOrganization) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_NOT_FOUND', {\n organizationId: organization._id,\n });\n return;\n }\n\n logger.info(`Organization deleted: ${String(deletedOrganization._id)}`);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization deleted successfully',\n fr: 'Organisation supprimée avec succès',\n es: 'Organización eliminada con éxito',\n }),\n description: t({\n en: 'Your organization has been deleted successfully',\n fr: 'Votre organisation a été supprimée avec succès',\n es: 'Su organización ha sido eliminada con éxito',\n }),\n data: deletedOrganization,\n });\n\n sessionAuthService.clearOrganizationAuth(res);\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type SelectOrganizationParam = { organizationId: ObjectId | string };\nexport type SelectOrganizationResult = ResponseData<Organization>;\n\n/**\n * Select an organization.\n */\nexport const selectOrganization = async (\n req: Request<SelectOrganizationParam>,\n res: ResponseWithInformation<SelectOrganizationResult>,\n _next: NextFunction\n): Promise<void> => {\n const { organizationId } = req.params as Partial<SelectOrganizationParam>;\n\n if (!organizationId) {\n ErrorHandler.handleGenericErrorResponse(res, 'ORGANIZATION_ID_NOT_FOUND');\n return;\n }\n\n try {\n const organization =\n await organizationService.getOrganizationById(organizationId);\n\n sessionAuthService.setOrganizationAuth(res, organization);\n\n const responseData = formatResponse<Organization>({\n message: t({\n en: 'Organization retrieved successfully',\n fr: 'Organisation récupérée avec succès',\n es: 'Organización recuperada con éxito',\n }),\n description: t({\n en: 'Your organization has been retrieved successfully',\n fr: 'Votre organisation a été récupérée avec succès',\n es: 'Su organización ha sido recuperada con éxito',\n }),\n data: organization,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n\nexport type UnselectOrganizationResult = ResponseData<null>;\n\n/**\n * Unselect an organization.\n */\nexport const unselectOrganization = (\n _req: Request,\n res: ResponseWithInformation<UnselectOrganizationResult>,\n _next: NextFunction\n): void => {\n try {\n sessionAuthService.clearOrganizationAuth(res);\n sessionAuthService.clearProjectAuth(res);\n\n const responseData = formatResponse<null>({\n message: t({\n en: 'Organization unselected successfully',\n fr: 'Organisation désélectionnée avec succès',\n es: 'Organización deseleccionada con éxito',\n }),\n description: t({\n en: 'Your organization has been unselected successfully',\n fr: 'Votre organisation a été désélectionnée avec succès',\n es: 'Su organización ha sido deseleccionada con éxito',\n }),\n data: null,\n });\n\n res.json(responseData);\n return;\n } catch (error) {\n ErrorHandler.handleAppErrorResponse(res, error as AppError);\n return;\n }\n};\n"],"mappings":"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","names":[]}
|