@vonall/auth 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @vonall/auth
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#16](https://github.com/SebastianvonAllmen/vonall-libs/pull/16) [`b2b45e6`](https://github.com/SebastianvonAllmen/vonall-libs/commit/b2b45e653396341b0023777d0d8de1ddee62f50d) Thanks [@SebastianvonAllmen](https://github.com/SebastianvonAllmen)! - One messages helper: `@vonall/messages` exports `defineMessages({ en, de })`, and every package's `configure…Messages({ locale })` takes the app's locale as is ("de-CH", "en-GB"), the language derived from it. In development, reading a package's strings before configuring them throws. The `Locale` type is gone. `@vonall/auth`: the near-duplicate keys `invalidEmailDot`, `passwordsDontMatchDot` and `passwordTooShortDot` are merged into `invalidEmail`, `passwordsMismatch` and `passwordTooShort`; `inviteIntro` takes the number of days.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`b2b45e6`](https://github.com/SebastianvonAllmen/vonall-libs/commit/b2b45e653396341b0023777d0d8de1ddee62f50d)]:
12
+ - @vonall/messages@0.1.0
13
+ - @vonall/mail@0.2.0
14
+
15
+ ## 0.4.0
16
+
17
+ ### Minor Changes
18
+
19
+ - The pass-through services are gone: `UserRepo.kontoLoeschen` replaces `KontoService.loeschen`; `EinladungRepo.listOpenBy`/`listAllOpen` replace `EinladungService.offene`/`alleOffenen`, and `EinladungService.zurueckziehen(null, id)` the admin's withdrawal; `AgentRepo` replaces `AgentService`. `@vonall/mcp`'s components use `@vonall/auth`'s `messageOf`.
20
+
3
21
  ## 0.3.1
4
22
 
5
23
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { configureAuthMessages, m, type AuthMessages, type Locale } from "./messages.js";
1
+ export { configureAuthMessages, m, type AuthMessages } from "./messages.js";
2
2
  export { ac, adminRole, roles, userRole } from "./permissions.js";
3
3
  export { emailSchema, MIN_PASSWORD_LENGTH, nameSchema, passwordSchema, SIGNUP_MODES, SIGNUP_STATES, type AppUserClient, type EinladungInfo, type OffeneEinladung, type SessionUser, type SignupMode, type SignupState, type UserInsert, type UserSelect, } from "./types.js";
4
4
  export { isSessionNotFresh, isStale, reauthPath, SESSION_NOT_FRESH } from "./util/fresh.js";
@@ -1,8 +1,3 @@
1
- /**
2
- * The package's strings, in English and German (Swiss spelling): what the server answers, what the mails say, and
3
- * (from the UI release on) what the pages show. A Product calls configureAuthMessages once, from a module its root
4
- * layout and its server wiring import, with its LOCALE and the few words it wants differently; code reads `m()`.
5
- */
6
1
  export declare const en: {
7
2
  needsEinladung: string;
8
3
  noMail: string;
@@ -61,7 +56,6 @@ export declare const en: {
61
56
  resetLinkNotSent: string;
62
57
  resetLinkSent: string;
63
58
  resetLinkNotRequested: string;
64
- invalidEmailDot: string;
65
59
  twoFactorTitle: string;
66
60
  twoFactorEnterCode: string;
67
61
  confirm: string;
@@ -78,7 +72,6 @@ export declare const en: {
78
72
  inviteOnly: (app: string) => string;
79
73
  alreadyHaveAccount: string;
80
74
  repeatPassword: string;
81
- passwordsDontMatchDot: string;
82
75
  needsValidEinladung: string;
83
76
  emailInUse: string;
84
77
  signupFailed: string;
@@ -86,7 +79,6 @@ export declare const en: {
86
79
  resetIntro: string;
87
80
  resetNoToken: string;
88
81
  resetLinkInvalid: string;
89
- passwordTooShortDot: (min: number) => string;
90
82
  newPassword: string;
91
83
  confirmNewPassword: string;
92
84
  savePassword: string;
@@ -192,7 +184,7 @@ export declare const en: {
192
184
  providerNotLinked: (provider: string) => string;
193
185
  providerNotUnlinked: (provider: string) => string;
194
186
  inviteSomeone: string;
195
- inviteIntro: string;
187
+ inviteIntro: (days: number) => string;
196
188
  linkWord: string;
197
189
  validUntil: (date: string) => string;
198
190
  withdrawInvitation: string;
@@ -238,10 +230,462 @@ export declare const en: {
238
230
  };
239
231
  export type AuthMessages = typeof en;
240
232
  export declare const de: AuthMessages;
241
- export type Locale = "en" | "de";
242
- export declare function configureAuthMessages({ locale, overrides }: {
243
- locale: Locale;
244
- overrides?: Partial<AuthMessages>;
245
- }): void;
246
- /** The configured messages. */
247
- export declare const m: () => AuthMessages;
233
+ export declare const m: () => {
234
+ needsEinladung: string;
235
+ noMail: string;
236
+ onlyAdminsInvite: string;
237
+ einladungUnbekannt: string;
238
+ einladungAbgelaufen: string;
239
+ einladungAngenommen: string;
240
+ unauthorized: string;
241
+ forbidden: string;
242
+ ownRole: string;
243
+ ownAccount: string;
244
+ passwordsMismatch: string;
245
+ mailFailed: string;
246
+ invalidEmail: string;
247
+ passwordTooShort: (min: number) => string;
248
+ nameRequired: string;
249
+ nameTooLong: (max: number) => string;
250
+ hello: (name: string) => string;
251
+ resetSubject: (app: string) => string;
252
+ resetText: (name: string, app: string, link: string) => string;
253
+ resetButton: string;
254
+ resetBody: (app: string) => string;
255
+ resetNotYou: string;
256
+ verifySubject: (app: string) => string;
257
+ verifyText: (name: string, app: string, link: string) => string;
258
+ verifyButton: string;
259
+ verifyBody: (app: string) => string;
260
+ verifyNotYou: string;
261
+ einladungSubject: (inviter: string, app: string) => string;
262
+ einladungText: (inviter: string, app: string, link: string, validUntil: string) => string;
263
+ einladungTitle: (app: string) => string;
264
+ einladungButton: string;
265
+ einladungHello: string;
266
+ einladungBody: (inviter: string, app: string) => string;
267
+ einladungValid: (validUntil: string) => string;
268
+ welcomeBack: string;
269
+ logInTo: (app: string) => string;
270
+ forgotPassword: string;
271
+ forgotIntro: string;
272
+ email: string;
273
+ emailPlaceholder: string;
274
+ password: string;
275
+ sendTheLink: string;
276
+ backToLogin: string;
277
+ orWithEmail: string;
278
+ logIn: string;
279
+ noAccountYet: string;
280
+ signUp: string;
281
+ continueWith: (provider: string) => string;
282
+ accountNotLinked: string;
283
+ noNewAccountInvite: string;
284
+ noNewAccountOpen: string;
285
+ loginTooOld: string;
286
+ confirmEmailFirst: string;
287
+ loginFailed: string;
288
+ resetLinkNotSent: string;
289
+ resetLinkSent: string;
290
+ resetLinkNotRequested: string;
291
+ twoFactorTitle: string;
292
+ twoFactorEnterCode: string;
293
+ confirm: string;
294
+ cancel: string;
295
+ invalidCode: string;
296
+ wrongCode: string;
297
+ codeNotVerified: string;
298
+ createAccount: string;
299
+ invitesYouTo: (inviter: string, app: string) => string;
300
+ signUpWith: (providers: string) => string;
301
+ or: string;
302
+ almostDone: (email: string, app: string) => string;
303
+ accountReady: string;
304
+ inviteOnly: (app: string) => string;
305
+ alreadyHaveAccount: string;
306
+ repeatPassword: string;
307
+ needsValidEinladung: string;
308
+ emailInUse: string;
309
+ signupFailed: string;
310
+ resetTitle: string;
311
+ resetIntro: string;
312
+ resetNoToken: string;
313
+ resetLinkInvalid: string;
314
+ newPassword: string;
315
+ confirmNewPassword: string;
316
+ savePassword: string;
317
+ passwordNotReset: string;
318
+ passwordWasReset: string;
319
+ somethingWentWrong: string;
320
+ invitationTitle: string;
321
+ invitationTo: (app: string) => string;
322
+ invitesYou: (inviter: string) => string;
323
+ askForNewLink: string;
324
+ toStartPage: string;
325
+ alreadyHaveAccountNoInvite: string;
326
+ openApp: (app: string) => string;
327
+ iHaveAnAccount: string;
328
+ settingsTitle: string;
329
+ backToOverview: string;
330
+ user: string;
331
+ profile: string;
332
+ memberSince: (since: string) => string;
333
+ tabProfile: string;
334
+ tabProfileHint: string;
335
+ tabSecurity: string;
336
+ tabSecurityHint: string;
337
+ tabSessions: string;
338
+ tabSessionsHint: string;
339
+ tabLinks: string;
340
+ tabLinksHint: string;
341
+ tabInvitations: string;
342
+ tabInvitationsHint: string;
343
+ tabDeletion: string;
344
+ tabDeletionHint: string;
345
+ name: string;
346
+ yourName: string;
347
+ save: string;
348
+ saving: string;
349
+ profileUpdated: string;
350
+ profileNotUpdated: string;
351
+ loadingSecurity: string;
352
+ changePassword: string;
353
+ changing: string;
354
+ passwordChanged: string;
355
+ passwordNotChanged: string;
356
+ currentPassword: string;
357
+ confirmNewPasswordShort: string;
358
+ setPassword: string;
359
+ setPasswordIntro: string;
360
+ setPasswordButton: string;
361
+ passwordSet: string;
362
+ passwordNotSet: string;
363
+ twoFactorHeading: string;
364
+ twoFactorIntro: string;
365
+ on: string;
366
+ off: string;
367
+ twoFactorProtects: string;
368
+ yourPassword: string;
369
+ turningOff: string;
370
+ turnOff: string;
371
+ turnOff2fa: string;
372
+ scanQr: string;
373
+ qrAlt: string;
374
+ scanWithApp: string;
375
+ saveBackupCodes: string;
376
+ backupCodesIntro: string;
377
+ copyBackupCodes: string;
378
+ backupCodesCopied: string;
379
+ confirmSetup: string;
380
+ enterCodeFromApp: string;
381
+ checking: string;
382
+ turnOn2fa: string;
383
+ setup2faIntro: string;
384
+ starting: string;
385
+ start2faSetup: string;
386
+ enterPasswordOn: string;
387
+ enterPasswordOff: string;
388
+ twoFactorNotOn: string;
389
+ twoFactorNotOff: string;
390
+ twoFactorIsOn: string;
391
+ twoFactorIsOff: string;
392
+ setupNotStarted: string;
393
+ activeSessions: string;
394
+ devicesLoggedIn: string;
395
+ endAllOthers: string;
396
+ noActiveSessions: string;
397
+ unknownBrowser: string;
398
+ thisSession: string;
399
+ noIpAddress: string;
400
+ lastActive: (when: string) => string;
401
+ unknown: string;
402
+ sessionEnded: string;
403
+ sessionNotEnded: string;
404
+ otherSessionsEnded: string;
405
+ otherSessionsNotEnded: string;
406
+ linkedAccounts: string;
407
+ linkedIntro: string;
408
+ linked: string;
409
+ notLinked: string;
410
+ unlink: string;
411
+ link: string;
412
+ noSocialLogin: string;
413
+ autoLinkNote: string;
414
+ providerLinked: (provider: string) => string;
415
+ providerUnlinked: (provider: string) => string;
416
+ providerNotLinked: (provider: string) => string;
417
+ providerNotUnlinked: (provider: string) => string;
418
+ inviteSomeone: string;
419
+ inviteIntro: (days: number) => string;
420
+ linkWord: string;
421
+ validUntil: (date: string) => string;
422
+ withdrawInvitation: string;
423
+ invitationWithdrawn: string;
424
+ invitationNotWithdrawn: string;
425
+ emailOptional: string;
426
+ creating: string;
427
+ createInvitation: string;
428
+ copy: string;
429
+ share: string;
430
+ linkShownOnce: string;
431
+ invitationText: (app: string, link: string) => string;
432
+ shareYourself: (error: string) => string;
433
+ invitationSentTo: (email: string) => string;
434
+ invitationNotCreated: string;
435
+ linkCopied: string;
436
+ copyLinkFailed: string;
437
+ deleteForGood: string;
438
+ cannotBeUndone: string;
439
+ deletionText: string;
440
+ deletionAgents: string;
441
+ deletionNoLogin: string;
442
+ typeToContinue: string;
443
+ type: string;
444
+ deleteWord: string;
445
+ deleting: string;
446
+ deletePermanently: string;
447
+ accountDeleted: string;
448
+ accountNotDeleted: string;
449
+ administration: string;
450
+ accounts: string;
451
+ since: (date: string) => string;
452
+ you: string;
453
+ roleOf: (name: string) => string;
454
+ roleChanged: string;
455
+ deleteAccountOf: (name: string) => string;
456
+ confirmDeleteAccount: (name: string) => string;
457
+ accountDeletedAdmin: string;
458
+ invitations: string;
459
+ noOpenInvitations: string;
460
+ by: (inviter: string) => string;
461
+ didntWork: string;
462
+ }, configureAuthMessages: import("@vonall/messages").Configure<{
463
+ needsEinladung: string;
464
+ noMail: string;
465
+ onlyAdminsInvite: string;
466
+ einladungUnbekannt: string;
467
+ einladungAbgelaufen: string;
468
+ einladungAngenommen: string;
469
+ unauthorized: string;
470
+ forbidden: string;
471
+ ownRole: string;
472
+ ownAccount: string;
473
+ passwordsMismatch: string;
474
+ mailFailed: string;
475
+ invalidEmail: string;
476
+ passwordTooShort: (min: number) => string;
477
+ nameRequired: string;
478
+ nameTooLong: (max: number) => string;
479
+ hello: (name: string) => string;
480
+ resetSubject: (app: string) => string;
481
+ resetText: (name: string, app: string, link: string) => string;
482
+ resetButton: string;
483
+ resetBody: (app: string) => string;
484
+ resetNotYou: string;
485
+ verifySubject: (app: string) => string;
486
+ verifyText: (name: string, app: string, link: string) => string;
487
+ verifyButton: string;
488
+ verifyBody: (app: string) => string;
489
+ verifyNotYou: string;
490
+ einladungSubject: (inviter: string, app: string) => string;
491
+ einladungText: (inviter: string, app: string, link: string, validUntil: string) => string;
492
+ einladungTitle: (app: string) => string;
493
+ einladungButton: string;
494
+ einladungHello: string;
495
+ einladungBody: (inviter: string, app: string) => string;
496
+ einladungValid: (validUntil: string) => string;
497
+ welcomeBack: string;
498
+ logInTo: (app: string) => string;
499
+ forgotPassword: string;
500
+ forgotIntro: string;
501
+ email: string;
502
+ emailPlaceholder: string;
503
+ password: string;
504
+ sendTheLink: string;
505
+ backToLogin: string;
506
+ orWithEmail: string;
507
+ logIn: string;
508
+ noAccountYet: string;
509
+ signUp: string;
510
+ continueWith: (provider: string) => string;
511
+ accountNotLinked: string;
512
+ noNewAccountInvite: string;
513
+ noNewAccountOpen: string;
514
+ loginTooOld: string;
515
+ confirmEmailFirst: string;
516
+ loginFailed: string;
517
+ resetLinkNotSent: string;
518
+ resetLinkSent: string;
519
+ resetLinkNotRequested: string;
520
+ twoFactorTitle: string;
521
+ twoFactorEnterCode: string;
522
+ confirm: string;
523
+ cancel: string;
524
+ invalidCode: string;
525
+ wrongCode: string;
526
+ codeNotVerified: string;
527
+ createAccount: string;
528
+ invitesYouTo: (inviter: string, app: string) => string;
529
+ signUpWith: (providers: string) => string;
530
+ or: string;
531
+ almostDone: (email: string, app: string) => string;
532
+ accountReady: string;
533
+ inviteOnly: (app: string) => string;
534
+ alreadyHaveAccount: string;
535
+ repeatPassword: string;
536
+ needsValidEinladung: string;
537
+ emailInUse: string;
538
+ signupFailed: string;
539
+ resetTitle: string;
540
+ resetIntro: string;
541
+ resetNoToken: string;
542
+ resetLinkInvalid: string;
543
+ newPassword: string;
544
+ confirmNewPassword: string;
545
+ savePassword: string;
546
+ passwordNotReset: string;
547
+ passwordWasReset: string;
548
+ somethingWentWrong: string;
549
+ invitationTitle: string;
550
+ invitationTo: (app: string) => string;
551
+ invitesYou: (inviter: string) => string;
552
+ askForNewLink: string;
553
+ toStartPage: string;
554
+ alreadyHaveAccountNoInvite: string;
555
+ openApp: (app: string) => string;
556
+ iHaveAnAccount: string;
557
+ settingsTitle: string;
558
+ backToOverview: string;
559
+ user: string;
560
+ profile: string;
561
+ memberSince: (since: string) => string;
562
+ tabProfile: string;
563
+ tabProfileHint: string;
564
+ tabSecurity: string;
565
+ tabSecurityHint: string;
566
+ tabSessions: string;
567
+ tabSessionsHint: string;
568
+ tabLinks: string;
569
+ tabLinksHint: string;
570
+ tabInvitations: string;
571
+ tabInvitationsHint: string;
572
+ tabDeletion: string;
573
+ tabDeletionHint: string;
574
+ name: string;
575
+ yourName: string;
576
+ save: string;
577
+ saving: string;
578
+ profileUpdated: string;
579
+ profileNotUpdated: string;
580
+ loadingSecurity: string;
581
+ changePassword: string;
582
+ changing: string;
583
+ passwordChanged: string;
584
+ passwordNotChanged: string;
585
+ currentPassword: string;
586
+ confirmNewPasswordShort: string;
587
+ setPassword: string;
588
+ setPasswordIntro: string;
589
+ setPasswordButton: string;
590
+ passwordSet: string;
591
+ passwordNotSet: string;
592
+ twoFactorHeading: string;
593
+ twoFactorIntro: string;
594
+ on: string;
595
+ off: string;
596
+ twoFactorProtects: string;
597
+ yourPassword: string;
598
+ turningOff: string;
599
+ turnOff: string;
600
+ turnOff2fa: string;
601
+ scanQr: string;
602
+ qrAlt: string;
603
+ scanWithApp: string;
604
+ saveBackupCodes: string;
605
+ backupCodesIntro: string;
606
+ copyBackupCodes: string;
607
+ backupCodesCopied: string;
608
+ confirmSetup: string;
609
+ enterCodeFromApp: string;
610
+ checking: string;
611
+ turnOn2fa: string;
612
+ setup2faIntro: string;
613
+ starting: string;
614
+ start2faSetup: string;
615
+ enterPasswordOn: string;
616
+ enterPasswordOff: string;
617
+ twoFactorNotOn: string;
618
+ twoFactorNotOff: string;
619
+ twoFactorIsOn: string;
620
+ twoFactorIsOff: string;
621
+ setupNotStarted: string;
622
+ activeSessions: string;
623
+ devicesLoggedIn: string;
624
+ endAllOthers: string;
625
+ noActiveSessions: string;
626
+ unknownBrowser: string;
627
+ thisSession: string;
628
+ noIpAddress: string;
629
+ lastActive: (when: string) => string;
630
+ unknown: string;
631
+ sessionEnded: string;
632
+ sessionNotEnded: string;
633
+ otherSessionsEnded: string;
634
+ otherSessionsNotEnded: string;
635
+ linkedAccounts: string;
636
+ linkedIntro: string;
637
+ linked: string;
638
+ notLinked: string;
639
+ unlink: string;
640
+ link: string;
641
+ noSocialLogin: string;
642
+ autoLinkNote: string;
643
+ providerLinked: (provider: string) => string;
644
+ providerUnlinked: (provider: string) => string;
645
+ providerNotLinked: (provider: string) => string;
646
+ providerNotUnlinked: (provider: string) => string;
647
+ inviteSomeone: string;
648
+ inviteIntro: (days: number) => string;
649
+ linkWord: string;
650
+ validUntil: (date: string) => string;
651
+ withdrawInvitation: string;
652
+ invitationWithdrawn: string;
653
+ invitationNotWithdrawn: string;
654
+ emailOptional: string;
655
+ creating: string;
656
+ createInvitation: string;
657
+ copy: string;
658
+ share: string;
659
+ linkShownOnce: string;
660
+ invitationText: (app: string, link: string) => string;
661
+ shareYourself: (error: string) => string;
662
+ invitationSentTo: (email: string) => string;
663
+ invitationNotCreated: string;
664
+ linkCopied: string;
665
+ copyLinkFailed: string;
666
+ deleteForGood: string;
667
+ cannotBeUndone: string;
668
+ deletionText: string;
669
+ deletionAgents: string;
670
+ deletionNoLogin: string;
671
+ typeToContinue: string;
672
+ type: string;
673
+ deleteWord: string;
674
+ deleting: string;
675
+ deletePermanently: string;
676
+ accountDeleted: string;
677
+ accountNotDeleted: string;
678
+ administration: string;
679
+ accounts: string;
680
+ since: (date: string) => string;
681
+ you: string;
682
+ roleOf: (name: string) => string;
683
+ roleChanged: string;
684
+ deleteAccountOf: (name: string) => string;
685
+ confirmDeleteAccount: (name: string) => string;
686
+ accountDeletedAdmin: string;
687
+ invitations: string;
688
+ noOpenInvitations: string;
689
+ by: (inviter: string) => string;
690
+ didntWork: string;
691
+ }>;
package/dist/messages.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * (from the UI release on) what the pages show. A Product calls configureAuthMessages once, from a module its root
4
4
  * layout and its server wiring import, with its LOCALE and the few words it wants differently; code reads `m()`.
5
5
  */
6
+ import { defineMessages } from "@vonall/messages";
6
7
  export const en = {
7
8
  // Signup
8
9
  needsEinladung: "Signing up needs an invitation",
@@ -67,7 +68,6 @@ export const en = {
67
68
  resetLinkNotSent: "The reset link could not be sent.",
68
69
  resetLinkSent: "If an account with this email address exists, a link to reset the password has been sent.",
69
70
  resetLinkNotRequested: "The reset link could not be requested.",
70
- invalidEmailDot: "Please enter a valid email address.",
71
71
  // Two-factor on login
72
72
  twoFactorTitle: "Two-factor authentication",
73
73
  twoFactorEnterCode: "Enter the 6-digit code from your authenticator app.",
@@ -86,7 +86,6 @@ export const en = {
86
86
  inviteOnly: (app) => `${app} is invite only. Ask someone who already has an account for an invitation link and open it on this device.`,
87
87
  alreadyHaveAccount: "Already have an account?",
88
88
  repeatPassword: "Repeat the password",
89
- passwordsDontMatchDot: "The passwords don't match.",
90
89
  needsValidEinladung: "Signing up needs a valid invitation.",
91
90
  emailInUse: "This email address is already in use.",
92
91
  signupFailed: "Signing up failed.",
@@ -95,7 +94,6 @@ export const en = {
95
94
  resetIntro: "Enter your new password",
96
95
  resetNoToken: "No valid token found. Please request a new link to reset your password.",
97
96
  resetLinkInvalid: "The reset link is invalid or incomplete.",
98
- passwordTooShortDot: (min) => `The password needs at least ${min} characters.`,
99
97
  newPassword: "New password",
100
98
  confirmNewPassword: "Confirm the new password",
101
99
  savePassword: "Save the password",
@@ -207,7 +205,7 @@ export const en = {
207
205
  providerNotUnlinked: (provider) => `${provider} could not be unlinked`,
208
206
  // Invitations
209
207
  inviteSomeone: "Invite someone",
210
- inviteIntro: "An invitation link works once and for 14 days. Whoever opens it can create an account.",
208
+ inviteIntro: (days) => `An invitation link works once and for ${days} days. Whoever opens it can create an account.`,
211
209
  linkWord: "Link",
212
210
  validUntil: (date) => `valid until ${date}`,
213
211
  withdrawInvitation: "Withdraw invitation",
@@ -311,7 +309,6 @@ export const de = {
311
309
  resetLinkNotSent: "Der Link zum Zurücksetzen konnte nicht verschickt werden.",
312
310
  resetLinkSent: "Wenn es ein Konto mit dieser E-Mail-Adresse gibt, ist ein Link zum Zurücksetzen des Passworts unterwegs.",
313
311
  resetLinkNotRequested: "Der Link zum Zurücksetzen konnte nicht angefordert werden.",
314
- invalidEmailDot: "Bitte gib eine gültige E-Mail-Adresse ein.",
315
312
  twoFactorTitle: "Zwei-Faktor-Authentisierung",
316
313
  twoFactorEnterCode: "Gib den 6-stelligen Code aus deiner Authenticator-App ein.",
317
314
  confirm: "Bestätigen",
@@ -328,7 +325,6 @@ export const de = {
328
325
  inviteOnly: (app) => `${app} gibt es nur auf Einladung. Frag jemanden, der schon ein Konto hat, nach einem Einladungslink und öffne ihn auf diesem Gerät.`,
329
326
  alreadyHaveAccount: "Schon ein Konto?",
330
327
  repeatPassword: "Passwort wiederholen",
331
- passwordsDontMatchDot: "Die Passwörter stimmen nicht überein.",
332
328
  needsValidEinladung: "Zum Registrieren braucht es eine gültige Einladung.",
333
329
  emailInUse: "Diese E-Mail-Adresse wird schon verwendet.",
334
330
  signupFailed: "Die Registrierung hat nicht geklappt.",
@@ -336,7 +332,6 @@ export const de = {
336
332
  resetIntro: "Gib dein neues Passwort ein",
337
333
  resetNoToken: "Kein gültiger Link. Bitte fordere einen neuen Link zum Zurücksetzen an.",
338
334
  resetLinkInvalid: "Der Link zum Zurücksetzen ist ungültig oder unvollständig.",
339
- passwordTooShortDot: (min) => `Das Passwort braucht mindestens ${min} Zeichen.`,
340
335
  newPassword: "Neues Passwort",
341
336
  confirmNewPassword: "Neues Passwort bestätigen",
342
337
  savePassword: "Passwort speichern",
@@ -442,7 +437,7 @@ export const de = {
442
437
  providerNotLinked: (provider) => `${provider} konnte nicht verknüpft werden`,
443
438
  providerNotUnlinked: (provider) => `${provider} konnte nicht getrennt werden`,
444
439
  inviteSomeone: "Jemanden einladen",
445
- inviteIntro: "Ein Einladungslink funktioniert einmal und 14 Tage lang. Wer ihn öffnet, kann ein Konto erstellen.",
440
+ inviteIntro: (days) => `Ein Einladungslink funktioniert einmal und ${days} Tage lang. Wer ihn öffnet, kann ein Konto erstellen.`,
446
441
  linkWord: "Link",
447
442
  validUntil: (date) => `gültig bis ${date}`,
448
443
  withdrawInvitation: "Einladung zurückziehen",
@@ -486,9 +481,4 @@ export const de = {
486
481
  by: (inviter) => `von ${inviter}`,
487
482
  didntWork: "Das hat nicht geklappt.",
488
483
  };
489
- let current = en;
490
- export function configureAuthMessages({ locale, overrides }) {
491
- current = { ...(locale === "de" ? de : en), ...overrides };
492
- }
493
- /** The configured messages. */
494
- export const m = () => current;
484
+ export const { m, configure: configureAuthMessages } = defineMessages({ en, de });
@@ -1,8 +1,8 @@
1
1
  /** The Admin option: every account. */
2
2
  export declare const getAllUsers: import("$app/server").RemoteQueryFunction<void, {
3
- id: string;
4
- name: string;
5
3
  email: string;
4
+ name: string;
5
+ id: string;
6
6
  image: string | null;
7
7
  emailVerified: boolean;
8
8
  createdAt: Date;
@@ -5,7 +5,6 @@ import { m } from "../messages.js";
5
5
  import { adminQuery, adminSchemaCommand, protectedCommand, protectedForm, protectedQuery, protectedSchemaCommand } from "../server/helpers.js";
6
6
  import { authInstance } from "../server/registry.js";
7
7
  import { UserRepo } from "../server/repositories/UserRepo.js";
8
- import { KontoService } from "../server/service/konto.service.js";
9
8
  import { emailSchema, nameSchema, passwordSchema } from "../types.js";
10
9
  import { isSessionNotFresh, reauthPath } from "../util/fresh.js";
11
10
  /** The Admin option: every account. */
@@ -80,12 +79,12 @@ export const deleteUser = adminSchemaCommand(z.object({ userId: z.string() }), a
80
79
  if (userId === admin.id) {
81
80
  throw error(400, { message: m().ownAccount, id: "own_account", timestamp: new Date().toISOString() });
82
81
  }
83
- await KontoService.loeschen(userId);
82
+ await UserRepo.kontoLoeschen(userId);
84
83
  await getAllUsers().refresh();
85
84
  return { success: true };
86
85
  });
87
86
  /** Deletes the user's own account with all its data. */
88
87
  export const deleteOwnAccount = protectedCommand(async (user) => {
89
- await KontoService.loeschen(user.id);
88
+ await UserRepo.kontoLoeschen(user.id);
90
89
  return { success: true };
91
90
  });
@@ -1,6 +1,11 @@
1
1
  /** The user's open Einladungen, and whether the server can send them by email. */
2
2
  export declare const getOffeneEinladungen: import("$app/server").RemoteQueryFunction<void, {
3
- einladungen: import("../types.js").OffeneEinladung[];
3
+ einladungen: {
4
+ id: string;
5
+ email: string | null;
6
+ expiresAt: Date;
7
+ createdAt: Date;
8
+ }[];
4
9
  mail: boolean;
5
10
  }, void>;
6
11
  /** Creates an Einladung; the link is returned only here. With an email, it is also sent (if mail is set up). */
@@ -3,6 +3,7 @@ import { z } from "zod";
3
3
  import { m } from "../messages.js";
4
4
  import { adminQuery, adminSchemaCommand, protectedQuery, protectedSchemaCommand } from "../server/helpers.js";
5
5
  import { registry } from "../server/registry.js";
6
+ import { EinladungRepo } from "../server/repositories/EinladungRepo.js";
6
7
  import { EinladungService } from "../server/service/einladung.service.js";
7
8
  import { sendEinladungEmail } from "../server/service/mail.js";
8
9
  import { emailSchema } from "../types.js";
@@ -15,7 +16,7 @@ function unwrap(result) {
15
16
  }
16
17
  /** The user's open Einladungen, and whether the server can send them by email. */
17
18
  export const getOffeneEinladungen = protectedQuery(async (user) => {
18
- return { einladungen: await EinladungService.offene(user.id), mail: registry().mailer.enabled };
19
+ return { einladungen: await EinladungRepo.listOpenBy(user.id, new Date()), mail: registry().mailer.enabled };
19
20
  });
20
21
  /** Creates an Einladung; the link is returned only here. With an email, it is also sent (if mail is set up). */
21
22
  export const createEinladung = protectedSchemaCommand(z.object({ email: emailSchema.nullable() }), async ({ email }, user) => {
@@ -47,10 +48,10 @@ export const withdrawEinladung = protectedSchemaCommand(z.object({ einladungId:
47
48
  });
48
49
  /** The Admin option: every open Einladung, and withdrawing any of them. */
49
50
  export const getAlleEinladungen = adminQuery(async () => {
50
- return await EinladungService.alleOffenen();
51
+ return await EinladungRepo.listAllOpen(new Date());
51
52
  });
52
53
  export const adminWithdrawEinladung = adminSchemaCommand(z.object({ einladungId: z.string() }), async ({ einladungId }) => {
53
- unwrap(await EinladungService.zurueckziehenAlsAdmin(einladungId));
54
+ unwrap(await EinladungService.zurueckziehen(null, einladungId));
54
55
  await getAlleEinladungen().refresh();
55
56
  await getOffeneEinladungen().refresh();
56
57
  });
@@ -5,5 +5,4 @@ export { authInstance, registry as authRegistry, type AuthLog, type Db } from ".
5
5
  export { EinladungRepo } from "./repositories/EinladungRepo.js";
6
6
  export { UserRepo } from "./repositories/UserRepo.js";
7
7
  export { EINLADUNG_COOKIE, EINLADUNG_GUELTIG_TAGE, EinladungService, type EinladungError } from "./service/einladung.service.js";
8
- export { KontoService } from "./service/konto.service.js";
9
8
  export { sendEinladungEmail, sendPasswordResetEmail, sendVerifyEmail } from "./service/mail.js";
@@ -5,5 +5,4 @@ export { authInstance, registry as authRegistry } from "./registry.js";
5
5
  export { EinladungRepo } from "./repositories/EinladungRepo.js";
6
6
  export { UserRepo } from "./repositories/UserRepo.js";
7
7
  export { EINLADUNG_COOKIE, EINLADUNG_GUELTIG_TAGE, EinladungService } from "./service/einladung.service.js";
8
- export { KontoService } from "./service/konto.service.js";
9
8
  export { sendEinladungEmail, sendPasswordResetEmail, sendVerifyEmail } from "./service/mail.js";
@@ -14,6 +14,9 @@ export declare const UserRepo: {
14
14
  providerId: string;
15
15
  updatedAt: Date;
16
16
  }[]>;
17
- /** Deletes the user; every row that belongs to them goes with it (foreign keys cascade). */
18
- deleteUser(userId: string): Promise<void>;
17
+ /**
18
+ * Deletes the Konto: the user with everything that belongs to them (the foreign keys of every user-owned table
19
+ * cascade, so a Product's own tables reference `user.id` with `onDelete: "cascade"`).
20
+ */
21
+ kontoLoeschen(userId: string): Promise<void>;
19
22
  };
@@ -59,8 +59,11 @@ export const UserRepo = {
59
59
  .from(schema.account)
60
60
  .where(eq(schema.account.userId, userId));
61
61
  },
62
- /** Deletes the user; every row that belongs to them goes with it (foreign keys cascade). */
63
- async deleteUser(userId) {
62
+ /**
63
+ * Deletes the Konto: the user with everything that belongs to them (the foreign keys of every user-owned table
64
+ * cascade, so a Product's own tables reference `user.id` with `onDelete: "cascade"`).
65
+ */
66
+ async kontoLoeschen(userId) {
64
67
  const { db, schema } = registry();
65
68
  await db.delete(schema.user).where(eq(schema.user.id, userId));
66
69
  },
@@ -1,6 +1,7 @@
1
1
  import { type Result } from "neverthrow";
2
- import type { EinladungInfo, OffeneEinladung, SignupMode, SignupState } from "../../types.js";
3
- export declare const EINLADUNG_GUELTIG_TAGE = 14;
2
+ import type { EinladungInfo, SignupMode, SignupState } from "../../types.js";
3
+ import { EINLADUNG_GUELTIG_TAGE } from "../../util/signup.js";
4
+ export { EINLADUNG_GUELTIG_TAGE };
4
5
  /** The cookie that carries an Einladung's token from its link through signup (email, Google or GitHub). */
5
6
  export declare const EINLADUNG_COOKIE = "einladung";
6
7
  export type EinladungError = {
@@ -33,16 +34,6 @@ export declare const EinladungService: {
33
34
  }>;
34
35
  /** Uses the Einladung for the new user: marks it as taken. */
35
36
  annehmen(userId: string, token: string, now?: Date): Promise<Result<void, EinladungError>>;
36
- offene(userId: string, now?: Date): Promise<OffeneEinladung[]>;
37
- /** Withdraws an open Einladung of the user. */
38
- zurueckziehen(userId: string, einladungId: string): Promise<Result<void, EinladungError>>;
39
- /** For the admin: every open Einladung, and withdrawing any of them. */
40
- alleOffenen(now?: Date): Promise<{
41
- id: string;
42
- email: string | null;
43
- inviterName: string;
44
- expiresAt: Date;
45
- createdAt: Date;
46
- }[]>;
47
- zurueckziehenAlsAdmin(einladungId: string): Promise<Result<void, EinladungError>>;
37
+ /** Withdraws an open Einladung of the user, or any open one when `userId` is null (the admin). */
38
+ zurueckziehen(userId: string | null, einladungId: string): Promise<Result<void, EinladungError>>;
48
39
  };
@@ -8,8 +8,8 @@ import { m } from "../../messages.js";
8
8
  import { registry } from "../registry.js";
9
9
  import { EinladungRepo } from "../repositories/EinladungRepo.js";
10
10
  import { UserRepo } from "../repositories/UserRepo.js";
11
- import { signupState } from "../../util/signup.js";
12
- export const EINLADUNG_GUELTIG_TAGE = 14;
11
+ import { EINLADUNG_GUELTIG_TAGE, signupState } from "../../util/signup.js";
12
+ export { EINLADUNG_GUELTIG_TAGE };
13
13
  /** The cookie that carries an Einladung's token from its link through signup (email, Google or GitHub). */
14
14
  export const EINLADUNG_COOKIE = "einladung";
15
15
  const hash = (token) => createHash("sha256").update(token).digest("hex");
@@ -59,18 +59,8 @@ export const EinladungService = {
59
59
  return err(fehler.angenommen());
60
60
  return ok(undefined);
61
61
  },
62
- async offene(userId, now = new Date()) {
63
- return await EinladungRepo.listOpenBy(userId, now);
64
- },
65
- /** Withdraws an open Einladung of the user. */
62
+ /** Withdraws an open Einladung of the user, or any open one when `userId` is null (the admin). */
66
63
  async zurueckziehen(userId, einladungId) {
67
64
  return (await EinladungRepo.deleteOpen(einladungId, userId)) ? ok(undefined) : err(fehler.unbekannt());
68
65
  },
69
- /** For the admin: every open Einladung, and withdrawing any of them. */
70
- async alleOffenen(now = new Date()) {
71
- return await EinladungRepo.listAllOpen(now);
72
- },
73
- async zurueckziehenAlsAdmin(einladungId) {
74
- return (await EinladungRepo.deleteOpen(einladungId, null)) ? ok(undefined) : err(fehler.unbekannt());
75
- },
76
66
  };
@@ -2,6 +2,7 @@
2
2
  import { Trash2, X } from "@lucide/svelte";
3
3
  import { toast } from "svelte-sonner";
4
4
  import { m } from "../messages.js";
5
+ import { EINLADUNG_GUELTIG_TAGE } from "../util/signup.js";
5
6
  import { deleteUser, getAllUsers, setUserRole } from "../remote/app_user.remote.js";
6
7
  import { adminWithdrawEinladung, getAlleEinladungen } from "../remote/einladung.remote.js";
7
8
  import { authUi } from "./context.js";
@@ -68,7 +69,7 @@
68
69
 
69
70
  <section class="panel grid gap-3 p-5">
70
71
  <span class="section-kicker">{m().invitations}</span>
71
- <p class="text-sm text-muted-foreground">{m().inviteIntro}</p>
72
+ <p class="text-sm text-muted-foreground">{m().inviteIntro(EINLADUNG_GUELTIG_TAGE)}</p>
72
73
  <EinladungErstellen />
73
74
  {#if einladungen.length === 0}
74
75
  <p class="text-sm text-muted-foreground">{m().noOpenInvitations}</p>
@@ -3,6 +3,7 @@
3
3
  import { toast } from "svelte-sonner";
4
4
  import * as Tabs from "../components/ui/tabs/index.js";
5
5
  import { m } from "../messages.js";
6
+ import { EINLADUNG_GUELTIG_TAGE } from "../util/signup.js";
6
7
  import { getOffeneEinladungen, withdrawEinladung } from "../remote/einladung.remote.js";
7
8
  import { authUi } from "./context.js";
8
9
  import EinladungErstellen from "./EinladungErstellen.svelte";
@@ -26,7 +27,7 @@
26
27
  <Tabs.Content value="invitations" class="panel mt-6 grid gap-4 p-6 md:p-8">
27
28
  <div class="space-y-1">
28
29
  <h3 class="text-lg font-medium">{m().inviteSomeone}</h3>
29
- <p class="text-sm text-muted-foreground">{m().inviteIntro}</p>
30
+ <p class="text-sm text-muted-foreground">{m().inviteIntro(EINLADUNG_GUELTIG_TAGE)}</p>
30
31
  </div>
31
32
 
32
33
  <EinladungErstellen />
@@ -54,7 +54,7 @@
54
54
  async function requestPasswordReset(e: SubmitEvent) {
55
55
  e.preventDefault();
56
56
  if (!forgotPasswordEmail || !forgotPasswordEmail.includes("@")) {
57
- toast.error(m().invalidEmailDot);
57
+ toast.error(m().invalidEmail);
58
58
  return;
59
59
  }
60
60
  sendingResetLink = true;
@@ -30,11 +30,11 @@
30
30
  return;
31
31
  }
32
32
  if (password.length < MIN_PASSWORD_LENGTH) {
33
- toast.error(m().passwordTooShortDot(MIN_PASSWORD_LENGTH));
33
+ toast.error(m().passwordTooShort(MIN_PASSWORD_LENGTH));
34
34
  return;
35
35
  }
36
36
  if (password !== confirmPassword) {
37
- toast.error(m().passwordsDontMatchDot);
37
+ toast.error(m().passwordsMismatch);
38
38
  return;
39
39
  }
40
40
  loading = true;
@@ -1,4 +1,6 @@
1
1
  import type { SignupMode, SignupState } from "../types.js";
2
+ /** How long an Einladung's link works. */
3
+ export declare const EINLADUNG_GUELTIG_TAGE = 14;
2
4
  /** Whether a user is an admin. Works without the admin option too: the user then has no role and nobody is. */
3
5
  export declare function isAdmin(user: object | null | undefined): boolean;
4
6
  /** Whether a user may create Einladungen in this signup mode. */
@@ -1,3 +1,5 @@
1
+ /** How long an Einladung's link works. */
2
+ export const EINLADUNG_GUELTIG_TAGE = 14;
1
3
  /** Whether a user is an admin. Works without the admin option too: the user then has no role and nobody is. */
2
4
  export function isAdmin(user) {
3
5
  return Boolean(user && "role" in user && user.role === "admin");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vonall/auth",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Accounts for a Web App Factory Product: better-auth with the hooks, the protected helpers, Einladungen, Konto, the auth pages and the settings; Admin as an option",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -102,7 +102,8 @@
102
102
  "tailwind-merge": "^3.7.0",
103
103
  "tailwind-variants": "^3.3.1",
104
104
  "uqr": "^0.1.3",
105
- "@vonall/mail": "^0.1.1"
105
+ "@vonall/messages": "^0.1.0",
106
+ "@vonall/mail": "^0.2.0"
106
107
  },
107
108
  "scripts": {
108
109
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
@@ -1,7 +0,0 @@
1
- export declare const KontoService: {
2
- /**
3
- * Deletes the account with everything that belongs to it: the foreign keys of every user-owned table cascade, so a
4
- * Product's own tables reference `user.id` with `onDelete: "cascade"`.
5
- */
6
- loeschen(userId: string): Promise<void>;
7
- };
@@ -1,11 +0,0 @@
1
- /** The user's account as a whole. */
2
- import { UserRepo } from "../repositories/UserRepo.js";
3
- export const KontoService = {
4
- /**
5
- * Deletes the account with everything that belongs to it: the foreign keys of every user-owned table cascade, so a
6
- * Product's own tables reference `user.id` with `onDelete: "cascade"`.
7
- */
8
- async loeschen(userId) {
9
- await UserRepo.deleteUser(userId);
10
- },
11
- };