@lenne.tech/nest-server 11.35.0 → 11.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.claude/rules/configurable-features.md +1 -1
  2. package/FRAMEWORK-API.md +1 -1
  3. package/dist/core/common/helpers/file.helper.js +3 -2
  4. package/dist/core/common/helpers/file.helper.js.map +1 -1
  5. package/dist/core/modules/file/core-file-access-audit.initializer.d.ts +13 -0
  6. package/dist/core/modules/file/core-file-access-audit.initializer.js +109 -0
  7. package/dist/core/modules/file/core-file-access-audit.initializer.js.map +1 -0
  8. package/dist/core/modules/file/file-roles.config.d.ts +21 -0
  9. package/dist/core/modules/file/file-roles.config.js +51 -2
  10. package/dist/core/modules/file/file-roles.config.js.map +1 -1
  11. package/dist/core/modules/file/file-roles.helper.d.ts +2 -2
  12. package/dist/core/modules/file/file-roles.helper.js +10 -16
  13. package/dist/core/modules/file/file-roles.helper.js.map +1 -1
  14. package/dist/core.module.js +3 -1
  15. package/dist/core.module.js.map +1 -1
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +4 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/tsconfig.build.tsbuildinfo +1 -1
  20. package/migration-guides/11.34.x-to-11.35.x.md +17 -3
  21. package/migration-guides/11.35.0-to-11.35.1.md +152 -0
  22. package/package.json +1 -1
  23. package/src/core/common/helpers/file.helper.ts +11 -5
  24. package/src/core/modules/file/README.md +10 -0
  25. package/src/core/modules/file/core-file-access-audit.initializer.ts +164 -0
  26. package/src/core/modules/file/file-roles.config.ts +156 -1
  27. package/src/core/modules/file/file-roles.helper.ts +15 -22
  28. package/src/core.module.ts +10 -2
  29. package/src/index.ts +4 -0
@@ -3,7 +3,7 @@ import { Logger } from '@nestjs/common';
3
3
  import { IFileConfig } from '../../common/interfaces/server-options.interface';
4
4
  import { CoreFileController } from './core-file.controller';
5
5
  import { CoreFileResolver } from './core-file.resolver';
6
- import { FileRoleKey, resolveRoles } from './file-roles.config';
6
+ import { FILE_ROLE_MEMBERS, FileEndpointClassName, FileRoleKey, resolveRoles } from './file-roles.config';
7
7
 
8
8
  const logger = new Logger('CoreFileRoles');
9
9
 
@@ -12,32 +12,25 @@ const logger = new Logger('CoreFileRoles');
12
12
  // imports the endpoint classes, which inject CoreFileService — see file-roles.config.ts.
13
13
  export {
14
14
  FILE_ROLE_DEFAULTS,
15
+ FILE_ROLE_MEMBERS,
15
16
  resolveRoles,
16
17
  warnOnPresignedDownloadsWithRestrictedRoles,
18
+ warnOnUndecidedEffectiveFileAccess,
17
19
  warnOnUndecidedFileAccess,
18
20
  } from './file-roles.config';
19
- export type { FileRoleKey } from './file-roles.config';
21
+ export type { FileEndpointClassName, FileRoleKey, ObservedFileHandler } from './file-roles.config';
20
22
 
21
23
  /**
22
- * Which member is governed by which knob.
24
+ * The prototypes the member names in {@link FILE_ROLE_MEMBERS} resolve against.
23
25
  *
24
- * `getFileInfo` rides with `downloadRoles` rather than getting its own knob:
25
- * it answers filename, size and content type for a blob, which is the metadata
26
- * half of a download. Splitting it would let a project accidentally publish the
27
- * bucket's contents list while believing downloads were still closed.
26
+ * The NAMES live in `file-roles.config.ts` so the boot audit can share them without importing these
27
+ * classes (that import is what makes this file a non-leaf see the header of `file-roles.config.ts`
28
+ * for the temporal-dead-zone crash it caused). Only the class lookup lives here.
28
29
  */
29
- const ROLE_TARGETS: { key: FileRoleKey; member: string; owner: () => unknown }[] = [
30
- {
31
- key: 'downloadRoles',
32
- member: 'CoreFileController.getFileById',
33
- owner: () => CoreFileController.prototype.getFileById,
34
- },
35
- { key: 'downloadRoles', member: 'CoreFileController.getFile', owner: () => CoreFileController.prototype.getFile },
36
- { key: 'downloadRoles', member: 'CoreFileResolver.getFileInfo', owner: () => CoreFileResolver.prototype.getFileInfo },
37
- { key: 'uploadRoles', member: 'CoreFileResolver.uploadFile', owner: () => CoreFileResolver.prototype.uploadFile },
38
- { key: 'uploadRoles', member: 'CoreFileResolver.uploadFiles', owner: () => CoreFileResolver.prototype.uploadFiles },
39
- { key: 'deleteRoles', member: 'CoreFileResolver.deleteFile', owner: () => CoreFileResolver.prototype.deleteFile },
40
- ];
30
+ const ENDPOINT_PROTOTYPES: Record<FileEndpointClassName, unknown> = {
31
+ CoreFileController: CoreFileController.prototype,
32
+ CoreFileResolver: CoreFileResolver.prototype,
33
+ };
41
34
 
42
35
  /**
43
36
  * Apply the configured file roles to the core file endpoints.
@@ -65,14 +58,14 @@ const ROLE_TARGETS: { key: FileRoleKey; member: string; owner: () => unknown }[]
65
58
  export function applyFileRoles(config?: IFileConfig): void {
66
59
  const resolved = new Map<FileRoleKey, string[]>();
67
60
 
68
- for (const { key, member, owner } of ROLE_TARGETS) {
61
+ for (const { className, key, method } of FILE_ROLE_MEMBERS) {
69
62
  if (!resolved.has(key)) {
70
63
  resolved.set(key, resolveRoles(key, config));
71
64
  }
72
65
 
73
- const target = owner();
66
+ const target = (ENDPOINT_PROTOTYPES[className] as Record<string, unknown>)[method];
74
67
  if (typeof target !== 'function') {
75
- logger.warn(`Cannot apply file.${key}: ${member} is not a function — skipping.`);
68
+ logger.warn(`Cannot apply file.${key}: ${className}.${method} is not a function — skipping.`);
76
69
  continue;
77
70
  }
78
71
 
@@ -1,6 +1,6 @@
1
1
  import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
2
2
  import { DynamicModule, Global, MiddlewareConsumer, Module, NestModule, UnauthorizedException } from '@nestjs/common';
3
- import { APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
3
+ import { APP_INTERCEPTOR, APP_PIPE, DiscoveryModule } from '@nestjs/core';
4
4
  import { GraphQLModule } from '@nestjs/graphql';
5
5
  import { MongooseModule } from '@nestjs/mongoose';
6
6
  import type { Context } from 'graphql-ws';
@@ -51,6 +51,7 @@ import { CoreBetterAuthUserMapper } from './core/modules/better-auth/core-better
51
51
  import { CoreBetterAuthModule } from './core/modules/better-auth/core-better-auth.module';
52
52
  import { CoreBetterAuthService } from './core/modules/better-auth/core-better-auth.service';
53
53
  import { ErrorCodeModule } from './core/modules/error-code/error-code.module';
54
+ import { CoreFileAccessAuditInitializer } from './core/modules/file/core-file-access-audit.initializer';
54
55
  import { applyFileRoles, warnOnPresignedDownloadsWithRestrictedRoles } from './core/modules/file/file-roles.helper';
55
56
  import { CoreHealthCheckModule } from './core/modules/health-check/core-health-check.module';
56
57
  import { CoreHubModule } from './core/modules/hub/core-hub.module';
@@ -305,6 +306,11 @@ export class CoreModule implements NestModule {
305
306
 
306
307
  // Core Services
307
308
  CoreCronJobsInitializer,
309
+ // Audits the file endpoints the project actually REGISTERED. applyFileRoles() above can only
310
+ // reach the base-class members; a subclass that re-declares one keeps its own @Roles() and the
311
+ // configuration never reaches that route. Only a bootstrap-time look at the registered class
312
+ // can tell those apart — see the initializer.
313
+ CoreFileAccessAuditInitializer,
308
314
  CoreRedisService,
309
315
  CoreS3Service,
310
316
  CoreTrustProxyInitializer,
@@ -381,7 +387,9 @@ export class CoreModule implements NestModule {
381
387
  }
382
388
  }
383
389
 
384
- const imports: any[] = [MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options)];
390
+ // DiscoveryModule: CoreFileAccessAuditInitializer needs the registered controller/resolver
391
+ // classes, which only exist once Nest has built its route table.
392
+ const imports: any[] = [DiscoveryModule, MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options)];
385
393
 
386
394
  if (isGraphQlEnabled && config.graphQl) {
387
395
  imports.push(
package/src/index.ts CHANGED
@@ -36,9 +36,11 @@ export * from './core/common/helpers/cookies.helper';
36
36
  export * from './core/common/helpers/graceful-shutdown.helper';
37
37
  export * from './core/common/helpers/db.helper';
38
38
  export * from './core/common/helpers/decorator.helper';
39
+ export * from './core/common/helpers/execution-context-request.helper';
39
40
  export * from './core/common/helpers/file.helper';
40
41
  export * from './core/common/helpers/filter.helper';
41
42
  export * from './core/common/helpers/graphql.helper';
43
+ export * from './core/common/helpers/graphql-ws-context.helper';
42
44
  export * from './core/common/helpers/interceptor.helper';
43
45
  export * from './core/common/helpers/gridfs.helper';
44
46
  export * from './core/common/helpers/input.helper';
@@ -94,6 +96,7 @@ export * from './core/common/services/core-cron-jobs.service';
94
96
  export * from './core/common/services/core-redis.service';
95
97
  export * from './core/common/services/core-redis-pubsub';
96
98
  export * from './core/common/services/core-s3.service';
99
+ export * from './core/common/services/core-tenant-context.registry';
97
100
  export * from './core/common/services/rate-limit-store';
98
101
  export * from './core/common/services/crud.service';
99
102
  export * from './core/common/services/email.service';
@@ -173,6 +176,7 @@ export * from './core/modules/error-code';
173
176
  // Core - Modules - File
174
177
  // =====================================================================================================================
175
178
 
179
+ export * from './core/modules/file/core-file-access-audit.initializer';
176
180
  export * from './core/modules/file/core-file-info.model';
177
181
  export * from './core/modules/file/core-file.controller';
178
182
  export * from './core/modules/file/core-file.resolver';