@aneuhold/be-ts-db-lib 4.2.19 → 4.2.21

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 (34) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/lib/index.d.ts +1 -2
  3. package/lib/index.d.ts.map +1 -1
  4. package/lib/index.js +1 -2
  5. package/lib/index.js.map +1 -1
  6. package/lib/index.ts +0 -2
  7. package/lib/repositories/common/UserRepository.d.ts.map +1 -1
  8. package/lib/repositories/common/UserRepository.js +0 -2
  9. package/lib/repositories/common/UserRepository.js.map +1 -1
  10. package/lib/repositories/common/UserRepository.ts +0 -3
  11. package/lib/services/GoogleAuthService.d.ts +16 -2
  12. package/lib/services/GoogleAuthService.d.ts.map +1 -1
  13. package/lib/services/GoogleAuthService.js +51 -34
  14. package/lib/services/GoogleAuthService.js.map +1 -1
  15. package/lib/services/GoogleAuthService.ts +60 -38
  16. package/lib/services/MigrationService.d.ts.map +1 -1
  17. package/lib/services/MigrationService.js +24 -6
  18. package/lib/services/MigrationService.js.map +1 -1
  19. package/lib/services/MigrationService.ts +30 -6
  20. package/lib/util/DbSchemaUpdater.d.ts.map +1 -1
  21. package/lib/util/DbSchemaUpdater.js +0 -2
  22. package/lib/util/DbSchemaUpdater.js.map +1 -1
  23. package/lib/util/DbSchemaUpdater.ts +0 -2
  24. package/package.json +3 -3
  25. package/lib/repositories/common/ApiKeyRepository.d.ts +0 -18
  26. package/lib/repositories/common/ApiKeyRepository.d.ts.map +0 -1
  27. package/lib/repositories/common/ApiKeyRepository.js +0 -45
  28. package/lib/repositories/common/ApiKeyRepository.js.map +0 -1
  29. package/lib/repositories/common/ApiKeyRepository.ts +0 -56
  30. package/lib/validators/common/ApiKeyValidator.d.ts +0 -9
  31. package/lib/validators/common/ApiKeyValidator.d.ts.map +0 -1
  32. package/lib/validators/common/ApiKeyValidator.js +0 -57
  33. package/lib/validators/common/ApiKeyValidator.js.map +0 -1
  34. package/lib/validators/common/ApiKeyValidator.ts +0 -69
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 🔖 [4.2.21] (2026-03-20)
9
+
10
+ ### 🏗️ Changed
11
+
12
+ - `GoogleAuthService.verifyAndFindUser` and `verifyAndFindOrCreateUser` no longer return `apiKey` in their result.
13
+ - Updated dependencies on `@aneuhold/be-ts-lib` to `^3.1.8` and `@aneuhold/core-ts-db-lib` to `^5.0.3`.
14
+
15
+ ### 🔥 Removed
16
+
17
+ - Removed `ApiKeyRepository` class, its tests, and its subscriber registration in `UserRepository`.
18
+ - Removed `ApiKeyValidator` class and its usage in `DbSchemaUpdater`.
19
+
20
+ ## 🔖 [4.2.20] (2026-03-19)
21
+
22
+ ### ✅ Added
23
+
24
+ - Added `GoogleAuthService.verifyAndFindUser` method that returns `null` when no matching user exists (does not create one).
25
+
26
+ ### 🏗️ Changed
27
+
28
+ - Refactored `GoogleAuthService`: extracted private `verifyToken` helper and restructured `verifyAndFindOrCreateUser` to delegate to `verifyAndFindUser`.
29
+ - Refactored `MigrationService` to fill in missing `projectAccess` fields with safe defaults instead of patching `refreshTokenHashes`.
30
+ - Updated dependencies on `@aneuhold/be-ts-lib` to `^3.1.7` and `@aneuhold/core-ts-db-lib` to `^5.0.2`.
31
+
8
32
  ## 🔖 [4.2.19] (2026-03-18)
9
33
 
10
34
  ### ✅ Added
@@ -348,6 +372,8 @@ Updated dependencies: now requires `@aneuhold/core-ts-db-lib@^3.0.0`, `@aneuhold
348
372
 
349
373
  <!-- Link References -->
350
374
 
375
+ [4.2.21]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v4.2.20...be-ts-db-lib-v4.2.21
376
+ [4.2.20]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v4.2.19...be-ts-db-lib-v4.2.20
351
377
  [4.2.19]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v4.2.18...be-ts-db-lib-v4.2.19
352
378
  [4.2.18]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v4.2.17...be-ts-db-lib-v4.2.18
353
379
  [4.2.17]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v4.2.16...be-ts-db-lib-v4.2.17
package/lib/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import BaseRepository from './repositories/BaseRepository.js';
2
- import ApiKeyRepository from './repositories/common/ApiKeyRepository.js';
3
2
  import UserRepository from './repositories/common/UserRepository.js';
4
3
  import DashboardBaseRepository from './repositories/dashboard/DashboardBaseRepository.js';
5
4
  import DashboardBaseWithUserIdRepository from './repositories/dashboard/DashboardBaseWithUserIdRepository.js';
@@ -21,6 +20,6 @@ import WorkoutSetRepository from './repositories/workout/WorkoutSetRepository.js
21
20
  import GoogleAuthService from './services/GoogleAuthService.js';
22
21
  import DbOperationMetaData from './util/DbOperationMetaData.js';
23
22
  import DocumentDb from './util/DocumentDb.js';
24
- export { ApiKeyRepository, BaseRepository, DashboardBaseRepository, DashboardBaseWithUserIdRepository, DashboardNonogramKatanaItemRepository, DashboardNonogramKatanaUpgradeRepository, DashboardTaskRepository, DashboardUserConfigRepository, DbOperationMetaData, DocumentDb, GoogleAuthService, UserRepository, WorkoutBaseRepository, WorkoutBaseWithUserIdRepository, WorkoutEquipmentTypeRepository, WorkoutExerciseCalibrationRepository, WorkoutExerciseRepository, WorkoutMesocycleRepository, WorkoutMicrocycleRepository, WorkoutMuscleGroupRepository, WorkoutSessionExerciseRepository, WorkoutSessionRepository, WorkoutSetRepository };
23
+ export { BaseRepository, DashboardBaseRepository, DashboardBaseWithUserIdRepository, DashboardNonogramKatanaItemRepository, DashboardNonogramKatanaUpgradeRepository, DashboardTaskRepository, DashboardUserConfigRepository, DbOperationMetaData, DocumentDb, GoogleAuthService, UserRepository, WorkoutBaseRepository, WorkoutBaseWithUserIdRepository, WorkoutEquipmentTypeRepository, WorkoutExerciseCalibrationRepository, WorkoutExerciseRepository, WorkoutMesocycleRepository, WorkoutMicrocycleRepository, WorkoutMuscleGroupRepository, WorkoutSessionExerciseRepository, WorkoutSessionRepository, WorkoutSetRepository };
25
24
  export type {};
26
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,gBAAgB,MAAM,2CAA2C,CAAC;AACzE,OAAO,cAAc,MAAM,yCAAyC,CAAC;AACrE,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,iCAAiC,MAAM,+DAA+D,CAAC;AAC9G,OAAO,qCAAqC,MAAM,mEAAmE,CAAC;AACtH,OAAO,wCAAwC,MAAM,sEAAsE,CAAC;AAC5H,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,2DAA2D,CAAC;AACtG,OAAO,qBAAqB,MAAM,iDAAiD,CAAC;AACpF,OAAO,+BAA+B,MAAM,2DAA2D,CAAC;AACxG,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AACtG,OAAO,oCAAoC,MAAM,gEAAgE,CAAC;AAClH,OAAO,yBAAyB,MAAM,qDAAqD,CAAC;AAC5F,OAAO,0BAA0B,MAAM,sDAAsD,CAAC;AAC9F,OAAO,2BAA2B,MAAM,uDAAuD,CAAC;AAChG,OAAO,4BAA4B,MAAM,wDAAwD,CAAC;AAClG,OAAO,gCAAgC,MAAM,4DAA4D,CAAC;AAC1G,OAAO,wBAAwB,MAAM,oDAAoD,CAAC;AAC1F,OAAO,oBAAoB,MAAM,gDAAgD,CAAC;AAClF,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,mBAAmB,MAAM,+BAA+B,CAAC;AAChE,OAAO,UAAU,MAAM,sBAAsB,CAAC;AAG9C,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,iCAAiC,EACjC,qCAAqC,EACrC,wCAAwC,EACxC,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,+BAA+B,EAC/B,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,gCAAgC,EAChC,wBAAwB,EACxB,oBAAoB,EACrB,CAAC;AAGF,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,cAAc,MAAM,yCAAyC,CAAC;AACrE,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,iCAAiC,MAAM,+DAA+D,CAAC;AAC9G,OAAO,qCAAqC,MAAM,mEAAmE,CAAC;AACtH,OAAO,wCAAwC,MAAM,sEAAsE,CAAC;AAC5H,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,2DAA2D,CAAC;AACtG,OAAO,qBAAqB,MAAM,iDAAiD,CAAC;AACpF,OAAO,+BAA+B,MAAM,2DAA2D,CAAC;AACxG,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AACtG,OAAO,oCAAoC,MAAM,gEAAgE,CAAC;AAClH,OAAO,yBAAyB,MAAM,qDAAqD,CAAC;AAC5F,OAAO,0BAA0B,MAAM,sDAAsD,CAAC;AAC9F,OAAO,2BAA2B,MAAM,uDAAuD,CAAC;AAChG,OAAO,4BAA4B,MAAM,wDAAwD,CAAC;AAClG,OAAO,gCAAgC,MAAM,4DAA4D,CAAC;AAC1G,OAAO,wBAAwB,MAAM,oDAAoD,CAAC;AAC1F,OAAO,oBAAoB,MAAM,gDAAgD,CAAC;AAClF,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,mBAAmB,MAAM,+BAA+B,CAAC;AAChE,OAAO,UAAU,MAAM,sBAAsB,CAAC;AAG9C,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,iCAAiC,EACjC,qCAAqC,EACrC,wCAAwC,EACxC,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,+BAA+B,EAC/B,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,gCAAgC,EAChC,wBAAwB,EACxB,oBAAoB,EACrB,CAAC;AAGF,YAAY,EAAE,CAAC"}
package/lib/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import BaseRepository from './repositories/BaseRepository.js';
2
- import ApiKeyRepository from './repositories/common/ApiKeyRepository.js';
3
2
  import UserRepository from './repositories/common/UserRepository.js';
4
3
  import DashboardBaseRepository from './repositories/dashboard/DashboardBaseRepository.js';
5
4
  import DashboardBaseWithUserIdRepository from './repositories/dashboard/DashboardBaseWithUserIdRepository.js';
@@ -22,5 +21,5 @@ import GoogleAuthService from './services/GoogleAuthService.js';
22
21
  import DbOperationMetaData from './util/DbOperationMetaData.js';
23
22
  import DocumentDb from './util/DocumentDb.js';
24
23
  // Export all the functions and classes from this library
25
- export { ApiKeyRepository, BaseRepository, DashboardBaseRepository, DashboardBaseWithUserIdRepository, DashboardNonogramKatanaItemRepository, DashboardNonogramKatanaUpgradeRepository, DashboardTaskRepository, DashboardUserConfigRepository, DbOperationMetaData, DocumentDb, GoogleAuthService, UserRepository, WorkoutBaseRepository, WorkoutBaseWithUserIdRepository, WorkoutEquipmentTypeRepository, WorkoutExerciseCalibrationRepository, WorkoutExerciseRepository, WorkoutMesocycleRepository, WorkoutMicrocycleRepository, WorkoutMuscleGroupRepository, WorkoutSessionExerciseRepository, WorkoutSessionRepository, WorkoutSetRepository };
24
+ export { BaseRepository, DashboardBaseRepository, DashboardBaseWithUserIdRepository, DashboardNonogramKatanaItemRepository, DashboardNonogramKatanaUpgradeRepository, DashboardTaskRepository, DashboardUserConfigRepository, DbOperationMetaData, DocumentDb, GoogleAuthService, UserRepository, WorkoutBaseRepository, WorkoutBaseWithUserIdRepository, WorkoutEquipmentTypeRepository, WorkoutExerciseCalibrationRepository, WorkoutExerciseRepository, WorkoutMesocycleRepository, WorkoutMicrocycleRepository, WorkoutMuscleGroupRepository, WorkoutSessionExerciseRepository, WorkoutSessionRepository, WorkoutSetRepository };
26
25
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,gBAAgB,MAAM,2CAA2C,CAAC;AACzE,OAAO,cAAc,MAAM,yCAAyC,CAAC;AACrE,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,iCAAiC,MAAM,+DAA+D,CAAC;AAC9G,OAAO,qCAAqC,MAAM,mEAAmE,CAAC;AACtH,OAAO,wCAAwC,MAAM,sEAAsE,CAAC;AAC5H,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,2DAA2D,CAAC;AACtG,OAAO,qBAAqB,MAAM,iDAAiD,CAAC;AACpF,OAAO,+BAA+B,MAAM,2DAA2D,CAAC;AACxG,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AACtG,OAAO,oCAAoC,MAAM,gEAAgE,CAAC;AAClH,OAAO,yBAAyB,MAAM,qDAAqD,CAAC;AAC5F,OAAO,0BAA0B,MAAM,sDAAsD,CAAC;AAC9F,OAAO,2BAA2B,MAAM,uDAAuD,CAAC;AAChG,OAAO,4BAA4B,MAAM,wDAAwD,CAAC;AAClG,OAAO,gCAAgC,MAAM,4DAA4D,CAAC;AAC1G,OAAO,wBAAwB,MAAM,oDAAoD,CAAC;AAC1F,OAAO,oBAAoB,MAAM,gDAAgD,CAAC;AAClF,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,mBAAmB,MAAM,+BAA+B,CAAC;AAChE,OAAO,UAAU,MAAM,sBAAsB,CAAC;AAE9C,yDAAyD;AACzD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,iCAAiC,EACjC,qCAAqC,EACrC,wCAAwC,EACxC,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,+BAA+B,EAC/B,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,gCAAgC,EAChC,wBAAwB,EACxB,oBAAoB,EACrB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,cAAc,MAAM,yCAAyC,CAAC;AACrE,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,iCAAiC,MAAM,+DAA+D,CAAC;AAC9G,OAAO,qCAAqC,MAAM,mEAAmE,CAAC;AACtH,OAAO,wCAAwC,MAAM,sEAAsE,CAAC;AAC5H,OAAO,uBAAuB,MAAM,qDAAqD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,2DAA2D,CAAC;AACtG,OAAO,qBAAqB,MAAM,iDAAiD,CAAC;AACpF,OAAO,+BAA+B,MAAM,2DAA2D,CAAC;AACxG,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AACtG,OAAO,oCAAoC,MAAM,gEAAgE,CAAC;AAClH,OAAO,yBAAyB,MAAM,qDAAqD,CAAC;AAC5F,OAAO,0BAA0B,MAAM,sDAAsD,CAAC;AAC9F,OAAO,2BAA2B,MAAM,uDAAuD,CAAC;AAChG,OAAO,4BAA4B,MAAM,wDAAwD,CAAC;AAClG,OAAO,gCAAgC,MAAM,4DAA4D,CAAC;AAC1G,OAAO,wBAAwB,MAAM,oDAAoD,CAAC;AAC1F,OAAO,oBAAoB,MAAM,gDAAgD,CAAC;AAClF,OAAO,iBAAiB,MAAM,iCAAiC,CAAC;AAChE,OAAO,mBAAmB,MAAM,+BAA+B,CAAC;AAChE,OAAO,UAAU,MAAM,sBAAsB,CAAC;AAE9C,yDAAyD;AACzD,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,iCAAiC,EACjC,qCAAqC,EACrC,wCAAwC,EACxC,uBAAuB,EACvB,6BAA6B,EAC7B,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,+BAA+B,EAC/B,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,gCAAgC,EAChC,wBAAwB,EACxB,oBAAoB,EACrB,CAAC"}
package/lib/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import BaseRepository from './repositories/BaseRepository.js';
2
- import ApiKeyRepository from './repositories/common/ApiKeyRepository.js';
3
2
  import UserRepository from './repositories/common/UserRepository.js';
4
3
  import DashboardBaseRepository from './repositories/dashboard/DashboardBaseRepository.js';
5
4
  import DashboardBaseWithUserIdRepository from './repositories/dashboard/DashboardBaseWithUserIdRepository.js';
@@ -24,7 +23,6 @@ import DocumentDb from './util/DocumentDb.js';
24
23
 
25
24
  // Export all the functions and classes from this library
26
25
  export {
27
- ApiKeyRepository,
28
26
  BaseRepository,
29
27
  DashboardBaseRepository,
30
28
  DashboardBaseWithUserIdRepository,
@@ -1 +1 @@
1
- {"version":3,"file":"UserRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAalD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,cAAc,CAAC,IAAI,CAAC;IAC9D,OAAO,CAAC,MAAM,CAAC,eAAe,CAAW;IAEzC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAA6B;IAE7D,OAAO;IAIP,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAclC;;OAEG;IACH,MAAM,CAAC,OAAO,IAAI,cAAc;IAO1B,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAWrE;;;;OAIG;IACG,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAQlE,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAO5D"}
1
+ {"version":3,"file":"UserRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAWlD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,cAAc,CAAC,IAAI,CAAC;IAC9D,OAAO,CAAC,MAAM,CAAC,eAAe,CAAW;IAEzC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAA6B;IAE7D,OAAO;IAIP,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAalC;;OAEG;IACH,MAAM,CAAC,OAAO,IAAI,cAAc;IAO1B,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAWrE;;;;OAIG;IACG,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAQlE,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAO5D"}
@@ -10,7 +10,6 @@ import WorkoutExerciseRepository from '../workout/WorkoutExerciseRepository.js';
10
10
  import WorkoutMesocycleRepository from '../workout/WorkoutMesocycleRepository.js';
11
11
  import WorkoutMicrocycleRepository from '../workout/WorkoutMicrocycleRepository.js';
12
12
  import WorkoutMuscleGroupRepository from '../workout/WorkoutMuscleGroupRepository.js';
13
- import ApiKeyRepository from './ApiKeyRepository.js';
14
13
  /**
15
14
  * The repository that contains {@link User} documents.
16
15
  */
@@ -21,7 +20,6 @@ export default class UserRepository extends BaseRepository {
21
20
  super(UserRepository.COLLECTION_NAME, new UserValidator());
22
21
  }
23
22
  setupSubscribers() {
24
- this.subscribeToChanges(ApiKeyRepository.getListenersForUserRepo());
25
23
  this.subscribeToChanges(DashboardUserConfigRepository.getListenersForUserRepo());
26
24
  this.subscribeToChanges(DashboardTaskRepository.getListenersForUserRepo());
27
25
  this.subscribeToChanges(DashboardNonogramKatanaItemRepository.getListenersForUserRepo());
@@ -1 +1 @@
1
- {"version":3,"file":"UserRepository.js","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UserRepository.js","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,6 @@ import WorkoutExerciseRepository from '../workout/WorkoutExerciseRepository.js';
12
12
  import WorkoutMesocycleRepository from '../workout/WorkoutMesocycleRepository.js';
13
13
  import WorkoutMicrocycleRepository from '../workout/WorkoutMicrocycleRepository.js';
14
14
  import WorkoutMuscleGroupRepository from '../workout/WorkoutMuscleGroupRepository.js';
15
- import ApiKeyRepository from './ApiKeyRepository.js';
16
-
17
15
  /**
18
16
  * The repository that contains {@link User} documents.
19
17
  */
@@ -27,7 +25,6 @@ export default class UserRepository extends BaseRepository<User> {
27
25
  }
28
26
 
29
27
  protected setupSubscribers(): void {
30
- this.subscribeToChanges(ApiKeyRepository.getListenersForUserRepo());
31
28
  this.subscribeToChanges(DashboardUserConfigRepository.getListenersForUserRepo());
32
29
  this.subscribeToChanges(DashboardTaskRepository.getListenersForUserRepo());
33
30
  this.subscribeToChanges(DashboardNonogramKatanaItemRepository.getListenersForUserRepo());
@@ -1,4 +1,4 @@
1
- import type { ApiKey, User } from '@aneuhold/core-ts-db-lib';
1
+ import type { User } from '@aneuhold/core-ts-db-lib';
2
2
  /**
3
3
  * Service for verifying Google ID tokens and finding or creating users.
4
4
  * Handles account linking by email when a matching user exists without a
@@ -6,6 +6,15 @@ import type { ApiKey, User } from '@aneuhold/core-ts-db-lib';
6
6
  */
7
7
  export default class GoogleAuthService {
8
8
  private static readonly client;
9
+ /**
10
+ * Verifies a Google ID token and finds the associated user. Returns
11
+ * `null` if no matching user exists (does **not** create one).
12
+ *
13
+ * @param googleCredentialToken - The Google ID token string from the client.
14
+ */
15
+ static verifyAndFindUser(googleCredentialToken: string): Promise<{
16
+ user: User;
17
+ } | null>;
9
18
  /**
10
19
  * Verifies a Google ID token and finds or creates the associated user.
11
20
  *
@@ -13,7 +22,12 @@ export default class GoogleAuthService {
13
22
  */
14
23
  static verifyAndFindOrCreateUser(googleCredentialToken: string): Promise<{
15
24
  user: User;
16
- apiKey: ApiKey;
17
25
  }>;
26
+ /**
27
+ * Verifies a Google ID token and returns the Google ID and email.
28
+ *
29
+ * @param googleCredentialToken - The Google ID token string from the client.
30
+ */
31
+ private static verifyToken;
18
32
  }
19
33
  //# sourceMappingURL=GoogleAuthService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleAuthService.d.ts","sourceRoot":"","sources":["../../src/services/GoogleAuthService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAM7D;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAEpE;;;;OAIG;WACU,yBAAyB,CACpC,qBAAqB,EAAE,MAAM,GAC5B,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAsD3C"}
1
+ {"version":3,"file":"GoogleAuthService.d.ts","sourceRoot":"","sources":["../../src/services/GoogleAuthService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAKrD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAEpE;;;;;OAKG;WACU,iBAAiB,CAAC,qBAAqB,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAyB7F;;;;OAIG;WACU,yBAAyB,CAAC,qBAAqB,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAwB9F;;;;OAIG;mBACkB,WAAW;CAmBjC"}
@@ -1,6 +1,5 @@
1
- import { GOOGLE_CLIENT_ID, UserSchema } from '@aneuhold/core-ts-db-lib';
1
+ import { GOOGLE_CLIENT_ID, ProjectName, UserSchema } from '@aneuhold/core-ts-db-lib';
2
2
  import { OAuth2Client } from 'google-auth-library';
3
- import ApiKeyRepository from '../repositories/common/ApiKeyRepository.js';
4
3
  import UserRepository from '../repositories/common/UserRepository.js';
5
4
  /**
6
5
  * Service for verifying Google ID tokens and finding or creating users.
@@ -10,25 +9,14 @@ import UserRepository from '../repositories/common/UserRepository.js';
10
9
  export default class GoogleAuthService {
11
10
  static client = new OAuth2Client(GOOGLE_CLIENT_ID);
12
11
  /**
13
- * Verifies a Google ID token and finds or creates the associated user.
12
+ * Verifies a Google ID token and finds the associated user. Returns
13
+ * `null` if no matching user exists (does **not** create one).
14
14
  *
15
15
  * @param googleCredentialToken - The Google ID token string from the client.
16
16
  */
17
- static async verifyAndFindOrCreateUser(googleCredentialToken) {
18
- const ticket = await this.client.verifyIdToken({
19
- idToken: googleCredentialToken,
20
- audience: GOOGLE_CLIENT_ID
21
- });
22
- const payload = ticket.getPayload();
23
- if (!payload) {
24
- throw new Error('Invalid Google token payload');
25
- }
26
- const { sub: googleId, email } = payload;
27
- if (!email) {
28
- throw new Error('Google account has no email');
29
- }
17
+ static async verifyAndFindUser(googleCredentialToken) {
18
+ const { googleId, email } = await this.verifyToken(googleCredentialToken);
30
19
  const userRepo = UserRepository.getRepo();
31
- const apiKeyRepo = ApiKeyRepository.getRepo();
32
20
  // 1. Look up by googleId
33
21
  let user = await userRepo.get({ auth: { googleId } });
34
22
  // 2. Fall back to email lookup (account linking)
@@ -40,26 +28,55 @@ export default class GoogleAuthService {
40
28
  user.auth.googleId = googleId;
41
29
  }
42
30
  }
43
- // 3. Create new user if neither match. The ApiKey subscriber on
44
- // UserRepository automatically creates an API key on user insertion.
45
31
  if (!user) {
46
- const newUser = UserSchema.parse({
47
- userName: email,
48
- email,
49
- auth: { googleId },
50
- projectAccess: { dashboard: false, workout: true }
51
- });
52
- const insertedUser = await userRepo.insertNew(newUser);
53
- if (!insertedUser) {
54
- throw new Error('Failed to create user');
55
- }
56
- user = insertedUser;
32
+ return null;
33
+ }
34
+ return { user };
35
+ }
36
+ /**
37
+ * Verifies a Google ID token and finds or creates the associated user.
38
+ *
39
+ * @param googleCredentialToken - The Google ID token string from the client.
40
+ */
41
+ static async verifyAndFindOrCreateUser(googleCredentialToken) {
42
+ const result = await this.verifyAndFindUser(googleCredentialToken);
43
+ if (result) {
44
+ return result;
45
+ }
46
+ // Create new user.
47
+ const { googleId, email } = await this.verifyToken(googleCredentialToken);
48
+ const userRepo = UserRepository.getRepo();
49
+ const newUser = UserSchema.parse({
50
+ userName: email,
51
+ email,
52
+ auth: { googleId },
53
+ projectAccess: { [ProjectName.Dashboard]: false, [ProjectName.Workout]: true }
54
+ });
55
+ const insertedUser = await userRepo.insertNew(newUser);
56
+ if (!insertedUser) {
57
+ throw new Error('Failed to create user');
57
58
  }
58
- const apiKey = await apiKeyRepo.get({ userId: user._id });
59
- if (!apiKey) {
60
- throw new Error(`No API key found for user ${user._id}`);
59
+ return { user: insertedUser };
60
+ }
61
+ /**
62
+ * Verifies a Google ID token and returns the Google ID and email.
63
+ *
64
+ * @param googleCredentialToken - The Google ID token string from the client.
65
+ */
66
+ static async verifyToken(googleCredentialToken) {
67
+ const ticket = await this.client.verifyIdToken({
68
+ idToken: googleCredentialToken,
69
+ audience: GOOGLE_CLIENT_ID
70
+ });
71
+ const payload = ticket.getPayload();
72
+ if (!payload) {
73
+ throw new Error('Invalid Google token payload');
74
+ }
75
+ const { sub: googleId, email } = payload;
76
+ if (!email) {
77
+ throw new Error('Google account has no email');
61
78
  }
62
- return { user, apiKey };
79
+ return { googleId, email };
63
80
  }
64
81
  }
65
82
  //# sourceMappingURL=GoogleAuthService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleAuthService.js","sourceRoot":"","sources":["../../src/services/GoogleAuthService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,gBAAgB,MAAM,4CAA4C,CAAC;AAC1E,OAAO,cAAc,MAAM,0CAA0C,CAAC;AAEtE;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC5B,MAAM,CAAU,MAAM,GAAG,IAAI,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAEpE;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,yBAAyB,CACpC,qBAA6B;QAE7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;YAC7C,OAAO,EAAE,qBAAqB;YAC9B,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;QACzC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAE9C,yBAAyB;QACzB,IAAI,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEtD,iDAAiD;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACrC,IAAI,IAAI,EAAE,CAAC;gBACT,qCAAqC;gBACrC,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAC3E,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,CAAC;QACH,CAAC;QAED,gEAAgE;QAChE,wEAAwE;QACxE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC;gBAC/B,QAAQ,EAAE,KAAK;gBACf,KAAK;gBACL,IAAI,EAAE,EAAE,QAAQ,EAAE;gBAClB,aAAa,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;aACnD,CAAC,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,GAAG,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC"}
1
+ {"version":3,"file":"GoogleAuthService.js","sourceRoot":"","sources":["../../src/services/GoogleAuthService.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import type { ApiKey, User } from '@aneuhold/core-ts-db-lib';
2
- import { GOOGLE_CLIENT_ID, UserSchema } from '@aneuhold/core-ts-db-lib';
1
+ import type { User } from '@aneuhold/core-ts-db-lib';
2
+ import { GOOGLE_CLIENT_ID, ProjectName, UserSchema } from '@aneuhold/core-ts-db-lib';
3
3
  import { OAuth2Client } from 'google-auth-library';
4
- import ApiKeyRepository from '../repositories/common/ApiKeyRepository.js';
5
4
  import UserRepository from '../repositories/common/UserRepository.js';
6
5
 
7
6
  /**
@@ -13,29 +12,15 @@ export default class GoogleAuthService {
13
12
  private static readonly client = new OAuth2Client(GOOGLE_CLIENT_ID);
14
13
 
15
14
  /**
16
- * Verifies a Google ID token and finds or creates the associated user.
15
+ * Verifies a Google ID token and finds the associated user. Returns
16
+ * `null` if no matching user exists (does **not** create one).
17
17
  *
18
18
  * @param googleCredentialToken - The Google ID token string from the client.
19
19
  */
20
- static async verifyAndFindOrCreateUser(
21
- googleCredentialToken: string
22
- ): Promise<{ user: User; apiKey: ApiKey }> {
23
- const ticket = await this.client.verifyIdToken({
24
- idToken: googleCredentialToken,
25
- audience: GOOGLE_CLIENT_ID
26
- });
27
- const payload = ticket.getPayload();
28
- if (!payload) {
29
- throw new Error('Invalid Google token payload');
30
- }
31
-
32
- const { sub: googleId, email } = payload;
33
- if (!email) {
34
- throw new Error('Google account has no email');
35
- }
20
+ static async verifyAndFindUser(googleCredentialToken: string): Promise<{ user: User } | null> {
21
+ const { googleId, email } = await this.verifyToken(googleCredentialToken);
36
22
 
37
23
  const userRepo = UserRepository.getRepo();
38
- const apiKeyRepo = ApiKeyRepository.getRepo();
39
24
 
40
25
  // 1. Look up by googleId
41
26
  let user = await userRepo.get({ auth: { googleId } });
@@ -50,27 +35,64 @@ export default class GoogleAuthService {
50
35
  }
51
36
  }
52
37
 
53
- // 3. Create new user if neither match. The ApiKey subscriber on
54
- // UserRepository automatically creates an API key on user insertion.
55
38
  if (!user) {
56
- const newUser = UserSchema.parse({
57
- userName: email,
58
- email,
59
- auth: { googleId },
60
- projectAccess: { dashboard: false, workout: true }
61
- });
62
- const insertedUser = await userRepo.insertNew(newUser);
63
- if (!insertedUser) {
64
- throw new Error('Failed to create user');
65
- }
66
- user = insertedUser;
39
+ return null;
40
+ }
41
+
42
+ return { user };
43
+ }
44
+
45
+ /**
46
+ * Verifies a Google ID token and finds or creates the associated user.
47
+ *
48
+ * @param googleCredentialToken - The Google ID token string from the client.
49
+ */
50
+ static async verifyAndFindOrCreateUser(googleCredentialToken: string): Promise<{ user: User }> {
51
+ const result = await this.verifyAndFindUser(googleCredentialToken);
52
+ if (result) {
53
+ return result;
67
54
  }
68
55
 
69
- const apiKey = await apiKeyRepo.get({ userId: user._id });
70
- if (!apiKey) {
71
- throw new Error(`No API key found for user ${user._id}`);
56
+ // Create new user.
57
+ const { googleId, email } = await this.verifyToken(googleCredentialToken);
58
+ const userRepo = UserRepository.getRepo();
59
+
60
+ const newUser = UserSchema.parse({
61
+ userName: email,
62
+ email,
63
+ auth: { googleId },
64
+ projectAccess: { [ProjectName.Dashboard]: false, [ProjectName.Workout]: true }
65
+ });
66
+ const insertedUser = await userRepo.insertNew(newUser);
67
+ if (!insertedUser) {
68
+ throw new Error('Failed to create user');
69
+ }
70
+
71
+ return { user: insertedUser };
72
+ }
73
+
74
+ /**
75
+ * Verifies a Google ID token and returns the Google ID and email.
76
+ *
77
+ * @param googleCredentialToken - The Google ID token string from the client.
78
+ */
79
+ private static async verifyToken(
80
+ googleCredentialToken: string
81
+ ): Promise<{ googleId: string; email: string }> {
82
+ const ticket = await this.client.verifyIdToken({
83
+ idToken: googleCredentialToken,
84
+ audience: GOOGLE_CLIENT_ID
85
+ });
86
+ const payload = ticket.getPayload();
87
+ if (!payload) {
88
+ throw new Error('Invalid Google token payload');
89
+ }
90
+
91
+ const { sub: googleId, email } = payload;
92
+ if (!email) {
93
+ throw new Error('Google account has no email');
72
94
  }
73
95
 
74
- return { user, apiKey };
96
+ return { googleId, email };
75
97
  }
76
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MigrationService.d.ts","sourceRoot":"","sources":["../../src/services/MigrationService.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC;;;;;;;;OAQG;WACU,SAAS,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAoCtD"}
1
+ {"version":3,"file":"MigrationService.d.ts","sourceRoot":"","sources":["../../src/services/MigrationService.ts"],"names":[],"mappings":"AAeA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC;;;;;;;;OAQG;WACU,SAAS,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAkDtD"}
@@ -2,6 +2,15 @@
2
2
  // @ts-nocheck
3
3
  import { DR } from '@aneuhold/core-ts-lib';
4
4
  import UserRepository from '../repositories/common/UserRepository.js';
5
+ /**
6
+ * The default values for each project access field. New fields should be
7
+ * added here and defaulted to `false` so existing users don't gain access
8
+ * automatically.
9
+ */
10
+ const PROJECT_ACCESS_DEFAULTS = {
11
+ dashboard: false,
12
+ workout: false
13
+ };
5
14
  /**
6
15
  * A service for migrating the DB to a new state after an existing document
7
16
  * change.
@@ -23,9 +32,14 @@ export default class MigrationService {
23
32
  DR.logger.info('Starting migration...');
24
33
  const userRepo = UserRepository.getRepo();
25
34
  const users = await userRepo.getAll();
26
- // Add refreshTokenHashes to users that don't have it yet
27
- const usersToUpdate = users.filter((user) => !user.auth.refreshTokenHashes);
28
- DR.logger.info(`Found ${usersToUpdate.length} of ${users.length} users missing auth.refreshTokenHashes.`);
35
+ // Find users that are missing projectAccess entirely or are missing
36
+ // any of the expected fields.
37
+ const usersToUpdate = users.filter((user) => {
38
+ if (!user.projectAccess)
39
+ return true;
40
+ return Object.keys(PROJECT_ACCESS_DEFAULTS).some((key) => user.projectAccess[key] === undefined);
41
+ });
42
+ DR.logger.info(`Found ${usersToUpdate.length} of ${users.length} users with missing projectAccess fields.`);
29
43
  if (usersToUpdate.length === 0) {
30
44
  DR.logger.success('No migration needed.');
31
45
  return;
@@ -33,16 +47,20 @@ export default class MigrationService {
33
47
  if (dryRun) {
34
48
  DR.logger.info('Dry run: Would update the following users:');
35
49
  usersToUpdate.forEach((user) => {
36
- DR.logger.info(` - ${user.userName} (${user._id})`);
50
+ const existing = user.projectAccess ?? {};
51
+ const merged = { ...PROJECT_ACCESS_DEFAULTS, ...existing };
52
+ DR.logger.info(` - ${user.userName} (${user._id}): ${JSON.stringify(existing)} → ${JSON.stringify(merged)}`);
37
53
  });
38
54
  return;
39
55
  }
40
56
  for (const user of usersToUpdate) {
57
+ const existing = user.projectAccess ?? {};
58
+ const merged = { ...PROJECT_ACCESS_DEFAULTS, ...existing };
41
59
  await userRepo.update({
42
60
  _id: user._id,
43
- auth: { ...user.auth, refreshTokenHashes: [] }
61
+ projectAccess: merged
44
62
  });
45
- DR.logger.info(`Updated user ${user.userName} (${user._id})`);
63
+ DR.logger.info(`Updated user ${user.userName} (${user._id}): ${JSON.stringify(existing)} → ${JSON.stringify(merged)}`);
46
64
  }
47
65
  DR.logger.success(`Migration complete. Updated ${usersToUpdate.length} users.`);
48
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MigrationService.js","sourceRoot":"","sources":["../../src/services/MigrationService.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,cAAc;AACd,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAC3C,OAAO,cAAc,MAAM,0CAA0C,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,KAAK;QACnC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAExC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;QAEtC,yDAAyD;QACzD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAE5E,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,SAAS,aAAa,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,yCAAyC,CAC1F,CAAC;QAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAC7D,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC7B,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,MAAM,QAAQ,CAAC,MAAM,CAAC;gBACpB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE;aAC/C,CAAC,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,+BAA+B,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;IAClF,CAAC;CACF"}
1
+ {"version":3,"file":"MigrationService.js","sourceRoot":"","sources":["../../src/services/MigrationService.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,cAAc;AACd,OAAO,EAAE,EAAE,EAAE,MAAM,uBAAuB,CAAC;AAC3C,OAAO,cAAc,MAAM,0CAA0C,CAAC;AAEtE;;;;GAIG;AACH,MAAM,uBAAuB,GAAG;IAC9B,SAAS,EAAE,KAAK;IAChB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,KAAK;QACnC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAExC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;QAEtC,oEAAoE;QACpE,8BAA8B;QAC9B,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YAC1C,IAAI,CAAC,IAAI,CAAC,aAAa;gBAAE,OAAO,IAAI,CAAC;YACrC,OAAO,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAC9C,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,SAAS,CAC/C,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,SAAS,aAAa,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,2CAA2C,CAC5F,CAAC;QAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAC7D,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;gBAC1C,MAAM,MAAM,GAAG,EAAE,GAAG,uBAAuB,EAAE,GAAG,QAAQ,EAAE,CAAC;gBAC3D,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAC9F,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,EAAE,GAAG,uBAAuB,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC3D,MAAM,QAAQ,CAAC,MAAM,CAAC;gBACpB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,aAAa,EAAE,MAAM;aACtB,CAAC,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,gBAAgB,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACvG,CAAC;QACJ,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,+BAA+B,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;IAClF,CAAC;CACF"}
@@ -3,6 +3,16 @@
3
3
  import { DR } from '@aneuhold/core-ts-lib';
4
4
  import UserRepository from '../repositories/common/UserRepository.js';
5
5
 
6
+ /**
7
+ * The default values for each project access field. New fields should be
8
+ * added here and defaulted to `false` so existing users don't gain access
9
+ * automatically.
10
+ */
11
+ const PROJECT_ACCESS_DEFAULTS = {
12
+ dashboard: false,
13
+ workout: false
14
+ };
15
+
6
16
  /**
7
17
  * A service for migrating the DB to a new state after an existing document
8
18
  * change.
@@ -26,11 +36,17 @@ export default class MigrationService {
26
36
  const userRepo = UserRepository.getRepo();
27
37
  const users = await userRepo.getAll();
28
38
 
29
- // Add refreshTokenHashes to users that don't have it yet
30
- const usersToUpdate = users.filter((user) => !user.auth.refreshTokenHashes);
39
+ // Find users that are missing projectAccess entirely or are missing
40
+ // any of the expected fields.
41
+ const usersToUpdate = users.filter((user) => {
42
+ if (!user.projectAccess) return true;
43
+ return Object.keys(PROJECT_ACCESS_DEFAULTS).some(
44
+ (key) => user.projectAccess[key] === undefined
45
+ );
46
+ });
31
47
 
32
48
  DR.logger.info(
33
- `Found ${usersToUpdate.length} of ${users.length} users missing auth.refreshTokenHashes.`
49
+ `Found ${usersToUpdate.length} of ${users.length} users with missing projectAccess fields.`
34
50
  );
35
51
 
36
52
  if (usersToUpdate.length === 0) {
@@ -41,17 +57,25 @@ export default class MigrationService {
41
57
  if (dryRun) {
42
58
  DR.logger.info('Dry run: Would update the following users:');
43
59
  usersToUpdate.forEach((user) => {
44
- DR.logger.info(` - ${user.userName} (${user._id})`);
60
+ const existing = user.projectAccess ?? {};
61
+ const merged = { ...PROJECT_ACCESS_DEFAULTS, ...existing };
62
+ DR.logger.info(
63
+ ` - ${user.userName} (${user._id}): ${JSON.stringify(existing)} → ${JSON.stringify(merged)}`
64
+ );
45
65
  });
46
66
  return;
47
67
  }
48
68
 
49
69
  for (const user of usersToUpdate) {
70
+ const existing = user.projectAccess ?? {};
71
+ const merged = { ...PROJECT_ACCESS_DEFAULTS, ...existing };
50
72
  await userRepo.update({
51
73
  _id: user._id,
52
- auth: { ...user.auth, refreshTokenHashes: [] }
74
+ projectAccess: merged
53
75
  });
54
- DR.logger.info(`Updated user ${user.userName} (${user._id})`);
76
+ DR.logger.info(
77
+ `Updated user ${user.userName} (${user._id}): ${JSON.stringify(existing)} → ${JSON.stringify(merged)}`
78
+ );
55
79
  }
56
80
 
57
81
  DR.logger.success(`Migration complete. Updated ${usersToUpdate.length} users.`);
@@ -1 +1 @@
1
- {"version":3,"file":"DbSchemaUpdater.d.ts","sourceRoot":"","sources":["../../src/util/DbSchemaUpdater.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;WACrB,uBAAuB,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAsBpE"}
1
+ {"version":3,"file":"DbSchemaUpdater.d.ts","sourceRoot":"","sources":["../../src/util/DbSchemaUpdater.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;WACrB,uBAAuB,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAqBpE"}
@@ -1,4 +1,3 @@
1
- import ApiKeyValidator from '../validators/common/ApiKeyValidator.js';
2
1
  import UserValidator from '../validators/common/UserValidator.js';
3
2
  import DashboardNonogramKatanaItemValidator from '../validators/dashboard/NonogramKatanaItemValidator.js';
4
3
  import DashboardNonogramKatanaUpgradeValidator from '../validators/dashboard/NonogramKatanaUpgradeValidator.js';
@@ -20,7 +19,6 @@ export default class DbSchemaUpdater {
20
19
  static async updateSchemaForAllRepos(dryRun = false) {
21
20
  // Common validators
22
21
  await new UserValidator().validateRepositoryInDb(dryRun);
23
- await new ApiKeyValidator().validateRepositoryInDb(dryRun);
24
22
  // Dashboard validators
25
23
  await new DashboardUserConfigValidator().validateRepositoryInDb(dryRun);
26
24
  await new DashboardTaskValidator().validateRepositoryInDb(dryRun);
@@ -1 +1 @@
1
- {"version":3,"file":"DbSchemaUpdater.js","sourceRoot":"","sources":["../../src/util/DbSchemaUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,yCAAyC,CAAC;AACtE,OAAO,aAAa,MAAM,uCAAuC,CAAC;AAClE,OAAO,oCAAoC,MAAM,wDAAwD,CAAC;AAC1G,OAAO,uCAAuC,MAAM,2DAA2D,CAAC;AAChH,OAAO,sBAAsB,MAAM,0CAA0C,CAAC;AAC9E,OAAO,4BAA4B,MAAM,gDAAgD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,iDAAiD,CAAC;AAC5F,OAAO,mCAAmC,MAAM,uDAAuD,CAAC;AACxG,OAAO,wBAAwB,MAAM,4CAA4C,CAAC;AAClF,OAAO,yBAAyB,MAAM,6CAA6C,CAAC;AACpF,OAAO,0BAA0B,MAAM,8CAA8C,CAAC;AACtF,OAAO,2BAA2B,MAAM,+CAA+C,CAAC;AACxF,OAAO,+BAA+B,MAAM,mDAAmD,CAAC;AAChG,OAAO,uBAAuB,MAAM,2CAA2C,CAAC;AAChF,OAAO,mBAAmB,MAAM,uCAAuC,CAAC;AAExE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,MAAM,GAAG,KAAK;QACjD,oBAAoB;QACpB,MAAM,IAAI,aAAa,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,IAAI,eAAe,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAE3D,uBAAuB;QACvB,MAAM,IAAI,4BAA4B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACxE,MAAM,IAAI,sBAAsB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,IAAI,oCAAoC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAChF,MAAM,IAAI,uCAAuC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAEnF,qBAAqB;QACrB,MAAM,IAAI,6BAA6B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACzE,MAAM,IAAI,mCAAmC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC/E,MAAM,IAAI,wBAAwB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,IAAI,yBAAyB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACrE,MAAM,IAAI,0BAA0B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACtE,MAAM,IAAI,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACvE,MAAM,IAAI,+BAA+B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC3E,MAAM,IAAI,uBAAuB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,IAAI,mBAAmB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;CACF"}
1
+ {"version":3,"file":"DbSchemaUpdater.js","sourceRoot":"","sources":["../../src/util/DbSchemaUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,uCAAuC,CAAC;AAClE,OAAO,oCAAoC,MAAM,wDAAwD,CAAC;AAC1G,OAAO,uCAAuC,MAAM,2DAA2D,CAAC;AAChH,OAAO,sBAAsB,MAAM,0CAA0C,CAAC;AAC9E,OAAO,4BAA4B,MAAM,gDAAgD,CAAC;AAC1F,OAAO,6BAA6B,MAAM,iDAAiD,CAAC;AAC5F,OAAO,mCAAmC,MAAM,uDAAuD,CAAC;AACxG,OAAO,wBAAwB,MAAM,4CAA4C,CAAC;AAClF,OAAO,yBAAyB,MAAM,6CAA6C,CAAC;AACpF,OAAO,0BAA0B,MAAM,8CAA8C,CAAC;AACtF,OAAO,2BAA2B,MAAM,+CAA+C,CAAC;AACxF,OAAO,+BAA+B,MAAM,mDAAmD,CAAC;AAChG,OAAO,uBAAuB,MAAM,2CAA2C,CAAC;AAChF,OAAO,mBAAmB,MAAM,uCAAuC,CAAC;AAExE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,MAAM,GAAG,KAAK;QACjD,oBAAoB;QACpB,MAAM,IAAI,aAAa,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAEzD,uBAAuB;QACvB,MAAM,IAAI,4BAA4B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACxE,MAAM,IAAI,sBAAsB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,IAAI,oCAAoC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAChF,MAAM,IAAI,uCAAuC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAEnF,qBAAqB;QACrB,MAAM,IAAI,6BAA6B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACzE,MAAM,IAAI,mCAAmC,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC/E,MAAM,IAAI,wBAAwB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,IAAI,yBAAyB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACrE,MAAM,IAAI,0BAA0B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACtE,MAAM,IAAI,2BAA2B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACvE,MAAM,IAAI,+BAA+B,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC3E,MAAM,IAAI,uBAAuB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,IAAI,mBAAmB,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;CACF"}
@@ -1,4 +1,3 @@
1
- import ApiKeyValidator from '../validators/common/ApiKeyValidator.js';
2
1
  import UserValidator from '../validators/common/UserValidator.js';
3
2
  import DashboardNonogramKatanaItemValidator from '../validators/dashboard/NonogramKatanaItemValidator.js';
4
3
  import DashboardNonogramKatanaUpgradeValidator from '../validators/dashboard/NonogramKatanaUpgradeValidator.js';
@@ -21,7 +20,6 @@ export default class DbSchemaUpdater {
21
20
  static async updateSchemaForAllRepos(dryRun = false): Promise<void> {
22
21
  // Common validators
23
22
  await new UserValidator().validateRepositoryInDb(dryRun);
24
- await new ApiKeyValidator().validateRepositoryInDb(dryRun);
25
23
 
26
24
  // Dashboard validators
27
25
  await new DashboardUserConfigValidator().validateRepositoryInDb(dryRun);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@aneuhold/be-ts-db-lib",
3
3
  "author": "Anton G. Neuhold Jr.",
4
4
  "license": "MIT",
5
- "version": "4.2.19",
5
+ "version": "4.2.21",
6
6
  "description": "A backend database library meant to actually interact with various databases in personal projects",
7
7
  "packageManager": "pnpm@10.25.0",
8
8
  "type": "module",
@@ -58,8 +58,8 @@
58
58
  "MongoDB"
59
59
  ],
60
60
  "dependencies": {
61
- "@aneuhold/be-ts-lib": "^3.1.6",
62
- "@aneuhold/core-ts-db-lib": "^5.0.1",
61
+ "@aneuhold/be-ts-lib": "^3.1.8",
62
+ "@aneuhold/core-ts-db-lib": "^5.0.3",
63
63
  "@aneuhold/core-ts-lib": "^2.4.3",
64
64
  "bson": "^7.0.0",
65
65
  "google-auth-library": "^10.6.1",
@@ -1,18 +0,0 @@
1
- import type { ApiKey, User } from '@aneuhold/core-ts-db-lib';
2
- import type { RepoListeners } from '../../services/RepoSubscriptionService.js';
3
- import BaseRepository from '../BaseRepository.js';
4
- /**
5
- * The repository that contains {@link ApiKey} documents.
6
- */
7
- export default class ApiKeyRepository extends BaseRepository<ApiKey> {
8
- private static COLLECTION_NAME;
9
- private static singletonInstance;
10
- static getListenersForUserRepo(): RepoListeners<User>;
11
- private constructor();
12
- protected setupSubscribers(): void;
13
- /**
14
- * Gets the singleton instance of the {@link ApiKeyRepository}.
15
- */
16
- static getRepo(): ApiKeyRepository;
17
- }
18
- //# sourceMappingURL=ApiKeyRepository.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiKeyRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/ApiKeyRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAE/E,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,cAAc,CAAC,MAAM,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAa;IAE3C,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAA+B;IAE/D,MAAM,CAAC,uBAAuB,IAAI,aAAa,CAAC,IAAI,CAAC;IA0BrD,OAAO;IAIP,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAElC;;OAEG;WACW,OAAO,IAAI,gBAAgB;CAM1C"}
@@ -1,45 +0,0 @@
1
- import { ApiKeySchema } from '@aneuhold/core-ts-db-lib';
2
- import ApiKeyValidator from '../../validators/common/ApiKeyValidator.js';
3
- import BaseRepository from '../BaseRepository.js';
4
- /**
5
- * The repository that contains {@link ApiKey} documents.
6
- */
7
- export default class ApiKeyRepository extends BaseRepository {
8
- static COLLECTION_NAME = 'apiKeys';
9
- static singletonInstance;
10
- static getListenersForUserRepo() {
11
- const apiKeyRepo = ApiKeyRepository.getRepo();
12
- return {
13
- deleteOne: async (userId) => {
14
- await (await apiKeyRepo.getCollection()).deleteOne({
15
- userId
16
- });
17
- },
18
- deleteList: async (userIds) => {
19
- await (await apiKeyRepo.getCollection()).deleteMany({
20
- userId: { $in: userIds }
21
- });
22
- },
23
- insertNew: async (user) => {
24
- await apiKeyRepo.insertNew(ApiKeySchema.parse({ userId: user._id }));
25
- },
26
- insertMany: async (users) => {
27
- await apiKeyRepo.insertMany(users.map((user) => ApiKeySchema.parse({ userId: user._id })));
28
- }
29
- };
30
- }
31
- constructor() {
32
- super(ApiKeyRepository.COLLECTION_NAME, new ApiKeyValidator());
33
- }
34
- setupSubscribers() { }
35
- /**
36
- * Gets the singleton instance of the {@link ApiKeyRepository}.
37
- */
38
- static getRepo() {
39
- if (!ApiKeyRepository.singletonInstance) {
40
- ApiKeyRepository.singletonInstance = new ApiKeyRepository();
41
- }
42
- return ApiKeyRepository.singletonInstance;
43
- }
44
- }
45
- //# sourceMappingURL=ApiKeyRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiKeyRepository.js","sourceRoot":"","sources":["../../../src/repositories/common/ApiKeyRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,eAAe,MAAM,4CAA4C,CAAC;AACzE,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,cAAsB;IAC1D,MAAM,CAAC,eAAe,GAAG,SAAS,CAAC;IAEnC,MAAM,CAAC,iBAAiB,CAA+B;IAE/D,MAAM,CAAC,uBAAuB;QAC5B,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO;YACL,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBAC1B,MAAM,CACJ,MAAM,UAAU,CAAC,aAAa,EAAE,CACjC,CAAC,SAAS,CAAC;oBACV,MAAM;iBACP,CAAC,CAAC;YACL,CAAC;YACD,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC5B,MAAM,CACJ,MAAM,UAAU,CAAC,aAAa,EAAE,CACjC,CAAC,UAAU,CAAC;oBACX,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;iBACzB,CAAC,CAAC;YACL,CAAC;YACD,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACxB,MAAM,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC;YACD,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1B,MAAM,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7F,CAAC;SACF,CAAC;IACJ,CAAC;IAED;QACE,KAAK,CAAC,gBAAgB,CAAC,eAAe,EAAE,IAAI,eAAe,EAAE,CAAC,CAAC;IACjE,CAAC;IAES,gBAAgB,KAAU,CAAC;IAErC;;OAEG;IACI,MAAM,CAAC,OAAO;QACnB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;YACxC,gBAAgB,CAAC,iBAAiB,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAC9D,CAAC;QACD,OAAO,gBAAgB,CAAC,iBAAiB,CAAC;IAC5C,CAAC"}
@@ -1,56 +0,0 @@
1
- import type { ApiKey, User } from '@aneuhold/core-ts-db-lib';
2
- import { ApiKeySchema } from '@aneuhold/core-ts-db-lib';
3
- import type { RepoListeners } from '../../services/RepoSubscriptionService.js';
4
- import ApiKeyValidator from '../../validators/common/ApiKeyValidator.js';
5
- import BaseRepository from '../BaseRepository.js';
6
-
7
- /**
8
- * The repository that contains {@link ApiKey} documents.
9
- */
10
- export default class ApiKeyRepository extends BaseRepository<ApiKey> {
11
- private static COLLECTION_NAME = 'apiKeys';
12
-
13
- private static singletonInstance: ApiKeyRepository | undefined;
14
-
15
- static getListenersForUserRepo(): RepoListeners<User> {
16
- const apiKeyRepo = ApiKeyRepository.getRepo();
17
- return {
18
- deleteOne: async (userId) => {
19
- await (
20
- await apiKeyRepo.getCollection()
21
- ).deleteOne({
22
- userId
23
- });
24
- },
25
- deleteList: async (userIds) => {
26
- await (
27
- await apiKeyRepo.getCollection()
28
- ).deleteMany({
29
- userId: { $in: userIds }
30
- });
31
- },
32
- insertNew: async (user) => {
33
- await apiKeyRepo.insertNew(ApiKeySchema.parse({ userId: user._id }));
34
- },
35
- insertMany: async (users) => {
36
- await apiKeyRepo.insertMany(users.map((user) => ApiKeySchema.parse({ userId: user._id })));
37
- }
38
- };
39
- }
40
-
41
- private constructor() {
42
- super(ApiKeyRepository.COLLECTION_NAME, new ApiKeyValidator());
43
- }
44
-
45
- protected setupSubscribers(): void {}
46
-
47
- /**
48
- * Gets the singleton instance of the {@link ApiKeyRepository}.
49
- */
50
- public static getRepo(): ApiKeyRepository {
51
- if (!ApiKeyRepository.singletonInstance) {
52
- ApiKeyRepository.singletonInstance = new ApiKeyRepository();
53
- }
54
- return ApiKeyRepository.singletonInstance;
55
- }
56
- }
@@ -1,9 +0,0 @@
1
- import type { ApiKey } from '@aneuhold/core-ts-db-lib';
2
- import IValidator from '../BaseValidator.js';
3
- export default class ApiKeyValidator extends IValidator<ApiKey> {
4
- constructor();
5
- protected validateNewObjectBusinessLogic(newApiKey: ApiKey): Promise<void>;
6
- protected validateUpdateObjectBusinessLogic(updatedApiKey: Partial<ApiKey>): Promise<void>;
7
- validateRepositoryInDb(dryRun: boolean): Promise<void>;
8
- }
9
- //# sourceMappingURL=ApiKeyValidator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiKeyValidator.d.ts","sourceRoot":"","sources":["../../../src/validators/common/ApiKeyValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAU,CAAC,MAAM,CAAC;;cAK7C,8BAA8B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBhF,SAAS,CAAC,iCAAiC,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpF,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAwB7D"}
@@ -1,57 +0,0 @@
1
- import { ApiKeySchema } from '@aneuhold/core-ts-db-lib';
2
- import { DR, ErrorUtils } from '@aneuhold/core-ts-lib';
3
- import ApiKeyRepository from '../../repositories/common/ApiKeyRepository.js';
4
- import UserRepository from '../../repositories/common/UserRepository.js';
5
- import IValidator from '../BaseValidator.js';
6
- export default class ApiKeyValidator extends IValidator {
7
- constructor() {
8
- super(ApiKeySchema, ApiKeySchema.partial());
9
- }
10
- async validateNewObjectBusinessLogic(newApiKey) {
11
- // Check if the user exists
12
- const userRepo = UserRepository.getRepo();
13
- const userInDb = await userRepo.get({ _id: newApiKey.userId });
14
- if (!userInDb) {
15
- DR.logger.error(`User with ID: ${newApiKey.userId} does not exist in the database.`);
16
- ErrorUtils.throwError(`User with ID: ${newApiKey.userId} does not exist in the database.`, newApiKey);
17
- return;
18
- }
19
- // Check if the user already has an API key
20
- const apiKeyRepo = ApiKeyRepository.getRepo();
21
- const apiKeyInDb = await apiKeyRepo.get({ userId: newApiKey.userId });
22
- if (apiKeyInDb) {
23
- DR.logger.error(`User with ID: ${newApiKey.userId} already has an API key.`);
24
- ErrorUtils.throwError(`User with ID: ${newApiKey.userId} already has an API key.`, newApiKey);
25
- }
26
- }
27
- validateUpdateObjectBusinessLogic(updatedApiKey) {
28
- // Throw, because API keys should not be updated. Only created and deleted.
29
- DR.logger.error(`API keys should not be updated at this time. Only created and deleted.`);
30
- ErrorUtils.throwError(`API keys should not be updated at this time. Only created and deleted.`, updatedApiKey);
31
- return Promise.resolve();
32
- }
33
- async validateRepositoryInDb(dryRun) {
34
- const apiKeyRepo = ApiKeyRepository.getRepo();
35
- const allApiKeys = await apiKeyRepo.getAll();
36
- const allUserIds = await UserRepository.getRepo().getAllIdsAsHash();
37
- await this.runStandardValidationForRepository({
38
- dryRun,
39
- docName: 'API Key',
40
- allDocs: allApiKeys,
41
- shouldDelete: (apiKey) => {
42
- if (!allUserIds[apiKey.userId]) {
43
- DR.logger.error(`API Key with ID: ${apiKey._id} has no valid associated user.`);
44
- return true;
45
- }
46
- return false;
47
- },
48
- deletionFunction: async (docIdsToDelete) => {
49
- await apiKeyRepo.deleteList(docIdsToDelete);
50
- },
51
- updateFunction: async (docsToUpdate) => {
52
- await apiKeyRepo.updateMany(docsToUpdate);
53
- }
54
- });
55
- }
56
- }
57
- //# sourceMappingURL=ApiKeyValidator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiKeyValidator.js","sourceRoot":"","sources":["../../../src/validators/common/ApiKeyValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,gBAAgB,MAAM,+CAA+C,CAAC;AAC7E,OAAO,cAAc,MAAM,6CAA6C,CAAC;AACzE,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,UAAkB;IAC7D;QACE,KAAK,CAAC,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAES,KAAK,CAAC,8BAA8B,CAAC,SAAiB;QAC9D,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,SAAS,CAAC,MAAM,kCAAkC,CAAC,CAAC;YACrF,UAAU,CAAC,UAAU,CACnB,iBAAiB,SAAS,CAAC,MAAM,kCAAkC,EACnE,SAAS,CACV,CAAC;YACF,OAAO;QACT,CAAC;QACD,2CAA2C;QAC3C,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,UAAU,EAAE,CAAC;YACf,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,SAAS,CAAC,MAAM,0BAA0B,CAAC,CAAC;YAC7E,UAAU,CAAC,UAAU,CAAC,iBAAiB,SAAS,CAAC,MAAM,0BAA0B,EAAE,SAAS,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAES,iCAAiC,CAAC,aAA8B;QACxE,2EAA2E;QAC3E,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QAC1F,UAAU,CAAC,UAAU,CACnB,wEAAwE,EACxE,aAAa,CACd,CAAC;QACF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,MAAe;QAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC,eAAe,EAAE,CAAC;QAEpE,MAAM,IAAI,CAAC,kCAAkC,CAAC;YAC5C,MAAM;YACN,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,UAAU;YACnB,YAAY,EAAE,CAAC,MAAc,EAAE,EAAE;gBAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC/B,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,GAAG,gCAAgC,CAAC,CAAC;oBAChF,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YACD,gBAAgB,EAAE,KAAK,EAAE,cAAsB,EAAE,EAAE;gBACjD,MAAM,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YAC9C,CAAC;YACD,cAAc,EAAE,KAAK,EAAE,YAAsB,EAAE,EAAE;gBAC/C,MAAM,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC5C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,69 +0,0 @@
1
- import type { ApiKey } from '@aneuhold/core-ts-db-lib';
2
- import { ApiKeySchema } from '@aneuhold/core-ts-db-lib';
3
- import { DR, ErrorUtils } from '@aneuhold/core-ts-lib';
4
- import type { UUID } from 'crypto';
5
- import ApiKeyRepository from '../../repositories/common/ApiKeyRepository.js';
6
- import UserRepository from '../../repositories/common/UserRepository.js';
7
- import IValidator from '../BaseValidator.js';
8
-
9
- export default class ApiKeyValidator extends IValidator<ApiKey> {
10
- constructor() {
11
- super(ApiKeySchema, ApiKeySchema.partial());
12
- }
13
-
14
- protected async validateNewObjectBusinessLogic(newApiKey: ApiKey): Promise<void> {
15
- // Check if the user exists
16
- const userRepo = UserRepository.getRepo();
17
- const userInDb = await userRepo.get({ _id: newApiKey.userId });
18
- if (!userInDb) {
19
- DR.logger.error(`User with ID: ${newApiKey.userId} does not exist in the database.`);
20
- ErrorUtils.throwError(
21
- `User with ID: ${newApiKey.userId} does not exist in the database.`,
22
- newApiKey
23
- );
24
- return;
25
- }
26
- // Check if the user already has an API key
27
- const apiKeyRepo = ApiKeyRepository.getRepo();
28
- const apiKeyInDb = await apiKeyRepo.get({ userId: newApiKey.userId });
29
- if (apiKeyInDb) {
30
- DR.logger.error(`User with ID: ${newApiKey.userId} already has an API key.`);
31
- ErrorUtils.throwError(`User with ID: ${newApiKey.userId} already has an API key.`, newApiKey);
32
- }
33
- }
34
-
35
- protected validateUpdateObjectBusinessLogic(updatedApiKey: Partial<ApiKey>): Promise<void> {
36
- // Throw, because API keys should not be updated. Only created and deleted.
37
- DR.logger.error(`API keys should not be updated at this time. Only created and deleted.`);
38
- ErrorUtils.throwError(
39
- `API keys should not be updated at this time. Only created and deleted.`,
40
- updatedApiKey
41
- );
42
- return Promise.resolve();
43
- }
44
-
45
- async validateRepositoryInDb(dryRun: boolean): Promise<void> {
46
- const apiKeyRepo = ApiKeyRepository.getRepo();
47
- const allApiKeys = await apiKeyRepo.getAll();
48
- const allUserIds = await UserRepository.getRepo().getAllIdsAsHash();
49
-
50
- await this.runStandardValidationForRepository({
51
- dryRun,
52
- docName: 'API Key',
53
- allDocs: allApiKeys,
54
- shouldDelete: (apiKey: ApiKey) => {
55
- if (!allUserIds[apiKey.userId]) {
56
- DR.logger.error(`API Key with ID: ${apiKey._id} has no valid associated user.`);
57
- return true;
58
- }
59
- return false;
60
- },
61
- deletionFunction: async (docIdsToDelete: UUID[]) => {
62
- await apiKeyRepo.deleteList(docIdsToDelete);
63
- },
64
- updateFunction: async (docsToUpdate: ApiKey[]) => {
65
- await apiKeyRepo.updateMany(docsToUpdate);
66
- }
67
- });
68
- }
69
- }