@fiado/type-kit 3.471.0 → 3.472.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/_test_/unit/common/IsStringValueRecord.test.ts +25 -0
- package/_test_/unit/platformRbac/dtos/tenantUserCustomFields.test.ts +55 -0
- package/bin/common/index.d.ts +1 -0
- package/bin/common/index.js +2 -0
- package/bin/common/validators/IsStringValueRecord.d.ts +5 -0
- package/bin/common/validators/IsStringValueRecord.js +25 -0
- package/bin/messagesConnector/validators/IsStringValueRecord.d.ts +1 -5
- package/bin/messagesConnector/validators/IsStringValueRecord.js +3 -21
- package/bin/platformRbac/dtos/CreateTenantUserRequest.d.ts +4 -0
- package/bin/platformRbac/dtos/CreateTenantUserRequest.js +9 -0
- package/bin/platformRbac/dtos/UpdateTenantUserRequest.d.ts +5 -2
- package/bin/platformRbac/dtos/UpdateTenantUserRequest.js +10 -2
- package/package.json +1 -1
- package/src/common/index.ts +3 -0
- package/src/common/validators/IsStringValueRecord.ts +13 -0
- package/src/messagesConnector/validators/IsStringValueRecord.ts +2 -12
- package/src/platformRbac/dtos/CreateTenantUserRequest.ts +8 -1
- package/src/platformRbac/dtos/UpdateTenantUserRequest.ts +9 -3
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { IsStringValueRecord } from '../../../src/common';
|
|
3
|
+
import { IsStringValueRecord as FromMessagesConnector } from '../../../src/messagesConnector/validators/IsStringValueRecord';
|
|
4
|
+
|
|
5
|
+
describe('IsStringValueRecord (common)', () => {
|
|
6
|
+
const validator = new IsStringValueRecord();
|
|
7
|
+
const args = {} as never;
|
|
8
|
+
|
|
9
|
+
it('acepta un mapa de strings', () => {
|
|
10
|
+
expect(validator.validate({ a: 'x', b: '' }, args)).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('rechaza un valor que no es string', () => {
|
|
14
|
+
expect(validator.validate({ a: 1 }, args)).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('rechaza null y valores que no son objeto', () => {
|
|
18
|
+
expect(validator.validate(null, args)).toBe(false);
|
|
19
|
+
expect(validator.validate('x', args)).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('messagesConnector reexporta la misma clase', () => {
|
|
23
|
+
expect(FromMessagesConnector).toBe(IsStringValueRecord);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { CreateTenantUserRequest } from '../../../../src/platformRbac/dtos/CreateTenantUserRequest';
|
|
5
|
+
import { UpdateTenantUserRequest } from '../../../../src/platformRbac/dtos/UpdateTenantUserRequest';
|
|
6
|
+
import { PermissionScope } from '../../../../src/platformRbac/enums/PermissionScope';
|
|
7
|
+
|
|
8
|
+
const createBase = {
|
|
9
|
+
email: 'agente@example.com',
|
|
10
|
+
roleId: 'role-agente',
|
|
11
|
+
scope: PermissionScope.LEVEL_1,
|
|
12
|
+
scopeRef: 'grp-1',
|
|
13
|
+
createdBy: 'admin-sub-1',
|
|
14
|
+
};
|
|
15
|
+
const updateBase = { actedBy: 'admin-sub-1' };
|
|
16
|
+
|
|
17
|
+
describe.each([
|
|
18
|
+
['CreateTenantUserRequest', CreateTenantUserRequest, createBase],
|
|
19
|
+
['UpdateTenantUserRequest', UpdateTenantUserRequest, updateBase],
|
|
20
|
+
] as const)('%s.customFields', (_name, Dto, base) => {
|
|
21
|
+
const validateWith = async (customFields: unknown) =>
|
|
22
|
+
validate(plainToInstance(Dto as new () => object, { ...base, customFields }));
|
|
23
|
+
|
|
24
|
+
it('es opcional', async () => {
|
|
25
|
+
expect(await validate(plainToInstance(Dto as new () => object, base))).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('acepta un mapa de strings y lo conserva', async () => {
|
|
29
|
+
const dto = plainToInstance(Dto as new () => object, {
|
|
30
|
+
...base,
|
|
31
|
+
customFields: { directory_id: 'dir-1', home_group_id: 'grp-1' },
|
|
32
|
+
}) as { customFields?: Record<string, string> };
|
|
33
|
+
expect(await validate(dto)).toEqual([]);
|
|
34
|
+
expect(dto.customFields).toEqual({ directory_id: 'dir-1', home_group_id: 'grp-1' });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('acepta la cadena vacía (marca de borrado del rbac)', async () => {
|
|
38
|
+
expect(await validateWith({ directory_id: '' })).toEqual([]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('rechaza un valor que no es string', async () => {
|
|
42
|
+
const errors = await validateWith({ directory_id: 123 });
|
|
43
|
+
expect(errors.some((e) => e.property === 'customFields')).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('rechaza un arreglo', async () => {
|
|
47
|
+
const errors = await validateWith(['dir-1']);
|
|
48
|
+
expect(errors.some((e) => e.property === 'customFields')).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rechaza un string suelto', async () => {
|
|
52
|
+
const errors = await validateWith('dir-1');
|
|
53
|
+
expect(errors.some((e) => e.property === 'customFields')).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
package/bin/common/index.d.ts
CHANGED
package/bin/common/index.js
CHANGED
|
@@ -16,6 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
//decorators
|
|
18
18
|
__exportStar(require("./decorators/Trim"), exports);
|
|
19
|
+
//validators
|
|
20
|
+
__exportStar(require("./validators/IsStringValueRecord"), exports);
|
|
19
21
|
//dtos
|
|
20
22
|
__exportStar(require("./dtos/ProcessValidationResultDto"), exports);
|
|
21
23
|
//Enums
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
export declare class IsStringValueRecord implements ValidatorConstraintInterface {
|
|
3
|
+
validate(value: unknown, _args: ValidationArguments): boolean;
|
|
4
|
+
defaultMessage(_args: ValidationArguments): string;
|
|
5
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.IsStringValueRecord = void 0;
|
|
10
|
+
const class_validator_1 = require("class-validator");
|
|
11
|
+
// Valida que un objeto sea un mapa clave → string.
|
|
12
|
+
let IsStringValueRecord = class IsStringValueRecord {
|
|
13
|
+
validate(value, _args) {
|
|
14
|
+
if (!value || typeof value !== 'object')
|
|
15
|
+
return false;
|
|
16
|
+
return Object.values(value).every(v => typeof v === 'string');
|
|
17
|
+
}
|
|
18
|
+
defaultMessage(_args) {
|
|
19
|
+
return 'All values in variables must be strings';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.IsStringValueRecord = IsStringValueRecord;
|
|
23
|
+
exports.IsStringValueRecord = IsStringValueRecord = __decorate([
|
|
24
|
+
(0, class_validator_1.ValidatorConstraint)({ name: 'IsStringValueRecord', async: false })
|
|
25
|
+
], IsStringValueRecord);
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare class IsStringValueRecord implements ValidatorConstraintInterface {
|
|
3
|
-
validate(value: unknown, _args: ValidationArguments): boolean;
|
|
4
|
-
defaultMessage(_args: ValidationArguments): string;
|
|
5
|
-
}
|
|
1
|
+
export { IsStringValueRecord } from '../../common/validators/IsStringValueRecord';
|
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
3
|
exports.IsStringValueRecord = void 0;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!value || typeof value !== 'object')
|
|
14
|
-
return false;
|
|
15
|
-
return Object.values(value).every(v => typeof v === 'string');
|
|
16
|
-
}
|
|
17
|
-
defaultMessage(_args) {
|
|
18
|
-
return 'All values in variables must be strings';
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
exports.IsStringValueRecord = IsStringValueRecord;
|
|
22
|
-
exports.IsStringValueRecord = IsStringValueRecord = __decorate([
|
|
23
|
-
(0, class_validator_1.ValidatorConstraint)({ name: 'IsStringValueRecord', async: false })
|
|
24
|
-
], IsStringValueRecord);
|
|
4
|
+
// Movido a common: se reexporta para no romper a quien importa desde messagesConnector.
|
|
5
|
+
var IsStringValueRecord_1 = require("../../common/validators/IsStringValueRecord");
|
|
6
|
+
Object.defineProperty(exports, "IsStringValueRecord", { enumerable: true, get: function () { return IsStringValueRecord_1.IsStringValueRecord; } });
|
|
@@ -8,6 +8,7 @@ import { PermissionScope } from '../enums/PermissionScope';
|
|
|
8
8
|
* - Idempotente por identidad Cognito.
|
|
9
9
|
* - `scope`/`scopeRef` = grant del rol (ej. LEVEL_3 + storeId para un vendedor de tienda).
|
|
10
10
|
* - `createdBy` = cognitoSub del admin real (audit + grantedBy del assignment).
|
|
11
|
+
* - `customFields` = valores de los campos personalizados del tenant; si el correo ya tiene usuario, se fusionan.
|
|
11
12
|
*/
|
|
12
13
|
export declare class CreateTenantUserRequest {
|
|
13
14
|
email: string;
|
|
@@ -16,4 +17,7 @@ export declare class CreateTenantUserRequest {
|
|
|
16
17
|
scope: PermissionScope;
|
|
17
18
|
scopeRef: string;
|
|
18
19
|
createdBy: string;
|
|
20
|
+
customFields?: {
|
|
21
|
+
[key: string]: string;
|
|
22
|
+
};
|
|
19
23
|
}
|
|
@@ -13,6 +13,7 @@ exports.CreateTenantUserRequest = void 0;
|
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const PermissionScope_1 = require("../enums/PermissionScope");
|
|
16
|
+
const IsStringValueRecord_1 = require("../../common/validators/IsStringValueRecord");
|
|
16
17
|
/**
|
|
17
18
|
* Body del POST /internal/tenants/{tenantId}/users (endpoint privado, VPC/ANONIMUS). `tenantId` viaja en el path.
|
|
18
19
|
* Provisiona Cognito + SharedUser + RoleAssignment (rol + scopeRef) en RBAC — reusa UserProvisioningService.
|
|
@@ -22,6 +23,7 @@ const PermissionScope_1 = require("../enums/PermissionScope");
|
|
|
22
23
|
* - Idempotente por identidad Cognito.
|
|
23
24
|
* - `scope`/`scopeRef` = grant del rol (ej. LEVEL_3 + storeId para un vendedor de tienda).
|
|
24
25
|
* - `createdBy` = cognitoSub del admin real (audit + grantedBy del assignment).
|
|
26
|
+
* - `customFields` = valores de los campos personalizados del tenant; si el correo ya tiene usuario, se fusionan.
|
|
25
27
|
*/
|
|
26
28
|
class CreateTenantUserRequest {
|
|
27
29
|
}
|
|
@@ -61,3 +63,10 @@ __decorate([
|
|
|
61
63
|
(0, class_validator_1.IsNotEmpty)(),
|
|
62
64
|
__metadata("design:type", String)
|
|
63
65
|
], CreateTenantUserRequest.prototype, "createdBy", void 0);
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, class_transformer_1.Expose)(),
|
|
68
|
+
(0, class_validator_1.IsOptional)(),
|
|
69
|
+
(0, class_validator_1.IsObject)(),
|
|
70
|
+
(0, class_validator_1.Validate)(IsStringValueRecord_1.IsStringValueRecord, { message: 'customFields: todos los valores deben ser string' }),
|
|
71
|
+
__metadata("design:type", Object)
|
|
72
|
+
], CreateTenantUserRequest.prototype, "customFields", void 0);
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Body del PUT que
|
|
3
|
-
*
|
|
2
|
+
* Body del PUT que edita a un usuario: nombre y campos personalizados. `customFields` se fusiona con los
|
|
3
|
+
* actuales (solo cambian las claves enviadas; "" borra una). Correo y grupo no viajan aquí.
|
|
4
4
|
*/
|
|
5
5
|
export declare class UpdateTenantUserRequest {
|
|
6
6
|
displayName?: string;
|
|
7
|
+
customFields?: {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
};
|
|
7
10
|
actedBy: string;
|
|
8
11
|
}
|
|
@@ -12,9 +12,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.UpdateTenantUserRequest = void 0;
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
+
const IsStringValueRecord_1 = require("../../common/validators/IsStringValueRecord");
|
|
15
16
|
/**
|
|
16
|
-
* Body del PUT que
|
|
17
|
-
*
|
|
17
|
+
* Body del PUT que edita a un usuario: nombre y campos personalizados. `customFields` se fusiona con los
|
|
18
|
+
* actuales (solo cambian las claves enviadas; "" borra una). Correo y grupo no viajan aquí.
|
|
18
19
|
*/
|
|
19
20
|
class UpdateTenantUserRequest {
|
|
20
21
|
}
|
|
@@ -27,6 +28,13 @@ __decorate([
|
|
|
27
28
|
(0, class_validator_1.MaxLength)(120),
|
|
28
29
|
__metadata("design:type", String)
|
|
29
30
|
], UpdateTenantUserRequest.prototype, "displayName", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.IsObject)(),
|
|
35
|
+
(0, class_validator_1.Validate)(IsStringValueRecord_1.IsStringValueRecord, { message: 'customFields: todos los valores deben ser string' }),
|
|
36
|
+
__metadata("design:type", Object)
|
|
37
|
+
], UpdateTenantUserRequest.prototype, "customFields", void 0);
|
|
30
38
|
__decorate([
|
|
31
39
|
(0, class_transformer_1.Expose)(),
|
|
32
40
|
(0, class_validator_1.IsString)(),
|
package/package.json
CHANGED
package/src/common/index.ts
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
|
|
2
|
+
|
|
3
|
+
// Valida que un objeto sea un mapa clave → string.
|
|
4
|
+
@ValidatorConstraint({ name: 'IsStringValueRecord', async: false })
|
|
5
|
+
export class IsStringValueRecord implements ValidatorConstraintInterface {
|
|
6
|
+
validate(value: unknown, _args: ValidationArguments): boolean {
|
|
7
|
+
if (!value || typeof value !== 'object') return false;
|
|
8
|
+
return Object.values(value as Record<string, unknown>).every(v => typeof v === 'string');
|
|
9
|
+
}
|
|
10
|
+
defaultMessage(_args: ValidationArguments): string {
|
|
11
|
+
return 'All values in variables must be strings';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
@ValidatorConstraint({ name: 'IsStringValueRecord', async: false })
|
|
4
|
-
export class IsStringValueRecord implements ValidatorConstraintInterface {
|
|
5
|
-
validate(value: unknown, _args: ValidationArguments): boolean {
|
|
6
|
-
if (!value || typeof value !== 'object') return false;
|
|
7
|
-
return Object.values(value as Record<string, unknown>).every(v => typeof v === 'string');
|
|
8
|
-
}
|
|
9
|
-
defaultMessage(_args: ValidationArguments): string {
|
|
10
|
-
return 'All values in variables must be strings';
|
|
11
|
-
}
|
|
12
|
-
}
|
|
1
|
+
// Movido a common: se reexporta para no romper a quien importa desde messagesConnector.
|
|
2
|
+
export { IsStringValueRecord } from '../../common/validators/IsStringValueRecord';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsEmail, IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
import { IsEmail, IsEnum, IsNotEmpty, IsObject, IsOptional, IsString, Validate } from 'class-validator';
|
|
3
3
|
import { PermissionScope } from '../enums/PermissionScope';
|
|
4
|
+
import { IsStringValueRecord } from '../../common/validators/IsStringValueRecord';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Body del POST /internal/tenants/{tenantId}/users (endpoint privado, VPC/ANONIMUS). `tenantId` viaja en el path.
|
|
@@ -11,6 +12,7 @@ import { PermissionScope } from '../enums/PermissionScope';
|
|
|
11
12
|
* - Idempotente por identidad Cognito.
|
|
12
13
|
* - `scope`/`scopeRef` = grant del rol (ej. LEVEL_3 + storeId para un vendedor de tienda).
|
|
13
14
|
* - `createdBy` = cognitoSub del admin real (audit + grantedBy del assignment).
|
|
15
|
+
* - `customFields` = valores de los campos personalizados del tenant; si el correo ya tiene usuario, se fusionan.
|
|
14
16
|
*/
|
|
15
17
|
export class CreateTenantUserRequest {
|
|
16
18
|
@Expose() @IsEmail() email!: string;
|
|
@@ -19,4 +21,9 @@ export class CreateTenantUserRequest {
|
|
|
19
21
|
@Expose() @IsEnum(PermissionScope) scope!: PermissionScope;
|
|
20
22
|
@Expose() @IsString() @IsNotEmpty() scopeRef!: string;
|
|
21
23
|
@Expose() @IsString() @IsNotEmpty() createdBy!: string;
|
|
24
|
+
@Expose()
|
|
25
|
+
@IsOptional()
|
|
26
|
+
@IsObject()
|
|
27
|
+
@Validate(IsStringValueRecord, { message: 'customFields: todos los valores deben ser string' })
|
|
28
|
+
customFields?: { [key: string]: string };
|
|
22
29
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator';
|
|
2
|
+
import { IsNotEmpty, IsObject, IsOptional, IsString, MaxLength, Validate } from 'class-validator';
|
|
3
|
+
import { IsStringValueRecord } from '../../common/validators/IsStringValueRecord';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* Body del PUT que
|
|
6
|
-
*
|
|
6
|
+
* Body del PUT que edita a un usuario: nombre y campos personalizados. `customFields` se fusiona con los
|
|
7
|
+
* actuales (solo cambian las claves enviadas; "" borra una). Correo y grupo no viajan aquí.
|
|
7
8
|
*/
|
|
8
9
|
export class UpdateTenantUserRequest {
|
|
9
10
|
@Expose() @IsOptional() @IsString() @IsNotEmpty() @MaxLength(120) displayName?: string;
|
|
11
|
+
@Expose()
|
|
12
|
+
@IsOptional()
|
|
13
|
+
@IsObject()
|
|
14
|
+
@Validate(IsStringValueRecord, { message: 'customFields: todos los valores deben ser string' })
|
|
15
|
+
customFields?: { [key: string]: string };
|
|
10
16
|
@Expose() @IsString() @IsNotEmpty() actedBy!: string;
|
|
11
17
|
}
|