emilsoftware-utilities 1.7.7 → 1.8.0-dev.1

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.
@@ -3,6 +3,14 @@ import { Options } from "es-node-firebird";
3
3
  export declare abstract class DatabaseUpdater {
4
4
  protected static options: Options;
5
5
  protected static logger: Logger;
6
+ protected static readonly versionParameterKeys: string[];
7
+ /**
8
+ * Checks if a table exists.
9
+ * @param options Database connection options.
10
+ * @param table Table name.
11
+ * @returns True if the table exists, false otherwise.
12
+ */
13
+ protected static tableExists(options: Options, table: string): Promise<boolean>;
6
14
  /**
7
15
  * Checks if a column exists in a specific table.
8
16
  * @param options Database connection options.
@@ -11,6 +19,20 @@ export declare abstract class DatabaseUpdater {
11
19
  * @returns True if the column exists, false otherwise.
12
20
  */
13
21
  protected static columnExists(options: Options, table: string, column: string): Promise<boolean>;
22
+ /**
23
+ * Checks if a generator/sequence exists.
24
+ * @param options Database connection options.
25
+ * @param generator Generator name.
26
+ * @returns True if the generator exists, false otherwise.
27
+ */
28
+ protected static generatorExists(options: Options, generator: string): Promise<boolean>;
29
+ /**
30
+ * Checks if a trigger exists.
31
+ * @param options Database connection options.
32
+ * @param trigger Trigger name.
33
+ * @returns True if the trigger exists, false otherwise.
34
+ */
35
+ protected static triggerExists(options: Options, trigger: string): Promise<boolean>;
14
36
  /**
15
37
  * Retrieves the current database version from the PARAMETRI table.
16
38
  * @param options Database connection options.
@@ -15,6 +15,29 @@ const Logger_1 = require("./Logger");
15
15
  class DatabaseUpdater {
16
16
  //#endregion
17
17
  //#region Utility Methods
18
+ /**
19
+ * Checks if a table exists.
20
+ * @param options Database connection options.
21
+ * @param table Table name.
22
+ * @returns True if the table exists, false otherwise.
23
+ */
24
+ static tableExists(options, table) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ try {
27
+ const query = `
28
+ SELECT 1
29
+ FROM RDB$RELATIONS
30
+ WHERE RDB$RELATION_NAME = ?
31
+ AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;
32
+ const result = yield Orm_1.Orm.query(options, query, [table.toUpperCase()]);
33
+ return result.length > 0;
34
+ }
35
+ catch (error) {
36
+ this.logger.error(`Error checking table ${table}:`, error);
37
+ throw error;
38
+ }
39
+ });
40
+ }
18
41
  /**
19
42
  * Checks if a column exists in a specific table.
20
43
  * @param options Database connection options.
@@ -42,6 +65,51 @@ class DatabaseUpdater {
42
65
  }
43
66
  });
44
67
  }
68
+ /**
69
+ * Checks if a generator/sequence exists.
70
+ * @param options Database connection options.
71
+ * @param generator Generator name.
72
+ * @returns True if the generator exists, false otherwise.
73
+ */
74
+ static generatorExists(options, generator) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ try {
77
+ const query = `
78
+ SELECT 1
79
+ FROM RDB$GENERATORS
80
+ WHERE RDB$GENERATOR_NAME = ?`;
81
+ const result = yield Orm_1.Orm.query(options, query, [generator.toUpperCase()]);
82
+ return result.length > 0;
83
+ }
84
+ catch (error) {
85
+ this.logger.error(`Error checking generator ${generator}:`, error);
86
+ throw error;
87
+ }
88
+ });
89
+ }
90
+ /**
91
+ * Checks if a trigger exists.
92
+ * @param options Database connection options.
93
+ * @param trigger Trigger name.
94
+ * @returns True if the trigger exists, false otherwise.
95
+ */
96
+ static triggerExists(options, trigger) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ try {
99
+ const query = `
100
+ SELECT 1
101
+ FROM RDB$TRIGGERS
102
+ WHERE RDB$TRIGGER_NAME = ?
103
+ AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;
104
+ const result = yield Orm_1.Orm.query(options, query, [trigger.toUpperCase()]);
105
+ return result.length > 0;
106
+ }
107
+ catch (error) {
108
+ this.logger.error(`Error checking trigger ${trigger}:`, error);
109
+ throw error;
110
+ }
111
+ });
112
+ }
45
113
  /**
46
114
  * Retrieves the current database version from the PARAMETRI table.
47
115
  * @param options Database connection options.
@@ -50,7 +118,17 @@ class DatabaseUpdater {
50
118
  static getDatabaseVersion(options) {
51
119
  return __awaiter(this, void 0, void 0, function* () {
52
120
  try {
53
- const parameters = (yield Orm_1.Orm.query(options, "SELECT CODPAR, DESPAR FROM PARAMETRI WHERE CODPAR = ?", ["VersioneDB"]));
121
+ if (!(yield this.tableExists(options, "PARAMETRI"))) {
122
+ return null;
123
+ }
124
+ const parameters = (yield Orm_1.Orm.query(options, `SELECT CODPAR, DESPAR
125
+ FROM PARAMETRI
126
+ WHERE CODPAR IN (?, ?)
127
+ ORDER BY CASE WHEN CODPAR = ? THEN 0 ELSE 1 END`, [
128
+ this.versionParameterKeys[0],
129
+ this.versionParameterKeys[1],
130
+ this.versionParameterKeys[0],
131
+ ]));
54
132
  return parameters.length > 0 ? parameters[0].DESPAR : null;
55
133
  }
56
134
  catch (error) {
@@ -66,11 +144,22 @@ class DatabaseUpdater {
66
144
  */
67
145
  static setDatabaseVersion(options, version) {
68
146
  return __awaiter(this, void 0, void 0, function* () {
147
+ var _a, _b, _c;
69
148
  try {
70
- yield Orm_1.Orm.query(options, "UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?", [
71
- version,
72
- "VersioneDB",
73
- ]);
149
+ if (!(yield this.tableExists(options, "PARAMETRI"))) {
150
+ yield this.createParametersTable(options);
151
+ }
152
+ const existingRows = (yield Orm_1.Orm.query(options, "SELECT CODPAR FROM PARAMETRI WHERE CODPAR IN (?, ?)", [this.versionParameterKeys[0], this.versionParameterKeys[1]]));
153
+ if (existingRows.length === 0) {
154
+ yield Orm_1.Orm.execute(options, "INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?, ?, ?, ?)", [this.versionParameterKeys[0], version, "versione", null]);
155
+ return;
156
+ }
157
+ for (const row of existingRows) {
158
+ yield Orm_1.Orm.execute(options, "UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?", [
159
+ version,
160
+ (_c = (_b = (_a = row.CODPAR) === null || _a === void 0 ? void 0 : _a.trim) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : row.CODPAR,
161
+ ]);
162
+ }
74
163
  }
75
164
  catch (error) {
76
165
  this.logger.error(`Error setting database version:`, error);
@@ -87,24 +176,25 @@ class DatabaseUpdater {
87
176
  static createParametersTable(options) {
88
177
  return __awaiter(this, void 0, void 0, function* () {
89
178
  try {
90
- const columnAlreadyExists = yield this.columnExists(options, "PARAMETRI", "CODPAR");
91
- if (columnAlreadyExists)
92
- return;
93
- const createTableQuery = `
94
- CREATE TABLE PARAMETRI (
95
- CODPAR VARCHAR(15) NOT NULL,
96
- DESPAR VARCHAR(255),
97
- NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,
98
- GRUPPO VARCHAR(20)
99
- );`;
100
- yield Orm_1.Orm.query(options, createTableQuery);
101
- yield Orm_1.Orm.query(options, "ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);");
102
- yield Orm_1.Orm.query(options, "GRANT ALL ON PARAMETRI TO PUBLIC;");
103
- yield Orm_1.Orm.query(options, "GRANT SELECT ON PARAMETRI TO TABX;");
179
+ const tableAlreadyExists = yield this.tableExists(options, "PARAMETRI");
180
+ if (!tableAlreadyExists) {
181
+ const createTableQuery = `
182
+ CREATE TABLE PARAMETRI (
183
+ CODPAR VARCHAR(15) NOT NULL,
184
+ DESPAR VARCHAR(255),
185
+ NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,
186
+ GRUPPO VARCHAR(20)
187
+ );`;
188
+ yield Orm_1.Orm.query(options, createTableQuery);
189
+ yield Orm_1.Orm.query(options, "ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);");
190
+ yield Orm_1.Orm.query(options, "GRANT ALL ON PARAMETRI TO PUBLIC;");
191
+ yield Orm_1.Orm.query(options, "GRANT SELECT ON PARAMETRI TO TABX;");
192
+ }
104
193
  const versioneDb = yield this.getDatabaseVersion(options);
105
- if (versioneDb !== null && versioneDb !== undefined)
194
+ if (versioneDb !== null && versioneDb !== undefined) {
106
195
  return;
107
- yield Orm_1.Orm.query(options, "INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)", ["VersioneDB", "0.0a", "versione", null]);
196
+ }
197
+ yield Orm_1.Orm.execute(options, "INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)", [this.versionParameterKeys[0], "0.0a", "versione", null]);
108
198
  }
109
199
  catch (error) {
110
200
  this.logger.error("Error creating table PARAMETRI:", error);
@@ -115,4 +205,5 @@ class DatabaseUpdater {
115
205
  }
116
206
  exports.DatabaseUpdater = DatabaseUpdater;
117
207
  DatabaseUpdater.logger = new Logger_1.Logger(DatabaseUpdater.name);
208
+ DatabaseUpdater.versionParameterKeys = ["VersioneDB", "DBVERSION"];
118
209
  //# sourceMappingURL=DatabaseUpdater.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseUpdater.js","sourceRoot":"","sources":["../src/DatabaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Orm } from \"./Orm\";\nimport { Logger } from \"./Logger\";\nimport { Options } from \"es-node-firebird\";\n\nexport abstract class DatabaseUpdater {\n //#region Fields and Options\n protected static options: Options;\n protected static logger: Logger = new Logger(DatabaseUpdater.name);\n //#endregion\n\n //#region Utility Methods\n /**\n * Checks if a column exists in a specific table.\n * @param options Database connection options.\n * @param table Table name.\n * @param column Column name.\n * @returns True if the column exists, false otherwise.\n */\n protected static async columnExists(\n options: Options,\n table: string,\n column: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1 \n FROM RDB$RELATION_FIELDS \n WHERE RDB$RELATION_NAME = ? \n AND RDB$FIELD_NAME = ?`;\n const result = await Orm.query(options, query, [\n table.toUpperCase(),\n column.toUpperCase(),\n ]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking column ${column} on table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Retrieves the current database version from the PARAMETRI table.\n * @param options Database connection options.\n * @returns The current database version or null if not found.\n */\n protected static async getDatabaseVersion(options: Options): Promise<string | null> {\n\n try {\n const parameters = (await Orm.query(\n options,\n \"SELECT CODPAR, DESPAR FROM PARAMETRI WHERE CODPAR = ?\",\n [\"VersioneDB\"]\n )) as any[];\n\n return parameters.length > 0 ? parameters[0].DESPAR : null;\n } catch (error: any) {\n this.logger.error(`Error getting database version:`, error);\n throw error;\n }\n }\n\n /**\n * Updates the database version in the PARAMETRI table.\n * @param options Database connection options.\n * @param version The new database version.\n */\n protected static async setDatabaseVersion(\n options: Options,\n version: string\n ): Promise<void> {\n\n try {\n\n await Orm.query(options, \"UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?\", [\n version,\n \"VersioneDB\",\n ]);\n } catch (error: any) {\n this.logger.error(`Error setting database version:`, error);\n throw error;\n }\n }\n //#endregion\n\n //#region Initialization Methods\n /**\n * Ensures the PARAMETRI table exists and initializes it if necessary.\n * @param options Database connection options.\n */\n protected static async createParametersTable(options: Options): Promise<void> {\n try {\n const columnAlreadyExists = await this.columnExists(options, \"PARAMETRI\", \"CODPAR\");\n if (columnAlreadyExists) return;\n\n const createTableQuery = `\n CREATE TABLE PARAMETRI (\n CODPAR VARCHAR(15) NOT NULL,\n DESPAR VARCHAR(255),\n NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,\n GRUPPO VARCHAR(20)\n );`;\n\n await Orm.query(options, createTableQuery);\n\n await Orm.query(\n options,\n \"ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);\"\n );\n\n await Orm.query(options, \"GRANT ALL ON PARAMETRI TO PUBLIC;\");\n await Orm.query(options, \"GRANT SELECT ON PARAMETRI TO TABX;\");\n\n const versioneDb = await this.getDatabaseVersion(options);\n if (versioneDb !== null && versioneDb !== undefined) return;\n\n await Orm.query(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)\",\n [\"VersioneDB\", \"0.0a\", \"versione\", null]\n );\n } catch (error: any) {\n this.logger.error(\"Error creating table PARAMETRI:\", error);\n throw error;\n }\n\n\n }\n //#endregion\n}\n"]}
1
+ {"version":3,"file":"DatabaseUpdater.js","sourceRoot":"","sources":["../src/DatabaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Orm } from \"./Orm\";\nimport { Logger } from \"./Logger\";\nimport { Options } from \"es-node-firebird\";\n\nexport abstract class DatabaseUpdater {\n //#region Fields and Options\n protected static options: Options;\n protected static logger: Logger = new Logger(DatabaseUpdater.name);\n protected static readonly versionParameterKeys = [\"VersioneDB\", \"DBVERSION\"];\n //#endregion\n\n //#region Utility Methods\n /**\n * Checks if a table exists.\n * @param options Database connection options.\n * @param table Table name.\n * @returns True if the table exists, false otherwise.\n */\n protected static async tableExists(\n options: Options,\n table: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$RELATIONS\n WHERE RDB$RELATION_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [table.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a column exists in a specific table.\n * @param options Database connection options.\n * @param table Table name.\n * @param column Column name.\n * @returns True if the column exists, false otherwise.\n */\n protected static async columnExists(\n options: Options,\n table: string,\n column: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1 \n FROM RDB$RELATION_FIELDS \n WHERE RDB$RELATION_NAME = ? \n AND RDB$FIELD_NAME = ?`;\n const result = await Orm.query(options, query, [\n table.toUpperCase(),\n column.toUpperCase(),\n ]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking column ${column} on table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a generator/sequence exists.\n * @param options Database connection options.\n * @param generator Generator name.\n * @returns True if the generator exists, false otherwise.\n */\n protected static async generatorExists(\n options: Options,\n generator: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$GENERATORS\n WHERE RDB$GENERATOR_NAME = ?`;\n const result = await Orm.query(options, query, [generator.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking generator ${generator}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a trigger exists.\n * @param options Database connection options.\n * @param trigger Trigger name.\n * @returns True if the trigger exists, false otherwise.\n */\n protected static async triggerExists(\n options: Options,\n trigger: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$TRIGGERS\n WHERE RDB$TRIGGER_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [trigger.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking trigger ${trigger}:`, error);\n throw error;\n }\n }\n\n /**\n * Retrieves the current database version from the PARAMETRI table.\n * @param options Database connection options.\n * @returns The current database version or null if not found.\n */\n protected static async getDatabaseVersion(options: Options): Promise<string | null> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n return null;\n }\n\n const parameters = (await Orm.query(\n options,\n `SELECT CODPAR, DESPAR\n FROM PARAMETRI\n WHERE CODPAR IN (?, ?)\n ORDER BY CASE WHEN CODPAR = ? THEN 0 ELSE 1 END`,\n [\n this.versionParameterKeys[0],\n this.versionParameterKeys[1],\n this.versionParameterKeys[0],\n ]\n )) as any[];\n\n return parameters.length > 0 ? parameters[0].DESPAR : null;\n } catch (error: any) {\n this.logger.error(`Error getting database version:`, error);\n throw error;\n }\n }\n\n /**\n * Updates the database version in the PARAMETRI table.\n * @param options Database connection options.\n * @param version The new database version.\n */\n protected static async setDatabaseVersion(\n options: Options,\n version: string\n ): Promise<void> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n await this.createParametersTable(options);\n }\n\n const existingRows = (await Orm.query(\n options,\n \"SELECT CODPAR FROM PARAMETRI WHERE CODPAR IN (?, ?)\",\n [this.versionParameterKeys[0], this.versionParameterKeys[1]]\n )) as any[];\n\n if (existingRows.length === 0) {\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?, ?, ?, ?)\",\n [this.versionParameterKeys[0], version, \"versione\", null]\n );\n return;\n }\n\n for (const row of existingRows) {\n await Orm.execute(options, \"UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?\", [\n version,\n row.CODPAR?.trim?.() ?? row.CODPAR,\n ]);\n }\n } catch (error: any) {\n this.logger.error(`Error setting database version:`, error);\n throw error;\n }\n }\n //#endregion\n\n //#region Initialization Methods\n /**\n * Ensures the PARAMETRI table exists and initializes it if necessary.\n * @param options Database connection options.\n */\n protected static async createParametersTable(options: Options): Promise<void> {\n try {\n const tableAlreadyExists = await this.tableExists(options, \"PARAMETRI\");\n if (!tableAlreadyExists) {\n const createTableQuery = `\n CREATE TABLE PARAMETRI (\n CODPAR VARCHAR(15) NOT NULL,\n DESPAR VARCHAR(255),\n NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,\n GRUPPO VARCHAR(20)\n );`;\n\n await Orm.query(options, createTableQuery);\n\n await Orm.query(\n options,\n \"ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);\"\n );\n\n await Orm.query(options, \"GRANT ALL ON PARAMETRI TO PUBLIC;\");\n await Orm.query(options, \"GRANT SELECT ON PARAMETRI TO TABX;\");\n }\n\n const versioneDb = await this.getDatabaseVersion(options);\n if (versioneDb !== null && versioneDb !== undefined) {\n return;\n }\n\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)\",\n [this.versionParameterKeys[0], \"0.0a\", \"versione\", null]\n );\n } catch (error: any) {\n this.logger.error(\"Error creating table PARAMETRI:\", error);\n throw error;\n }\n\n\n }\n //#endregion\n}\n"]}
@@ -47,6 +47,7 @@ export interface AccessiOptions {
47
47
  encryptionKey: string;
48
48
  mockDemoUser: boolean;
49
49
  passwordExpiration?: boolean;
50
+ autoUpdateDatabase?: boolean;
50
51
  jwtOptions: JwtOptions;
51
52
  emailOptions: EmailOptions;
52
53
  extensionFieldsOptions?: ExtensionFieldsOptions[];
@@ -23,6 +23,7 @@ const ConfiguratorController_1 = require("./Controllers/ConfiguratorController")
23
23
  const ConfiguratorService_1 = require("./Services/ConfiguratorService/ConfiguratorService");
24
24
  const jwt_strategy_1 = require("./jwt/jwt.strategy");
25
25
  const authenticateGen_1 = require("./middleware/authenticateGen");
26
+ const AccessiDatabaseUpdater_1 = require("./database-updates/AccessiDatabaseUpdater");
26
27
  let AccessiModule = AccessiModule_1 = class AccessiModule {
27
28
  static forRoot(options) {
28
29
  return {
@@ -39,7 +40,8 @@ let AccessiModule = AccessiModule_1 = class AccessiModule {
39
40
  FiltriService_1.FiltriService,
40
41
  ConfiguratorService_1.ConfiguratorService,
41
42
  jwt_strategy_1.JwtSimpleGuard,
42
- authenticateGen_1.AuthenticateGenService
43
+ authenticateGen_1.AuthenticateGenService,
44
+ AccessiDatabaseUpdater_1.AccessiDatabaseUpdater
43
45
  ],
44
46
  exports: [
45
47
  'ACCESSI_OPTIONS',
@@ -67,7 +69,7 @@ exports.AccessiModule = AccessiModule = AccessiModule_1 = __decorate([
67
69
  FiltriController_1.FiltriController,
68
70
  ConfiguratorController_1.ConfiguratorController
69
71
  ],
70
- providers: [AuthService_1.AuthService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService],
72
+ providers: [AuthService_1.AuthService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService, AccessiDatabaseUpdater_1.AccessiDatabaseUpdater],
71
73
  exports: [AuthService_1.AuthService, UserService_1.UserService, EmailService_1.EmailService, PermissionService_1.PermissionService, FiltriService_1.FiltriService, ConfiguratorService_1.ConfiguratorService, jwt_strategy_1.JwtSimpleGuard, authenticateGen_1.AuthenticateGenService],
72
74
  })
73
75
  ], AccessiModule);
@@ -1 +1 @@
1
- {"version":3,"file":"AccessiModule.js","sourceRoot":"","sources":["../../src/accessi-module/AccessiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAOA,2CAA+D;AAC/D,oEAAiE;AACjE,uEAAoE;AACpE,sFAAmF;AACnF,oEAAiE;AACjE,mEAAgE;AAChE,iEAA8D;AAC9D,6EAA0E;AAC1E,iEAA8D;AAC9D,0EAAuE;AACvE,qEAAkE;AAClE,iFAA8E;AAC9E,4FAAyF;AACzF,qDAAoD;AACpD,kEAAsE;AAgE/D,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB,MAAM,CAAC,OAAO,CAAC,OAAuB;QACpC,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;gBACD,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;aACvB;YACD,OAAO,EAAE;gBACP,iBAAiB;gBACjB,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;aACvB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA/BY,sCAAa;wBAAb,aAAa;IAbzB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,WAAW,EAAE;YACX,iCAAe;YACf,+BAAc;YACd,2CAAoB;YACpB,+BAAc;YACd,mCAAgB;YAChB,+CAAsB;SACvB;QACD,SAAS,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,CAAC;QAClJ,OAAO,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,CAAC;KACjJ,CAAC;GACW,aAAa,CA+BzB","sourcesContent":["/**\n * Modulo che gestisce le operazioni di accesso degli utenti, incluse le rotte, il controller e il modello.\n *\n * @module AccessiModule\n * @author mttdev382\n */\nimport { Options } from 'es-node-firebird';\nimport { DynamicModule, Global, Module } from '@nestjs/common';\nimport { AuthService } from './Services/AuthService/AuthService';\nimport { EmailService } from './Services/EmailService/EmailService';\nimport { PermissionService } from './Services/PermissionService/PermissionService';\nimport { UserService } from './Services/UserService/UserService';\nimport { EmailController } from './Controllers/EmailController';\nimport { AuthController } from './Controllers/AuthController';\nimport { PermissionController } from './Controllers/PermissionController';\nimport { UserController } from './Controllers/UserController';\nimport { FiltriService } from './Services/FiltriService/FiltriService';\nimport { FiltriController } from './Controllers/FiltriController';\nimport { ConfiguratorController } from './Controllers/ConfiguratorController';\nimport { ConfiguratorService } from './Services/ConfiguratorService/ConfiguratorService';\nimport { JwtSimpleGuard } from './jwt/jwt.strategy';\nimport { AuthenticateGenService } from './middleware/authenticateGen';\n\nexport interface JwtOptions {\n secret: string;\n expiresIn: string;\n}\n\nexport interface EmailOptions {\n host: string;\n port: number;\n secure: boolean;\n requireTLS : boolean;\n tls: {\n rejectUnauthorized: boolean,\n }\n from: string;\n auth: {\n user: string;\n pass: string;\n };\n}\n\nexport interface ExtensionFieldsOptions {\n databaseOptions: Options;\n objectKey: string;\n tableName: string;\n tableFields: string[];\n tableJoinFieldName: string;\n}\n\nexport interface AccessiOptions {\n databaseOptions: Options;\n /**\n * Basepath del sito es: 'http://www.il-mio-sito.it/nome-progetto(se c'è)'\n */\n confirmationEmailUrl: string;\n /**\n * Percorso della pagina di reset personalizzata es. http://localhost:4200/#/admin/reset-password\n * N.B si sostituisce al confirmationMailURl\n */\n customResetPage?: string;\n confirmationEmailReturnUrl: string;\n confirmationEmailPrefix?: string;\n encryptionKey: string;\n mockDemoUser: boolean;\n passwordExpiration?: boolean;\n jwtOptions: JwtOptions;\n emailOptions: EmailOptions;\n extensionFieldsOptions?: ExtensionFieldsOptions[];\n}\n\n@Global()\n@Module({\n controllers: [\n EmailController,\n AuthController,\n PermissionController,\n UserController,\n FiltriController,\n ConfiguratorController\n ],\n providers: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService],\n})\nexport class AccessiModule {\n static forRoot(options: AccessiOptions): DynamicModule {\n return {\n module: AccessiModule,\n providers: [\n {\n provide: 'ACCESSI_OPTIONS',\n useValue: options,\n },\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService\n ],\n exports: [\n 'ACCESSI_OPTIONS',\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService\n ],\n };\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiModule.js","sourceRoot":"","sources":["../../src/accessi-module/AccessiModule.ts"],"names":[],"mappings":";;;;;;;;;;AAOA,2CAA+D;AAC/D,oEAAiE;AACjE,uEAAoE;AACpE,sFAAmF;AACnF,oEAAiE;AACjE,mEAAgE;AAChE,iEAA8D;AAC9D,6EAA0E;AAC1E,iEAA8D;AAC9D,0EAAuE;AACvE,qEAAkE;AAClE,iFAA8E;AAC9E,4FAAyF;AACzF,qDAAoD;AACpD,kEAAsE;AACtE,sFAAmF;AAiE5E,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB,MAAM,CAAC,OAAO,CAAC,OAAuB;QACpC,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;gBACD,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;gBACtB,+CAAsB;aACvB;YACD,OAAO,EAAE;gBACP,iBAAiB;gBACjB,yBAAW;gBACX,yBAAW;gBACX,2BAAY;gBACZ,qCAAiB;gBACjB,6BAAa;gBACb,yCAAmB;gBACnB,6BAAc;gBACd,wCAAsB;aACvB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAhCY,sCAAa;wBAAb,aAAa;IAbzB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,WAAW,EAAE;YACX,iCAAe;YACf,+BAAc;YACd,2CAAoB;YACpB,+BAAc;YACd,mCAAgB;YAChB,+CAAsB;SACvB;QACD,SAAS,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,EAAE,+CAAsB,CAAC;QAC1K,OAAO,EAAE,CAAC,yBAAW,EAAE,yBAAW,EAAE,2BAAY,EAAE,qCAAiB,EAAE,6BAAa,EAAE,yCAAmB,EAAE,6BAAc,EAAE,wCAAsB,CAAC;KACjJ,CAAC;GACW,aAAa,CAgCzB","sourcesContent":["/**\n * Modulo che gestisce le operazioni di accesso degli utenti, incluse le rotte, il controller e il modello.\n *\n * @module AccessiModule\n * @author mttdev382\n */\nimport { Options } from 'es-node-firebird';\nimport { DynamicModule, Global, Module } from '@nestjs/common';\nimport { AuthService } from './Services/AuthService/AuthService';\nimport { EmailService } from './Services/EmailService/EmailService';\nimport { PermissionService } from './Services/PermissionService/PermissionService';\nimport { UserService } from './Services/UserService/UserService';\nimport { EmailController } from './Controllers/EmailController';\nimport { AuthController } from './Controllers/AuthController';\nimport { PermissionController } from './Controllers/PermissionController';\nimport { UserController } from './Controllers/UserController';\nimport { FiltriService } from './Services/FiltriService/FiltriService';\nimport { FiltriController } from './Controllers/FiltriController';\nimport { ConfiguratorController } from './Controllers/ConfiguratorController';\nimport { ConfiguratorService } from './Services/ConfiguratorService/ConfiguratorService';\nimport { JwtSimpleGuard } from './jwt/jwt.strategy';\nimport { AuthenticateGenService } from './middleware/authenticateGen';\nimport { AccessiDatabaseUpdater } from './database-updates/AccessiDatabaseUpdater';\n\nexport interface JwtOptions {\n secret: string;\n expiresIn: string;\n}\n\nexport interface EmailOptions {\n host: string;\n port: number;\n secure: boolean;\n requireTLS : boolean;\n tls: {\n rejectUnauthorized: boolean,\n }\n from: string;\n auth: {\n user: string;\n pass: string;\n };\n}\n\nexport interface ExtensionFieldsOptions {\n databaseOptions: Options;\n objectKey: string;\n tableName: string;\n tableFields: string[];\n tableJoinFieldName: string;\n}\n\nexport interface AccessiOptions {\n databaseOptions: Options;\n /**\n * Basepath del sito es: 'http://www.il-mio-sito.it/nome-progetto(se c'è)'\n */\n confirmationEmailUrl: string;\n /**\n * Percorso della pagina di reset personalizzata es. http://localhost:4200/#/admin/reset-password\n * N.B si sostituisce al confirmationMailURl\n */\n customResetPage?: string;\n confirmationEmailReturnUrl: string;\n confirmationEmailPrefix?: string;\n encryptionKey: string;\n mockDemoUser: boolean;\n passwordExpiration?: boolean;\n autoUpdateDatabase?: boolean;\n jwtOptions: JwtOptions;\n emailOptions: EmailOptions;\n extensionFieldsOptions?: ExtensionFieldsOptions[];\n}\n\n@Global()\n@Module({\n controllers: [\n EmailController,\n AuthController,\n PermissionController,\n UserController,\n FiltriController,\n ConfiguratorController\n ],\n providers: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService, AccessiDatabaseUpdater],\n exports: [AuthService, UserService, EmailService, PermissionService, FiltriService, ConfiguratorService, JwtSimpleGuard, AuthenticateGenService],\n})\nexport class AccessiModule {\n static forRoot(options: AccessiOptions): DynamicModule {\n return {\n module: AccessiModule,\n providers: [\n {\n provide: 'ACCESSI_OPTIONS',\n useValue: options,\n },\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService,\n AccessiDatabaseUpdater\n ],\n exports: [\n 'ACCESSI_OPTIONS',\n AuthService,\n UserService,\n EmailService,\n PermissionService,\n FiltriService,\n ConfiguratorService,\n JwtSimpleGuard,\n AuthenticateGenService\n ],\n };\n }\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { OnModuleInit } from "@nestjs/common";
2
+ import { DatabaseUpdater } from "../../DatabaseUpdater";
3
+ import { AccessiOptions } from "../AccessiModule";
4
+ import { Logger } from "../../Logger";
5
+ export declare class AccessiDatabaseUpdater extends DatabaseUpdater implements OnModuleInit {
6
+ private readonly accessiOptions;
7
+ protected static logger: Logger;
8
+ private static readonly updates;
9
+ constructor(accessiOptions: AccessiOptions);
10
+ onModuleInit(): Promise<void>;
11
+ static run(options: AccessiOptions): Promise<void>;
12
+ static getCurrentVersion(options: AccessiOptions): Promise<string | null>;
13
+ static getLatestVersion(): string;
14
+ private static ensureColumn;
15
+ private static upsertFiltroTipo;
16
+ private static upsertMenu;
17
+ }
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ var AccessiDatabaseUpdater_1;
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.AccessiDatabaseUpdater = void 0;
26
+ const common_1 = require("@nestjs/common");
27
+ const DatabaseUpdater_1 = require("../../DatabaseUpdater");
28
+ const Orm_1 = require("../../Orm");
29
+ const Logger_1 = require("../../Logger");
30
+ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpdater extends DatabaseUpdater_1.DatabaseUpdater {
31
+ constructor(accessiOptions) {
32
+ super();
33
+ this.accessiOptions = accessiOptions;
34
+ }
35
+ onModuleInit() {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ if (this.accessiOptions.autoUpdateDatabase === false) {
38
+ AccessiDatabaseUpdater_1.logger.info("Aggiornamento automatico database accessi disabilitato da configurazione.");
39
+ return;
40
+ }
41
+ yield AccessiDatabaseUpdater_1.run(this.accessiOptions);
42
+ });
43
+ }
44
+ static run(options) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ yield this.createParametersTable(options.databaseOptions);
47
+ const currentVersion = yield this.getDatabaseVersion(options.databaseOptions);
48
+ const currentIndex = this.updates.findIndex((update) => update.toVersion === currentVersion);
49
+ const startIndex = currentIndex >= 0 ? currentIndex + 1 : 0;
50
+ if (currentVersion && currentIndex === this.updates.length - 1) {
51
+ this.logger.info(`Database accessi gia' all'ultima versione disponibile (${currentVersion}).`);
52
+ }
53
+ else if (currentVersion && currentIndex >= 0) {
54
+ this.logger.info(`Database accessi rilevato alla versione ${currentVersion}.`);
55
+ }
56
+ else if (currentVersion) {
57
+ this.logger.warning(`Versione database accessi non riconosciuta (${currentVersion}). Verifico tutti gli update idempotenti.`);
58
+ }
59
+ else {
60
+ this.logger.warning("Versione database accessi assente. Verifico tutti gli update idempotenti.");
61
+ }
62
+ for (let index = startIndex; index < this.updates.length; index++) {
63
+ const update = this.updates[index];
64
+ this.logger.info(`Applico aggiornamento accessi ${update.fromVersion} -> ${update.toVersion}: ${update.description}`);
65
+ yield update.apply(options);
66
+ yield this.setDatabaseVersion(options.databaseOptions, update.toVersion);
67
+ }
68
+ });
69
+ }
70
+ static getCurrentVersion(options) {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ return yield this.getDatabaseVersion(options.databaseOptions);
73
+ });
74
+ }
75
+ static getLatestVersion() {
76
+ var _a, _b;
77
+ return (_b = (_a = this.updates[this.updates.length - 1]) === null || _a === void 0 ? void 0 : _a.toVersion) !== null && _b !== void 0 ? _b : "0.0.0";
78
+ }
79
+ static ensureColumn(options, tableName, columnDefinition, columnName, comment) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ const exists = yield this.columnExists(options.databaseOptions, tableName, columnName);
82
+ if (!exists) {
83
+ yield Orm_1.Orm.execute(options.databaseOptions, `ALTER TABLE ${tableName} ADD ${columnDefinition}`);
84
+ }
85
+ if (comment) {
86
+ yield Orm_1.Orm.execute(options.databaseOptions, `COMMENT ON COLUMN ${tableName}.${columnName} IS '${comment.replace(/'/g, "''")}'`);
87
+ }
88
+ return !exists;
89
+ });
90
+ }
91
+ static upsertFiltroTipo(options, tipfil, desfil, fldfil, flgEnabled) {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ const hasEnabledColumn = yield this.columnExists(options.databaseOptions, "FILTRI_TIPO", "FLGENABLED");
94
+ const existing = yield Orm_1.Orm.query(options.databaseOptions, "SELECT TIPFIL FROM FILTRI_TIPO WHERE TIPFIL = ?", [tipfil]);
95
+ if (existing.length === 0) {
96
+ if (hasEnabledColumn && flgEnabled !== undefined) {
97
+ yield Orm_1.Orm.execute(options.databaseOptions, "INSERT INTO FILTRI_TIPO (TIPFIL, DESFIL, FLDFIL, FLGENABLED) VALUES (?, ?, ?, ?)", [tipfil, desfil, fldfil, flgEnabled]);
98
+ return;
99
+ }
100
+ yield Orm_1.Orm.execute(options.databaseOptions, "INSERT INTO FILTRI_TIPO (TIPFIL, DESFIL, FLDFIL) VALUES (?, ?, ?)", [tipfil, desfil, fldfil]);
101
+ return;
102
+ }
103
+ if (hasEnabledColumn && flgEnabled !== undefined) {
104
+ yield Orm_1.Orm.execute(options.databaseOptions, "UPDATE FILTRI_TIPO SET DESFIL = ?, FLDFIL = ?, FLGENABLED = COALESCE(FLGENABLED, ?) WHERE TIPFIL = ?", [desfil, fldfil, flgEnabled, tipfil]);
105
+ return;
106
+ }
107
+ yield Orm_1.Orm.execute(options.databaseOptions, "UPDATE FILTRI_TIPO SET DESFIL = ?, FLDFIL = ? WHERE TIPFIL = ?", [desfil, fldfil, tipfil]);
108
+ });
109
+ }
110
+ static upsertMenu(options, menu) {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ const existing = yield Orm_1.Orm.query(options.databaseOptions, "SELECT CODMNU FROM MENU WHERE CODMNU = ?", [menu.CODMNU]);
113
+ if (existing.length === 0) {
114
+ yield Orm_1.Orm.execute(options.databaseOptions, `INSERT INTO MENU (CODMNU, DESMNU, CODGRP, FLGENABLED, ICON, ORDINE, CODTIP, PAGINA, RIFMENU)
115
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
116
+ menu.CODMNU,
117
+ menu.DESMNU,
118
+ menu.CODGRP,
119
+ menu.FLGENABLED,
120
+ menu.ICON,
121
+ menu.ORDINE,
122
+ menu.CODTIP,
123
+ menu.PAGINA,
124
+ menu.RIFMENU,
125
+ ]);
126
+ return;
127
+ }
128
+ yield Orm_1.Orm.execute(options.databaseOptions, `UPDATE MENU
129
+ SET DESMNU = ?,
130
+ CODGRP = ?,
131
+ FLGENABLED = COALESCE(FLGENABLED, ?),
132
+ ICON = ?,
133
+ ORDINE = ?,
134
+ CODTIP = ?,
135
+ PAGINA = ?,
136
+ RIFMENU = ?
137
+ WHERE CODMNU = ?`, [
138
+ menu.DESMNU,
139
+ menu.CODGRP,
140
+ menu.FLGENABLED,
141
+ menu.ICON,
142
+ menu.ORDINE,
143
+ menu.CODTIP,
144
+ menu.PAGINA,
145
+ menu.RIFMENU,
146
+ menu.CODMNU,
147
+ ]);
148
+ });
149
+ }
150
+ };
151
+ exports.AccessiDatabaseUpdater = AccessiDatabaseUpdater;
152
+ AccessiDatabaseUpdater.logger = new Logger_1.Logger(AccessiDatabaseUpdater_1.name);
153
+ AccessiDatabaseUpdater.updates = [
154
+ {
155
+ fromVersion: "1.0.0",
156
+ toVersion: "1.1.0",
157
+ description: "Aggiunge filtro postazione, colonna IDXPOS e menu verifica RFID",
158
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
159
+ yield AccessiDatabaseUpdater_1.upsertFiltroTipo(options, 20, "POSTAZIONE", "IDXPOS", undefined);
160
+ yield AccessiDatabaseUpdater_1.ensureColumn(options, "FILTRI", "IDXPOS SMALLINT", "IDXPOS", "idx della postazione nella tabella ANTENNE_POS di PROLAV");
161
+ yield AccessiDatabaseUpdater_1.upsertMenu(options, {
162
+ CODMNU: "MNUVERRFID",
163
+ DESMNU: "Verifica RFID",
164
+ CODGRP: "F",
165
+ FLGENABLED: 1,
166
+ ICON: "hardware-chip-outline",
167
+ ORDINE: 10,
168
+ CODTIP: "M",
169
+ PAGINA: "/verifica-rfid",
170
+ RIFMENU: null,
171
+ });
172
+ }),
173
+ },
174
+ {
175
+ fromVersion: "1.1.0",
176
+ toVersion: "1.1.1",
177
+ description: "Aggiunge FLGENABLED su FILTRI_TIPO",
178
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
179
+ const columnCreated = yield AccessiDatabaseUpdater_1.ensureColumn(options, "FILTRI_TIPO", "FLGENABLED SMALLINT DEFAULT 1 NOT NULL", "FLGENABLED");
180
+ if (!columnCreated) {
181
+ yield Orm_1.Orm.execute(options.databaseOptions, "UPDATE FILTRI_TIPO SET FLGENABLED = 1 WHERE FLGENABLED IS NULL");
182
+ }
183
+ }),
184
+ },
185
+ {
186
+ fromVersion: "1.1.1",
187
+ toVersion: "1.1.2",
188
+ description: "Aggiunge filtro vettore e colonna CODVET",
189
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
190
+ yield AccessiDatabaseUpdater_1.upsertFiltroTipo(options, 30, "VETTORE", "CODVET", 1);
191
+ yield AccessiDatabaseUpdater_1.ensureColumn(options, "FILTRI", "CODVET INTEGER", "CODVET", "CODICE DEL VETTORE DA INSERIRE SE COME FILTRO HA 30");
192
+ }),
193
+ },
194
+ {
195
+ fromVersion: "1.1.2",
196
+ toVersion: "1.1.3",
197
+ description: "Aggiunge FLGADMINCONFIG e inizializza PARAMETRI",
198
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
199
+ yield AccessiDatabaseUpdater_1.ensureColumn(options, "UTENTI_CONFIG", "FLGADMINCONFIG SMALLINT DEFAULT 0", "FLGADMINCONFIG", "flag utente configuratore dei menu amministratore");
200
+ yield AccessiDatabaseUpdater_1.createParametersTable(options.databaseOptions);
201
+ }),
202
+ },
203
+ {
204
+ fromVersion: "1.1.3",
205
+ toVersion: "1.1.4",
206
+ description: "Aggiunge sequence e trigger per RUOLI",
207
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
208
+ if (!(yield AccessiDatabaseUpdater_1.generatorExists(options.databaseOptions, "GEN_RUOLI_ID"))) {
209
+ yield Orm_1.Orm.execute(options.databaseOptions, "CREATE SEQUENCE GEN_RUOLI_ID");
210
+ }
211
+ if (!(yield AccessiDatabaseUpdater_1.triggerExists(options.databaseOptions, "RUOLI_BI"))) {
212
+ yield Orm_1.Orm.execute(options.databaseOptions, `CREATE TRIGGER RUOLI_BI FOR RUOLI
213
+ ACTIVE BEFORE INSERT POSITION 0
214
+ AS
215
+ BEGIN
216
+ IF (NEW.CODRUO IS NULL) THEN
217
+ NEW.CODRUO = GEN_ID(GEN_RUOLI_ID,1);
218
+ END`);
219
+ }
220
+ }),
221
+ },
222
+ {
223
+ fromVersion: "1.1.4",
224
+ toVersion: "1.1.5",
225
+ description: "Aggiunge NOTE su MENU",
226
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
227
+ yield AccessiDatabaseUpdater_1.ensureColumn(options, "MENU", "NOTE VARCHAR(1000)", "NOTE");
228
+ }),
229
+ },
230
+ {
231
+ fromVersion: "1.1.5",
232
+ toVersion: "1.1.6",
233
+ description: "Aggiunge NUMMAC su UTENTI_CONFIG",
234
+ apply: (options) => __awaiter(void 0, void 0, void 0, function* () {
235
+ yield AccessiDatabaseUpdater_1.ensureColumn(options, "UTENTI_CONFIG", "NUMMAC INTEGER", "NUMMAC", 'Numero macchina DESPOST PROLAV');
236
+ }),
237
+ },
238
+ ];
239
+ exports.AccessiDatabaseUpdater = AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = __decorate([
240
+ (0, common_1.Injectable)(),
241
+ __param(0, (0, common_1.Inject)("ACCESSI_OPTIONS")),
242
+ __metadata("design:paramtypes", [Object])
243
+ ], AccessiDatabaseUpdater);
244
+ //# sourceMappingURL=AccessiDatabaseUpdater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessiDatabaseUpdater.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/AccessiDatabaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Inject, OnModuleInit } from \"@nestjs/common\";\nimport { DatabaseUpdater } from \"../../DatabaseUpdater\";\nimport { AccessiOptions } from \"../AccessiModule\";\nimport { Orm } from \"../../Orm\";\nimport { Logger } from \"../../Logger\";\n\ntype AccessiUpdateStep = {\n fromVersion: string;\n toVersion: string;\n description: string;\n apply: (options: AccessiOptions) => Promise<void>;\n};\n\n@Injectable()\nexport class AccessiDatabaseUpdater extends DatabaseUpdater implements OnModuleInit {\n protected static override logger: Logger = new Logger(AccessiDatabaseUpdater.name);\n\n private static readonly updates: AccessiUpdateStep[] = [\n {\n fromVersion: \"1.0.0\",\n toVersion: \"1.1.0\",\n description: \"Aggiunge filtro postazione, colonna IDXPOS e menu verifica RFID\",\n apply: async (options) => {\n await AccessiDatabaseUpdater.upsertFiltroTipo(options, 20, \"POSTAZIONE\", \"IDXPOS\", undefined);\n await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"FILTRI\",\n \"IDXPOS SMALLINT\",\n \"IDXPOS\",\n \"idx della postazione nella tabella ANTENNE_POS di PROLAV\"\n );\n await AccessiDatabaseUpdater.upsertMenu(options, {\n CODMNU: \"MNUVERRFID\",\n DESMNU: \"Verifica RFID\",\n CODGRP: \"F\",\n FLGENABLED: 1,\n ICON: \"hardware-chip-outline\",\n ORDINE: 10,\n CODTIP: \"M\",\n PAGINA: \"/verifica-rfid\",\n RIFMENU: null,\n });\n },\n },\n {\n fromVersion: \"1.1.0\",\n toVersion: \"1.1.1\",\n description: \"Aggiunge FLGENABLED su FILTRI_TIPO\",\n apply: async (options) => {\n const columnCreated = await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"FILTRI_TIPO\",\n \"FLGENABLED SMALLINT DEFAULT 1 NOT NULL\",\n \"FLGENABLED\"\n );\n\n if (!columnCreated) {\n await Orm.execute(\n options.databaseOptions,\n \"UPDATE FILTRI_TIPO SET FLGENABLED = 1 WHERE FLGENABLED IS NULL\"\n );\n }\n },\n },\n {\n fromVersion: \"1.1.1\",\n toVersion: \"1.1.2\",\n description: \"Aggiunge filtro vettore e colonna CODVET\",\n apply: async (options) => {\n await AccessiDatabaseUpdater.upsertFiltroTipo(options, 30, \"VETTORE\", \"CODVET\", 1);\n await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"FILTRI\",\n \"CODVET INTEGER\",\n \"CODVET\",\n \"CODICE DEL VETTORE DA INSERIRE SE COME FILTRO HA 30\"\n );\n },\n },\n {\n fromVersion: \"1.1.2\",\n toVersion: \"1.1.3\",\n description: \"Aggiunge FLGADMINCONFIG e inizializza PARAMETRI\",\n apply: async (options) => {\n await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"UTENTI_CONFIG\",\n \"FLGADMINCONFIG SMALLINT DEFAULT 0\",\n \"FLGADMINCONFIG\",\n \"flag utente configuratore dei menu amministratore\"\n );\n await AccessiDatabaseUpdater.createParametersTable(options.databaseOptions);\n },\n },\n {\n fromVersion: \"1.1.3\",\n toVersion: \"1.1.4\",\n description: \"Aggiunge sequence e trigger per RUOLI\",\n apply: async (options) => {\n if (!(await AccessiDatabaseUpdater.generatorExists(options.databaseOptions, \"GEN_RUOLI_ID\"))) {\n await Orm.execute(options.databaseOptions, \"CREATE SEQUENCE GEN_RUOLI_ID\");\n }\n\n if (!(await AccessiDatabaseUpdater.triggerExists(options.databaseOptions, \"RUOLI_BI\"))) {\n await Orm.execute(\n options.databaseOptions,\n `CREATE TRIGGER RUOLI_BI FOR RUOLI\nACTIVE BEFORE INSERT POSITION 0\nAS\nBEGIN\n IF (NEW.CODRUO IS NULL) THEN\n NEW.CODRUO = GEN_ID(GEN_RUOLI_ID,1);\nEND`\n );\n }\n },\n },\n {\n fromVersion: \"1.1.4\",\n toVersion: \"1.1.5\",\n description: \"Aggiunge NOTE su MENU\",\n apply: async (options) => {\n await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"MENU\",\n \"NOTE VARCHAR(1000)\",\n \"NOTE\"\n );\n },\n },\n {\n fromVersion: \"1.1.5\",\n toVersion: \"1.1.6\",\n description: \"Aggiunge NUMMAC su UTENTI_CONFIG\",\n apply: async (options) => {\n await AccessiDatabaseUpdater.ensureColumn(\n options,\n \"UTENTI_CONFIG\",\n \"NUMMAC INTEGER\",\n \"NUMMAC\",\n 'Numero macchina DESPOST PROLAV'\n );\n },\n },\n ];\n\n constructor(\n @Inject(\"ACCESSI_OPTIONS\") private readonly accessiOptions: AccessiOptions\n ) {\n super();\n }\n\n async onModuleInit(): Promise<void> {\n if (this.accessiOptions.autoUpdateDatabase === false) {\n AccessiDatabaseUpdater.logger.info(\"Aggiornamento automatico database accessi disabilitato da configurazione.\");\n return;\n }\n\n await AccessiDatabaseUpdater.run(this.accessiOptions);\n }\n\n static async run(options: AccessiOptions): Promise<void> {\n await this.createParametersTable(options.databaseOptions);\n\n const currentVersion = await this.getDatabaseVersion(options.databaseOptions);\n const currentIndex = this.updates.findIndex(\n (update) => update.toVersion === currentVersion\n );\n const startIndex = currentIndex >= 0 ? currentIndex + 1 : 0;\n\n if (currentVersion && currentIndex === this.updates.length - 1) {\n this.logger.info(`Database accessi gia' all'ultima versione disponibile (${currentVersion}).`);\n } else if (currentVersion && currentIndex >= 0) {\n this.logger.info(`Database accessi rilevato alla versione ${currentVersion}.`);\n } else if (currentVersion) {\n this.logger.warning(\n `Versione database accessi non riconosciuta (${currentVersion}). Verifico tutti gli update idempotenti.`\n );\n } else {\n this.logger.warning(\n \"Versione database accessi assente. Verifico tutti gli update idempotenti.\"\n );\n }\n\n for (let index = startIndex; index < this.updates.length; index++) {\n const update = this.updates[index];\n this.logger.info(\n `Applico aggiornamento accessi ${update.fromVersion} -> ${update.toVersion}: ${update.description}`\n );\n await update.apply(options);\n await this.setDatabaseVersion(options.databaseOptions, update.toVersion);\n }\n }\n\n static async getCurrentVersion(options: AccessiOptions): Promise<string | null> {\n return await this.getDatabaseVersion(options.databaseOptions);\n }\n\n static getLatestVersion(): string {\n return this.updates[this.updates.length - 1]?.toVersion ?? \"0.0.0\";\n }\n\n private static async ensureColumn(\n options: AccessiOptions,\n tableName: string,\n columnDefinition: string,\n columnName: string,\n comment?: string\n ): Promise<boolean> {\n const exists = await this.columnExists(\n options.databaseOptions,\n tableName,\n columnName\n );\n\n if (!exists) {\n await Orm.execute(\n options.databaseOptions,\n `ALTER TABLE ${tableName} ADD ${columnDefinition}`\n );\n }\n\n if (comment) {\n await Orm.execute(\n options.databaseOptions,\n `COMMENT ON COLUMN ${tableName}.${columnName} IS '${comment.replace(/'/g, \"''\")}'`\n );\n }\n\n return !exists;\n }\n\n private static async upsertFiltroTipo(\n options: AccessiOptions,\n tipfil: number,\n desfil: string,\n fldfil: string,\n flgEnabled?: number\n ): Promise<void> {\n const hasEnabledColumn = await this.columnExists(\n options.databaseOptions,\n \"FILTRI_TIPO\",\n \"FLGENABLED\"\n );\n\n const existing = await Orm.query(\n options.databaseOptions,\n \"SELECT TIPFIL FROM FILTRI_TIPO WHERE TIPFIL = ?\",\n [tipfil]\n );\n\n if (existing.length === 0) {\n if (hasEnabledColumn && flgEnabled !== undefined) {\n await Orm.execute(\n options.databaseOptions,\n \"INSERT INTO FILTRI_TIPO (TIPFIL, DESFIL, FLDFIL, FLGENABLED) VALUES (?, ?, ?, ?)\",\n [tipfil, desfil, fldfil, flgEnabled]\n );\n return;\n }\n\n await Orm.execute(\n options.databaseOptions,\n \"INSERT INTO FILTRI_TIPO (TIPFIL, DESFIL, FLDFIL) VALUES (?, ?, ?)\",\n [tipfil, desfil, fldfil]\n );\n return;\n }\n\n if (hasEnabledColumn && flgEnabled !== undefined) {\n await Orm.execute(\n options.databaseOptions,\n \"UPDATE FILTRI_TIPO SET DESFIL = ?, FLDFIL = ?, FLGENABLED = COALESCE(FLGENABLED, ?) WHERE TIPFIL = ?\",\n [desfil, fldfil, flgEnabled, tipfil]\n );\n return;\n }\n\n await Orm.execute(\n options.databaseOptions,\n \"UPDATE FILTRI_TIPO SET DESFIL = ?, FLDFIL = ? WHERE TIPFIL = ?\",\n [desfil, fldfil, tipfil]\n );\n }\n\n private static async upsertMenu(\n options: AccessiOptions,\n menu: {\n CODMNU: string;\n DESMNU: string;\n CODGRP: string;\n FLGENABLED: number;\n ICON: string;\n ORDINE: number;\n CODTIP: string;\n PAGINA: string;\n RIFMENU: string | null;\n }\n ): Promise<void> {\n const existing = await Orm.query(\n options.databaseOptions,\n \"SELECT CODMNU FROM MENU WHERE CODMNU = ?\",\n [menu.CODMNU]\n );\n\n if (existing.length === 0) {\n await Orm.execute(\n options.databaseOptions,\n `INSERT INTO MENU (CODMNU, DESMNU, CODGRP, FLGENABLED, ICON, ORDINE, CODTIP, PAGINA, RIFMENU)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n menu.CODMNU,\n menu.DESMNU,\n menu.CODGRP,\n menu.FLGENABLED,\n menu.ICON,\n menu.ORDINE,\n menu.CODTIP,\n menu.PAGINA,\n menu.RIFMENU,\n ]\n );\n return;\n }\n\n await Orm.execute(\n options.databaseOptions,\n `UPDATE MENU\n SET DESMNU = ?,\n CODGRP = ?,\n FLGENABLED = COALESCE(FLGENABLED, ?),\n ICON = ?,\n ORDINE = ?,\n CODTIP = ?,\n PAGINA = ?,\n RIFMENU = ?\n WHERE CODMNU = ?`,\n [\n menu.DESMNU,\n menu.CODGRP,\n menu.FLGENABLED,\n menu.ICON,\n menu.ORDINE,\n menu.CODTIP,\n menu.PAGINA,\n menu.RIFMENU,\n menu.CODMNU,\n ]\n );\n }\n}\n"]}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const AccessiDatabaseUpdater_1 = require("./AccessiDatabaseUpdater");
13
+ const Utilities_1 = require("../../Utilities");
14
+ function getEnv(name, fallback) {
15
+ var _a;
16
+ const value = (_a = process.env[name]) !== null && _a !== void 0 ? _a : fallback;
17
+ if (!value) {
18
+ throw new Error(`Variabile ambiente mancante: ${name}`);
19
+ }
20
+ return value;
21
+ }
22
+ function getOptionalBoolean(name, fallback) {
23
+ const value = process.env[name];
24
+ if (value === undefined) {
25
+ return fallback;
26
+ }
27
+ return value.toLowerCase() === "true";
28
+ }
29
+ function createAccessiOptionsFromEnv() {
30
+ return {
31
+ databaseOptions: Utilities_1.DatabaseUtilities.createOption(getEnv("ACCESSI_DB_HOST"), Number(getEnv("ACCESSI_DB_PORT", "3050")), getEnv("ACCESSI_DB_DATABASE"), getEnv("ACCESSI_DB_USER", "SYSDBA"), getEnv("ACCESSI_DB_PASSWORD", "masterkey")),
32
+ confirmationEmailUrl: getEnv("ACCESSI_CONFIRMATION_EMAIL_URL", "http://localhost"),
33
+ confirmationEmailReturnUrl: getEnv("ACCESSI_CONFIRMATION_RETURN_EMAIL_URL", "http://localhost"),
34
+ confirmationEmailPrefix: process.env.ACCESSI_CONFIRMATION_EMAIL_PREFIX,
35
+ customResetPage: process.env.ACCESSI_CUSTOM_RESET_PAGE,
36
+ encryptionKey: getEnv("ACCESSI_ENCRYPTION_KEY", "1234567890ABCDEF"),
37
+ mockDemoUser: getOptionalBoolean("ACCESSI_MOCK_DEMO_USER", false),
38
+ passwordExpiration: getOptionalBoolean("ACCESSI_PASSWORD_EXPIRATION", false),
39
+ autoUpdateDatabase: true,
40
+ jwtOptions: {
41
+ secret: getEnv("ACCESSI_JWT_SECRET", "local-accessi-update"),
42
+ expiresIn: getEnv("ACCESSI_JWT_EXPIRES", "24h"),
43
+ },
44
+ emailOptions: {
45
+ host: getEnv("ACCESSI_EMAIL_HOST", "localhost"),
46
+ port: Number(getEnv("ACCESSI_EMAIL_PORT", "25")),
47
+ secure: getOptionalBoolean("ACCESSI_EMAIL_SECURE", false),
48
+ requireTLS: getOptionalBoolean("ACCESSI_EMAIL_REQUIRE_TLS", false),
49
+ tls: {
50
+ rejectUnauthorized: getOptionalBoolean("ACCESSI_EMAIL_TLS_REJECT_UNAUTHORIZED", false),
51
+ },
52
+ from: getEnv("ACCESSI_EMAIL_FROM", "noreply@example.local"),
53
+ auth: {
54
+ user: getEnv("ACCESSI_EMAIL_USER", "local-user"),
55
+ pass: getEnv("ACCESSI_EMAIL_PASSWORD", "local-password"),
56
+ },
57
+ },
58
+ extensionFieldsOptions: [],
59
+ };
60
+ }
61
+ function main() {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ const options = createAccessiOptionsFromEnv();
64
+ console.log("[Accessi DB Update] Avvio aggiornamento database...");
65
+ console.log(`[Accessi DB Update] Target: ${options.databaseOptions.host}:${options.databaseOptions.port} -> ${options.databaseOptions.database}`);
66
+ yield AccessiDatabaseUpdater_1.AccessiDatabaseUpdater.run(options);
67
+ const currentVersion = yield AccessiDatabaseUpdater_1.AccessiDatabaseUpdater.getCurrentVersion(options);
68
+ console.log(`[Accessi DB Update] Completato. Versione corrente: ${currentVersion !== null && currentVersion !== void 0 ? currentVersion : "N/D"} | Ultima disponibile: ${AccessiDatabaseUpdater_1.AccessiDatabaseUpdater.getLatestVersion()}`);
69
+ });
70
+ }
71
+ main().catch((error) => {
72
+ console.error("[Accessi DB Update] Errore durante l'aggiornamento:", error);
73
+ process.exit(1);
74
+ });
75
+ //# sourceMappingURL=runAccessiDbUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runAccessiDbUpdate.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/runAccessiDbUpdate.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccessiOptions } from \"../AccessiModule\";\nimport { AccessiDatabaseUpdater } from \"./AccessiDatabaseUpdater\";\nimport { DatabaseUtilities } from \"../../Utilities\";\n\nfunction getEnv(name: string, fallback?: string): string {\n const value = process.env[name] ?? fallback;\n if (!value) {\n throw new Error(`Variabile ambiente mancante: ${name}`);\n }\n return value;\n}\n\nfunction getOptionalBoolean(name: string, fallback: boolean): boolean {\n const value = process.env[name];\n if (value === undefined) {\n return fallback;\n }\n\n return value.toLowerCase() === \"true\";\n}\n\nfunction createAccessiOptionsFromEnv(): AccessiOptions {\n return {\n databaseOptions: DatabaseUtilities.createOption(\n getEnv(\"ACCESSI_DB_HOST\"),\n Number(getEnv(\"ACCESSI_DB_PORT\", \"3050\")),\n getEnv(\"ACCESSI_DB_DATABASE\"),\n getEnv(\"ACCESSI_DB_USER\", \"SYSDBA\"),\n getEnv(\"ACCESSI_DB_PASSWORD\", \"masterkey\")\n ),\n confirmationEmailUrl: getEnv(\"ACCESSI_CONFIRMATION_EMAIL_URL\", \"http://localhost\"),\n confirmationEmailReturnUrl: getEnv(\"ACCESSI_CONFIRMATION_RETURN_EMAIL_URL\", \"http://localhost\"),\n confirmationEmailPrefix: process.env.ACCESSI_CONFIRMATION_EMAIL_PREFIX,\n customResetPage: process.env.ACCESSI_CUSTOM_RESET_PAGE,\n encryptionKey: getEnv(\"ACCESSI_ENCRYPTION_KEY\", \"1234567890ABCDEF\"),\n mockDemoUser: getOptionalBoolean(\"ACCESSI_MOCK_DEMO_USER\", false),\n passwordExpiration: getOptionalBoolean(\"ACCESSI_PASSWORD_EXPIRATION\", false),\n autoUpdateDatabase: true,\n jwtOptions: {\n secret: getEnv(\"ACCESSI_JWT_SECRET\", \"local-accessi-update\"),\n expiresIn: getEnv(\"ACCESSI_JWT_EXPIRES\", \"24h\"),\n },\n emailOptions: {\n host: getEnv(\"ACCESSI_EMAIL_HOST\", \"localhost\"),\n port: Number(getEnv(\"ACCESSI_EMAIL_PORT\", \"25\")),\n secure: getOptionalBoolean(\"ACCESSI_EMAIL_SECURE\", false),\n requireTLS: getOptionalBoolean(\"ACCESSI_EMAIL_REQUIRE_TLS\", false),\n tls: {\n rejectUnauthorized: getOptionalBoolean(\"ACCESSI_EMAIL_TLS_REJECT_UNAUTHORIZED\", false),\n },\n from: getEnv(\"ACCESSI_EMAIL_FROM\", \"noreply@example.local\"),\n auth: {\n user: getEnv(\"ACCESSI_EMAIL_USER\", \"local-user\"),\n pass: getEnv(\"ACCESSI_EMAIL_PASSWORD\", \"local-password\"),\n },\n },\n extensionFieldsOptions: [],\n };\n}\n\nasync function main(): Promise<void> {\n const options = createAccessiOptionsFromEnv();\n\n console.log(\"[Accessi DB Update] Avvio aggiornamento database...\");\n console.log(\n `[Accessi DB Update] Target: ${options.databaseOptions.host}:${options.databaseOptions.port} -> ${options.databaseOptions.database}`\n );\n\n await AccessiDatabaseUpdater.run(options);\n\n const currentVersion = await AccessiDatabaseUpdater.getCurrentVersion(options);\n console.log(\n `[Accessi DB Update] Completato. Versione corrente: ${currentVersion ?? \"N/D\"} | Ultima disponibile: ${AccessiDatabaseUpdater.getLatestVersion()}`\n );\n}\n\nmain().catch((error) => {\n console.error(\"[Accessi DB Update] Errore durante l'aggiornamento:\", error);\n process.exit(1);\n});\n"]}
@@ -2,6 +2,7 @@ import { Application } from "express";
2
2
  import { AccessiOptions } from "./AccessiModule";
3
3
  export declare function initializeAccessiModule(app: Application, options: AccessiOptions): Promise<void>;
4
4
  export { AccessiModule } from "./AccessiModule";
5
+ export { AccessiDatabaseUpdater } from "./database-updates/AccessiDatabaseUpdater";
5
6
  export * from "./Dtos";
6
7
  export { authorizeAccessi, authenticateGen } from "./middleware/authenticateGen";
7
8
  export { accessiRequirement } from "./middleware/accessiRequirements";
@@ -23,7 +23,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
23
23
  });
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.accessiRequirement = exports.authenticateGen = exports.authorizeAccessi = exports.AccessiModule = void 0;
26
+ exports.accessiRequirement = exports.authenticateGen = exports.authorizeAccessi = exports.AccessiDatabaseUpdater = exports.AccessiModule = void 0;
27
27
  exports.initializeAccessiModule = initializeAccessiModule;
28
28
  const core_1 = require("@nestjs/core");
29
29
  const platform_express_1 = require("@nestjs/platform-express");
@@ -33,6 +33,7 @@ const authenticateGen_1 = require("./middleware/authenticateGen");
33
33
  function initializeAccessiModule(app, options) {
34
34
  return __awaiter(this, void 0, void 0, function* () {
35
35
  const logger = new Logger_1.Logger("initializeAccessiModule");
36
+ (0, authenticateGen_1.beginAccessiAuthInitialization)();
36
37
  console.log("Accessi initialized");
37
38
  try {
38
39
  // Creiamo un'istanza Express separata per NestJS
@@ -47,9 +48,12 @@ function initializeAccessiModule(app, options) {
47
48
  });
48
49
  // Note: Swagger setup is now handled by the unified module
49
50
  yield nestApp.init();
50
- app.locals.accessiAuthService = nestApp.get(authenticateGen_1.AuthenticateGenService);
51
+ const authService = nestApp.get(authenticateGen_1.AuthenticateGenService);
52
+ app.locals.accessiAuthService = authService;
53
+ (0, authenticateGen_1.setAccessiAuthService)(authService);
51
54
  }
52
55
  catch (error) {
56
+ (0, authenticateGen_1.failAccessiAuthInitialization)(error);
53
57
  logger.error("Errore in initialize AccessiModule:", error);
54
58
  throw error;
55
59
  }
@@ -57,6 +61,8 @@ function initializeAccessiModule(app, options) {
57
61
  }
58
62
  var AccessiModule_2 = require("./AccessiModule");
59
63
  Object.defineProperty(exports, "AccessiModule", { enumerable: true, get: function () { return AccessiModule_2.AccessiModule; } });
64
+ var AccessiDatabaseUpdater_1 = require("./database-updates/AccessiDatabaseUpdater");
65
+ Object.defineProperty(exports, "AccessiDatabaseUpdater", { enumerable: true, get: function () { return AccessiDatabaseUpdater_1.AccessiDatabaseUpdater; } });
60
66
  __exportStar(require("./Dtos"), exports);
61
67
  var authenticateGen_2 = require("./middleware/authenticateGen");
62
68
  Object.defineProperty(exports, "authorizeAccessi", { enumerable: true, get: function () { return authenticateGen_2.authorizeAccessi; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,0DA2BC;AAjCD,uCAA2C;AAC3C,+DAA0D;AAC1D,mDAAgE;AAChE,sCAAmC;AACnC,kEAAsE;AAEtE,SAAsB,uBAAuB,CAAC,GAAgB,EAAE,OAAuB;;QACnF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,yBAAyB,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,IAAI,CAAC;YACD,iDAAiD;YACjD,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,GAAG,CAAC,CAAC;YAEpD,2CAA2C;YAC3C,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,6BAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC1F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,2DAA2D;YAC3D,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,GAAG,CAAC,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,wCAAsB,CAAC,CAAC;QAExE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA;AAED,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,yCAAuB;AACvB,gEAGsC;AAFlC,mHAAA,gBAAgB,OAAA;AAChB,kHAAA,eAAe,OAAA;AAEnB,wEAAsE;AAA7D,yHAAA,kBAAkB,OAAA","sourcesContent":["import { Application } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport { AuthenticateGenService } from \"./middleware/authenticateGen\";\n\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions) {\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n\n console.log(\"Accessi initialized\");\n try {\n // Creiamo un'istanza Express separata per NestJS\n const nestExpressInstance = new ExpressAdapter(app);\n\n // Creiamo l'app NestJS attaccata a Express\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n\n nestApp.enableCors();\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n // Note: Swagger setup is now handled by the unified module\n await nestApp.init();\n app.locals.accessiAuthService = nestApp.get(AuthenticateGenService);\n\n } catch (error) {\n logger.error(\"Errore in initialize AccessiModule:\", error);\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,0DA+BC;AA1CD,uCAA2C;AAC3C,+DAA0D;AAC1D,mDAAgE;AAChE,sCAAmC;AACnC,kEAKsC;AAEtC,SAAsB,uBAAuB,CAAC,GAAgB,EAAE,OAAuB;;QACnF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,yBAAyB,CAAC,CAAC;QAC7D,IAAA,gDAA8B,GAAE,CAAC;QAEjC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,IAAI,CAAC;YACD,iDAAiD;YACjD,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,GAAG,CAAC,CAAC;YAEpD,2CAA2C;YAC3C,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,6BAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC1F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,2DAA2D;YAC3D,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wCAAsB,CAAC,CAAC;YACxD,GAAG,CAAC,MAAM,CAAC,kBAAkB,GAAG,WAAW,CAAC;YAC5C,IAAA,uCAAqB,EAAC,WAAW,CAAC,CAAC;QAEvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAA,+CAA6B,EAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA;AAED,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,oFAAmF;AAA1E,gIAAA,sBAAsB,OAAA;AAC/B,yCAAuB;AACvB,gEAGsC;AAFlC,mHAAA,gBAAgB,OAAA;AAChB,kHAAA,eAAe,OAAA;AAEnB,wEAAsE;AAA7D,yHAAA,kBAAkB,OAAA","sourcesContent":["import { Application } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n AuthenticateGenService,\n setAccessiAuthService\n} from \"./middleware/authenticateGen\";\n\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions) {\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n beginAccessiAuthInitialization();\n\n console.log(\"Accessi initialized\");\n try {\n // Creiamo un'istanza Express separata per NestJS\n const nestExpressInstance = new ExpressAdapter(app);\n\n // Creiamo l'app NestJS attaccata a Express\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n\n nestApp.enableCors();\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n // Note: Swagger setup is now handled by the unified module\n await nestApp.init();\n const authService = nestApp.get(AuthenticateGenService);\n app.locals.accessiAuthService = authService;\n setAccessiAuthService(authService);\n\n } catch (error) {\n failAccessiAuthInitialization(error);\n logger.error(\"Errore in initialize AccessiModule:\", error);\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport { AccessiDatabaseUpdater } from \"./database-updates/AccessiDatabaseUpdater\";\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
@@ -8,5 +8,8 @@ export declare class AuthenticateGenService {
8
8
  constructor(accessiOptions: AccessiOptions, permissionService: PermissionService);
9
9
  authorize(req: Request, res: Response, next: NextFunction, options?: AccessiAuthorizationOptions): Promise<void | Response<any, Record<string, any>>>;
10
10
  }
11
+ export declare function beginAccessiAuthInitialization(): void;
12
+ export declare function setAccessiAuthService(service: AuthenticateGenService): void;
13
+ export declare function failAccessiAuthInitialization(error: unknown): void;
11
14
  export declare function authorizeAccessi(req: Request, res: Response, next: NextFunction, options?: AccessiAuthorizationOptions): Promise<void | Response<any, Record<string, any>>>;
12
15
  export declare const authenticateGen: typeof authorizeAccessi;
@@ -55,6 +55,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
55
55
  };
56
56
  Object.defineProperty(exports, "__esModule", { value: true });
57
57
  exports.authenticateGen = exports.AuthenticateGenService = void 0;
58
+ exports.beginAccessiAuthInitialization = beginAccessiAuthInitialization;
59
+ exports.setAccessiAuthService = setAccessiAuthService;
60
+ exports.failAccessiAuthInitialization = failAccessiAuthInitialization;
58
61
  exports.authorizeAccessi = authorizeAccessi;
59
62
  const jwt = __importStar(require("jsonwebtoken"));
60
63
  const common_1 = require("@nestjs/common");
@@ -62,6 +65,9 @@ const PermissionService_1 = require("../Services/PermissionService/PermissionSer
62
65
  const Logger_1 = require("../../Logger");
63
66
  const accessiRequirements_1 = require("./accessiRequirements");
64
67
  const logger = new Logger_1.Logger("AuthenticateGen");
68
+ const ACCESSI_AUTH_SERVICE_LOCALS_KEY = "accessiAuthService";
69
+ const ACCESSI_AUTH_SERVICE_GLOBAL_KEY = Symbol.for("emilsoftware.accessiAuthService");
70
+ const ACCESSI_AUTH_SERVICE_WAIT_MS = 15000;
65
71
  class AuthMiddlewareError extends Error {
66
72
  constructor(status, code, message, details) {
67
73
  super(message);
@@ -193,18 +199,100 @@ exports.AuthenticateGenService = AuthenticateGenService = __decorate([
193
199
  __param(0, (0, common_1.Inject)("ACCESSI_OPTIONS")),
194
200
  __metadata("design:paramtypes", [Object, PermissionService_1.PermissionService])
195
201
  ], AuthenticateGenService);
202
+ let authenticateGenServiceRef = null;
203
+ let authServiceBootstrapDeferred = null;
204
+ function createDeferred() {
205
+ let resolve;
206
+ let reject;
207
+ const promise = new Promise((res, rej) => {
208
+ resolve = res;
209
+ reject = rej;
210
+ });
211
+ return { promise, resolve, reject };
212
+ }
213
+ function isAuthenticateGenService(value) {
214
+ return Boolean(value &&
215
+ typeof value.authorize === "function");
216
+ }
217
+ function beginAccessiAuthInitialization() {
218
+ if (!authServiceBootstrapDeferred) {
219
+ authServiceBootstrapDeferred = createDeferred();
220
+ }
221
+ }
222
+ function setAccessiAuthService(service) {
223
+ authenticateGenServiceRef = service;
224
+ globalThis[ACCESSI_AUTH_SERVICE_GLOBAL_KEY] = service;
225
+ if (authServiceBootstrapDeferred) {
226
+ authServiceBootstrapDeferred.resolve(service);
227
+ authServiceBootstrapDeferred = null;
228
+ }
229
+ }
230
+ function failAccessiAuthInitialization(error) {
231
+ if (authServiceBootstrapDeferred) {
232
+ authServiceBootstrapDeferred.reject(error);
233
+ authServiceBootstrapDeferred = null;
234
+ }
235
+ }
236
+ function getAccessiAuthServiceFromRequest(req) {
237
+ var _a, _b;
238
+ const appLocalsService = (_b = (_a = req.app) === null || _a === void 0 ? void 0 : _a.locals) === null || _b === void 0 ? void 0 : _b[ACCESSI_AUTH_SERVICE_LOCALS_KEY];
239
+ if (isAuthenticateGenService(appLocalsService)) {
240
+ return appLocalsService;
241
+ }
242
+ const globalService = globalThis[ACCESSI_AUTH_SERVICE_GLOBAL_KEY];
243
+ if (isAuthenticateGenService(globalService)) {
244
+ return globalService;
245
+ }
246
+ return authenticateGenServiceRef;
247
+ }
248
+ function waitForBootstrappedService() {
249
+ return __awaiter(this, void 0, void 0, function* () {
250
+ if (!authServiceBootstrapDeferred) {
251
+ return null;
252
+ }
253
+ const bootstrapPromise = authServiceBootstrapDeferred.promise;
254
+ const timeoutPromise = new Promise((resolve) => {
255
+ setTimeout(() => resolve(null), ACCESSI_AUTH_SERVICE_WAIT_MS);
256
+ });
257
+ try {
258
+ const resolved = yield Promise.race([bootstrapPromise, timeoutPromise]);
259
+ return isAuthenticateGenService(resolved) ? resolved : null;
260
+ }
261
+ catch (_a) {
262
+ return null;
263
+ }
264
+ });
265
+ }
266
+ function resolveAccessiAuthService(req) {
267
+ return __awaiter(this, void 0, void 0, function* () {
268
+ const immediateService = getAccessiAuthServiceFromRequest(req);
269
+ if (immediateService) {
270
+ return immediateService;
271
+ }
272
+ const bootstrappedService = yield waitForBootstrappedService();
273
+ if (bootstrappedService) {
274
+ return bootstrappedService;
275
+ }
276
+ return getAccessiAuthServiceFromRequest(req);
277
+ });
278
+ }
196
279
  function authorizeAccessi(req, res, next, options) {
197
280
  return __awaiter(this, void 0, void 0, function* () {
198
- var _a, _b, _c;
199
- const authService = (_b = (_a = req === null || req === void 0 ? void 0 : req.app) === null || _a === void 0 ? void 0 : _a.locals) === null || _b === void 0 ? void 0 : _b.accessiAuthService;
281
+ var _a;
282
+ const authService = yield resolveAccessiAuthService(req);
200
283
  if (!authService) {
284
+ const status = authServiceBootstrapDeferred ? 503 : 500;
285
+ const message = authServiceBootstrapDeferred
286
+ ? "Accessi authentication service is still initializing"
287
+ : "Accessi authentication service not initialized";
201
288
  logger.error(`Authentication service not initialized ${JSON.stringify({
202
289
  method: req.method,
203
- path: (_c = req.originalUrl) !== null && _c !== void 0 ? _c : req.url,
290
+ path: (_a = req.originalUrl) !== null && _a !== void 0 ? _a : req.url,
291
+ status,
204
292
  })}`);
205
293
  return res
206
- .status(500)
207
- .json({ message: "Accessi authentication service not initialized" });
294
+ .status(status)
295
+ .json({ message });
208
296
  }
209
297
  return authService.authorize(req, res, next, options);
210
298
  });
@@ -1 +1 @@
1
- {"version":3,"file":"authenticateGen.js","sourceRoot":"","sources":["../../../src/accessi-module/middleware/authenticateGen.ts"],"names":[],"mappings":"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","sourcesContent":["import { NextFunction, Request, Response } from \"express\";\nimport * as jwt from \"jsonwebtoken\";\nimport { Inject, Injectable } from \"@nestjs/common\";\nimport { AccessiOptions } from \"../AccessiModule\";\nimport { PermissionService } from \"../Services/PermissionService/PermissionService\";\nimport { Logger } from \"../../Logger\";\nimport {\n AccessiAuthorizationOptions,\n AccessiCustomRequirementContext,\n GrantsResult,\n RequirementEvaluationError,\n buildRequirementTree,\n evaluateRequirement,\n} from \"./accessiRequirements\";\n\nconst logger = new Logger(\"AuthenticateGen\");\n\nclass AuthMiddlewareError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n public readonly details?: Record<string, unknown>\n ) {\n super(message);\n this.name = \"AuthMiddlewareError\";\n }\n}\n\nfunction resolveCodiceUtente(decoded: any): number | undefined {\n return (\n decoded?.userData?.utente?.codiceUtente ??\n decoded?.utente?.codiceUtente ??\n decoded?.codiceUtente\n );\n}\n\nfunction authError(\n status: number,\n code: string,\n message: string,\n details?: Record<string, unknown>\n) {\n return new AuthMiddlewareError(status, code, message, details);\n}\n\nfunction normalizeAuthError(error: unknown): AuthMiddlewareError {\n if (error instanceof AuthMiddlewareError) return error;\n if (error instanceof RequirementEvaluationError) {\n return authError(500, error.code, error.message);\n }\n if (error instanceof Error) {\n return authError(500, \"AUTH_INTERNAL_ERROR\", error.message, {\n originalError: error.name,\n });\n }\n return authError(500, \"AUTH_INTERNAL_ERROR\", \"Unexpected authentication error\");\n}\n\nfunction logAuthFailure(req: Request, authErr: AuthMiddlewareError) {\n const payload = {\n code: authErr.code,\n status: authErr.status,\n message: authErr.message,\n details: authErr.details,\n method: req.method,\n path: req.originalUrl ?? req.url,\n ip: req.ip,\n };\n\n const message = `${authErr.status >= 500 ? \"Authentication failure\" : \"Authentication denied\"} ${JSON.stringify(payload)}`;\n if (authErr.status >= 500) logger.error(message);\n else logger.warning(message);\n}\n\nasync function authorizeWithDependencies(\n req: Request,\n res: Response,\n next: NextFunction,\n options: AccessiAuthorizationOptions | undefined,\n accessiOptions: AccessiOptions,\n permissionService: PermissionService\n) {\n try {\n const authHeader = req.headers.authorization;\n if (!authHeader) {\n throw authError(401, \"AUTH_HEADER_MISSING\", \"Authorization header not found\");\n }\n\n const token = authHeader.split(\" \")[1];\n if (!token) {\n throw authError(\n 401,\n \"AUTH_TOKEN_MISSING\",\n \"Token not found in Authorization header\"\n );\n }\n\n const secret = accessiOptions?.jwtOptions?.secret ?? process.env.ACC_JWT_SECRET;\n if (!secret) {\n throw authError(500, \"AUTH_JWT_SECRET_MISSING\", \"JWT secret not configured\");\n }\n\n let decoded: any;\n try {\n decoded = jwt.verify(token, secret);\n } catch {\n throw authError(401, \"AUTH_TOKEN_INVALID\", \"Invalid JWT token\");\n }\n\n const codiceUtente = resolveCodiceUtente(decoded);\n if (!codiceUtente) {\n throw authError(\n 401,\n \"AUTH_USER_CODE_MISSING\",\n \"codiceUtente not found in token payload\"\n );\n }\n\n const requirementTree = buildRequirementTree(options);\n if (requirementTree) {\n if (!accessiOptions?.databaseOptions) {\n throw authError(\n 500,\n \"AUTH_DATABASE_OPTIONS_MISSING\",\n \"Database options not configured\"\n );\n }\n\n let grantsResultCache: GrantsResult | null = null;\n const getGrantsResult = async () => {\n if (!grantsResultCache) {\n grantsResultCache = await permissionService.getUserRolesAndGrants(\n codiceUtente\n );\n }\n return grantsResultCache;\n };\n\n const requirementContext: AccessiCustomRequirementContext = {\n req,\n decodedToken: decoded,\n userCode: codiceUtente,\n getGrantsResult,\n };\n\n const hasPermissions = await evaluateRequirement(\n requirementTree,\n requirementContext,\n options\n );\n\n if (!hasPermissions) {\n throw authError(\n 403,\n \"AUTH_INSUFFICIENT_PERMISSIONS\",\n \"User does not have required permissions\"\n );\n }\n\n (req as any).userGrants = await getGrantsResult();\n }\n\n (req as any).data = decoded;\n return next();\n } catch (error: unknown) {\n const authErr = normalizeAuthError(error);\n logAuthFailure(req, authErr);\n const publicMessage =\n authErr.status === 403\n ? \"Forbidden\"\n : authErr.status >= 500\n ? \"Internal server error\"\n : \"Unauthorized\";\n return res\n .status(authErr.status)\n .json({ message: publicMessage, error: authErr.message, code: authErr.code });\n }\n}\n\n@Injectable()\nexport class AuthenticateGenService {\n constructor(\n @Inject(\"ACCESSI_OPTIONS\")\n private readonly accessiOptions: AccessiOptions,\n private readonly permissionService: PermissionService\n ) { }\n\n async authorize(\n req: Request,\n res: Response,\n next: NextFunction,\n options?: AccessiAuthorizationOptions\n ) {\n return authorizeWithDependencies(\n req,\n res,\n next,\n options,\n this.accessiOptions,\n this.permissionService\n );\n }\n}\n\nexport async function authorizeAccessi(\n req: Request,\n res: Response,\n next: NextFunction,\n options?: AccessiAuthorizationOptions\n) {\n const authService = (req as any)?.app?.locals?.accessiAuthService as\n | AuthenticateGenService\n | undefined;\n if (!authService) {\n logger.error(\n `Authentication service not initialized ${JSON.stringify({\n method: req.method,\n path: req.originalUrl ?? req.url,\n })}`\n );\n return res\n .status(500)\n .json({ message: \"Accessi authentication service not initialized\" });\n }\n\n return authService.authorize(req, res, next, options);\n}\n\nexport const authenticateGen = authorizeAccessi;\n"]}
1
+ {"version":3,"file":"authenticateGen.js","sourceRoot":"","sources":["../../../src/accessi-module/middleware/authenticateGen.ts"],"names":[],"mappings":"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","sourcesContent":["import { NextFunction, Request, Response } from \"express\";\nimport * as jwt from \"jsonwebtoken\";\nimport { Inject, Injectable } from \"@nestjs/common\";\nimport { AccessiOptions } from \"../AccessiModule\";\nimport { PermissionService } from \"../Services/PermissionService/PermissionService\";\nimport { Logger } from \"../../Logger\";\nimport {\n AccessiAuthorizationOptions,\n AccessiCustomRequirementContext,\n GrantsResult,\n RequirementEvaluationError,\n buildRequirementTree,\n evaluateRequirement,\n} from \"./accessiRequirements\";\n\nconst logger = new Logger(\"AuthenticateGen\");\nconst ACCESSI_AUTH_SERVICE_LOCALS_KEY = \"accessiAuthService\";\nconst ACCESSI_AUTH_SERVICE_GLOBAL_KEY = Symbol.for(\"emilsoftware.accessiAuthService\");\nconst ACCESSI_AUTH_SERVICE_WAIT_MS = 15000;\n\ntype Deferred<T> = {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason?: unknown) => void;\n};\n\nclass AuthMiddlewareError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n public readonly details?: Record<string, unknown>\n ) {\n super(message);\n this.name = \"AuthMiddlewareError\";\n }\n}\n\nfunction resolveCodiceUtente(decoded: any): number | undefined {\n return (\n decoded?.userData?.utente?.codiceUtente ??\n decoded?.utente?.codiceUtente ??\n decoded?.codiceUtente\n );\n}\n\nfunction authError(\n status: number,\n code: string,\n message: string,\n details?: Record<string, unknown>\n) {\n return new AuthMiddlewareError(status, code, message, details);\n}\n\nfunction normalizeAuthError(error: unknown): AuthMiddlewareError {\n if (error instanceof AuthMiddlewareError) return error;\n if (error instanceof RequirementEvaluationError) {\n return authError(500, error.code, error.message);\n }\n if (error instanceof Error) {\n return authError(500, \"AUTH_INTERNAL_ERROR\", error.message, {\n originalError: error.name,\n });\n }\n return authError(500, \"AUTH_INTERNAL_ERROR\", \"Unexpected authentication error\");\n}\n\nfunction logAuthFailure(req: Request, authErr: AuthMiddlewareError) {\n const payload = {\n code: authErr.code,\n status: authErr.status,\n message: authErr.message,\n details: authErr.details,\n method: req.method,\n path: req.originalUrl ?? req.url,\n ip: req.ip,\n };\n\n const message = `${authErr.status >= 500 ? \"Authentication failure\" : \"Authentication denied\"} ${JSON.stringify(payload)}`;\n if (authErr.status >= 500) logger.error(message);\n else logger.warning(message);\n}\n\nasync function authorizeWithDependencies(\n req: Request,\n res: Response,\n next: NextFunction,\n options: AccessiAuthorizationOptions | undefined,\n accessiOptions: AccessiOptions,\n permissionService: PermissionService\n) {\n try {\n const authHeader = req.headers.authorization;\n if (!authHeader) {\n throw authError(401, \"AUTH_HEADER_MISSING\", \"Authorization header not found\");\n }\n\n const token = authHeader.split(\" \")[1];\n if (!token) {\n throw authError(\n 401,\n \"AUTH_TOKEN_MISSING\",\n \"Token not found in Authorization header\"\n );\n }\n\n const secret = accessiOptions?.jwtOptions?.secret ?? process.env.ACC_JWT_SECRET;\n if (!secret) {\n throw authError(500, \"AUTH_JWT_SECRET_MISSING\", \"JWT secret not configured\");\n }\n\n let decoded: any;\n try {\n decoded = jwt.verify(token, secret);\n } catch {\n throw authError(401, \"AUTH_TOKEN_INVALID\", \"Invalid JWT token\");\n }\n\n const codiceUtente = resolveCodiceUtente(decoded);\n if (!codiceUtente) {\n throw authError(\n 401,\n \"AUTH_USER_CODE_MISSING\",\n \"codiceUtente not found in token payload\"\n );\n }\n\n const requirementTree = buildRequirementTree(options);\n if (requirementTree) {\n if (!accessiOptions?.databaseOptions) {\n throw authError(\n 500,\n \"AUTH_DATABASE_OPTIONS_MISSING\",\n \"Database options not configured\"\n );\n }\n\n let grantsResultCache: GrantsResult | null = null;\n const getGrantsResult = async () => {\n if (!grantsResultCache) {\n grantsResultCache = await permissionService.getUserRolesAndGrants(\n codiceUtente\n );\n }\n return grantsResultCache;\n };\n\n const requirementContext: AccessiCustomRequirementContext = {\n req,\n decodedToken: decoded,\n userCode: codiceUtente,\n getGrantsResult,\n };\n\n const hasPermissions = await evaluateRequirement(\n requirementTree,\n requirementContext,\n options\n );\n\n if (!hasPermissions) {\n throw authError(\n 403,\n \"AUTH_INSUFFICIENT_PERMISSIONS\",\n \"User does not have required permissions\"\n );\n }\n\n (req as any).userGrants = await getGrantsResult();\n }\n\n (req as any).data = decoded;\n return next();\n } catch (error: unknown) {\n const authErr = normalizeAuthError(error);\n logAuthFailure(req, authErr);\n const publicMessage =\n authErr.status === 403\n ? \"Forbidden\"\n : authErr.status >= 500\n ? \"Internal server error\"\n : \"Unauthorized\";\n return res\n .status(authErr.status)\n .json({ message: publicMessage, error: authErr.message, code: authErr.code });\n }\n}\n\n@Injectable()\nexport class AuthenticateGenService {\n constructor(\n @Inject(\"ACCESSI_OPTIONS\")\n private readonly accessiOptions: AccessiOptions,\n private readonly permissionService: PermissionService\n ) { }\n\n async authorize(\n req: Request,\n res: Response,\n next: NextFunction,\n options?: AccessiAuthorizationOptions\n ) {\n return authorizeWithDependencies(\n req,\n res,\n next,\n options,\n this.accessiOptions,\n this.permissionService\n );\n }\n}\n\nlet authenticateGenServiceRef: AuthenticateGenService | null = null;\nlet authServiceBootstrapDeferred: Deferred<AuthenticateGenService> | null = null;\n\nfunction createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (reason?: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\n\nfunction isAuthenticateGenService(value: unknown): value is AuthenticateGenService {\n return Boolean(\n value &&\n typeof (value as { authorize?: unknown }).authorize === \"function\"\n );\n}\n\nexport function beginAccessiAuthInitialization() {\n if (!authServiceBootstrapDeferred) {\n authServiceBootstrapDeferred = createDeferred<AuthenticateGenService>();\n }\n}\n\nexport function setAccessiAuthService(service: AuthenticateGenService) {\n authenticateGenServiceRef = service;\n (globalThis as Record<symbol, unknown>)[ACCESSI_AUTH_SERVICE_GLOBAL_KEY] = service;\n if (authServiceBootstrapDeferred) {\n authServiceBootstrapDeferred.resolve(service);\n authServiceBootstrapDeferred = null;\n }\n}\n\nexport function failAccessiAuthInitialization(error: unknown) {\n if (authServiceBootstrapDeferred) {\n authServiceBootstrapDeferred.reject(error);\n authServiceBootstrapDeferred = null;\n }\n}\n\nfunction getAccessiAuthServiceFromRequest(req: Request): AuthenticateGenService | null {\n const appLocalsService = (req.app?.locals as Record<string, unknown> | undefined)?.[\n ACCESSI_AUTH_SERVICE_LOCALS_KEY\n ];\n\n if (isAuthenticateGenService(appLocalsService)) {\n return appLocalsService as AuthenticateGenService;\n }\n\n const globalService = (globalThis as Record<symbol, unknown>)[\n ACCESSI_AUTH_SERVICE_GLOBAL_KEY\n ];\n if (isAuthenticateGenService(globalService)) {\n return globalService as AuthenticateGenService;\n }\n\n return authenticateGenServiceRef;\n}\n\nasync function waitForBootstrappedService(): Promise<AuthenticateGenService | null> {\n if (!authServiceBootstrapDeferred) {\n return null;\n }\n\n const bootstrapPromise = authServiceBootstrapDeferred.promise;\n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), ACCESSI_AUTH_SERVICE_WAIT_MS);\n });\n\n try {\n const resolved = await Promise.race([bootstrapPromise, timeoutPromise]);\n return isAuthenticateGenService(resolved) ? resolved : null;\n } catch {\n return null;\n }\n}\n\nasync function resolveAccessiAuthService(req: Request): Promise<AuthenticateGenService | null> {\n const immediateService = getAccessiAuthServiceFromRequest(req);\n if (immediateService) {\n return immediateService;\n }\n\n const bootstrappedService = await waitForBootstrappedService();\n if (bootstrappedService) {\n return bootstrappedService;\n }\n\n return getAccessiAuthServiceFromRequest(req);\n}\n\nexport async function authorizeAccessi(\n req: Request,\n res: Response,\n next: NextFunction,\n options?: AccessiAuthorizationOptions\n) {\n const authService = await resolveAccessiAuthService(req);\n\n if (!authService) {\n const status = authServiceBootstrapDeferred ? 503 : 500;\n const message = authServiceBootstrapDeferred\n ? \"Accessi authentication service is still initializing\"\n : \"Accessi authentication service not initialized\";\n logger.error(\n `Authentication service not initialized ${JSON.stringify({\n method: req.method,\n path: req.originalUrl ?? req.url,\n status,\n })}`\n );\n return res\n .status(status)\n .json({ message });\n }\n\n return authService.authorize(req, res, next, options);\n}\n\nexport const authenticateGen = authorizeAccessi;\n"]}
@@ -19,6 +19,7 @@ const platform_express_1 = require("@nestjs/platform-express");
19
19
  const SwaggerConfig_1 = require("./swagger/SwaggerConfig");
20
20
  const Logger_1 = require("./Logger");
21
21
  const EmilsoftwareModule_1 = require("./EmilsoftwareModule");
22
+ const authenticateGen_1 = require("./accessi-module/middleware/authenticateGen");
22
23
  /**
23
24
  * Initializes the unified module that combines Accessi and Allegati functionality
24
25
  * @param app Express application instance
@@ -27,6 +28,9 @@ const EmilsoftwareModule_1 = require("./EmilsoftwareModule");
27
28
  function initEmilsoftwareModule(app, options) {
28
29
  return __awaiter(this, void 0, void 0, function* () {
29
30
  const logger = new Logger_1.Logger(initEmilsoftwareModule.name);
31
+ if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
32
+ (0, authenticateGen_1.beginAccessiAuthInitialization)();
33
+ }
30
34
  try {
31
35
  // Isolate Nest on a dedicated Express instance and dispatch only module routes.
32
36
  // This keeps pre-existing routes/middlewares on the host app untouched.
@@ -53,9 +57,17 @@ function initEmilsoftwareModule(app, options) {
53
57
  // Setup unified Swagger documentation for all modules
54
58
  (0, SwaggerConfig_1.setupSwagger)(nestApp);
55
59
  yield nestApp.init();
60
+ if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
61
+ const authService = nestApp.get(authenticateGen_1.AuthenticateGenService);
62
+ app.locals.accessiAuthService = authService;
63
+ (0, authenticateGen_1.setAccessiAuthService)(authService);
64
+ }
56
65
  logger.info("Emilsoftware module initialized successfully");
57
66
  }
58
67
  catch (error) {
68
+ if (options === null || options === void 0 ? void 0 : options.accessiOptions) {
69
+ (0, authenticateGen_1.failAccessiAuthInitialization)(error);
70
+ }
59
71
  logger.error("Error initializing Emilsoftware Module:", error);
60
72
  throw error;
61
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAYA,wDA2CC;AAvDD,sDAAwD;AACxD,uCAA2C;AAC3C,+DAA0D;AAC1D,2DAAuD;AACvD,qCAAkC;AAClC,6DAA+E;AAE/E;;;;GAIG;AACH,SAAsB,sBAAsB,CAAC,GAAgB,EAAE,OAA4B;;QACvF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAE/D,IAAI,CAAC;YACD,gFAAgF;YAChF,wEAAwE;YACxE,MAAM,WAAW,GAAG,IAAA,iBAAO,GAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CACjC,IAAI,KAAK,MAAM;gBACf,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBACxB,IAAI,KAAK,UAAU;gBACnB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;gBAC5B,IAAI,KAAK,eAAe,CAAC;YAE7B,GAAG,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;gBAChC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,OAAO,IAAI,EAAE,CAAC;gBAClB,CAAC;gBACD,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC,CAAC,CAAC;YAEH,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,WAAW,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,uCAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC/F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,sDAAsD;YACtD,IAAA,4BAAY,EAAC,OAAO,CAAC,CAAC;YAEtB,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YAErB,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAEhE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;YAC/D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { setupSwagger } from \"./swagger/SwaggerConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n */\nexport async function initEmilsoftwareModule(app: Application, options: EmilsoftwareOptions) {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n path === \"/swagger\" ||\n path.startsWith(\"/swagger/\") ||\n path === \"/swagger-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n\n nestApp.enableCors();\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n // Setup unified Swagger documentation for all modules\n setupSwagger(nestApp);\n\n await nestApp.init();\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n } catch (error) {\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n} \n"]}
1
+ {"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAkBA,wDAsDC;AAxED,sDAAwD;AACxD,uCAA2C;AAC3C,+DAA0D;AAC1D,2DAAuD;AACvD,qCAAkC;AAClC,6DAA+E;AAC/E,iFAKqD;AAErD;;;;GAIG;AACH,SAAsB,sBAAsB,CAAC,GAAgB,EAAE,OAA4B;;QACvF,MAAM,MAAM,GAAW,IAAI,eAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,EAAE,CAAC;YAC1B,IAAA,gDAA8B,GAAE,CAAC;QACrC,CAAC;QAED,IAAI,CAAC;YACD,gFAAgF;YAChF,wEAAwE;YACxE,MAAM,WAAW,GAAG,IAAA,iBAAO,GAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CACjC,IAAI,KAAK,MAAM;gBACf,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBACxB,IAAI,KAAK,UAAU;gBACnB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;gBAC5B,IAAI,KAAK,eAAe,CAAC;YAE7B,GAAG,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;gBAChC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,OAAO,IAAI,EAAE,CAAC;gBAClB,CAAC;gBACD,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC,CAAC,CAAC;YAEH,MAAM,mBAAmB,GAAG,IAAI,iCAAc,CAAC,WAAW,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,uCAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE;gBAC/F,UAAU,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE;gBAC3B,OAAO,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YAEH,sDAAsD;YACtD,IAAA,4BAAY,EAAC,OAAO,CAAC,CAAC;YAEtB,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,EAAE,CAAC;gBAC1B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wCAAsB,CAAC,CAAC;gBACxD,GAAG,CAAC,MAAM,CAAC,kBAAkB,GAAG,WAAW,CAAC;gBAC5C,IAAA,uCAAqB,EAAC,WAAW,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAEhE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,EAAE,CAAC;gBAC1B,IAAA,+CAA6B,EAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;YAC/D,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CAAA","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { setupSwagger } from \"./swagger/SwaggerConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n AuthenticateGenService,\n setAccessiAuthService\n} from \"./accessi-module/middleware/authenticateGen\";\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n */\nexport async function initEmilsoftwareModule(app: Application, options: EmilsoftwareOptions) {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n if (options?.accessiOptions) {\n beginAccessiAuthInitialization();\n }\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n path === \"/swagger\" ||\n path.startsWith(\"/swagger/\") ||\n path === \"/swagger-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n\n nestApp.enableCors();\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n // Setup unified Swagger documentation for all modules\n setupSwagger(nestApp);\n\n await nestApp.init();\n if (options?.accessiOptions) {\n const authService = nestApp.get(AuthenticateGenService);\n app.locals.accessiAuthService = authService;\n setAccessiAuthService(authService);\n }\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n } catch (error) {\n if (options?.accessiOptions) {\n failAccessiAuthInitialization(error);\n }\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emilsoftware-utilities",
3
- "version": "1.7.7",
3
+ "version": "1.8.0-dev.1",
4
4
  "description": "Utilities for EmilSoftware",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -9,6 +9,8 @@
9
9
  "release": "semantic-release",
10
10
  "build": "tsc && npm run copy-views",
11
11
  "copy-views": "node copy-views.js",
12
+ "db:update:accessi": "ts-node src/accessi-module/database-updates/runAccessiDbUpdate.ts",
13
+ "db:update:accessi:dist": "npm run build && node dist/accessi-module/database-updates/runAccessiDbUpdate.js",
12
14
  "prepublishOnly": "npm run build",
13
15
  "test:allegati": "ts-node src/tests/allegati/allegati.ts",
14
16
  "test:accessi": "npm run build && ts-node test/index.js"