@openinc/parse-server-opendash 3.27.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/features/config/helper/baseOptions.js +9 -0
  2. package/dist/features/config/helper/customOptions.js +1 -8
  3. package/dist/features/config/states/Config.js +0 -1
  4. package/dist/features/notifications/index.d.ts +3 -0
  5. package/dist/features/notifications/index.js +8 -1
  6. package/dist/features/notifications/services/initEmailTransport.d.ts +1 -0
  7. package/dist/features/notifications/services/initEmailTransport.js +45 -0
  8. package/dist/features/notifications/services/sendMails.d.ts +21 -0
  9. package/dist/features/notifications/services/sendMails.js +83 -0
  10. package/dist/features/notifications/states/EmailState.d.ts +39 -0
  11. package/dist/features/notifications/states/EmailState.js +58 -0
  12. package/dist/features/openservice/functions/assignUsersAndRoles.js +27 -8
  13. package/dist/features/openservice/ticket/getTicketLink.d.ts +2 -0
  14. package/dist/features/openservice/ticket/getTicketLink.js +20 -0
  15. package/dist/features/translations/index.d.ts +1 -0
  16. package/dist/features/translations/index.js +5 -0
  17. package/dist/features/translations/services/initTranslation.d.ts +5 -0
  18. package/dist/features/translations/services/initTranslation.js +45 -0
  19. package/dist/helper/getUserLanguage.d.ts +2 -0
  20. package/dist/helper/getUserLanguage.js +9 -0
  21. package/dist/hooks/Core_Email.d.ts +0 -10
  22. package/dist/hooks/Core_Email.js +3 -79
  23. package/dist/hooks/Notification.js +1 -0
  24. package/dist/i18n/de-DE/maintenance.json +16 -0
  25. package/dist/i18n/en-US/maintenance.json +16 -0
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +6 -17
  28. package/package.json +11 -8
@@ -47,4 +47,13 @@ exports.baseoptions = {
47
47
  default: "true",
48
48
  description: "Enable (or disable) anonymous users, defaults to true",
49
49
  },
50
+ PARSE_PUBLIC_SERVER_URL: {
51
+ env: "PARSE_PUBLIC_SERVER_URL",
52
+ type: "string",
53
+ required: true,
54
+ secret: false,
55
+ public: true,
56
+ default: "",
57
+ description: "The public URL of your Parse Server. This will be used in various places such as email links and push notification callbacks.",
58
+ },
50
59
  };
@@ -276,14 +276,7 @@ exports.customoptions = {
276
276
  public: true,
277
277
  default: "false",
278
278
  description: "Enable SMTP for sending e-mails.",
279
- dependencies: [
280
- "SMTP_HOST",
281
- "SMTP_PORT",
282
- "SMTP_USER",
283
- "SMTP_PASS",
284
- "SMTP_FROM",
285
- "SMTP_SECURE",
286
- ],
279
+ dependencies: ["SMTP_HOST", "SMTP_PORT", "SMTP_FROM", "SMTP_SECURE"],
287
280
  },
288
281
  SMTP_HOST: {
289
282
  env: "OPENINC_PARSE_SMTP_HOST",
@@ -105,7 +105,6 @@ class ConfigState {
105
105
  const t = this.configs[key]?.type;
106
106
  if (!types.includes(t)) {
107
107
  console.error(new Error(`Invalid getter for config key '${key}' is of type ${t} but was called as ${types.join("|")}.`));
108
- process.exit(1);
109
108
  }
110
109
  }
111
110
  log() {
@@ -2,3 +2,6 @@ export { FunctionKeys, NotificationInterface, NotificationMap, } from "./types/N
2
2
  export { Notifications } from "./types/Notifications";
3
3
  export { RegisteredNotification } from "./states/NotificationClass";
4
4
  export { getAllNotifications, default as initNotifications, } from "./services/registerNotification";
5
+ export { EmailState } from "./states/EmailState";
6
+ export { sendSimpleEmail, sendTemplateEmail } from "./services/sendMails";
7
+ export { initEmailTransport } from "./services/initEmailTransport";
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.initNotifications = exports.getAllNotifications = exports.RegisteredNotification = exports.Notifications = void 0;
6
+ exports.initEmailTransport = exports.sendTemplateEmail = exports.sendSimpleEmail = exports.EmailState = exports.initNotifications = exports.getAllNotifications = exports.RegisteredNotification = exports.Notifications = void 0;
7
7
  var Notifications_1 = require("./types/Notifications");
8
8
  Object.defineProperty(exports, "Notifications", { enumerable: true, get: function () { return Notifications_1.Notifications; } });
9
9
  var NotificationClass_1 = require("./states/NotificationClass");
@@ -11,3 +11,10 @@ Object.defineProperty(exports, "RegisteredNotification", { enumerable: true, get
11
11
  var registerNotification_1 = require("./services/registerNotification");
12
12
  Object.defineProperty(exports, "getAllNotifications", { enumerable: true, get: function () { return registerNotification_1.getAllNotifications; } });
13
13
  Object.defineProperty(exports, "initNotifications", { enumerable: true, get: function () { return __importDefault(registerNotification_1).default; } });
14
+ var EmailState_1 = require("./states/EmailState");
15
+ Object.defineProperty(exports, "EmailState", { enumerable: true, get: function () { return EmailState_1.EmailState; } });
16
+ var sendMails_1 = require("./services/sendMails");
17
+ Object.defineProperty(exports, "sendSimpleEmail", { enumerable: true, get: function () { return sendMails_1.sendSimpleEmail; } });
18
+ Object.defineProperty(exports, "sendTemplateEmail", { enumerable: true, get: function () { return sendMails_1.sendTemplateEmail; } });
19
+ var initEmailTransport_1 = require("./services/initEmailTransport");
20
+ Object.defineProperty(exports, "initEmailTransport", { enumerable: true, get: function () { return initEmailTransport_1.initEmailTransport; } });
@@ -0,0 +1 @@
1
+ export declare function initEmailTransport(): Promise<void>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initEmailTransport = initEmailTransport;
7
+ const nodemailer_1 = __importDefault(require("nodemailer"));
8
+ const nunjucks_1 = __importDefault(require("nunjucks"));
9
+ const path_1 = require("path");
10
+ const __1 = require("..");
11
+ const config_1 = require("../../config");
12
+ async function initEmailTransport() {
13
+ const emailState = __1.EmailState.getInstance();
14
+ try {
15
+ if (config_1.ConfigInstance.getInstance().getBoolean("SMTP_ENABLED")) {
16
+ const transportOptions = {
17
+ host: config_1.ConfigInstance.getInstance().get("SMTP_HOST"),
18
+ port: config_1.ConfigInstance.getInstance().getNumber("SMTP_PORT"),
19
+ secure: config_1.ConfigInstance.getInstance().getBoolean("SMTP_SECURE"),
20
+ ignoreTLS: config_1.ConfigInstance.getInstance().getBoolean("SMTP_IGNORE_TLS"),
21
+ };
22
+ if (config_1.ConfigInstance.getInstance().get("SMTP_USER") &&
23
+ config_1.ConfigInstance.getInstance().get("SMTP_PASS")) {
24
+ transportOptions.auth = {
25
+ user: config_1.ConfigInstance.getInstance().get("SMTP_USER"),
26
+ pass: config_1.ConfigInstance.getInstance().get("SMTP_PASS"),
27
+ };
28
+ }
29
+ const transport = nodemailer_1.default.createTransport(transportOptions);
30
+ await transport.verify();
31
+ emailState.setTransport(transport);
32
+ const templateDir = (0, path_1.resolve)(process.cwd(), config_1.ConfigInstance.getInstance().get("EMAIL_TEMPLATE_DIR"));
33
+ emailState.setEmailTemplateDir(templateDir);
34
+ nunjucks_1.default.configure(templateDir, { autoescape: true });
35
+ console.log("[@openinc/parse-server-opendash] Email transport initialized successfully");
36
+ }
37
+ else {
38
+ console.log("[@openinc/parse-server-opendash] SMTP disabled, skipping email transport initialization");
39
+ }
40
+ }
41
+ catch (error) {
42
+ console.error(`Parse SMTP Adapter: Error when trying to establish the SMTP connection:`);
43
+ console.error(error);
44
+ }
45
+ }
@@ -0,0 +1,21 @@
1
+ import { Core_Email } from "../../../types";
2
+ /**
3
+ * Send a simple email
4
+ * @param to The recipient email address
5
+ * @param subject The subject of the email
6
+ * @param text The plain text content of the email
7
+ * @returns The saved email object
8
+ */
9
+ export declare function sendSimpleEmail(to: string, subject: string, text: string): Promise<Core_Email>;
10
+ /**
11
+ * Send a template email
12
+ * @param param0
13
+ * @returns
14
+ */
15
+ export declare function sendTemplateEmail({ to, subject, fallback, template, data, }: {
16
+ to: string;
17
+ subject: string;
18
+ fallback: string;
19
+ template: string;
20
+ data: any;
21
+ }): Promise<Core_Email>;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.sendSimpleEmail = sendSimpleEmail;
7
+ exports.sendTemplateEmail = sendTemplateEmail;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const nunjucks_1 = __importDefault(require("nunjucks"));
10
+ const path_1 = require("path");
11
+ const types_1 = require("../../../types");
12
+ const EmailState_1 = require("../states/EmailState");
13
+ /**
14
+ * Send a simple email
15
+ * @param to The recipient email address
16
+ * @param subject The subject of the email
17
+ * @param text The plain text content of the email
18
+ * @returns The saved email object
19
+ */
20
+ async function sendSimpleEmail(to, subject, text) {
21
+ const email = new types_1.Core_Email({
22
+ payload: {
23
+ to,
24
+ subject,
25
+ text,
26
+ },
27
+ });
28
+ await email.save(null, { useMasterKey: true });
29
+ return email;
30
+ }
31
+ /**
32
+ * Send a template email
33
+ * @param param0
34
+ * @returns
35
+ */
36
+ async function sendTemplateEmail({ to, subject, fallback, template, data, }) {
37
+ const email = new types_1.Core_Email({
38
+ payload: {
39
+ to,
40
+ subject: renderEmailTemplate("subject", template, data, subject),
41
+ text: renderEmailTemplate("txt", template, data, fallback),
42
+ html: renderEmailTemplate("html", template, data, undefined),
43
+ },
44
+ });
45
+ await email.save(null, { useMasterKey: true });
46
+ return email;
47
+ }
48
+ /**
49
+ * Validate if an email template exists in the specified directory
50
+ * @param templateDir The directory where email templates are stored
51
+ * @param template The specific template file to validate
52
+ * @returns Whether the template exists in the directory
53
+ */
54
+ function validateEmailTemplate(templateDir, template) {
55
+ const templatePath = (0, path_1.join)(templateDir, template);
56
+ if (!fs_1.default.existsSync(templateDir)) {
57
+ return false;
58
+ }
59
+ if (!fs_1.default.existsSync(templatePath)) {
60
+ return false;
61
+ }
62
+ return true;
63
+ }
64
+ /**
65
+ * Render an email template
66
+ * @param type The type of the email template (txt, html, subject)
67
+ * @param template The base name of the template file
68
+ * @param data The data to be used for rendering the template
69
+ * @param fallback The fallback content if the template is not found
70
+ * @returns The rendered email content
71
+ */
72
+ function renderEmailTemplate(type, template, data, fallback) {
73
+ const emailState = EmailState_1.EmailState.getInstance();
74
+ const emailTemplateDir = emailState.getEmailTemplateDir();
75
+ const fullTemplate = template + "." + type;
76
+ if (validateEmailTemplate(emailTemplateDir, fullTemplate)) {
77
+ return nunjucks_1.default.render(fullTemplate, data);
78
+ }
79
+ if (type === "html") {
80
+ return renderEmailTemplate("txt", template, data, fallback);
81
+ }
82
+ return fallback || "";
83
+ }
@@ -0,0 +1,39 @@
1
+ import { Transporter } from "nodemailer";
2
+ import SMTPTransport from "nodemailer/lib/smtp-transport";
3
+ /**
4
+ * Singleton class to manage email transport and template directory
5
+ */
6
+ export declare class EmailState {
7
+ private static instance;
8
+ emailTemplateDir: string;
9
+ transport: Transporter<SMTPTransport.SentMessageInfo> | undefined;
10
+ private constructor();
11
+ /**
12
+ * Get the singleton instance
13
+ */
14
+ static getInstance(): EmailState;
15
+ /**
16
+ * Set the email transport
17
+ */
18
+ setTransport(transport: Transporter<SMTPTransport.SentMessageInfo>): void;
19
+ /**
20
+ * Get the email transport
21
+ */
22
+ getTransport(): Transporter<SMTPTransport.SentMessageInfo> | undefined;
23
+ /**
24
+ * Set the email template directory
25
+ */
26
+ setEmailTemplateDir(dir: string): void;
27
+ /**
28
+ * Get the email template directory
29
+ */
30
+ getEmailTemplateDir(): string;
31
+ /**
32
+ * Check if email transport is configured and ready
33
+ */
34
+ isConfigured(): boolean;
35
+ /**
36
+ * Reset the singleton (useful for testing)
37
+ */
38
+ static reset(): void;
39
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EmailState = void 0;
4
+ /**
5
+ * Singleton class to manage email transport and template directory
6
+ */
7
+ class EmailState {
8
+ constructor() {
9
+ this.emailTemplateDir = "";
10
+ this.transport = undefined;
11
+ }
12
+ /**
13
+ * Get the singleton instance
14
+ */
15
+ static getInstance() {
16
+ if (!EmailState.instance) {
17
+ EmailState.instance = new EmailState();
18
+ }
19
+ return EmailState.instance;
20
+ }
21
+ /**
22
+ * Set the email transport
23
+ */
24
+ setTransport(transport) {
25
+ this.transport = transport;
26
+ }
27
+ /**
28
+ * Get the email transport
29
+ */
30
+ getTransport() {
31
+ return this.transport;
32
+ }
33
+ /**
34
+ * Set the email template directory
35
+ */
36
+ setEmailTemplateDir(dir) {
37
+ this.emailTemplateDir = dir;
38
+ }
39
+ /**
40
+ * Get the email template directory
41
+ */
42
+ getEmailTemplateDir() {
43
+ return this.emailTemplateDir;
44
+ }
45
+ /**
46
+ * Check if email transport is configured and ready
47
+ */
48
+ isConfigured() {
49
+ return this.transport !== undefined;
50
+ }
51
+ /**
52
+ * Reset the singleton (useful for testing)
53
+ */
54
+ static reset() {
55
+ EmailState.instance = undefined;
56
+ }
57
+ }
58
+ exports.EmailState = EmailState;
@@ -1,10 +1,16 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.assignUsersAndRoles = assignUsersAndRoles;
7
+ const i18next_1 = __importDefault(require("i18next"));
4
8
  const parse_1 = require("parse");
5
9
  const openinc_openservice_save_ticket_data_1 = require("../../../functions/openinc-openservice-save-ticket-data");
6
10
  const openinc_openservice_ticket_data_1 = require("../../../functions/openinc-openservice-ticket-data");
11
+ const getUserLanguage_1 = require("../../../helper/getUserLanguage");
7
12
  const types_1 = require("../../../types");
13
+ const getTicketLink_1 = require("../ticket/getTicketLink");
8
14
  async function assignUsersAndRoles(ticket, assignedTo, fetchOptions, assigningUser) {
9
15
  const assignedUsers = (await ticket
10
16
  .relation("assignedusers")
@@ -41,7 +47,9 @@ async function assignUsersAndRoles(ticket, assignedTo, fetchOptions, assigningUs
41
47
  }));
42
48
  }
43
49
  const userNotifiedIds = [];
44
- for (const assignedTo of newUsers) {
50
+ for await (const assignedTo of newUsers) {
51
+ const resipientlanguage = await (0, getUserLanguage_1.getUserLanguage)(assignedTo);
52
+ await i18next_1.default.changeLanguage(resipientlanguage);
45
53
  assignments.push(new types_1.Maintenance_Ticket_Assignment({
46
54
  ticket,
47
55
  assignedUser: assignedTo,
@@ -61,10 +69,14 @@ async function assignUsersAndRoles(ticket, assignedTo, fetchOptions, assigningUs
61
69
  },
62
70
  },
63
71
  isSent: false,
64
- title: "maintenance:ticket.assignuser.notification.title",
72
+ title: i18next_1.default.t("maintenance:ticket.assignuser.notification.title"),
65
73
  user: assignedTo,
66
- description: "maintenance:ticket.assignuser.notification.description",
67
- }).save(null, fetchOptions);
74
+ description: i18next_1.default.t("maintenance:ticket.assignuser.notification.description", {
75
+ username: (0, openinc_openservice_save_ticket_data_1.getUsername)(assigningUser) ?? "System",
76
+ ticketName: ticket.get("title"),
77
+ ticketLink: (0, getTicketLink_1.getTicketLink)(ticket),
78
+ }),
79
+ }).save(null, { useMasterKey: true });
68
80
  userNotifiedIds.push(assignedTo.id);
69
81
  }
70
82
  for (const assignedTo of newRoles) {
@@ -79,10 +91,12 @@ async function assignUsersAndRoles(ticket, assignedTo, fetchOptions, assigningUs
79
91
  .relation("users")
80
92
  .query()
81
93
  .find(fetchOptions);
82
- for (const roleUser of roleUsers) {
94
+ for await (const roleUser of roleUsers) {
83
95
  if (userNotifiedIds.includes(roleUser.id) ||
84
96
  roleUser.id === assigningUser?.id)
85
97
  continue;
98
+ const resipientlanguage = await (0, getUserLanguage_1.getUserLanguage)(roleUser);
99
+ await i18next_1.default.changeLanguage(resipientlanguage);
86
100
  await new types_1.Notification({
87
101
  data: {
88
102
  ticketId: ticket.id,
@@ -94,10 +108,15 @@ async function assignUsersAndRoles(ticket, assignedTo, fetchOptions, assigningUs
94
108
  },
95
109
  },
96
110
  isSent: false,
97
- title: "maintenance:ticket.assignrole.notification.title",
111
+ title: i18next_1.default.t("maintenance:ticket.assignrole.notification.title"),
98
112
  user: roleUser,
99
- description: "maintenance:ticket.assignrole.notification.description",
100
- }).save(null, fetchOptions);
113
+ description: i18next_1.default.t("maintenance:ticket.assignrole.notification.description", {
114
+ username: (0, openinc_openservice_save_ticket_data_1.getUsername)(assigningUser) ?? "System",
115
+ ticketName: ticket.get("title"),
116
+ role: assignedTo.get("label"),
117
+ ticketLink: (0, getTicketLink_1.getTicketLink)(ticket),
118
+ }),
119
+ }).save(null, { useMasterKey: true });
101
120
  }
102
121
  }
103
122
  await types_1.Maintenance_Ticket_Assignment.saveAll(assignments, fetchOptions);
@@ -0,0 +1,2 @@
1
+ import { Maintenance_Ticket } from "../../../types";
2
+ export declare function getTicketLink(ticket: Maintenance_Ticket): string;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTicketLink = getTicketLink;
4
+ const config_1 = require("../../config");
5
+ function getTicketLink(ticket) {
6
+ //Get hostname from environment variable or default to localhost
7
+ let hostname = "localhost";
8
+ try {
9
+ const publicurl = config_1.ConfigInstance.getInstance()
10
+ .get("PARSE_PUBLIC_SERVER_URL")
11
+ .replace("/parse", "");
12
+ if (publicurl) {
13
+ hostname = publicurl;
14
+ }
15
+ }
16
+ catch (error) {
17
+ console.warn("[@openinc/parse-server-opendash] Could not get PARSE_PUBLIC_SERVER_URL from config, defaulting to localhost");
18
+ }
19
+ return `${hostname}/openservice/ticket/${ticket.id}`;
20
+ }
@@ -0,0 +1 @@
1
+ export { initTranslations } from "./services/initTranslation.js";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initTranslations = void 0;
4
+ var initTranslation_js_1 = require("./services/initTranslation.js");
5
+ Object.defineProperty(exports, "initTranslations", { enumerable: true, get: function () { return initTranslation_js_1.initTranslations; } });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @file Init Translations
3
+ * @description Initializes the translation service for the application.
4
+ */
5
+ export declare function initTranslations(): Promise<void>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initTranslations = initTranslations;
7
+ const i18next_1 = __importDefault(require("i18next"));
8
+ const i18next_fs_backend_1 = __importDefault(require("i18next-fs-backend"));
9
+ const path_1 = __importDefault(require("path"));
10
+ /**
11
+ * @file Init Translations
12
+ * @description Initializes the translation service for the application.
13
+ */
14
+ async function initTranslations() {
15
+ try {
16
+ console.log("[@openinc/parse-server-opendash] Init translations");
17
+ const i18npath = path_1.default.join(__dirname, "../../../i18n");
18
+ const loadPath = path_1.default.join(i18npath, "{{lng}}/{{ns}}.json");
19
+ const addPath = path_1.default.join(i18npath, "{{lng}}/{{ns}}.missing.json");
20
+ // Initialize i18next with backend configuration
21
+ await i18next_1.default.use(i18next_fs_backend_1.default).init({
22
+ // Backend configuration
23
+ backend: {
24
+ loadPath: loadPath,
25
+ addPath: addPath,
26
+ },
27
+ // Use the correct language codes that match your directory names
28
+ lng: "de-DE",
29
+ fallbackLng: "en-US",
30
+ // Specify available languages to match your directories
31
+ supportedLngs: ["de-DE", "en-US"],
32
+ ns: ["maintenance"],
33
+ defaultNS: "server",
34
+ debug: false,
35
+ // Ensure resources are loaded
36
+ initImmediate: false,
37
+ });
38
+ console.log("[@openinc/parse-server-opendash] Current language:", i18next_1.default.language);
39
+ }
40
+ catch (error) {
41
+ console.error("[@openinc/parse-server-opendash] Error while initializing translations");
42
+ console.error(error);
43
+ process.exit(1);
44
+ }
45
+ }
@@ -0,0 +1,2 @@
1
+ import { _User } from "../types";
2
+ export declare function getUserLanguage(recipient: _User): Promise<string>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getUserLanguage = getUserLanguage;
4
+ async function getUserLanguage(recipient) {
5
+ const language = recipient.get("settings")
6
+ ? recipient.get("settings").get("preferred_language")
7
+ : "de-DE";
8
+ return language;
9
+ }
@@ -1,11 +1 @@
1
- import { Core_Email } from "../types";
2
- export declare function initEmailTransport(): Promise<void>;
3
- export declare function sendSimpleEmail(to: string, subject: string, text: string): Promise<Core_Email>;
4
- export declare function sendTemplateEmail({ to, subject, fallback, template, data, }: {
5
- to: string;
6
- subject: string;
7
- fallback: string;
8
- template: string;
9
- data: any;
10
- }): Promise<Core_Email>;
11
1
  export declare function init(): Promise<void>;
@@ -1,92 +1,16 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.initEmailTransport = initEmailTransport;
7
- exports.sendSimpleEmail = sendSimpleEmail;
8
- exports.sendTemplateEmail = sendTemplateEmail;
9
3
  exports.init = init;
10
- const fs_1 = __importDefault(require("fs"));
11
- const nodemailer_1 = __importDefault(require("nodemailer"));
12
- const nunjucks_1 = __importDefault(require("nunjucks"));
13
- const path_1 = require("path");
14
4
  const __1 = require("..");
15
5
  const config_1 = require("../features/config");
6
+ const notifications_1 = require("../features/notifications");
16
7
  const types_1 = require("../types");
17
- let emailTemplateDir = "";
18
- let transport = undefined;
19
- async function initEmailTransport() {
20
- try {
21
- if (config_1.ConfigInstance.getInstance().getBoolean("SMTP_ENABLED")) {
22
- transport = nodemailer_1.default.createTransport({
23
- host: config_1.ConfigInstance.getInstance().get("SMTP_HOST"),
24
- port: config_1.ConfigInstance.getInstance().getNumber("SMTP_PORT"),
25
- secure: config_1.ConfigInstance.getInstance().getBoolean("SMTP_SECURE"),
26
- ignoreTLS: config_1.ConfigInstance.getInstance().getBoolean("SMTP_IGNORE_TLS"),
27
- auth: {
28
- user: config_1.ConfigInstance.getInstance().get("SMTP_USER"),
29
- pass: config_1.ConfigInstance.getInstance().get("SMTP_PASS"),
30
- },
31
- });
32
- await transport.verify();
33
- emailTemplateDir = (0, path_1.resolve)(process.cwd(), config_1.ConfigInstance.getInstance().get("EMAIL_TEMPLATE_DIR"));
34
- nunjucks_1.default.configure(emailTemplateDir, { autoescape: true });
35
- }
36
- }
37
- catch (error) {
38
- console.error(`Parse SMTP Adapter: Error when trying to establish the SMTP connection:`);
39
- console.error(error);
40
- process.exit(1);
41
- }
42
- }
43
- async function sendSimpleEmail(to, subject, text) {
44
- const email = new types_1.Core_Email({
45
- payload: {
46
- to,
47
- subject,
48
- text,
49
- },
50
- });
51
- await email.save(null, { useMasterKey: true });
52
- return email;
53
- }
54
- async function sendTemplateEmail({ to, subject, fallback, template, data, }) {
55
- const email = new types_1.Core_Email({
56
- payload: {
57
- to,
58
- subject: renderEmailTemplate("subject", template, data, subject),
59
- text: renderEmailTemplate("txt", template, data, fallback),
60
- html: renderEmailTemplate("html", template, data, undefined),
61
- },
62
- });
63
- await email.save(null, { useMasterKey: true });
64
- return email;
65
- }
66
- function validateEmailTemplate(templateDir, template) {
67
- const templatePath = (0, path_1.join)(templateDir, template);
68
- if (!fs_1.default.existsSync(templateDir)) {
69
- return false;
70
- }
71
- if (!fs_1.default.existsSync(templatePath)) {
72
- return false;
73
- }
74
- return true;
75
- }
76
- function renderEmailTemplate(type, template, data, fallback) {
77
- const fullTemplate = template + "." + type;
78
- if (validateEmailTemplate(emailTemplateDir, fullTemplate)) {
79
- return nunjucks_1.default.render(fullTemplate, data);
80
- }
81
- if (type === "html") {
82
- return renderEmailTemplate("txt", template, data, fallback);
83
- }
84
- return fallback || "";
85
- }
86
8
  async function init() {
87
9
  (0, __1.beforeSaveHook)(types_1.Core_Email, async (request) => {
88
10
  const { object } = request;
89
11
  object.setACL(new Parse.ACL());
12
+ const emailState = notifications_1.EmailState.getInstance();
13
+ const transport = emailState.getTransport();
90
14
  if (!transport) {
91
15
  object.sent = false;
92
16
  object.success = false;
@@ -24,6 +24,7 @@ async function init() {
24
24
  // Handle Email
25
25
  if (config_1.ConfigInstance.getInstance().getBoolean("APP_NOTIFICATIONS_PER_EMAIL")) {
26
26
  const email = user?.getEmail();
27
+ console.log("[@openinc/parse-server-opendash][Notification]", `notification="${object.id}"`, `type="email"`, `to="${email}"`);
27
28
  if (email) {
28
29
  let body = description || "";
29
30
  if (object.get("data")?.url) {
@@ -0,0 +1,16 @@
1
+ {
2
+ "ticket": {
3
+ "assignuser": {
4
+ "notification": {
5
+ "title": "Sie wurden einem Ticket zugewiesen",
6
+ "description": "Hallo,\n\n{{username}} hat Sie dem Ticket {{ticketName}} zugeordnet. \n\nLink zum Ticket: {{- ticketLink}}"
7
+ }
8
+ },
9
+ "assignrole": {
10
+ "notification": {
11
+ "title": "Ein Ticket wurde Ihrer Rolle zugewiesen",
12
+ "description": "Hallo,\n\n{{username}} hat das Ticket {{ticketName}} der Rolle {{role}} zugewiesen. \n\nLink zum Ticket: {{- ticketLink}}"
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "ticket": {
3
+ "assignuser": {
4
+ "notification": {
5
+ "title": "You've been assigned to a ticket",
6
+ "description": "Hello,\n\n{{username}} assigned you to the ticket {{ticketName}}. \n\nLink: {{- ticketLink}}"
7
+ }
8
+ },
9
+ "assignrole": {
10
+ "notification": {
11
+ "title": "A ticket was assigned to your role",
12
+ "description": "Hello,\n\n{{username}} assigned ticket {{ticketName}} to the role {{role}}. \n\nLink: {{- ticketLink}}"
13
+ }
14
+ }
15
+ }
16
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Cloud as ParseCloud } from "parse";
2
2
  import { Permission } from "./types";
3
- export { sendSimpleEmail, sendTemplateEmail } from "./hooks/Core_Email";
3
+ export { sendSimpleEmail, sendTemplateEmail } from "./features/notifications";
4
4
  /**
5
5
  * Initializes the Cloud Code for open.DASH.
6
6
  * This function performs various initialization tasks such as
package/dist/index.js CHANGED
@@ -38,9 +38,9 @@ const types_1 = require("./types");
38
38
  const notifications_1 = require("./features/notifications");
39
39
  const permissions_1 = require("./features/permissions");
40
40
  const settings_1 = require("./features/user/settings");
41
- const Core_Email_1 = require("./hooks/Core_Email");
42
41
  const importDocs_1 = require("./features/documentation/functions/importDocs");
43
42
  const openservice_1 = require("./features/openservice");
43
+ const translations_1 = require("./features/translations");
44
44
  const _init_1 = require("./functions/_init");
45
45
  const _init_2 = require("./hooks/_init");
46
46
  dayjs_1.default.extend(objectSupport_1.default);
@@ -48,9 +48,9 @@ dayjs_1.default.extend(weekday_1.default);
48
48
  dayjs_1.default.extend(dayOfYear_1.default);
49
49
  dayjs_1.default.extend(weekOfYear_1.default);
50
50
  dayjs_1.default.extend(duration_1.default);
51
- var Core_Email_2 = require("./hooks/Core_Email");
52
- Object.defineProperty(exports, "sendSimpleEmail", { enumerable: true, get: function () { return Core_Email_2.sendSimpleEmail; } });
53
- Object.defineProperty(exports, "sendTemplateEmail", { enumerable: true, get: function () { return Core_Email_2.sendTemplateEmail; } });
51
+ var notifications_2 = require("./features/notifications");
52
+ Object.defineProperty(exports, "sendSimpleEmail", { enumerable: true, get: function () { return notifications_2.sendSimpleEmail; } });
53
+ Object.defineProperty(exports, "sendTemplateEmail", { enumerable: true, get: function () { return notifications_2.sendTemplateEmail; } });
54
54
  const PREFIX = "OD3_";
55
55
  let config;
56
56
  // const lang_deu = require("../i18n/deu.json");
@@ -83,8 +83,8 @@ async function init() {
83
83
  catch (error) { }
84
84
  config = config_1.ConfigInstance.getInstance();
85
85
  await config.init(true);
86
- await initTranslations();
87
- await (0, Core_Email_1.initEmailTransport)();
86
+ await (0, translations_1.initTranslations)();
87
+ await (0, notifications_1.initEmailTransport)();
88
88
  await initWebPush();
89
89
  await initSchema();
90
90
  await initDefaultRoles();
@@ -100,17 +100,6 @@ async function init() {
100
100
  if ((0, config_1.isFeatureEnabled)("DOCUMENTATION"))
101
101
  await (0, importDocs_1.importDocs)();
102
102
  }
103
- async function initTranslations() {
104
- // try {
105
- // console.log("init translations");
106
- // registerLanguage("deu", "Deutsch", "eng", true);
107
- // registerTranslationResolver("deu", "server", async () => lang_deu);
108
- // } catch (error) {
109
- // console.error("Error while initializing translations");
110
- // console.error(error);
111
- // process.exit(1);
112
- // }
113
- }
114
103
  async function initWebPush() {
115
104
  try {
116
105
  if (config.getBoolean("WEB_PUSH_ENABLED")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openinc/parse-server-opendash",
3
- "version": "3.27.0",
3
+ "version": "3.29.0",
4
4
  "description": "Parse Server Cloud Code for open.INC Stack.",
5
5
  "packageManager": "pnpm@10.20.0",
6
6
  "keywords": [
@@ -47,7 +47,8 @@
47
47
  "scripts": {
48
48
  "start": "tsc -w",
49
49
  "dockerstart": "concurrently \"pnpm run start\" \"cd ./docker-dev && docker-compose watch\"",
50
- "build": "tsc",
50
+ "build": "tsc && node scripts/copyTranslationFiles.js",
51
+ "copy:i18n": "node scripts/copyTranslationFiles.js",
51
52
  "deploy": "opendash deploy",
52
53
  "schema-down": "parse-server-schema down --prefix OD3_ ./schema",
53
54
  "schema-up": "parse-server-schema up --prefix OD3_ ./schema",
@@ -73,14 +74,16 @@
73
74
  "@opentelemetry/winston-transport": "^0.19.0",
74
75
  "cron": "^4.3.4",
75
76
  "dayjs": "^1.11.19",
76
- "fast-equals": "^5.3.2",
77
+ "fast-equals": "^5.3.3",
78
+ "i18next": "^25.6.2",
79
+ "i18next-fs-backend": "^2.6.1",
77
80
  "jsonwebtoken": "^9.0.2",
78
81
  "jwks-rsa": "^3.2.0",
79
82
  "nodemailer": "^7.0.10",
80
83
  "nunjucks": "^3.2.4",
81
84
  "parse-server": "^8.4.0",
82
85
  "pdf-img-convert": "2.0.0",
83
- "semantic-release": "^25.0.1",
86
+ "semantic-release": "^25.0.2",
84
87
  "table": "^6.9.0",
85
88
  "web-push": "^3.6.7",
86
89
  "winston": "^3.18.3"
@@ -90,12 +93,12 @@
90
93
  "@semantic-release/commit-analyzer": "^13.0.1",
91
94
  "@semantic-release/exec": "^7.1.0",
92
95
  "@semantic-release/git": "^10.0.1",
93
- "@semantic-release/github": "^12.0.1",
94
- "@semantic-release/npm": "^13.1.1",
96
+ "@semantic-release/github": "^12.0.2",
97
+ "@semantic-release/npm": "^13.1.2",
95
98
  "@semantic-release/release-notes-generator": "^14.1.0",
96
99
  "@types/jsonwebtoken": "^9.0.10",
97
- "@types/node": "^24.10.0",
98
- "@types/nodemailer": "^7.0.3",
100
+ "@types/node": "^24.10.1",
101
+ "@types/nodemailer": "^7.0.4",
99
102
  "@types/nunjucks": "^3.2.6",
100
103
  "@types/parse": "^3.0.9",
101
104
  "@types/safe-timers": "^1.1.2",