@fiado/type-kit 3.662.0 → 3.664.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/cognitoBackofficeConnector/dtos/CreatePoolRequest.allowAdminCreateUserOnly.test.ts +37 -0
- package/_test_/unit/cognitoBackofficeConnector/dtos/OtpLoginConnectorDtos.test.ts +90 -0
- package/_test_/unit/messagesConnector/otpLoginContract.test.ts +47 -0
- package/_test_/unit/platformRbac/customerAccountDtos.test.ts +84 -0
- package/_test_/unit/platformRbac/customerPortalContract.test.ts +39 -0
- package/_test_/unit/platformRbac/enums/__snapshots__/permissionBits.test.ts.snap +2 -1
- package/_test_/unit/platformRbac/enums/retailIntegrationPermission.test.ts +3 -4
- package/_test_/unit/platformRbac/loginModeChallengeDtos.test.ts +58 -0
- package/bin/cognitoBackofficeConnector/dtos/AppClientConfig.d.ts +3 -4
- package/bin/cognitoBackofficeConnector/dtos/AppClientConfig.js +7 -4
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolClientResponse.d.ts +1 -1
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolClientResponse.js +1 -1
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolRequest.d.ts +2 -0
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolRequest.js +6 -0
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolResponse.d.ts +1 -7
- package/bin/cognitoBackofficeConnector/dtos/CreatePoolResponse.js +1 -7
- package/bin/cognitoBackofficeConnector/dtos/RefreshTokensRequest.d.ts +2 -0
- package/bin/cognitoBackofficeConnector/dtos/RefreshTokensRequest.js +13 -0
- package/bin/cognitoBackofficeConnector/dtos/RespondToChallengeRequest.d.ts +1 -0
- package/bin/cognitoBackofficeConnector/dtos/RespondToChallengeRequest.js +6 -0
- package/bin/cognitoBackofficeConnector/dtos/StartOtpLoginRequest.d.ts +8 -0
- package/bin/cognitoBackofficeConnector/dtos/StartOtpLoginRequest.js +48 -0
- package/bin/cognitoBackofficeConnector/index.d.ts +1 -0
- package/bin/cognitoBackofficeConnector/index.js +1 -0
- package/bin/messagesConnector/dtos/OtpLoginStateRequest.d.ts +5 -0
- package/bin/messagesConnector/dtos/OtpLoginStateRequest.js +30 -0
- package/bin/messagesConnector/dtos/OtpLoginStateResponse.d.ts +5 -0
- package/bin/messagesConnector/dtos/OtpLoginStateResponse.js +7 -0
- package/bin/messagesConnector/index.d.ts +2 -0
- package/bin/messagesConnector/index.js +2 -0
- package/bin/platformRbac/application/Application.d.ts +3 -0
- package/bin/platformRbac/auth/DefineNextChallengeResponse.d.ts +2 -0
- package/bin/platformRbac/auth/DefineNextChallengeResponse.js +6 -0
- package/bin/platformRbac/auth/PrepareChallengeRequest.d.ts +3 -0
- package/bin/platformRbac/auth/PrepareChallengeRequest.js +11 -0
- package/bin/platformRbac/dtos/EnsureCustomerAccountRequest.d.ts +8 -0
- package/bin/platformRbac/dtos/EnsureCustomerAccountRequest.js +49 -0
- package/bin/platformRbac/dtos/EnsureCustomerAccountResponse.d.ts +5 -0
- package/bin/platformRbac/dtos/EnsureCustomerAccountResponse.js +2 -0
- package/bin/platformRbac/dtos/OtpLoginRequest.d.ts +5 -0
- package/bin/platformRbac/dtos/OtpLoginRequest.js +30 -0
- package/bin/platformRbac/dtos/UserProfileResponse.d.ts +2 -0
- package/bin/platformRbac/enums/LoginModeEnum.d.ts +4 -0
- package/bin/platformRbac/enums/LoginModeEnum.js +8 -0
- package/bin/platformRbac/enums/Permission.d.ts +2 -1
- package/bin/platformRbac/enums/Permission.js +3 -0
- package/bin/platformRbac/index.d.ts +4 -0
- package/bin/platformRbac/index.js +3 -0
- package/bin/referral-business/dtos/GroupOwnersByGroupIdsResponse.d.ts +2 -0
- package/package.json +1 -1
- package/src/cognitoBackofficeConnector/dtos/AppClientConfig.ts +3 -4
- package/src/cognitoBackofficeConnector/dtos/CreatePoolClientResponse.ts +1 -1
- package/src/cognitoBackofficeConnector/dtos/CreatePoolRequest.ts +4 -1
- package/src/cognitoBackofficeConnector/dtos/CreatePoolResponse.ts +1 -7
- package/src/cognitoBackofficeConnector/dtos/RefreshTokensRequest.ts +4 -1
- package/src/cognitoBackofficeConnector/dtos/RespondToChallengeRequest.ts +2 -1
- package/src/cognitoBackofficeConnector/dtos/StartOtpLoginRequest.ts +11 -0
- package/src/cognitoBackofficeConnector/index.ts +1 -0
- package/src/messagesConnector/dtos/OtpLoginStateRequest.ts +8 -0
- package/src/messagesConnector/dtos/OtpLoginStateResponse.ts +5 -0
- package/src/messagesConnector/index.ts +2 -0
- package/src/platformRbac/application/Application.ts +3 -0
- package/src/platformRbac/auth/DefineNextChallengeResponse.ts +5 -0
- package/src/platformRbac/auth/PrepareChallengeRequest.ts +11 -1
- package/src/platformRbac/dtos/EnsureCustomerAccountRequest.ts +12 -0
- package/src/platformRbac/dtos/EnsureCustomerAccountResponse.ts +5 -0
- package/src/platformRbac/dtos/OtpLoginRequest.ts +8 -0
- package/src/platformRbac/dtos/UserProfileResponse.ts +2 -0
- package/src/platformRbac/enums/LoginModeEnum.ts +4 -0
- package/src/platformRbac/enums/Permission.ts +3 -0
- package/src/platformRbac/index.ts +4 -0
- package/src/referral-business/dtos/GroupOwnersByGroupIdsResponse.ts +3 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { CreatePoolRequest } from '../../../../src/cognitoBackofficeConnector/dtos/CreatePoolRequest';
|
|
5
|
+
|
|
6
|
+
const BODY = {
|
|
7
|
+
region: 'us-east-1',
|
|
8
|
+
displayName: 'Clientes',
|
|
9
|
+
passwordPolicy: {},
|
|
10
|
+
customAttributes: [],
|
|
11
|
+
appClientConfig: {},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const toRequest = (body: object): CreatePoolRequest =>
|
|
15
|
+
plainToInstance(CreatePoolRequest, body, { excludeExtraneousValues: true });
|
|
16
|
+
|
|
17
|
+
const hasFieldError = async (body: object): Promise<boolean> => {
|
|
18
|
+
const errors = await validate(toRequest(body), { skipMissingProperties: false });
|
|
19
|
+
return errors.some((error) => error.property === 'allowAdminCreateUserOnly');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe('CreatePoolRequest.allowAdminCreateUserOnly', () => {
|
|
23
|
+
it('es opcional', async () => {
|
|
24
|
+
expect(await hasFieldError(BODY)).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it.each([true, false])('acepta %s y lo conserva', async (allowAdminCreateUserOnly) => {
|
|
28
|
+
const body = { ...BODY, allowAdminCreateUserOnly };
|
|
29
|
+
|
|
30
|
+
expect(await hasFieldError(body)).toBe(false);
|
|
31
|
+
expect(toRequest(body).allowAdminCreateUserOnly).toBe(allowAdminCreateUserOnly);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('rechaza un valor no booleano', async () => {
|
|
35
|
+
expect(await hasFieldError({ ...BODY, allowAdminCreateUserOnly: 'true' })).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { CognitoBackofficeConnector } from '../../../../src/index';
|
|
5
|
+
import { AppClientConfig } from '../../../../src/cognitoBackofficeConnector/dtos/AppClientConfig';
|
|
6
|
+
import { RefreshTokensRequest } from '../../../../src/cognitoBackofficeConnector/dtos/RefreshTokensRequest';
|
|
7
|
+
import { RespondToChallengeRequest } from '../../../../src/cognitoBackofficeConnector/dtos/RespondToChallengeRequest';
|
|
8
|
+
import { StartOtpLoginRequest } from '../../../../src/cognitoBackofficeConnector/dtos/StartOtpLoginRequest';
|
|
9
|
+
import { CognitoChallengeType } from '../../../../src/cognitoBackofficeConnector/enums/CognitoChallengeType';
|
|
10
|
+
|
|
11
|
+
const START = { userPoolId: 'us-east-1_abc', region: 'us-east-1', clientId: 'client-1', username: 'sub-1' };
|
|
12
|
+
const RESPOND = {
|
|
13
|
+
userPoolId: 'us-east-1_abc',
|
|
14
|
+
region: 'us-east-1',
|
|
15
|
+
clientId: 'client-1',
|
|
16
|
+
challengeName: CognitoChallengeType.CUSTOM_CHALLENGE,
|
|
17
|
+
session: 'sess-1',
|
|
18
|
+
challengeResponses: { USERNAME: 'sub-1', ANSWER: '1234' },
|
|
19
|
+
};
|
|
20
|
+
const REFRESH = { userPoolId: 'us-east-1_abc', region: 'us-east-1', clientId: 'client-1', refreshToken: 'ref-1' };
|
|
21
|
+
const CLIENT = { explicitAuthFlows: ['ALLOW_CUSTOM_AUTH'] };
|
|
22
|
+
|
|
23
|
+
const propertiesWithError = async (dtoClass: new () => object, body: object): Promise<string[]> => {
|
|
24
|
+
const errors = await validate(plainToInstance(dtoClass, body) as object);
|
|
25
|
+
return errors.map((error) => error.property);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe('StartOtpLoginRequest', () => {
|
|
29
|
+
it('valida sin useClientSecret', async () => {
|
|
30
|
+
expect(await propertiesWithError(StartOtpLoginRequest, START)).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('acepta useClientSecret booleano', async () => {
|
|
34
|
+
expect(await propertiesWithError(StartOtpLoginRequest, { ...START, useClientSecret: true })).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('rechaza useClientSecret que no sea booleano', async () => {
|
|
38
|
+
expect(await propertiesWithError(StartOtpLoginRequest, { ...START, useClientSecret: 'si' })).toEqual(['useClientSecret']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it.each(['userPoolId', 'region', 'clientId', 'username'])('exige %s', async (field) => {
|
|
42
|
+
expect(await propertiesWithError(StartOtpLoginRequest, { ...START, [field]: '' })).toEqual([field]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('sale por el index raíz', () => {
|
|
46
|
+
expect(CognitoBackofficeConnector.StartOtpLoginRequest).toBe(StartOtpLoginRequest);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('RespondToChallengeRequest.useClientSecret', () => {
|
|
51
|
+
it('es opcional', async () => {
|
|
52
|
+
expect(await propertiesWithError(RespondToChallengeRequest, RESPOND)).toEqual([]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('rechaza un valor no booleano', async () => {
|
|
56
|
+
expect(await propertiesWithError(RespondToChallengeRequest, { ...RESPOND, useClientSecret: 1 })).toEqual(['useClientSecret']);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('RefreshTokensRequest', () => {
|
|
61
|
+
it('username y useClientSecret son opcionales', async () => {
|
|
62
|
+
expect(await propertiesWithError(RefreshTokensRequest, REFRESH)).toEqual([]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('acepta username y useClientSecret', async () => {
|
|
66
|
+
expect(await propertiesWithError(RefreshTokensRequest, { ...REFRESH, username: 'sub-1', useClientSecret: true })).toEqual([]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('rechaza username vacío', async () => {
|
|
70
|
+
expect(await propertiesWithError(RefreshTokensRequest, { ...REFRESH, username: '' })).toEqual(['username']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('rechaza useClientSecret no booleano', async () => {
|
|
74
|
+
expect(await propertiesWithError(RefreshTokensRequest, { ...REFRESH, useClientSecret: 'no' })).toEqual(['useClientSecret']);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('AppClientConfig.generateSecret', () => {
|
|
79
|
+
it('es opcional', async () => {
|
|
80
|
+
expect(await propertiesWithError(AppClientConfig, CLIENT)).toEqual([]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('acepta true', async () => {
|
|
84
|
+
expect(await propertiesWithError(AppClientConfig, { ...CLIENT, generateSecret: true })).toEqual([]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('rechaza un valor no booleano', async () => {
|
|
88
|
+
expect(await propertiesWithError(AppClientConfig, { ...CLIENT, generateSecret: 'true' })).toEqual(['generateSecret']);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { MessagesConnector } from '../../../src/index';
|
|
5
|
+
import { OtpLoginStateRequest } from '../../../src/messagesConnector/dtos/OtpLoginStateRequest';
|
|
6
|
+
import { OtpLoginStateResponse } from '../../../src/messagesConnector/dtos/OtpLoginStateResponse';
|
|
7
|
+
|
|
8
|
+
const BODY = { directoryId: 'sub-1', typeOfDirectoryId: 'BACKOFFICE_USER' };
|
|
9
|
+
|
|
10
|
+
const propertiesWithError = async (body: object): Promise<string[]> => {
|
|
11
|
+
const errors = await validate(plainToInstance(OtpLoginStateRequest, body));
|
|
12
|
+
return errors.map((error) => error.property);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
describe('OtpLoginStateRequest', () => {
|
|
16
|
+
it('valida el body completo', async () => {
|
|
17
|
+
expect(await propertiesWithError(BODY)).toEqual([]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it.each(['directoryId', 'typeOfDirectoryId'])('exige %s', async (field) => {
|
|
21
|
+
expect(await propertiesWithError({ ...BODY, [field]: '' })).toEqual([field]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it.each(['directoryId', 'typeOfDirectoryId'])('rechaza %s que no sea texto', async (field) => {
|
|
25
|
+
expect(await propertiesWithError({ ...BODY, [field]: 42 })).toEqual([field]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('sale por el index raíz', () => {
|
|
29
|
+
expect(MessagesConnector.OtpLoginStateRequest).toBe(OtpLoginStateRequest);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('OtpLoginStateResponse', () => {
|
|
34
|
+
it('sale por el index raíz', () => {
|
|
35
|
+
expect(MessagesConnector.OtpLoginStateResponse).toBe(OtpLoginStateResponse);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('admite estado sin fallo y sin tope', () => {
|
|
39
|
+
const state: OtpLoginStateResponse = { lastFailureCode: null, lockedUntil: null };
|
|
40
|
+
expect(state.lastFailureCode).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it.each(['OTP_NOT_FOUND', 'OTP_EXPIRED', 'OTP_ALREADY_USED'] as const)('admite %s', (lastFailureCode) => {
|
|
44
|
+
const state: OtpLoginStateResponse = { lastFailureCode, lockedUntil: 1_800_000_000_000 };
|
|
45
|
+
expect(state.lastFailureCode).toBe(lastFailureCode);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { PlatformRbac } from '../../../src/index';
|
|
5
|
+
import { EnsureCustomerAccountRequest } from '../../../src/platformRbac/dtos/EnsureCustomerAccountRequest';
|
|
6
|
+
import type { EnsureCustomerAccountResponse } from '../../../src/platformRbac/dtos/EnsureCustomerAccountResponse';
|
|
7
|
+
import { OtpLoginRequest } from '../../../src/platformRbac/dtos/OtpLoginRequest';
|
|
8
|
+
import type { UserProfileResponse } from '../../../src/platformRbac/dtos/UserProfileResponse';
|
|
9
|
+
|
|
10
|
+
const BODY = {
|
|
11
|
+
phone: '+525512345678',
|
|
12
|
+
retailCustomerId: 'customer-1',
|
|
13
|
+
directoryId: 'directory-1',
|
|
14
|
+
displayName: 'Ana Pérez',
|
|
15
|
+
createdBy: 'wizard',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const propertiesWithError = async (body: object): Promise<string[]> => {
|
|
19
|
+
const errors = await validate(plainToInstance(EnsureCustomerAccountRequest, body));
|
|
20
|
+
return errors.map((error) => error.property);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
describe('EnsureCustomerAccountRequest', () => {
|
|
24
|
+
it('valida el body completo', async () => {
|
|
25
|
+
expect(await propertiesWithError(BODY)).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it.each(['retailCustomerId', 'directoryId', 'displayName', 'createdBy'])('exige %s', async (field) => {
|
|
29
|
+
expect(await propertiesWithError({ ...BODY, [field]: '' })).toEqual([field]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it.each(['5512345678', '+15512345678', '+52551234567', '+5255123456789', ''])('rechaza el celular %s', async (phone) => {
|
|
33
|
+
expect(await propertiesWithError({ ...BODY, phone })).toEqual(['phone']);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('sale por el index raíz', () => {
|
|
37
|
+
expect(PlatformRbac.EnsureCustomerAccountRequest).toBe(EnsureCustomerAccountRequest);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('OtpLoginRequest', () => {
|
|
42
|
+
const LOGIN = { phone: '+525512345678', tenantId: 'surekeep-customers' };
|
|
43
|
+
|
|
44
|
+
const loginErrors = async (body: object): Promise<string[]> => {
|
|
45
|
+
const errors = await validate(plainToInstance(OtpLoginRequest, body));
|
|
46
|
+
return errors.map((error) => error.property);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
it('valida el body completo', async () => {
|
|
50
|
+
expect(await loginErrors(LOGIN)).toEqual([]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('deja la normalización del celular al endpoint', async () => {
|
|
54
|
+
expect(await loginErrors({ ...LOGIN, phone: '5512345678' })).toEqual([]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it.each(['phone', 'tenantId'])('exige %s', async (field) => {
|
|
58
|
+
expect(await loginErrors({ ...LOGIN, [field]: '' })).toEqual([field]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it.each(['phone', 'tenantId'])('rechaza %s que no sea texto', async (field) => {
|
|
62
|
+
expect(await loginErrors({ ...LOGIN, [field]: 42 })).toEqual([field]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('sale por el index raíz', () => {
|
|
66
|
+
expect(PlatformRbac.OtpLoginRequest).toBe(OtpLoginRequest);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('EnsureCustomerAccountResponse', () => {
|
|
71
|
+
it.each(['CREATED', 'EXISTING'] as const)('admite outcome %s', (outcome) => {
|
|
72
|
+
const response: EnsureCustomerAccountResponse = { outcome, cognitoSub: 'sub-1' };
|
|
73
|
+
expect(response.outcome).toBe(outcome);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('UserProfileResponse', () => {
|
|
78
|
+
it('admite los datos del cliente con valor y en null', () => {
|
|
79
|
+
const withData: UserProfileResponse = { cognitoSub: 's', tenantId: 't', retailCustomerId: 'c', directoryId: 'd' };
|
|
80
|
+
const empty: UserProfileResponse = { cognitoSub: 's', tenantId: 't', retailCustomerId: null, directoryId: null };
|
|
81
|
+
expect(withData.retailCustomerId).toBe('c');
|
|
82
|
+
expect(empty.directoryId).toBeNull();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ApplicationDefaults } from '../../../src/platformRbac/application/Application';
|
|
2
|
+
import { LoginModeEnum } from '../../../src/platformRbac/enums/LoginModeEnum';
|
|
3
|
+
import {
|
|
4
|
+
Permission,
|
|
5
|
+
PERMISSION_BIT_ORDER,
|
|
6
|
+
bitsToPermissions,
|
|
7
|
+
permissionsToBits,
|
|
8
|
+
} from '../../../src/platformRbac/enums/Permission';
|
|
9
|
+
|
|
10
|
+
describe('Permission.CUSTOMER_PORTAL_READ', () => {
|
|
11
|
+
it('tiene la llave customer.portal.read', () => {
|
|
12
|
+
expect(Permission.CUSTOMER_PORTAL_READ).toBe('customer.portal.read');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('va al final del orden de bits', () => {
|
|
16
|
+
expect(PERMISSION_BIT_ORDER[PERMISSION_BIT_ORDER.length - 1]).toBe(Permission.CUSTOMER_PORTAL_READ);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('sobrevive la ida y vuelta por el bitset', () => {
|
|
20
|
+
expect(bitsToPermissions(permissionsToBits([Permission.CUSTOMER_PORTAL_READ]))).toEqual([Permission.CUSTOMER_PORTAL_READ]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('ApplicationDefaults.loginMode', () => {
|
|
25
|
+
it('admite OTP_ONLY', () => {
|
|
26
|
+
const defaults: ApplicationDefaults = { loginMode: LoginModeEnum.OTP_ONLY };
|
|
27
|
+
expect(defaults.loginMode).toBe('OTP_ONLY');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('admite null', () => {
|
|
31
|
+
const defaults: ApplicationDefaults = { loginMode: null };
|
|
32
|
+
expect(defaults.loginMode).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('es opcional', () => {
|
|
36
|
+
const defaults: ApplicationDefaults = {};
|
|
37
|
+
expect(defaults.loginMode).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
2
|
|
|
3
|
-
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `
|
|
3
|
+
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `2836776829`;
|
|
4
4
|
|
|
5
5
|
exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe ante cualquier reorden/inserción) 1`] = `
|
|
6
6
|
[
|
|
@@ -97,5 +97,6 @@ exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe an
|
|
|
97
97
|
"tenant.integration.diagnostic",
|
|
98
98
|
"tenant.api_user.manage",
|
|
99
99
|
"platform.retail_integration.activate",
|
|
100
|
+
"customer.portal.read",
|
|
100
101
|
]
|
|
101
102
|
`;
|
|
@@ -5,9 +5,8 @@ describe('Permiso de activación de la integración retail', () => {
|
|
|
5
5
|
expect(Permission.PLATFORM_RETAIL_INTEGRATION_ACTIVATE).toBe('platform.retail_integration.activate');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
-
it('
|
|
9
|
-
const
|
|
10
|
-
expect(PERMISSION_BIT_ORDER[
|
|
11
|
-
expect(PERMISSION_BIT_ORDER[last - 1]).toBe(Permission.TENANT_API_USER_MANAGE);
|
|
8
|
+
it('conserva su bit, justo después de tenant.api_user.manage', () => {
|
|
9
|
+
const index = PERMISSION_BIT_ORDER.indexOf(Permission.PLATFORM_RETAIL_INTEGRATION_ACTIVATE);
|
|
10
|
+
expect(PERMISSION_BIT_ORDER[index - 1]).toBe(Permission.TENANT_API_USER_MANAGE);
|
|
12
11
|
});
|
|
13
12
|
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { PlatformRbac } from '../../../src/index';
|
|
5
|
+
import { DefineNextChallengeResponse } from '../../../src/platformRbac/auth/DefineNextChallengeResponse';
|
|
6
|
+
import { PrepareChallengeRequest } from '../../../src/platformRbac/auth/PrepareChallengeRequest';
|
|
7
|
+
import { ChallengeNameEnum } from '../../../src/platformRbac/enums/ChallengeNameEnum';
|
|
8
|
+
import { LoginModeEnum } from '../../../src/platformRbac/enums/LoginModeEnum';
|
|
9
|
+
|
|
10
|
+
const PREPARE = { cognitoSub: 'sub-1', challengeName: ChallengeNameEnum.SMS_OTP, phone: '+525512345678' };
|
|
11
|
+
const DECISION = { nextChallenge: ChallengeNameEnum.SMS_OTP, issueTokens: false, failAuthentication: false };
|
|
12
|
+
|
|
13
|
+
const propertiesWithError = async (dtoClass: new () => object, body: object): Promise<string[]> => {
|
|
14
|
+
const errors = await validate(plainToInstance(dtoClass, body) as object);
|
|
15
|
+
return errors.map((error) => error.property);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('LoginModeEnum', () => {
|
|
19
|
+
it('solo tiene OTP_ONLY', () => {
|
|
20
|
+
expect(Object.values(LoginModeEnum)).toEqual(['OTP_ONLY']);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('sale por el index raíz', () => {
|
|
24
|
+
expect(PlatformRbac.LoginModeEnum.OTP_ONLY).toBe('OTP_ONLY');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('DefineNextChallengeResponse.loginMode', () => {
|
|
29
|
+
it('es opcional', async () => {
|
|
30
|
+
expect(await propertiesWithError(DefineNextChallengeResponse, DECISION)).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('acepta OTP_ONLY', async () => {
|
|
34
|
+
expect(await propertiesWithError(DefineNextChallengeResponse, { ...DECISION, loginMode: 'OTP_ONLY' })).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('rechaza un valor fuera del enum', async () => {
|
|
38
|
+
expect(await propertiesWithError(DefineNextChallengeResponse, { ...DECISION, loginMode: 'PASSWORD' })).toEqual(['loginMode']);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('PrepareChallengeRequest', () => {
|
|
43
|
+
it('loginMode e isRetry son opcionales', async () => {
|
|
44
|
+
expect(await propertiesWithError(PrepareChallengeRequest, PREPARE)).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('acepta loginMode e isRetry válidos', async () => {
|
|
48
|
+
expect(await propertiesWithError(PrepareChallengeRequest, { ...PREPARE, loginMode: 'OTP_ONLY', isRetry: true })).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rechaza loginMode fuera del enum', async () => {
|
|
52
|
+
expect(await propertiesWithError(PrepareChallengeRequest, { ...PREPARE, loginMode: 'OTRO' })).toEqual(['loginMode']);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('rechaza isRetry que no sea booleano', async () => {
|
|
56
|
+
expect(await propertiesWithError(PrepareChallengeRequest, { ...PREPARE, isRetry: 'true' })).toEqual(['isRetry']);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
export declare const COGNITO_EXPLICIT_AUTH_FLOWS: readonly string[];
|
|
3
3
|
/** Unidades de vigencia de token; el conector aplica una sola a los tres tokens. */
|
|
4
4
|
export declare const COGNITO_TOKEN_VALIDITY_UNITS: readonly string[];
|
|
5
|
-
/**
|
|
6
|
-
* Config de un app client (el del pool nuevo de POST /pools o uno extra de POST /pools/{id}/clients).
|
|
7
|
-
* Sin `generateSecret`: el conector fija GenerateSecret false (A21).
|
|
8
|
-
*/
|
|
5
|
+
/** Config de un app client (el del pool nuevo de POST /pools o uno extra de POST /pools/{id}/clients). */
|
|
9
6
|
export declare class AppClientConfig {
|
|
10
7
|
clientName?: string;
|
|
11
8
|
explicitAuthFlows: string[];
|
|
@@ -17,4 +14,6 @@ export declare class AppClientConfig {
|
|
|
17
14
|
enableTokenRevocation?: boolean;
|
|
18
15
|
/** Atributos que el usuario puede escribir con su propio token. Ausente ⇒ todos (default de Cognito). */
|
|
19
16
|
writeAttributes?: string[];
|
|
17
|
+
/** Crea el client con secreto. Ausente ⇒ sin secreto. */
|
|
18
|
+
generateSecret?: boolean;
|
|
20
19
|
}
|
|
@@ -23,10 +23,7 @@ exports.COGNITO_EXPLICIT_AUTH_FLOWS = [
|
|
|
23
23
|
];
|
|
24
24
|
/** Unidades de vigencia de token; el conector aplica una sola a los tres tokens. */
|
|
25
25
|
exports.COGNITO_TOKEN_VALIDITY_UNITS = ['seconds', 'minutes', 'hours', 'days'];
|
|
26
|
-
/**
|
|
27
|
-
* Config de un app client (el del pool nuevo de POST /pools o uno extra de POST /pools/{id}/clients).
|
|
28
|
-
* Sin `generateSecret`: el conector fija GenerateSecret false (A21).
|
|
29
|
-
*/
|
|
26
|
+
/** Config de un app client (el del pool nuevo de POST /pools o uno extra de POST /pools/{id}/clients). */
|
|
30
27
|
class AppClientConfig {
|
|
31
28
|
}
|
|
32
29
|
exports.AppClientConfig = AppClientConfig;
|
|
@@ -85,3 +82,9 @@ __decorate([
|
|
|
85
82
|
(0, class_validator_1.IsString)({ each: true }),
|
|
86
83
|
__metadata("design:type", Array)
|
|
87
84
|
], AppClientConfig.prototype, "writeAttributes", void 0);
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, class_transformer_1.Expose)(),
|
|
87
|
+
(0, class_validator_1.IsOptional)(),
|
|
88
|
+
(0, class_validator_1.IsBoolean)(),
|
|
89
|
+
__metadata("design:type", Boolean)
|
|
90
|
+
], AppClientConfig.prototype, "generateSecret", void 0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Respuesta de POST /pools/{userPoolId}/clients.
|
|
1
|
+
/** Respuesta de POST /pools/{userPoolId}/clients. Nunca expone el secreto del client. */
|
|
2
2
|
export declare class CreatePoolClientResponse {
|
|
3
3
|
appClientId: string;
|
|
4
4
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CreatePoolClientResponse = void 0;
|
|
4
|
-
/** Respuesta de POST /pools/{userPoolId}/clients.
|
|
4
|
+
/** Respuesta de POST /pools/{userPoolId}/clients. Nunca expone el secreto del client. */
|
|
5
5
|
class CreatePoolClientResponse {
|
|
6
6
|
}
|
|
7
7
|
exports.CreatePoolClientResponse = CreatePoolClientResponse;
|
|
@@ -24,4 +24,6 @@ export declare class CreatePoolRequest {
|
|
|
24
24
|
* default-ea a ['email'] (backward-compatible con los pools ya creados).
|
|
25
25
|
*/
|
|
26
26
|
usernameAttributes?: Array<'email' | 'phone_number'>;
|
|
27
|
+
/** Solo un administrador puede crear usuarios en el pool. Ausente ⇒ default de Cognito. */
|
|
28
|
+
allowAdminCreateUserOnly?: boolean;
|
|
27
29
|
}
|
|
@@ -66,3 +66,9 @@ __decorate([
|
|
|
66
66
|
(0, class_validator_1.IsIn)(['email', 'phone_number'], { each: true }),
|
|
67
67
|
__metadata("design:type", Array)
|
|
68
68
|
], CreatePoolRequest.prototype, "usernameAttributes", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
(0, class_transformer_1.Expose)(),
|
|
71
|
+
(0, class_validator_1.IsOptional)(),
|
|
72
|
+
(0, class_validator_1.IsBoolean)(),
|
|
73
|
+
__metadata("design:type", Boolean)
|
|
74
|
+
], CreatePoolRequest.prototype, "allowAdminCreateUserOnly", void 0);
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Response del endpoint POST /pools (pivote v1.4.1 stateless).
|
|
3
|
-
*
|
|
4
|
-
* NO expone `clientSecret` — el SDK Cognito no lo devuelve cuando
|
|
5
|
-
* `GenerateSecret: false` (BFF pattern A21). Si aparece consumer B2B/M2M
|
|
6
|
-
* que requiera client secret, evaluar con líder + bump major del connector.
|
|
7
|
-
*/
|
|
1
|
+
/** Respuesta de POST /pools. Nunca expone el secreto del app client. */
|
|
8
2
|
export declare class CreatePoolResponse {
|
|
9
3
|
userPoolId: string;
|
|
10
4
|
userPoolArn: string;
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CreatePoolResponse = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Response del endpoint POST /pools (pivote v1.4.1 stateless).
|
|
6
|
-
*
|
|
7
|
-
* NO expone `clientSecret` — el SDK Cognito no lo devuelve cuando
|
|
8
|
-
* `GenerateSecret: false` (BFF pattern A21). Si aparece consumer B2B/M2M
|
|
9
|
-
* que requiera client secret, evaluar con líder + bump major del connector.
|
|
10
|
-
*/
|
|
4
|
+
/** Respuesta de POST /pools. Nunca expone el secreto del app client. */
|
|
11
5
|
class CreatePoolResponse {
|
|
12
6
|
}
|
|
13
7
|
exports.CreatePoolResponse = CreatePoolResponse;
|
|
@@ -39,3 +39,16 @@ __decorate([
|
|
|
39
39
|
(0, class_validator_1.IsNotEmpty)(),
|
|
40
40
|
__metadata("design:type", String)
|
|
41
41
|
], RefreshTokensRequest.prototype, "refreshToken", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, class_transformer_1.Expose)(),
|
|
44
|
+
(0, class_validator_1.IsOptional)(),
|
|
45
|
+
(0, class_validator_1.IsString)(),
|
|
46
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
47
|
+
__metadata("design:type", String)
|
|
48
|
+
], RefreshTokensRequest.prototype, "username", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, class_transformer_1.Expose)(),
|
|
51
|
+
(0, class_validator_1.IsOptional)(),
|
|
52
|
+
(0, class_validator_1.IsBoolean)(),
|
|
53
|
+
__metadata("design:type", Boolean)
|
|
54
|
+
], RefreshTokensRequest.prototype, "useClientSecret", void 0);
|
|
@@ -50,3 +50,9 @@ __decorate([
|
|
|
50
50
|
(0, class_validator_1.IsObject)(),
|
|
51
51
|
__metadata("design:type", Object)
|
|
52
52
|
], RespondToChallengeRequest.prototype, "challengeResponses", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, class_transformer_1.Expose)(),
|
|
55
|
+
(0, class_validator_1.IsOptional)(),
|
|
56
|
+
(0, class_validator_1.IsBoolean)(),
|
|
57
|
+
__metadata("design:type", Boolean)
|
|
58
|
+
], RespondToChallengeRequest.prototype, "useClientSecret", void 0);
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.StartOtpLoginRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/** Body de POST /auth/start-otp-login: inicia CUSTOM_AUTH sin SRP ni contraseña. */
|
|
16
|
+
class StartOtpLoginRequest {
|
|
17
|
+
}
|
|
18
|
+
exports.StartOtpLoginRequest = StartOtpLoginRequest;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_transformer_1.Expose)(),
|
|
21
|
+
(0, class_validator_1.IsString)(),
|
|
22
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], StartOtpLoginRequest.prototype, "userPoolId", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
(0, class_validator_1.IsString)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], StartOtpLoginRequest.prototype, "region", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsString)(),
|
|
34
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], StartOtpLoginRequest.prototype, "clientId", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, class_transformer_1.Expose)(),
|
|
39
|
+
(0, class_validator_1.IsString)(),
|
|
40
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], StartOtpLoginRequest.prototype, "username", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, class_transformer_1.Expose)(),
|
|
45
|
+
(0, class_validator_1.IsOptional)(),
|
|
46
|
+
(0, class_validator_1.IsBoolean)(),
|
|
47
|
+
__metadata("design:type", Boolean)
|
|
48
|
+
], StartOtpLoginRequest.prototype, "useClientSecret", void 0);
|
|
@@ -23,6 +23,7 @@ export * from './dtos/AuthEventResponse';
|
|
|
23
23
|
export * from './dtos/AuthTokensResponse';
|
|
24
24
|
export * from './dtos/AuthStartLoginRequest';
|
|
25
25
|
export * from './dtos/AuthStartLoginResponse';
|
|
26
|
+
export * from './dtos/StartOtpLoginRequest';
|
|
26
27
|
export * from './dtos/InitiateAuthRequest';
|
|
27
28
|
export * from './dtos/InitiateAuthResponse';
|
|
28
29
|
export * from './dtos/VerifyPasswordRequest';
|
|
@@ -39,6 +39,7 @@ __exportStar(require("./dtos/AuthEventResponse"), exports);
|
|
|
39
39
|
__exportStar(require("./dtos/AuthTokensResponse"), exports);
|
|
40
40
|
__exportStar(require("./dtos/AuthStartLoginRequest"), exports);
|
|
41
41
|
__exportStar(require("./dtos/AuthStartLoginResponse"), exports);
|
|
42
|
+
__exportStar(require("./dtos/StartOtpLoginRequest"), exports);
|
|
42
43
|
__exportStar(require("./dtos/InitiateAuthRequest"), exports);
|
|
43
44
|
__exportStar(require("./dtos/InitiateAuthResponse"), exports);
|
|
44
45
|
__exportStar(require("./dtos/VerifyPasswordRequest"), exports);
|