@lenne.tech/nest-server 11.10.4 → 11.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.10.4",
3
+ "version": "11.10.5",
4
4
  "description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
5
5
  "keywords": [
6
6
  "node",
@@ -20,6 +20,7 @@ import { Roles } from '../../common/decorators/roles.decorator';
20
20
  import { RoleEnum } from '../../common/enums/role.enum';
21
21
  import { maskEmail, maskToken } from '../../common/helpers/logging.helper';
22
22
  import { ConfigService } from '../../common/services/config.service';
23
+ import { ErrorCode } from '../error-code/error-codes';
23
24
  import { BetterAuthSignInResponse, hasSession, hasUser, requires2FA } from './better-auth.types';
24
25
  import { BetterAuthSessionUser, CoreBetterAuthUserMapper } from './core-better-auth-user.mapper';
25
26
  import { sendWebResponse, toWebRequest } from './core-better-auth-web.helper';
@@ -227,7 +228,7 @@ export class CoreBetterAuthController {
227
228
 
228
229
  const api = this.betterAuthService.getApi();
229
230
  if (!api) {
230
- throw new BadRequestException('Better-Auth API not available');
231
+ throw new BadRequestException(ErrorCode.BETTERAUTH_API_NOT_AVAILABLE);
231
232
  }
232
233
 
233
234
  // Step 1: Try legacy user migration BEFORE Better Auth handles the request
@@ -255,7 +256,7 @@ export class CoreBetterAuthController {
255
256
  })) as BetterAuthSignInResponse | null;
256
257
 
257
258
  if (!response) {
258
- throw new UnauthorizedException('Invalid credentials');
259
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
259
260
  }
260
261
 
261
262
  // Check for 2FA requirement
@@ -268,7 +269,7 @@ export class CoreBetterAuthController {
268
269
  // We need to modify the request body to use the normalized password
269
270
  const authInstance = this.betterAuthService.getInstance();
270
271
  if (!authInstance) {
271
- throw new InternalServerErrorException('Better-Auth not initialized');
272
+ throw new InternalServerErrorException(ErrorCode.BETTERAUTH_NOT_INITIALIZED);
272
273
  }
273
274
 
274
275
  // Create a modified request body with normalized password
@@ -311,7 +312,7 @@ export class CoreBetterAuthController {
311
312
  // Check if response indicates an error
312
313
  const responseAny = response as any;
313
314
  if (responseAny?.error || responseAny?.code === 'CREDENTIAL_ACCOUNT_NOT_FOUND') {
314
- throw new UnauthorizedException('Invalid credentials');
315
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
315
316
  }
316
317
 
317
318
  if (hasUser(response)) {
@@ -334,7 +335,7 @@ export class CoreBetterAuthController {
334
335
  return this.processCookies(res, result);
335
336
  }
336
337
 
337
- throw new UnauthorizedException('Invalid credentials');
338
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
338
339
  } catch (error) {
339
340
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
340
341
  this.logger.debug(`Sign-in error: ${errorMessage}`);
@@ -343,7 +344,7 @@ export class CoreBetterAuthController {
343
344
  throw error;
344
345
  }
345
346
 
346
- throw new UnauthorizedException('Invalid credentials');
347
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
347
348
  }
348
349
  }
349
350
 
@@ -380,7 +381,7 @@ export class CoreBetterAuthController {
380
381
 
381
382
  const api = this.betterAuthService.getApi();
382
383
  if (!api) {
383
- throw new BadRequestException('Better-Auth API not available');
384
+ throw new BadRequestException(ErrorCode.BETTERAUTH_API_NOT_AVAILABLE);
384
385
  }
385
386
 
386
387
  // Normalize password to SHA256 format for consistency with Legacy Auth
@@ -396,7 +397,7 @@ export class CoreBetterAuthController {
396
397
  });
397
398
 
398
399
  if (!response) {
399
- throw new BadRequestException('Sign-up failed');
400
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
400
401
  }
401
402
 
402
403
  if (hasUser(response)) {
@@ -419,14 +420,14 @@ export class CoreBetterAuthController {
419
420
  return this.processCookies(res, result);
420
421
  }
421
422
 
422
- throw new BadRequestException('Sign-up failed');
423
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
423
424
  } catch (error) {
424
425
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
425
426
  this.logger.debug(`Sign-up error: ${errorMessage}`);
426
427
  if (errorMessage.includes('already exists')) {
427
- throw new BadRequestException('User with this email already exists');
428
+ throw new BadRequestException(ErrorCode.EMAIL_ALREADY_EXISTS);
428
429
  }
429
- throw new BadRequestException('Sign-up failed');
430
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
430
431
  }
431
432
  }
432
433
 
@@ -557,7 +558,7 @@ export class CoreBetterAuthController {
557
558
  */
558
559
  protected ensureEnabled(): void {
559
560
  if (!this.betterAuthService.isEnabled()) {
560
- throw new BadRequestException('Better-Auth is not enabled');
561
+ throw new BadRequestException(ErrorCode.BETTERAUTH_DISABLED);
561
562
  }
562
563
  }
563
564
 
@@ -735,7 +736,7 @@ export class CoreBetterAuthController {
735
736
 
736
737
  const authInstance = this.betterAuthService.getInstance();
737
738
  if (!authInstance) {
738
- throw new InternalServerErrorException('Better-Auth not initialized');
739
+ throw new InternalServerErrorException(ErrorCode.BETTERAUTH_NOT_INITIALIZED);
739
740
  }
740
741
 
741
742
  this.logger.debug(`Forwarding to Better Auth: ${req.method} ${req.path}`);
@@ -5,6 +5,7 @@ import { Request, Response } from 'express';
5
5
  import { Roles } from '../../common/decorators/roles.decorator';
6
6
  import { RoleEnum } from '../../common/enums/role.enum';
7
7
  import { maskEmail } from '../../common/helpers/logging.helper';
8
+ import { ErrorCode } from '../error-code/error-codes';
8
9
  import {
9
10
  BetterAuth2FAResponse,
10
11
  BetterAuthSignInResponse,
@@ -203,7 +204,7 @@ export class CoreBetterAuthResolver {
203
204
 
204
205
  const api = this.betterAuthService.getApi();
205
206
  if (!api) {
206
- throw new BadRequestException('Better-Auth API not available');
207
+ throw new BadRequestException(ErrorCode.BETTERAUTH_API_NOT_AVAILABLE);
207
208
  }
208
209
 
209
210
  // Try to sign in, with automatic legacy user migration
@@ -239,7 +240,7 @@ export class CoreBetterAuthResolver {
239
240
  }
240
241
 
241
242
  if (!response) {
242
- throw new UnauthorizedException('Invalid credentials');
243
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
243
244
  }
244
245
 
245
246
  // Check for 2FA requirement
@@ -271,7 +272,7 @@ export class CoreBetterAuthResolver {
271
272
  };
272
273
  }
273
274
 
274
- throw new UnauthorizedException('Invalid credentials');
275
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
275
276
  } catch (error) {
276
277
  this.logger.debug(
277
278
  `[SignIn] Sign-in failed for ${maskEmail(email)}: ${error instanceof Error ? error.message : 'Unknown error'}`,
@@ -291,7 +292,7 @@ export class CoreBetterAuthResolver {
291
292
  }
292
293
  }
293
294
 
294
- throw new UnauthorizedException('Invalid credentials');
295
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
295
296
  }
296
297
  }
297
298
 
@@ -308,7 +309,7 @@ export class CoreBetterAuthResolver {
308
309
  })) as BetterAuthSignInResponse | null;
309
310
 
310
311
  if (!response || !hasUser(response)) {
311
- throw new UnauthorizedException('Invalid credentials');
312
+ throw new UnauthorizedException(ErrorCode.INVALID_CREDENTIALS);
312
313
  }
313
314
 
314
315
  if (requires2FA(response)) {
@@ -348,7 +349,7 @@ export class CoreBetterAuthResolver {
348
349
 
349
350
  const api = this.betterAuthService.getApi();
350
351
  if (!api) {
351
- throw new BadRequestException('Better-Auth API not available');
352
+ throw new BadRequestException(ErrorCode.BETTERAUTH_API_NOT_AVAILABLE);
352
353
  }
353
354
 
354
355
  try {
@@ -361,7 +362,7 @@ export class CoreBetterAuthResolver {
361
362
  })) as BetterAuthSignUpResponse | null;
362
363
 
363
364
  if (!response) {
364
- throw new BadRequestException('Sign-up failed');
365
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
365
366
  }
366
367
 
367
368
  if (hasUser(response)) {
@@ -379,14 +380,14 @@ export class CoreBetterAuthResolver {
379
380
  };
380
381
  }
381
382
 
382
- throw new BadRequestException('Sign-up failed');
383
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
383
384
  } catch (error) {
384
385
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
385
386
  this.logger.debug(`Sign-up error: ${errorMessage}`);
386
387
  if (errorMessage.includes('already exists')) {
387
- throw new BadRequestException('User with this email already exists');
388
+ throw new BadRequestException(ErrorCode.EMAIL_ALREADY_EXISTS);
388
389
  }
389
- throw new BadRequestException('Sign-up failed');
390
+ throw new BadRequestException(ErrorCode.SIGNUP_FAILED);
390
391
  }
391
392
  }
392
393
 
@@ -429,12 +430,12 @@ export class CoreBetterAuthResolver {
429
430
  this.ensureEnabled();
430
431
 
431
432
  if (!this.betterAuthService.isTwoFactorEnabled()) {
432
- throw new BadRequestException('Two-factor authentication is not enabled');
433
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_NOT_ENABLED_SERVER);
433
434
  }
434
435
 
435
436
  const api = this.betterAuthService.getApi();
436
437
  if (!api) {
437
- throw new BadRequestException('Better-Auth API not available');
438
+ throw new BadRequestException(ErrorCode.BETTERAUTH_API_NOT_AVAILABLE);
438
439
  }
439
440
 
440
441
  try {
@@ -450,7 +451,7 @@ export class CoreBetterAuthResolver {
450
451
  };
451
452
 
452
453
  if (!twoFactorApi?.verifyTotp) {
453
- throw new BadRequestException('2FA verification method not available');
454
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_METHOD_NOT_AVAILABLE);
454
455
  }
455
456
 
456
457
  const response = await twoFactorApi.verifyTotp({
@@ -469,10 +470,10 @@ export class CoreBetterAuthResolver {
469
470
  };
470
471
  }
471
472
 
472
- throw new UnauthorizedException('Invalid 2FA code');
473
+ throw new UnauthorizedException(ErrorCode.INVALID_2FA_CODE);
473
474
  } catch (error) {
474
475
  this.logger.debug(`2FA verification error: ${error instanceof Error ? error.message : 'Unknown error'}`);
475
- throw new UnauthorizedException('Invalid 2FA code');
476
+ throw new UnauthorizedException(ErrorCode.INVALID_2FA_CODE);
476
477
  }
477
478
  }
478
479
 
@@ -546,7 +547,7 @@ export class CoreBetterAuthResolver {
546
547
  this.ensureEnabled();
547
548
 
548
549
  if (!this.betterAuthService.isTwoFactorEnabled()) {
549
- throw new BadRequestException('Two-factor authentication is not enabled on this server');
550
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_NOT_ENABLED_SERVER);
550
551
  }
551
552
 
552
553
  const api = this.betterAuthService.getApi();
@@ -564,7 +565,7 @@ export class CoreBetterAuthResolver {
564
565
  };
565
566
 
566
567
  if (!twoFactorApi?.disable) {
567
- throw new BadRequestException('2FA disable method not available');
568
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_METHOD_NOT_AVAILABLE);
568
569
  }
569
570
 
570
571
  const response = await twoFactorApi.disable({
@@ -591,7 +592,7 @@ export class CoreBetterAuthResolver {
591
592
  this.ensureEnabled();
592
593
 
593
594
  if (!this.betterAuthService.isTwoFactorEnabled()) {
594
- throw new BadRequestException('Two-factor authentication is not enabled on this server');
595
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_NOT_ENABLED_SERVER);
595
596
  }
596
597
 
597
598
  const api = this.betterAuthService.getApi();
@@ -609,7 +610,7 @@ export class CoreBetterAuthResolver {
609
610
  };
610
611
 
611
612
  if (!twoFactorApi?.generateBackupCodes) {
612
- throw new BadRequestException('Generate backup codes method not available');
613
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_METHOD_NOT_AVAILABLE);
613
614
  }
614
615
 
615
616
  const response = await twoFactorApi.generateBackupCodes({ headers });
@@ -731,7 +732,7 @@ export class CoreBetterAuthResolver {
731
732
  this.ensureEnabled();
732
733
 
733
734
  if (!this.betterAuthService.isPasskeyEnabled()) {
734
- throw new BadRequestException('Passkey authentication is not enabled on this server');
735
+ throw new BadRequestException(ErrorCode.PASSKEY_NOT_ENABLED_SERVER);
735
736
  }
736
737
 
737
738
  const api = this.betterAuthService.getApi();
@@ -749,7 +750,7 @@ export class CoreBetterAuthResolver {
749
750
  };
750
751
 
751
752
  if (!passkeyApi?.deletePasskey) {
752
- throw new BadRequestException('Delete passkey method not available');
753
+ throw new BadRequestException(ErrorCode.TWO_FACTOR_METHOD_NOT_AVAILABLE);
753
754
  }
754
755
 
755
756
  const response = await passkeyApi.deletePasskey({
@@ -773,9 +774,7 @@ export class CoreBetterAuthResolver {
773
774
  */
774
775
  protected ensureEnabled(): void {
775
776
  if (!this.betterAuthService.isEnabled()) {
776
- throw new BadRequestException(
777
- 'Better-Auth is not enabled. Check that betterAuth.enabled is not set to false in your environment.',
778
- );
777
+ throw new BadRequestException(ErrorCode.BETTERAUTH_DISABLED);
779
778
  }
780
779
  }
781
780
 
@@ -133,6 +133,106 @@ export const LtnsErrors = {
133
133
  },
134
134
  },
135
135
 
136
+ // BetterAuth specific errors (LTNS_0010-LTNS_0049)
137
+ INVALID_CREDENTIALS: {
138
+ code: 'LTNS_0010',
139
+ message: 'Invalid credentials',
140
+ translations: {
141
+ de: 'Ungültige Anmeldedaten.',
142
+ en: 'Invalid credentials.',
143
+ },
144
+ },
145
+
146
+ INVALID_2FA_CODE: {
147
+ code: 'LTNS_0011',
148
+ message: 'Invalid 2FA code',
149
+ translations: {
150
+ de: 'Der 2FA-Code ist ungültig.',
151
+ en: 'The 2FA code is invalid.',
152
+ },
153
+ },
154
+
155
+ TWO_FACTOR_NOT_ENABLED: {
156
+ code: 'LTNS_0012',
157
+ message: 'Two-factor authentication is not enabled',
158
+ translations: {
159
+ de: 'Zwei-Faktor-Authentifizierung ist nicht aktiviert.',
160
+ en: 'Two-factor authentication is not enabled.',
161
+ },
162
+ },
163
+
164
+ TWO_FACTOR_NOT_ENABLED_SERVER: {
165
+ code: 'LTNS_0013',
166
+ message: 'Two-factor authentication is not enabled on this server',
167
+ translations: {
168
+ de: 'Zwei-Faktor-Authentifizierung ist auf diesem Server nicht aktiviert.',
169
+ en: 'Two-factor authentication is not enabled on this server.',
170
+ },
171
+ },
172
+
173
+ PASSKEY_NOT_ENABLED_SERVER: {
174
+ code: 'LTNS_0014',
175
+ message: 'Passkey authentication is not enabled on this server',
176
+ translations: {
177
+ de: 'Passkey-Authentifizierung ist auf diesem Server nicht aktiviert.',
178
+ en: 'Passkey authentication is not enabled on this server.',
179
+ },
180
+ },
181
+
182
+ SIGNUP_FAILED: {
183
+ code: 'LTNS_0015',
184
+ message: 'Sign-up failed',
185
+ translations: {
186
+ de: 'Die Registrierung ist fehlgeschlagen.',
187
+ en: 'Sign-up failed.',
188
+ },
189
+ },
190
+
191
+ BETTERAUTH_NOT_INITIALIZED: {
192
+ code: 'LTNS_0016',
193
+ message: 'Better-Auth not initialized',
194
+ translations: {
195
+ de: 'Better-Auth ist nicht initialisiert.',
196
+ en: 'Better-Auth is not initialized.',
197
+ },
198
+ },
199
+
200
+ BETTERAUTH_DISABLED: {
201
+ code: 'LTNS_0017',
202
+ message: 'Better-Auth is disabled',
203
+ translations: {
204
+ de: 'Better-Auth ist deaktiviert.',
205
+ en: 'Better-Auth is disabled.',
206
+ },
207
+ },
208
+
209
+ BETTERAUTH_API_NOT_AVAILABLE: {
210
+ code: 'LTNS_0018',
211
+ message: 'Better-Auth API not available',
212
+ translations: {
213
+ de: 'Better-Auth API ist nicht verfügbar.',
214
+ en: 'Better-Auth API is not available.',
215
+ },
216
+ },
217
+
218
+ TWO_FACTOR_METHOD_NOT_AVAILABLE: {
219
+ code: 'LTNS_0019',
220
+ message: '2FA verification method not available',
221
+ translations: {
222
+ de: '2FA-Verifizierungsmethode ist nicht verfügbar.',
223
+ en: '2FA verification method is not available.',
224
+ },
225
+ },
226
+
227
+ RATE_LIMIT_EXCEEDED: {
228
+ code: 'LTNS_0020',
229
+ message: 'Too many requests',
230
+ translations: {
231
+ de: 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.',
232
+ en: 'Too many requests. Please try again later.',
233
+ },
234
+ },
235
+
136
236
  // =====================================================
137
237
  // Authorization Errors (LTNS_0100-LTNS_0199)
138
238
  // =====================================================