@lenne.tech/nest-server 11.41.9 → 11.42.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/.claude/rules/configurable-features.md +3 -2
- package/.claude/rules/role-system.md +31 -0
- package/.claude/rules/testing.md +4 -4
- package/CLAUDE.md +6 -0
- package/FRAMEWORK-API.md +3 -2
- package/dist/core/common/helpers/graphql-ws-context.helper.js +1 -1
- package/dist/core/common/helpers/graphql-ws-context.helper.js.map +1 -1
- package/dist/core/common/helpers/outbound-url.helper.d.ts +14 -0
- package/dist/core/common/helpers/outbound-url.helper.js +234 -0
- package/dist/core/common/helpers/outbound-url.helper.js.map +1 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +5 -0
- package/dist/core/common/middleware/request-context.middleware.js +1 -0
- package/dist/core/common/middleware/request-context.middleware.js.map +1 -1
- package/dist/core/common/services/request-context.service.d.ts +1 -0
- package/dist/core/common/services/request-context.service.js.map +1 -1
- package/dist/core/modules/ai/core-ai-mcp.controller.js +5 -2
- package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-mcp.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-mcp.service.js +3 -2
- package/dist/core/modules/ai/services/core-ai-mcp.service.js.map +1 -1
- package/dist/core/modules/ai/tools/ai-tool.registry.js +15 -2
- package/dist/core/modules/ai/tools/ai-tool.registry.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant-role.helper.d.ts +2 -0
- package/dist/core/modules/tenant/core-tenant-role.helper.js +36 -0
- package/dist/core/modules/tenant/core-tenant-role.helper.js.map +1 -0
- package/dist/core/modules/tenant/core-tenant.guard.d.ts +7 -1
- package/dist/core/modules/tenant/core-tenant.guard.js +56 -4
- package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +1 -0
- package/dist/core/modules/user/core-user.service.js +24 -0
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +4 -2
- package/migration-guides/11.41.8-to-11.41.9.md +5 -0
- package/migration-guides/11.41.x-to-11.42.x.md +161 -0
- package/migration-guides/11.9.x-to-11.10.x.md +3 -2
- package/package.json +2 -1
- package/src/core/common/helpers/graphql-ws-context.helper.ts +1 -1
- package/src/core/common/helpers/outbound-url.helper.ts +310 -0
- package/src/core/common/interfaces/server-options.interface.ts +54 -0
- package/src/core/common/middleware/request-context.middleware.ts +1 -0
- package/src/core/common/services/request-context.service.ts +9 -0
- package/src/core/modules/ai/README.md +25 -0
- package/src/core/modules/ai/core-ai-mcp.controller.ts +22 -3
- package/src/core/modules/ai/services/core-ai-mcp.service.ts +9 -3
- package/src/core/modules/ai/tools/ai-tool.registry.ts +33 -3
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +18 -11
- package/src/core/modules/tenant/INTEGRATION-CHECKLIST.md +14 -0
- package/src/core/modules/tenant/README.md +80 -8
- package/src/core/modules/tenant/core-tenant-role.helper.ts +75 -0
- package/src/core/modules/tenant/core-tenant.guard.ts +78 -5
- package/src/core/modules/tus/INTEGRATION-CHECKLIST.md +3 -1
- package/src/core/modules/tus/README.md +9 -0
- package/src/core/modules/user/core-user.service.ts +53 -0
- package/src/index.ts +2 -0
|
@@ -392,6 +392,15 @@ for them.
|
|
|
392
392
|
| Header naming a tenant the caller belongs to | the finished file gets `metadata.tenantId` |
|
|
393
393
|
| Header naming a tenant the caller does NOT belong to | **403**, nothing is stored |
|
|
394
394
|
|
|
395
|
+
**The header has to come from the TUS client itself.** Projects usually add `X-Tenant-Id` in an
|
|
396
|
+
interceptor of their generated API client, and `tus-js-client` does not go through that client. Without
|
|
397
|
+
an explicit header the upload is accepted, stays tenant-less and bypasses tenant filtering and any
|
|
398
|
+
per-tenant quota, with no error anywhere. Pass it to the upload, e.g. with nuxt-extensions:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
const { addFiles } = useLtTusUpload({ headers: { 'X-Tenant-Id': currentTenantId } });
|
|
402
|
+
```
|
|
403
|
+
|
|
395
404
|
The tenant is recorded under `TUS_TENANT_METADATA_KEY` (`ltTenantId`), next to the owner under
|
|
396
405
|
`TUS_OWNER_METADATA_KEY`. Both keys are framework-owned and always overwritten, so a client cannot
|
|
397
406
|
put either of them into its own `Upload-Metadata`. `metadata.tenantId` on the finished file is what
|
|
@@ -5,6 +5,7 @@ import { sha256 } from 'js-sha256';
|
|
|
5
5
|
import { Document, Model } from 'mongoose';
|
|
6
6
|
|
|
7
7
|
import { looksLikeSystemRole, SYSTEM_ROLE_PREFIX } from '../../common/enums/role.enum';
|
|
8
|
+
import { accessDeniedException } from '../../common/exceptions/access-denied.exception';
|
|
8
9
|
import { resolveAppUrlFromConfig } from '../../common/helpers/cookies.helper';
|
|
9
10
|
import { maskEmail } from '../../common/helpers/logging.helper';
|
|
10
11
|
import { assignPlain, isQueryableString, prepareServiceOptionsForCreate } from '../../common/helpers/input.helper';
|
|
@@ -673,6 +674,8 @@ export abstract class CoreUserService<
|
|
|
673
674
|
const oldUser = (await this.mainDbModel.findById(id).lean().exec()) as null | TUser;
|
|
674
675
|
const oldEmail = oldUser?.email;
|
|
675
676
|
|
|
677
|
+
this.assertCredentialChangeAllowed(oldUser, input, serviceOptions);
|
|
678
|
+
|
|
676
679
|
// Capture the submitted password for the IAM sync before super.update()
|
|
677
680
|
// hashes it in place.
|
|
678
681
|
//
|
|
@@ -738,6 +741,56 @@ export abstract class CoreUserService<
|
|
|
738
741
|
return updatedUser;
|
|
739
742
|
}
|
|
740
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Refuses a change of another account's e-mail address or password where the configuration promises
|
|
746
|
+
* tenant isolation from platform administrators.
|
|
747
|
+
*
|
|
748
|
+
* With multi-tenancy active and `adminBypass: false`, a platform administrator deliberately has no
|
|
749
|
+
* way into a tenant's data. Setting a tenant user's address or password is a way around that: change
|
|
750
|
+
* the address, request a reset, sign in as that person. The same holds for whoever created the
|
|
751
|
+
* account, because `S_CREATOR` may update it and the e-mail field is open to everyone who may.
|
|
752
|
+
*
|
|
753
|
+
* Untouched by design:
|
|
754
|
+
* - the account changing its own credentials,
|
|
755
|
+
* - profile fields, and an e-mail address sent along unchanged,
|
|
756
|
+
* - work without a signed-in user (invitation, password reset), which is the system's own,
|
|
757
|
+
* - every configuration other than multi-tenancy with `adminBypass: false`.
|
|
758
|
+
*
|
|
759
|
+
* `force` does not lift it: the rule is about WHO acts, and system work is defined by the absence of
|
|
760
|
+
* a current user. Protected so a project can widen or narrow it.
|
|
761
|
+
*/
|
|
762
|
+
protected assertCredentialChangeAllowed(
|
|
763
|
+
target: null | TUser,
|
|
764
|
+
input: TUserInput,
|
|
765
|
+
serviceOptions?: ServiceOptions,
|
|
766
|
+
): void {
|
|
767
|
+
const multiTenancy = ConfigService.configFastButReadOnly?.multiTenancy;
|
|
768
|
+
if (!multiTenancy || multiTenancy.enabled === false || multiTenancy.adminBypass !== false) {
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
const currentUser = serviceOptions?.currentUser;
|
|
772
|
+
if (!currentUser?.id || !target) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
// No exemption for administrator TARGETS: an administrator may write `roles`, so "promote the
|
|
776
|
+
// tenant account to ADMIN, then change its address" would open every account in two requests.
|
|
777
|
+
const targetId = String((target as any)._id ?? (target as any).id);
|
|
778
|
+
if (String(currentUser.id) === targetId) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const submitted = input as { email?: unknown; password?: unknown };
|
|
783
|
+
const normalize = (value: unknown) => (typeof value === 'string' ? value.trim().toLowerCase() : value);
|
|
784
|
+
const changesEmail = submitted?.email !== undefined && normalize(submitted.email) !== normalize(target.email);
|
|
785
|
+
const changesPassword = submitted?.password !== undefined;
|
|
786
|
+
if (changesEmail || changesPassword) {
|
|
787
|
+
throw accessDeniedException(
|
|
788
|
+
currentUser,
|
|
789
|
+
'The e-mail address and password of a tenant account can only be changed by the account itself',
|
|
790
|
+
);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
741
794
|
/**
|
|
742
795
|
* Delete user with automatic cleanup of IAM auth data
|
|
743
796
|
*
|
package/src/index.ts
CHANGED
|
@@ -47,6 +47,7 @@ export * from './core/common/helpers/input.helper';
|
|
|
47
47
|
export * from './core/common/helpers/logging.helper';
|
|
48
48
|
export * from './core/common/helpers/meta.helper';
|
|
49
49
|
export * from './core/common/helpers/model.helper';
|
|
50
|
+
export * from './core/common/helpers/outbound-url.helper';
|
|
50
51
|
export * from './core/common/helpers/process-diagnostics.helper';
|
|
51
52
|
export * from './core/common/helpers/register-enum.helper';
|
|
52
53
|
export * from './core/common/helpers/scim.helper';
|
|
@@ -258,6 +259,7 @@ export * from './core/modules/tenant/core-tenant.decorators';
|
|
|
258
259
|
export * from './core/modules/tenant/core-tenant.enums';
|
|
259
260
|
export * from './core/modules/tenant/core-tenant.guard';
|
|
260
261
|
export * from './core/modules/tenant/core-role-scope.registry';
|
|
262
|
+
export * from './core/modules/tenant/core-tenant-role.helper';
|
|
261
263
|
export * from './core/modules/tenant/core-tenant.helpers';
|
|
262
264
|
export * from './core/modules/tenant/core-tenant.module';
|
|
263
265
|
export * from './core/modules/tenant/core-tenant.service';
|