emilsoftware-utilities 2.0.0-dev.24 → 2.0.0-dev.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.MD +185 -182
  2. package/dist/ContractGenerator.js.map +1 -1
  3. package/dist/DailyFileTransport.js.map +1 -1
  4. package/dist/DatabaseUpdater.js +24 -24
  5. package/dist/DatabaseUpdater.js.map +1 -1
  6. package/dist/EmilsoftwareModule.js.map +1 -1
  7. package/dist/ExecutionTimeLogger.js.map +1 -1
  8. package/dist/Orm.js.map +1 -1
  9. package/dist/RoutesLoggerMiddleware.js.map +1 -1
  10. package/dist/Utilities.js.map +1 -1
  11. package/dist/accessi-module/AccessiModule.js.map +1 -1
  12. package/dist/accessi-module/Console/console.js.map +1 -1
  13. package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
  14. package/dist/accessi-module/Controllers/FiltriController.js.map +1 -1
  15. package/dist/accessi-module/Controllers/PermissionController.js.map +1 -1
  16. package/dist/accessi-module/Controllers/UserController.js.map +1 -1
  17. package/dist/accessi-module/Dtos/Abilitazione.js.map +1 -1
  18. package/dist/accessi-module/Dtos/AbilitazioneMenu.js.map +1 -1
  19. package/dist/accessi-module/Dtos/AssignPermissionsToUserRequest.js.map +1 -1
  20. package/dist/accessi-module/Dtos/AssignRolesToUserRequest.js.map +1 -1
  21. package/dist/accessi-module/Dtos/BaseResponse.js.map +1 -1
  22. package/dist/accessi-module/Dtos/FiltriUtente.js.map +1 -1
  23. package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
  24. package/dist/accessi-module/Dtos/GetMenusResponse.js.map +1 -1
  25. package/dist/accessi-module/Dtos/GetRolesResponse.js.map +1 -1
  26. package/dist/accessi-module/Dtos/GetUsersResponse.js.map +1 -1
  27. package/dist/accessi-module/Dtos/LoginRequest.js.map +1 -1
  28. package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
  29. package/dist/accessi-module/Dtos/Permission.js.map +1 -1
  30. package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
  31. package/dist/accessi-module/Dtos/Role.js.map +1 -1
  32. package/dist/accessi-module/Dtos/RuoliMenu.js.map +1 -1
  33. package/dist/accessi-module/Dtos/SetStatoRegistrazione.js.map +1 -1
  34. package/dist/accessi-module/Dtos/StatoRegistrazione.js.map +1 -1
  35. package/dist/accessi-module/Dtos/TipoAbilitazione.js.map +1 -1
  36. package/dist/accessi-module/Dtos/TipoFiltro.js.map +1 -1
  37. package/dist/accessi-module/Dtos/TokenResult.js.map +1 -1
  38. package/dist/accessi-module/Dtos/UpdateEnabledStatusRequest.js.map +1 -1
  39. package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
  40. package/dist/accessi-module/Dtos/UserGrantsDto.js.map +1 -1
  41. package/dist/accessi-module/Dtos/index.js.map +1 -1
  42. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  43. package/dist/accessi-module/Services/ConfiguratorService/ConfiguratorService.js.map +1 -1
  44. package/dist/accessi-module/Services/EmailService/EmailService.js +11 -11
  45. package/dist/accessi-module/Services/EmailService/EmailService.js.map +1 -1
  46. package/dist/accessi-module/Services/FiltriService/FiltriService.js.map +1 -1
  47. package/dist/accessi-module/Services/PermissionService/PermissionService.js +118 -118
  48. package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
  49. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js +4 -4
  50. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js.map +1 -1
  51. package/dist/accessi-module/Services/UserService/UserService.js +72 -72
  52. package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
  53. package/dist/accessi-module/Views/reset-password.html +213 -213
  54. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.d.ts +1 -0
  55. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +56 -42
  56. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
  57. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js.map +1 -1
  58. package/dist/accessi-module/index.js.map +1 -1
  59. package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
  60. package/dist/accessi-module/middleware/accessiRequirements.js.map +1 -1
  61. package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
  62. package/dist/accessi-module/security/accessControl.js.map +1 -1
  63. package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
  64. package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
  65. package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
  66. package/dist/allegati-module/AllegatiModule.js.map +1 -1
  67. package/dist/allegati-module/Controllers/AllegatiController.js.map +1 -1
  68. package/dist/allegati-module/Dtos/AllegatoDto.js.map +1 -1
  69. package/dist/allegati-module/Dtos/BaseResponse.js.map +1 -1
  70. package/dist/allegati-module/Dtos/UploadSingleFileRequest.js.map +1 -1
  71. package/dist/allegati-module/Dtos/index.js.map +1 -1
  72. package/dist/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.js.map +1 -1
  73. package/dist/allegati-module/Dtos/responses/GetListResponse.js.map +1 -1
  74. package/dist/allegati-module/Dtos/responses/UploadAllegatoResponseDto.js.map +1 -1
  75. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js +49 -49
  76. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js.map +1 -1
  77. package/dist/allegati-module/index.js.map +1 -1
  78. package/dist/autobind.js.map +1 -1
  79. package/dist/emilsoftware-utilities-2.0.0-dev.25.tgz +0 -0
  80. package/dist/firebird-compat.js.map +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/initEmilsoftwareModule.js.map +1 -1
  83. package/dist/swagger/SwaggerConfig.js.map +1 -1
  84. package/package.json +103 -103
  85. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.d.ts +0 -12
  86. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.js +0 -9
  87. package/dist/accessi-module/Console/generated/model/abilitazioneMenuIcona.js.map +0 -1
  88. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.d.ts +0 -12
  89. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.js +0 -9
  90. package/dist/accessi-module/Console/generated/model/abilitazioneMenuNote.js.map +0 -1
  91. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.d.ts +0 -12
  92. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.js +0 -9
  93. package/dist/accessi-module/Console/generated/model/abilitazioneMenuPagina.js.map +0 -1
  94. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.d.ts +0 -12
  95. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.js +0 -9
  96. package/dist/accessi-module/Console/generated/model/abilitazioneMenuTipo.js.map +0 -1
  97. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.d.ts +0 -13
  98. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.js +0 -9
  99. package/dist/accessi-module/Console/generated/model/publicRegisterRequestCellulare.js.map +0 -1
  100. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.d.ts +0 -13
  101. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.js +0 -9
  102. package/dist/accessi-module/Console/generated/model/registerRequestCellulare.js.map +0 -1
  103. package/dist/accessi-module/Console/generated/model/userDtoAvatar.d.ts +0 -13
  104. package/dist/accessi-module/Console/generated/model/userDtoAvatar.js +0 -9
  105. package/dist/accessi-module/Console/generated/model/userDtoAvatar.js.map +0 -1
  106. package/dist/accessi-module/Console/generated/model/userDtoCellulare.d.ts +0 -13
  107. package/dist/accessi-module/Console/generated/model/userDtoCellulare.js +0 -9
  108. package/dist/accessi-module/Console/generated/model/userDtoCellulare.js.map +0 -1
  109. package/dist/accessi-module/Console/openApiClient.d.ts +0 -34
  110. package/dist/accessi-module/Console/openApiClient.js +0 -111
  111. package/dist/accessi-module/Console/openApiClient.js.map +0 -1
@@ -1,213 +1,213 @@
1
- <!DOCTYPE html>
2
- <html lang="it">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Reset Password</title>
8
- <style>
9
- * {
10
- box-sizing: border-box;
11
- margin: 0;
12
- padding: 0;
13
- font-family: Arial, sans-serif;
14
- }
15
-
16
- body {
17
- display: flex;
18
- justify-content: center;
19
- align-items: center;
20
- height: 100vh;
21
- background: linear-gradient(135deg, #0068ae, #004e80, #002c50);
22
- color: #fff;
23
- }
24
-
25
- .container {
26
- background: rgba(255, 255, 255, 0.15);
27
- padding: 25px;
28
- border-radius: 12px;
29
- backdrop-filter: blur(12px);
30
- box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.3);
31
- width: 380px;
32
- text-align: center;
33
- border: 1px solid rgba(255, 255, 255, 0.2);
34
- }
35
-
36
- h1 {
37
- font-size: 24px;
38
- margin-bottom: 15px;
39
- color: #ffffff;
40
- }
41
-
42
- .form-group {
43
- margin: 12px 0;
44
- text-align: left;
45
- }
46
-
47
- label {
48
- font-size: 14px;
49
- font-weight: bold;
50
- display: block;
51
- margin-bottom: 5px;
52
- color: #ffffff;
53
- }
54
-
55
- input {
56
- width: 100%;
57
- padding: 12px;
58
- border: none;
59
- border-radius: 6px;
60
- font-size: 14px;
61
- margin-top: 5px;
62
- background: rgba(255, 255, 255, 0.15);
63
- color: #ffffff;
64
- border: 1px solid rgba(255, 255, 255, 0.3);
65
- }
66
-
67
- input:focus {
68
- outline: none;
69
- border: 2px solid #ffffff;
70
- background: rgba(255, 255, 255, 0.2);
71
- }
72
-
73
- .error {
74
- color: #ff6b6b;
75
- font-size: 12px;
76
- margin-top: 5px;
77
- display: none;
78
- }
79
-
80
- button {
81
- background: linear-gradient(90deg, #0080ff, #0068ae);
82
- border: none;
83
- padding: 12px;
84
- font-size: 16px;
85
- border-radius: 6px;
86
- width: 100%;
87
- color: #ffffff;
88
- cursor: pointer;
89
- font-weight: bold;
90
- transition: all 0.3s ease;
91
- box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2);
92
- }
93
-
94
- button:hover {
95
- background: linear-gradient(90deg, #0095ff, #0070c0);
96
- transform: scale(1.05);
97
- }
98
- </style>
99
- </head>
100
-
101
- <body>
102
- <div class="container">
103
- <h1>Reimposta la tua password</h1>
104
- <form id="resetForm">
105
- <input type="hidden" id="token" value="">
106
- <input type="hidden" id="returnUrl" value="">
107
- <input type="hidden" id="prefix" value="">
108
-
109
- <div class="form-group">
110
- <label for="password">Nuova Password:</label>
111
- <input type="password" id="password" required>
112
- <p class="error" id="passwordError">La password deve avere almeno 8 caratteri.</p>
113
- </div>
114
-
115
- <div class="form-group">
116
- <label for="confirmPassword">Conferma Password:</label>
117
- <input type="password" id="confirmPassword" required>
118
- <p class="error" id="confirmError">Le password non corrispondono.</p>
119
- </div>
120
-
121
- <button type="submit">Aggiorna password</button>
122
- </form>
123
- </div>
124
-
125
- <script>
126
- document.addEventListener("DOMContentLoaded", function () {
127
- function resolveSafeReturnUrl(rawReturnUrl) {
128
- if (!rawReturnUrl) {
129
- return "/";
130
- }
131
-
132
- if (rawReturnUrl.startsWith("/")) {
133
- return rawReturnUrl;
134
- }
135
-
136
- try {
137
- const parsed = new URL(rawReturnUrl, window.location.origin);
138
- if (parsed.origin === window.location.origin) {
139
- return `${parsed.pathname}${parsed.search}${parsed.hash}`;
140
- }
141
- } catch (error) {}
142
-
143
- return "/";
144
- }
145
-
146
- function resolveSafePrefix(rawPrefix) {
147
- if (!rawPrefix) {
148
- return "";
149
- }
150
-
151
- let normalizedPrefix = rawPrefix.trim();
152
- if (!normalizedPrefix.startsWith("/")) {
153
- normalizedPrefix = "/" + normalizedPrefix;
154
- }
155
-
156
- if (normalizedPrefix.endsWith("/")) {
157
- normalizedPrefix = normalizedPrefix.slice(0, -1);
158
- }
159
-
160
- return /^\/[A-Za-z0-9/_-]*$/.test(normalizedPrefix) ? normalizedPrefix : "";
161
- }
162
-
163
- const urlParams = new URLSearchParams(window.location.search);
164
- const token = window.location.pathname.split("/").pop();
165
- const returnUrl = resolveSafeReturnUrl(urlParams.get("returnUrl"));
166
- const prefix = resolveSafePrefix(urlParams.get("prefix"));
167
-
168
- document.getElementById("token").value = token;
169
- document.getElementById("returnUrl").value = returnUrl;
170
- document.getElementById("prefix").value = prefix;
171
-
172
- document.getElementById("resetForm").addEventListener("submit", async function (event) {
173
- event.preventDefault();
174
- const password = document.getElementById("password").value;
175
- const confirmPassword = document.getElementById("confirmPassword").value;
176
- const passwordError = document.getElementById("passwordError");
177
- const confirmError = document.getElementById("confirmError");
178
-
179
- passwordError.style.display = "none";
180
- confirmError.style.display = "none";
181
-
182
- if (password.length < 8) {
183
- passwordError.style.display = "block";
184
- return;
185
- }
186
-
187
- if (password !== confirmPassword) {
188
- confirmError.style.display = "block";
189
- return;
190
- }
191
-
192
- try {
193
- const response = await fetch(`${prefix}/api/accessi/auth/confirm-reset-password/${token}`, {
194
- method: "POST",
195
- headers: { "Content-Type": "application/json" },
196
- body: JSON.stringify({ newPassword: password })
197
- });
198
-
199
- const data = await response.json();
200
- alert(data.message || "Password aggiornata con successo!");
201
- } catch (error) {
202
- alert("Errore nel reset della password. Riprova piu tardi.");
203
- } finally {
204
- setTimeout(() => {
205
- window.location.href = returnUrl;
206
- }, 500);
207
- }
208
- });
209
- });
210
- </script>
211
- </body>
212
-
213
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="it">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Reset Password</title>
8
+ <style>
9
+ * {
10
+ box-sizing: border-box;
11
+ margin: 0;
12
+ padding: 0;
13
+ font-family: Arial, sans-serif;
14
+ }
15
+
16
+ body {
17
+ display: flex;
18
+ justify-content: center;
19
+ align-items: center;
20
+ height: 100vh;
21
+ background: linear-gradient(135deg, #0068ae, #004e80, #002c50);
22
+ color: #fff;
23
+ }
24
+
25
+ .container {
26
+ background: rgba(255, 255, 255, 0.15);
27
+ padding: 25px;
28
+ border-radius: 12px;
29
+ backdrop-filter: blur(12px);
30
+ box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.3);
31
+ width: 380px;
32
+ text-align: center;
33
+ border: 1px solid rgba(255, 255, 255, 0.2);
34
+ }
35
+
36
+ h1 {
37
+ font-size: 24px;
38
+ margin-bottom: 15px;
39
+ color: #ffffff;
40
+ }
41
+
42
+ .form-group {
43
+ margin: 12px 0;
44
+ text-align: left;
45
+ }
46
+
47
+ label {
48
+ font-size: 14px;
49
+ font-weight: bold;
50
+ display: block;
51
+ margin-bottom: 5px;
52
+ color: #ffffff;
53
+ }
54
+
55
+ input {
56
+ width: 100%;
57
+ padding: 12px;
58
+ border: none;
59
+ border-radius: 6px;
60
+ font-size: 14px;
61
+ margin-top: 5px;
62
+ background: rgba(255, 255, 255, 0.15);
63
+ color: #ffffff;
64
+ border: 1px solid rgba(255, 255, 255, 0.3);
65
+ }
66
+
67
+ input:focus {
68
+ outline: none;
69
+ border: 2px solid #ffffff;
70
+ background: rgba(255, 255, 255, 0.2);
71
+ }
72
+
73
+ .error {
74
+ color: #ff6b6b;
75
+ font-size: 12px;
76
+ margin-top: 5px;
77
+ display: none;
78
+ }
79
+
80
+ button {
81
+ background: linear-gradient(90deg, #0080ff, #0068ae);
82
+ border: none;
83
+ padding: 12px;
84
+ font-size: 16px;
85
+ border-radius: 6px;
86
+ width: 100%;
87
+ color: #ffffff;
88
+ cursor: pointer;
89
+ font-weight: bold;
90
+ transition: all 0.3s ease;
91
+ box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2);
92
+ }
93
+
94
+ button:hover {
95
+ background: linear-gradient(90deg, #0095ff, #0070c0);
96
+ transform: scale(1.05);
97
+ }
98
+ </style>
99
+ </head>
100
+
101
+ <body>
102
+ <div class="container">
103
+ <h1>Reimposta la tua password</h1>
104
+ <form id="resetForm">
105
+ <input type="hidden" id="token" value="">
106
+ <input type="hidden" id="returnUrl" value="">
107
+ <input type="hidden" id="prefix" value="">
108
+
109
+ <div class="form-group">
110
+ <label for="password">Nuova Password:</label>
111
+ <input type="password" id="password" required>
112
+ <p class="error" id="passwordError">La password deve avere almeno 8 caratteri.</p>
113
+ </div>
114
+
115
+ <div class="form-group">
116
+ <label for="confirmPassword">Conferma Password:</label>
117
+ <input type="password" id="confirmPassword" required>
118
+ <p class="error" id="confirmError">Le password non corrispondono.</p>
119
+ </div>
120
+
121
+ <button type="submit">Aggiorna password</button>
122
+ </form>
123
+ </div>
124
+
125
+ <script>
126
+ document.addEventListener("DOMContentLoaded", function () {
127
+ function resolveSafeReturnUrl(rawReturnUrl) {
128
+ if (!rawReturnUrl) {
129
+ return "/";
130
+ }
131
+
132
+ if (rawReturnUrl.startsWith("/")) {
133
+ return rawReturnUrl;
134
+ }
135
+
136
+ try {
137
+ const parsed = new URL(rawReturnUrl, window.location.origin);
138
+ if (parsed.origin === window.location.origin) {
139
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
140
+ }
141
+ } catch (error) {}
142
+
143
+ return "/";
144
+ }
145
+
146
+ function resolveSafePrefix(rawPrefix) {
147
+ if (!rawPrefix) {
148
+ return "";
149
+ }
150
+
151
+ let normalizedPrefix = rawPrefix.trim();
152
+ if (!normalizedPrefix.startsWith("/")) {
153
+ normalizedPrefix = "/" + normalizedPrefix;
154
+ }
155
+
156
+ if (normalizedPrefix.endsWith("/")) {
157
+ normalizedPrefix = normalizedPrefix.slice(0, -1);
158
+ }
159
+
160
+ return /^\/[A-Za-z0-9/_-]*$/.test(normalizedPrefix) ? normalizedPrefix : "";
161
+ }
162
+
163
+ const urlParams = new URLSearchParams(window.location.search);
164
+ const token = window.location.pathname.split("/").pop();
165
+ const returnUrl = resolveSafeReturnUrl(urlParams.get("returnUrl"));
166
+ const prefix = resolveSafePrefix(urlParams.get("prefix"));
167
+
168
+ document.getElementById("token").value = token;
169
+ document.getElementById("returnUrl").value = returnUrl;
170
+ document.getElementById("prefix").value = prefix;
171
+
172
+ document.getElementById("resetForm").addEventListener("submit", async function (event) {
173
+ event.preventDefault();
174
+ const password = document.getElementById("password").value;
175
+ const confirmPassword = document.getElementById("confirmPassword").value;
176
+ const passwordError = document.getElementById("passwordError");
177
+ const confirmError = document.getElementById("confirmError");
178
+
179
+ passwordError.style.display = "none";
180
+ confirmError.style.display = "none";
181
+
182
+ if (password.length < 8) {
183
+ passwordError.style.display = "block";
184
+ return;
185
+ }
186
+
187
+ if (password !== confirmPassword) {
188
+ confirmError.style.display = "block";
189
+ return;
190
+ }
191
+
192
+ try {
193
+ const response = await fetch(`${prefix}/api/accessi/auth/confirm-reset-password/${token}`, {
194
+ method: "POST",
195
+ headers: { "Content-Type": "application/json" },
196
+ body: JSON.stringify({ newPassword: password })
197
+ });
198
+
199
+ const data = await response.json();
200
+ alert(data.message || "Password aggiornata con successo!");
201
+ } catch (error) {
202
+ alert("Errore nel reset della password. Riprova piu tardi.");
203
+ } finally {
204
+ setTimeout(() => {
205
+ window.location.href = returnUrl;
206
+ }, 500);
207
+ }
208
+ });
209
+ });
210
+ </script>
211
+ </body>
212
+
213
+ </html>
@@ -24,6 +24,7 @@ export declare class AccessiDatabaseUpdater extends DatabaseUpdater implements O
24
24
  private static execute;
25
25
  private static sequenceExists;
26
26
  private static relationIssues;
27
+ private static engineInfo;
27
28
  private static engineIssue;
28
29
  private static columns;
29
30
  private static defaultValue;
@@ -96,30 +96,41 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
96
96
  }
97
97
  static relationIssues(options) {
98
98
  return __awaiter(this, void 0, void 0, function* () {
99
- const rows = yield this.query(options, `SELECT TRIM(RDB$RELATION_NAME) AS NAME, COALESCE(RDB$RELATION_TYPE, 0) AS KIND
100
- FROM RDB$RELATIONS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0`);
101
- return rows.filter(row => accessiSchema_1.accessiTables[String(row.NAME)] && Number(row.KIND) !== 0).map(row => `${row.NAME}: richiesta tabella persistente, trovato tipo relazione ${row.KIND}`);
99
+ // RDB$VIEW_BLR esiste in tutte le versioni; RDB$RELATION_TYPE solo da Firebird 3.0.
100
+ // Una vista ha RDB$VIEW_BLR non nullo: se una tabella Accessi esiste come vista, va segnalato.
101
+ const rows = yield this.query(options, `SELECT TRIM(RDB$RELATION_NAME) AS NAME
102
+ FROM RDB$RELATIONS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0 AND RDB$VIEW_BLR IS NOT NULL`);
103
+ return rows.filter(row => accessiSchema_1.accessiTables[String(row.NAME)]).map(row => `${row.NAME}: richiesta tabella persistente, trovata vista`);
102
104
  });
103
105
  }
104
- static engineIssue(options) {
106
+ static engineInfo(options) {
105
107
  return __awaiter(this, void 0, void 0, function* () {
106
108
  var _a, _b;
107
109
  const rows = yield this.query(options, "SELECT RDB$GET_CONTEXT('SYSTEM', 'ENGINE_VERSION') AS ENGINE_VERSION FROM RDB$DATABASE");
108
110
  const version = String((_b = (_a = rows[0]) === null || _a === void 0 ? void 0 : _a.ENGINE_VERSION) !== null && _b !== void 0 ? _b : 'sconosciuta');
109
- if (!(Number.parseInt(version, 10) >= 3))
110
- return `Firebird ${version}: lo schema Accessi richiede Firebird 3.0 o successivo`;
111
+ const match = /^(\d+)(?:\.(\d+))?/.exec(version);
112
+ return { version, major: match ? Number(match[1]) : Number.NaN, minor: (match === null || match === void 0 ? void 0 : match[2]) ? Number(match[2]) : 0 };
113
+ });
114
+ }
115
+ static engineIssue(options) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const { version, major, minor } = yield this.engineInfo(options);
118
+ // Firebird 2.5 e successivi: la 2.5 usa CREATE GENERATOR, dalla 3.0 lo schema usa CREATE SEQUENCE.
119
+ const supported = major > 2 || (major === 2 && minor >= 5);
120
+ if (!supported)
121
+ return `Firebird ${version}: lo schema Accessi richiede Firebird 2.5 o successivo`;
111
122
  });
112
123
  }
113
124
  static columns(options) {
114
125
  return __awaiter(this, void 0, void 0, function* () {
115
- return this.query(options, `SELECT TRIM(RF.RDB$RELATION_NAME) AS TABLE_NAME, TRIM(RF.RDB$FIELD_NAME) AS COLUMN_NAME,
116
- F.RDB$FIELD_TYPE AS FIELD_TYPE, F.RDB$FIELD_SUB_TYPE AS SUB_TYPE, F.RDB$FIELD_SCALE AS FIELD_SCALE,
117
- F.RDB$CHARACTER_LENGTH AS TEXT_LENGTH, TRIM(CS.RDB$CHARACTER_SET_NAME) AS CHARSET_NAME,
118
- COALESCE(RF.RDB$NULL_FLAG, F.RDB$NULL_FLAG, 0) AS NOT_NULL,
119
- CAST(COALESCE(RF.RDB$DEFAULT_SOURCE, F.RDB$DEFAULT_SOURCE) AS VARCHAR(1024)) AS DEFAULT_SOURCE,
120
- CASE WHEN F.RDB$COMPUTED_BLR IS NULL THEN 0 ELSE 1 END AS IS_COMPUTED
121
- FROM RDB$RELATION_FIELDS RF JOIN RDB$FIELDS F ON F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE
122
- LEFT JOIN RDB$CHARACTER_SETS CS ON CS.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID
126
+ return this.query(options, `SELECT TRIM(RF.RDB$RELATION_NAME) AS TABLE_NAME, TRIM(RF.RDB$FIELD_NAME) AS COLUMN_NAME,
127
+ F.RDB$FIELD_TYPE AS FIELD_TYPE, F.RDB$FIELD_SUB_TYPE AS SUB_TYPE, F.RDB$FIELD_SCALE AS FIELD_SCALE,
128
+ F.RDB$CHARACTER_LENGTH AS TEXT_LENGTH, TRIM(CS.RDB$CHARACTER_SET_NAME) AS CHARSET_NAME,
129
+ COALESCE(RF.RDB$NULL_FLAG, F.RDB$NULL_FLAG, 0) AS NOT_NULL,
130
+ CAST(COALESCE(RF.RDB$DEFAULT_SOURCE, F.RDB$DEFAULT_SOURCE) AS VARCHAR(1024)) AS DEFAULT_SOURCE,
131
+ CASE WHEN F.RDB$COMPUTED_BLR IS NULL THEN 0 ELSE 1 END AS IS_COMPUTED
132
+ FROM RDB$RELATION_FIELDS RF JOIN RDB$FIELDS F ON F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE
133
+ LEFT JOIN RDB$CHARACTER_SETS CS ON CS.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID
123
134
  WHERE RF.RDB$RELATION_NAME IN (${Object.keys(accessiSchema_1.accessiTables).map(name => `'${name}'`).join(', ')})`);
124
135
  });
125
136
  }
@@ -162,15 +173,15 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
162
173
  }
163
174
  static constraints(options) {
164
175
  return __awaiter(this, void 0, void 0, function* () {
165
- return this.query(options, `SELECT TRIM(C.RDB$CONSTRAINT_NAME) AS NAME, TRIM(C.RDB$RELATION_NAME) AS TABLE_NAME,
166
- TRIM(C.RDB$CONSTRAINT_TYPE) AS KIND, TRIM(S.RDB$FIELD_NAME) AS COLUMN_NAME, S.RDB$FIELD_POSITION AS POS,
167
- TRIM(T.RDB$RELATION_NAME) AS TARGET_TABLE, TRIM(TS.RDB$FIELD_NAME) AS TARGET_COLUMN,
168
- TRIM(R.RDB$DELETE_RULE) AS DELETE_RULE
169
- FROM RDB$RELATION_CONSTRAINTS C
170
- LEFT JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = C.RDB$INDEX_NAME
171
- LEFT JOIN RDB$REF_CONSTRAINTS R ON R.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME
172
- LEFT JOIN RDB$RELATION_CONSTRAINTS T ON T.RDB$CONSTRAINT_NAME = R.RDB$CONST_NAME_UQ
173
- LEFT JOIN RDB$INDEX_SEGMENTS TS ON TS.RDB$INDEX_NAME = T.RDB$INDEX_NAME AND TS.RDB$FIELD_POSITION = S.RDB$FIELD_POSITION
176
+ return this.query(options, `SELECT TRIM(C.RDB$CONSTRAINT_NAME) AS NAME, TRIM(C.RDB$RELATION_NAME) AS TABLE_NAME,
177
+ TRIM(C.RDB$CONSTRAINT_TYPE) AS KIND, TRIM(S.RDB$FIELD_NAME) AS COLUMN_NAME, S.RDB$FIELD_POSITION AS POS,
178
+ TRIM(T.RDB$RELATION_NAME) AS TARGET_TABLE, TRIM(TS.RDB$FIELD_NAME) AS TARGET_COLUMN,
179
+ TRIM(R.RDB$DELETE_RULE) AS DELETE_RULE
180
+ FROM RDB$RELATION_CONSTRAINTS C
181
+ LEFT JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = C.RDB$INDEX_NAME
182
+ LEFT JOIN RDB$REF_CONSTRAINTS R ON R.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME
183
+ LEFT JOIN RDB$RELATION_CONSTRAINTS T ON T.RDB$CONSTRAINT_NAME = R.RDB$CONST_NAME_UQ
184
+ LEFT JOIN RDB$INDEX_SEGMENTS TS ON TS.RDB$INDEX_NAME = T.RDB$INDEX_NAME AND TS.RDB$FIELD_POSITION = S.RDB$FIELD_POSITION
174
185
  ORDER BY C.RDB$CONSTRAINT_NAME, S.RDB$FIELD_POSITION`);
175
186
  });
176
187
  }
@@ -191,10 +202,10 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
191
202
  }
192
203
  static checks(options) {
193
204
  return __awaiter(this, void 0, void 0, function* () {
194
- return this.query(options, `SELECT DISTINCT TRIM(C.RDB$CONSTRAINT_NAME) AS NAME,
195
- TRIM(C.RDB$RELATION_NAME) AS TABLE_NAME, CAST(T.RDB$TRIGGER_SOURCE AS VARCHAR(2048)) AS CHECK_SOURCE
196
- FROM RDB$RELATION_CONSTRAINTS C JOIN RDB$CHECK_CONSTRAINTS K ON K.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME
197
- JOIN RDB$TRIGGERS T ON T.RDB$TRIGGER_NAME = K.RDB$TRIGGER_NAME
205
+ return this.query(options, `SELECT DISTINCT TRIM(C.RDB$CONSTRAINT_NAME) AS NAME,
206
+ TRIM(C.RDB$RELATION_NAME) AS TABLE_NAME, CAST(T.RDB$TRIGGER_SOURCE AS VARCHAR(2048)) AS CHECK_SOURCE
207
+ FROM RDB$RELATION_CONSTRAINTS C JOIN RDB$CHECK_CONSTRAINTS K ON K.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME
208
+ JOIN RDB$TRIGGERS T ON T.RDB$TRIGGER_NAME = K.RDB$TRIGGER_NAME
198
209
  WHERE C.RDB$CONSTRAINT_TYPE = 'CHECK'`);
199
210
  });
200
211
  }
@@ -204,9 +215,9 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
204
215
  }
205
216
  static indexes(options) {
206
217
  return __awaiter(this, void 0, void 0, function* () {
207
- return this.groups(yield this.query(options, `SELECT TRIM(I.RDB$INDEX_NAME) AS NAME, TRIM(I.RDB$RELATION_NAME) AS TABLE_NAME,
208
- COALESCE(I.RDB$INDEX_INACTIVE, 0) AS INACTIVE, TRIM(S.RDB$FIELD_NAME) AS COLUMN_NAME
209
- FROM RDB$INDICES I LEFT JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = I.RDB$INDEX_NAME
218
+ return this.groups(yield this.query(options, `SELECT TRIM(I.RDB$INDEX_NAME) AS NAME, TRIM(I.RDB$RELATION_NAME) AS TABLE_NAME,
219
+ COALESCE(I.RDB$INDEX_INACTIVE, 0) AS INACTIVE, TRIM(S.RDB$FIELD_NAME) AS COLUMN_NAME
220
+ FROM RDB$INDICES I LEFT JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = I.RDB$INDEX_NAME
210
221
  ORDER BY I.RDB$INDEX_NAME, S.RDB$FIELD_POSITION`));
211
222
  });
212
223
  }
@@ -215,10 +226,10 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
215
226
  }
216
227
  static triggers(options) {
217
228
  return __awaiter(this, void 0, void 0, function* () {
218
- return this.query(options, `SELECT TRIM(RDB$TRIGGER_NAME) AS NAME, TRIM(RDB$RELATION_NAME) AS TABLE_NAME,
219
- RDB$TRIGGER_INACTIVE AS INACTIVE, RDB$TRIGGER_TYPE AS TRIGGER_TYPE,
220
- CAST(RDB$TRIGGER_SOURCE AS VARCHAR(8191)) AS SOURCE
221
- FROM RDB$TRIGGERS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0
229
+ return this.query(options, `SELECT TRIM(RDB$TRIGGER_NAME) AS NAME, TRIM(RDB$RELATION_NAME) AS TABLE_NAME,
230
+ RDB$TRIGGER_INACTIVE AS INACTIVE, RDB$TRIGGER_TYPE AS TRIGGER_TYPE,
231
+ CAST(RDB$TRIGGER_SOURCE AS VARCHAR(8191)) AS SOURCE
232
+ FROM RDB$TRIGGERS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0
222
233
  AND RDB$RELATION_NAME IN (${Object.keys(accessiSchema_1.accessiTables).map(name => `'${name}'`).join(', ')})`);
223
234
  });
224
235
  }
@@ -315,7 +326,7 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
315
326
  }
316
327
  for (const generator of accessiSchema_1.accessiGenerators) {
317
328
  if (!(yield this.sequenceExists(options, generator.name)))
318
- issues.push(`${generator.name}: sequence mancante`);
329
+ issues.push(`${generator.name}: sequence/generatore mancante`);
319
330
  else if (columns.some(row => row.TABLE_NAME === generator.table && row.COLUMN_NAME === generator.column)) {
320
331
  const rows = yield this.query(options, `SELECT GEN_ID(${generator.name}, 0) AS CURRENT_VALUE, (SELECT COALESCE(MAX(${generator.column}), 0) FROM ${generator.table}) AS MAX_VALUE FROM RDB$DATABASE`);
321
332
  if (Number((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.CURRENT_VALUE) < Number((_b = rows[0]) === null || _b === void 0 ? void 0 : _b.MAX_VALUE))
@@ -347,6 +358,7 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
347
358
  const engine = yield this.engineIssue(options);
348
359
  if (engine)
349
360
  throw new Error(engine);
361
+ const { major: engineMajor } = yield this.engineInfo(options);
350
362
  const columns = yield this.columns(options);
351
363
  const future = yield this.futureVersionIssue(options, columns);
352
364
  if (future)
@@ -402,8 +414,8 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
402
414
  yield this.execute(options, `ALTER TABLE ${table} ADD CONSTRAINT PK_${table} PRIMARY KEY (${schema.primaryKey.join(', ')})`);
403
415
  }
404
416
  // Only preserve provider namespaces already referenced by historical SSO identities.
405
- yield this.execute(options, `INSERT INTO SSO_PROVIDER (PROVIDER, DESCRIZIONE, FLGATTIVO)
406
- SELECT DISTINCT I.PROVIDER, I.PROVIDER, 1 FROM UTENTI_IDENTITA_EXT I
417
+ yield this.execute(options, `INSERT INTO SSO_PROVIDER (PROVIDER, DESCRIZIONE, FLGATTIVO)
418
+ SELECT DISTINCT I.PROVIDER, I.PROVIDER, 1 FROM UTENTI_IDENTITA_EXT I
407
419
  WHERE NOT EXISTS (SELECT 1 FROM SSO_PROVIDER P WHERE P.PROVIDER = I.PROVIDER)`);
408
420
  for (const fk of accessiSchema_1.accessiForeignKeys) {
409
421
  const existing = constraints.find(rows => rows[0].KIND === 'FOREIGN KEY' && rows[0].TABLE_NAME === fk.table && this.sameColumns(rows, [fk.column]));
@@ -435,12 +447,14 @@ let AccessiDatabaseUpdater = AccessiDatabaseUpdater_1 = class AccessiDatabaseUpd
435
447
  }
436
448
  }
437
449
  for (const generator of accessiSchema_1.accessiGenerators) {
438
- if (!(yield this.sequenceExists(options, generator.name)))
439
- yield this.execute(options, `CREATE SEQUENCE ${generator.name}`);
450
+ if (!(yield this.sequenceExists(options, generator.name))) {
451
+ // Firebird 2.5 non conosce CREATE SEQUENCE: usa CREATE GENERATOR. Da 3.0 si usa la sintassi standard.
452
+ yield this.execute(options, engineMajor >= 3 ? `CREATE SEQUENCE ${generator.name}` : `CREATE GENERATOR ${generator.name}`);
453
+ }
440
454
  // Advance by a positive delta only: do not reset an existing sequence or reuse an allocated value.
441
- yield this.execute(options, `EXECUTE BLOCK AS DECLARE VARIABLE MAX_ID BIGINT; DECLARE VARIABLE CURRENT_ID BIGINT; DECLARE VARIABLE NEXT_ID BIGINT;
442
- BEGIN SELECT COALESCE(MAX(${generator.column}), 0) FROM ${generator.table} INTO :MAX_ID;
443
- CURRENT_ID = GEN_ID(${generator.name}, 0);
455
+ yield this.execute(options, `EXECUTE BLOCK AS DECLARE VARIABLE MAX_ID BIGINT; DECLARE VARIABLE CURRENT_ID BIGINT; DECLARE VARIABLE NEXT_ID BIGINT;
456
+ BEGIN SELECT COALESCE(MAX(${generator.column}), 0) FROM ${generator.table} INTO :MAX_ID;
457
+ CURRENT_ID = GEN_ID(${generator.name}, 0);
444
458
  IF (MAX_ID > CURRENT_ID) THEN NEXT_ID = GEN_ID(${generator.name}, MAX_ID - CURRENT_ID); END`);
445
459
  }
446
460
  const triggers = yield this.triggers(options);