@gugananuvem/aws-local-simulator 1.0.2 → 1.0.5

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 (37) hide show
  1. package/bin/aws-local-simulator.js +1 -62
  2. package/package.json +8 -10
  3. package/src/index.js +1 -131
  4. package/src/config/config-loader.js +0 -113
  5. package/src/config/default-config.js +0 -65
  6. package/src/config/env-loader.js +0 -67
  7. package/src/index.mjs +0 -124
  8. package/src/server.js +0 -219
  9. package/src/services/apigateway/index.js +0 -67
  10. package/src/services/apigateway/server.js +0 -435
  11. package/src/services/apigateway/simulator.js +0 -1252
  12. package/src/services/cognito/index.js +0 -66
  13. package/src/services/cognito/server.js +0 -229
  14. package/src/services/cognito/simulator.js +0 -848
  15. package/src/services/dynamodb/index.js +0 -71
  16. package/src/services/dynamodb/server.js +0 -122
  17. package/src/services/dynamodb/simulator.js +0 -614
  18. package/src/services/eventbridge/index.js +0 -85
  19. package/src/services/index.js +0 -19
  20. package/src/services/lambda/handler-loader.js +0 -173
  21. package/src/services/lambda/index.js +0 -73
  22. package/src/services/lambda/route-registry.js +0 -275
  23. package/src/services/lambda/server.js +0 -153
  24. package/src/services/lambda/simulator.js +0 -278
  25. package/src/services/s3/index.js +0 -70
  26. package/src/services/s3/server.js +0 -239
  27. package/src/services/s3/simulator.js +0 -740
  28. package/src/services/sns/index.js +0 -76
  29. package/src/services/sqs/index.js +0 -96
  30. package/src/services/sqs/server.js +0 -274
  31. package/src/services/sqs/simulator.js +0 -660
  32. package/src/template/aws-config-template.js +0 -88
  33. package/src/template/aws-config-template.mjs +0 -91
  34. package/src/template/config-template.json +0 -165
  35. package/src/utils/aws-config.js +0 -92
  36. package/src/utils/local-store.js +0 -68
  37. package/src/utils/logger.js +0 -60
@@ -1,848 +0,0 @@
1
- /**
2
- * Cognito Simulator Core
3
- * Simula User Pools, Identity Pools, Autenticação, Tokens JWT
4
- */
5
-
6
- const crypto = require('crypto');
7
- const jwt = require('jsonwebtoken');
8
- const { v4: uuidv4 } = require('uuid');
9
- const logger = require('../../utils/logger');
10
- const LocalStore = require('../../utils/local-store');
11
- const path = require('path');
12
-
13
- class CognitoSimulator {
14
- constructor(config) {
15
- this.config = config;
16
- this.dataDir = path.join(process.env.AWS_LOCAL_SIMULATOR_DATA_DIR, 'cognito');
17
- this.store = new LocalStore(this.dataDir);
18
- this.userPools = new Map();
19
- this.identityPools = new Map();
20
- this.users = new Map();
21
- this.sessions = new Map();
22
- this.refreshTokens = new Map();
23
- this.accessTokens = new Map();
24
- this.jwtSecret = crypto.randomBytes(64).toString('hex');
25
- }
26
-
27
- async initialize() {
28
- logger.debug('Inicializando Cognito Simulator...');
29
- this.loadUserPools();
30
- this.loadIdentityPools();
31
- this.loadUsers();
32
- this.loadSessions();
33
-
34
- logger.debug(`✅ Cognito Simulator inicializado com ${this.userPools.size} user pools, ${this.identityPools.size} identity pools, ${this.users.size} usuários`);
35
- }
36
-
37
- // ============ User Pool Operations ============
38
-
39
- createUserPool(params) {
40
- const { PoolName, Policies, LambdaConfig, AutoVerifiedAttributes, AliasAttributes, UsernameAttributes, MfaConfiguration } = params;
41
-
42
- const poolId = `local_${PoolName}_${Date.now()}`;
43
- const userPool = {
44
- Id: poolId,
45
- Name: PoolName,
46
- Arn: `arn:aws:cognito:local:000000000000:userpool/${poolId}`,
47
- Status: 'ACTIVE',
48
- CreationDate: new Date().toISOString(),
49
- LastModifiedDate: new Date().toISOString(),
50
- Policies: Policies || {
51
- PasswordPolicy: {
52
- MinimumLength: 8,
53
- RequireUppercase: true,
54
- RequireLowercase: true,
55
- RequireNumbers: true,
56
- RequireSymbols: false
57
- }
58
- },
59
- LambdaConfig: LambdaConfig || {},
60
- AutoVerifiedAttributes: AutoVerifiedAttributes || ['email'],
61
- AliasAttributes: AliasAttributes || [],
62
- UsernameAttributes: UsernameAttributes || ['email'],
63
- MfaConfiguration: MfaConfiguration || 'OFF',
64
- EstimatedNumberOfUsers: 0,
65
- Users: [],
66
- Clients: new Map(),
67
- Groups: new Map(),
68
- IdentityProviders: new Map(),
69
- ResourceServers: new Map()
70
- };
71
-
72
- this.userPools.set(poolId, userPool);
73
- this.persistUserPools();
74
-
75
- logger.debug(`✅ User Pool criado: ${PoolName} (${poolId})`);
76
-
77
- return {
78
- UserPool: {
79
- Id: userPool.Id,
80
- Name: userPool.Name,
81
- Arn: userPool.Arn,
82
- Status: userPool.Status,
83
- CreationDate: userPool.CreationDate,
84
- LastModifiedDate: userPool.LastModifiedDate,
85
- MfaConfiguration: userPool.MfaConfiguration,
86
- EstimatedNumberOfUsers: 0
87
- }
88
- };
89
- }
90
-
91
- listUserPools(params = {}) {
92
- const { MaxResults = 60, NextToken } = params;
93
- let userPools = Array.from(this.userPools.values());
94
-
95
- if (NextToken) {
96
- const startIndex = parseInt(NextToken);
97
- userPools = userPools.slice(startIndex);
98
- }
99
-
100
- const results = userPools.slice(0, MaxResults);
101
- const nextToken = results.length === MaxResults ? String(MaxResults) : null;
102
-
103
- return {
104
- UserPools: results.map(pool => ({
105
- Id: pool.Id,
106
- Name: pool.Name,
107
- Arn: pool.Arn,
108
- Status: pool.Status,
109
- CreationDate: pool.CreationDate,
110
- LastModifiedDate: pool.LastModifiedDate
111
- })),
112
- NextToken: nextToken
113
- };
114
- }
115
-
116
- describeUserPool(params) {
117
- const { UserPoolId } = params;
118
- const userPool = this.userPools.get(UserPoolId);
119
-
120
- if (!userPool) {
121
- throw new Error(`User pool ${UserPoolId} not found`);
122
- }
123
-
124
- return {
125
- UserPool: {
126
- Id: userPool.Id,
127
- Name: userPool.Name,
128
- Arn: userPool.Arn,
129
- Status: userPool.Status,
130
- CreationDate: userPool.CreationDate,
131
- LastModifiedDate: userPool.LastModifiedDate,
132
- Policies: userPool.Policies,
133
- LambdaConfig: userPool.LambdaConfig,
134
- AutoVerifiedAttributes: userPool.AutoVerifiedAttributes,
135
- AliasAttributes: userPool.AliasAttributes,
136
- UsernameAttributes: userPool.UsernameAttributes,
137
- MfaConfiguration: userPool.MfaConfiguration,
138
- EstimatedNumberOfUsers: userPool.Users.length
139
- }
140
- };
141
- }
142
-
143
- deleteUserPool(params) {
144
- const { UserPoolId } = params;
145
-
146
- if (!this.userPools.has(UserPoolId)) {
147
- throw new Error(`User pool ${UserPoolId} not found`);
148
- }
149
-
150
- this.userPools.delete(UserPoolId);
151
- this.persistUserPools();
152
-
153
- return {};
154
- }
155
-
156
- // ============ User Pool Client Operations ============
157
-
158
- createUserPoolClient(params) {
159
- const { UserPoolId, ClientName, GenerateSecret, RefreshTokenValidity, AccessTokenValidity, IdTokenValidity, AllowedOAuthFlows, AllowedOAuthScopes, CallbackURLs, LogoutURLs } = params;
160
-
161
- const userPool = this.userPools.get(UserPoolId);
162
- if (!userPool) {
163
- throw new Error(`User pool ${UserPoolId} not found`);
164
- }
165
-
166
- const clientId = crypto.randomBytes(20).toString('hex');
167
- const clientSecret = GenerateSecret ? crypto.randomBytes(32).toString('hex') : null;
168
-
169
- const client = {
170
- ClientId: clientId,
171
- ClientName: ClientName,
172
- ClientSecret: clientSecret,
173
- UserPoolId: UserPoolId,
174
- RefreshTokenValidity: RefreshTokenValidity || 30,
175
- AccessTokenValidity: AccessTokenValidity || 1,
176
- IdTokenValidity: IdTokenValidity || 1,
177
- AllowedOAuthFlows: AllowedOAuthFlows || ['code'],
178
- AllowedOAuthScopes: AllowedOAuthScopes || ['openid', 'email', 'profile'],
179
- CallbackURLs: CallbackURLs || [],
180
- LogoutURLs: LogoutURLs || [],
181
- CreatedDate: new Date().toISOString(),
182
- LastModifiedDate: new Date().toISOString()
183
- };
184
-
185
- userPool.Clients.set(clientId, client);
186
- this.persistUserPools();
187
-
188
- logger.debug(`✅ User Pool Client criado: ${ClientName} (${clientId})`);
189
-
190
- return {
191
- UserPoolClient: {
192
- ClientId: client.ClientId,
193
- ClientName: client.ClientName,
194
- ClientSecret: client.ClientSecret,
195
- UserPoolId: client.UserPoolId,
196
- RefreshTokenValidity: client.RefreshTokenValidity,
197
- AccessTokenValidity: client.AccessTokenValidity,
198
- IdTokenValidity: client.IdTokenValidity,
199
- AllowedOAuthFlows: client.AllowedOAuthFlows,
200
- AllowedOAuthScopes: client.AllowedOAuthScopes,
201
- CallbackURLs: client.CallbackURLs,
202
- LogoutURLs: client.LogoutURLs,
203
- CreationDate: client.CreatedDate
204
- }
205
- };
206
- }
207
-
208
- // ============ User Operations ============
209
-
210
- signUp(params) {
211
- const { ClientId, Username, Password, UserAttributes, ValidationData } = params;
212
-
213
- // Encontra o user pool pelo client id
214
- const userPool = this.findUserPoolByClientId(ClientId);
215
- if (!userPool) {
216
- throw new Error(`Client ${ClientId} not found`);
217
- }
218
-
219
- // Verifica se usuário já existe
220
- const existingUser = Array.from(this.users.values()).find(
221
- u => u.Username === Username && u.UserPoolId === userPool.Id
222
- );
223
-
224
- if (existingUser) {
225
- throw new Error(`User already exists: ${Username}`);
226
- }
227
-
228
- const userId = uuidv4();
229
- const user = {
230
- Username: Username,
231
- UserPoolId: userPool.Id,
232
- UserId: userId,
233
- Attributes: this.normalizeUserAttributes(UserAttributes || []),
234
- Enabled: true,
235
- UserStatus: 'CONFIRMED', // Por padrão, confirma imediatamente (para teste)
236
- CreatedDate: new Date().toISOString(),
237
- LastModifiedDate: new Date().toISOString(),
238
- Password: this.hashPassword(Password),
239
- MfaOptions: [],
240
- PreferredMfaSetting: null,
241
- UserMFASettingList: []
242
- };
243
-
244
- this.users.set(userId, user);
245
- userPool.Users.push(userId);
246
- userPool.EstimatedNumberOfUsers++;
247
- this.persistUsers();
248
- this.persistUserPools();
249
-
250
- logger.debug(`✅ Usuário criado: ${Username} (${userId})`);
251
-
252
- return {
253
- UserConfirmed: true,
254
- UserSub: userId,
255
- CodeDeliveryDetails: null
256
- };
257
- }
258
-
259
- confirmSignUp(params) {
260
- const { ClientId, Username, ConfirmationCode } = params;
261
-
262
- const user = this.findUserByUsername(Username, ClientId);
263
- if (!user) {
264
- throw new Error(`User not found: ${Username}`);
265
- }
266
-
267
- user.UserStatus = 'CONFIRMED';
268
- user.LastModifiedDate = new Date().toISOString();
269
- this.persistUsers();
270
-
271
- return {};
272
- }
273
-
274
- initiateAuth(params) {
275
- const { AuthFlow, ClientId, AuthParameters } = params;
276
- const userPool = this.findUserPoolByClientId(ClientId);
277
-
278
- if (!userPool) {
279
- throw new Error(`Client ${ClientId} not found`);
280
- }
281
-
282
- const username = AuthParameters.USERNAME;
283
- const password = AuthParameters.PASSWORD;
284
-
285
- const user = this.findUserByUsername(username, ClientId);
286
- if (!user) {
287
- throw new Error(`User not found: ${username}`);
288
- }
289
-
290
- if (user.UserStatus !== 'CONFIRMED') {
291
- throw new Error(`User not confirmed: ${username}`);
292
- }
293
-
294
- if (!this.verifyPassword(password, user.Password)) {
295
- throw new Error('Incorrect username or password');
296
- }
297
-
298
- // Gera tokens JWT
299
- const accessToken = this.generateAccessToken(user, userPool, ClientId);
300
- const idToken = this.generateIdToken(user, userPool, ClientId);
301
- const refreshToken = this.generateRefreshToken(user, userPool, ClientId);
302
-
303
- const sessionId = uuidv4();
304
- const session = {
305
- Id: sessionId,
306
- UserId: user.UserId,
307
- UserPoolId: userPool.Id,
308
- ClientId: ClientId,
309
- AccessToken: accessToken,
310
- IdToken: idToken,
311
- RefreshToken: refreshToken,
312
- CreatedAt: new Date().toISOString(),
313
- ExpiresAt: new Date(Date.now() + 3600000).toISOString() // 1 hora
314
- };
315
-
316
- this.sessions.set(sessionId, session);
317
- this.accessTokens.set(accessToken, session);
318
- this.refreshTokens.set(refreshToken, session);
319
- this.persistSessions();
320
-
321
- logger.debug(`🔐 Usuário autenticado: ${username}`);
322
-
323
- return {
324
- AuthenticationResult: {
325
- AccessToken: accessToken,
326
- IdToken: idToken,
327
- RefreshToken: refreshToken,
328
- TokenType: 'Bearer',
329
- ExpiresIn: 3600
330
- },
331
- ChallengeName: null,
332
- Session: null
333
- };
334
- }
335
-
336
- getToken(params) {
337
- const { AuthFlow, ClientId, AuthParameters } = params;
338
-
339
- if (AuthFlow === 'REFRESH_TOKEN_AUTH') {
340
- const refreshToken = AuthParameters.REFRESH_TOKEN;
341
- const session = this.refreshTokens.get(refreshToken);
342
-
343
- if (!session) {
344
- throw new Error('Invalid refresh token');
345
- }
346
-
347
- const user = this.users.get(session.UserId);
348
- const userPool = this.userPools.get(session.UserPoolId);
349
-
350
- if (!user || !userPool) {
351
- throw new Error('Invalid session');
352
- }
353
-
354
- // Gera novos tokens
355
- const newAccessToken = this.generateAccessToken(user, userPool, session.ClientId);
356
- const newIdToken = this.generateIdToken(user, userPool, session.ClientId);
357
-
358
- session.AccessToken = newAccessToken;
359
- session.IdToken = newIdToken;
360
- session.ExpiresAt = new Date(Date.now() + 3600000).toISOString();
361
-
362
- this.accessTokens.set(newAccessToken, session);
363
- this.persistSessions();
364
-
365
- return {
366
- AuthenticationResult: {
367
- AccessToken: newAccessToken,
368
- IdToken: newIdToken,
369
- TokenType: 'Bearer',
370
- ExpiresIn: 3600
371
- }
372
- };
373
- }
374
-
375
- throw new Error(`Unsupported AuthFlow: ${AuthFlow}`);
376
- }
377
-
378
- // ============ Token Management ============
379
-
380
- generateAccessToken(user, userPool, clientId) {
381
- const payload = {
382
- sub: user.UserId,
383
- token_use: 'access',
384
- client_id: clientId,
385
- username: user.Username,
386
- scope: 'aws.cognito.signin.user.admin',
387
- iss: `https://cognito-idp.local/${userPool.Id}`,
388
- exp: Math.floor(Date.now() / 1000) + 3600,
389
- iat: Math.floor(Date.now() / 1000)
390
- };
391
-
392
- return jwt.sign(payload, this.jwtSecret, { algorithm: 'HS256' });
393
- }
394
-
395
- generateIdToken(user, userPool, clientId) {
396
- const payload = {
397
- sub: user.UserId,
398
- token_use: 'id',
399
- client_id: clientId,
400
- email: user.Attributes.email,
401
- email_verified: user.Attributes.email_verified || true,
402
- username: user.Username,
403
- iss: `https://cognito-idp.local/${userPool.Id}`,
404
- exp: Math.floor(Date.now() / 1000) + 3600,
405
- iat: Math.floor(Date.now() / 1000)
406
- };
407
-
408
- // Adiciona outros atributos do usuário
409
- for (const [key, value] of Object.entries(user.Attributes)) {
410
- if (key !== 'email' && key !== 'email_verified') {
411
- payload[key] = value;
412
- }
413
- }
414
-
415
- return jwt.sign(payload, this.jwtSecret, { algorithm: 'HS256' });
416
- }
417
-
418
- generateRefreshToken(user, userPool, clientId) {
419
- const payload = {
420
- sub: user.UserId,
421
- token_use: 'refresh',
422
- client_id: clientId,
423
- username: user.Username,
424
- iss: `https://cognito-idp.local/${userPool.Id}`,
425
- exp: Math.floor(Date.now() / 1000) + 2592000, // 30 dias
426
- iat: Math.floor(Date.now() / 1000)
427
- };
428
-
429
- return jwt.sign(payload, this.jwtSecret, { algorithm: 'HS256' });
430
- }
431
-
432
- verifyAccessToken(token) {
433
- try {
434
- const decoded = jwt.verify(token, this.jwtSecret);
435
- const session = this.accessTokens.get(token);
436
-
437
- if (!session || session.ExpiresAt < new Date().toISOString()) {
438
- return null;
439
- }
440
-
441
- return decoded;
442
- } catch (error) {
443
- return null;
444
- }
445
- }
446
-
447
- // ============ Admin Operations ============
448
-
449
- adminGetUser(params) {
450
- const { UserPoolId, Username } = params;
451
- const userPool = this.userPools.get(UserPoolId);
452
-
453
- if (!userPool) {
454
- throw new Error(`User pool ${UserPoolId} not found`);
455
- }
456
-
457
- const user = this.findUserByUsername(Username, null, UserPoolId);
458
- if (!user) {
459
- throw new Error(`User not found: ${Username}`);
460
- }
461
-
462
- return {
463
- Username: user.Username,
464
- UserAttributes: this.formatUserAttributes(user.Attributes),
465
- UserCreateDate: user.CreatedDate,
466
- UserLastModifiedDate: user.LastModifiedDate,
467
- Enabled: user.Enabled,
468
- UserStatus: user.UserStatus,
469
- MFAOptions: user.MfaOptions,
470
- PreferredMfaSetting: user.PreferredMfaSetting,
471
- UserMFASettingList: user.UserMFASettingList
472
- };
473
- }
474
-
475
- adminCreateUser(params) {
476
- const { UserPoolId, Username, UserAttributes, TemporaryPassword, DesiredDeliveryMediums } = params;
477
- const userPool = this.userPools.get(UserPoolId);
478
-
479
- if (!userPool) {
480
- throw new Error(`User pool ${UserPoolId} not found`);
481
- }
482
-
483
- const userId = uuidv4();
484
- const user = {
485
- Username: Username,
486
- UserPoolId: UserPoolId,
487
- UserId: userId,
488
- Attributes: this.normalizeUserAttributes(UserAttributes || []),
489
- Enabled: true,
490
- UserStatus: 'FORCE_CHANGE_PASSWORD',
491
- CreatedDate: new Date().toISOString(),
492
- LastModifiedDate: new Date().toISOString(),
493
- Password: this.hashPassword(TemporaryPassword || 'Temp123!'),
494
- MfaOptions: [],
495
- PreferredMfaSetting: null,
496
- UserMFASettingList: []
497
- };
498
-
499
- this.users.set(userId, user);
500
- userPool.Users.push(userId);
501
- userPool.EstimatedNumberOfUsers++;
502
- this.persistUsers();
503
- this.persistUserPools();
504
-
505
- logger.debug(`👤 Usuário administrador criado: ${Username}`);
506
-
507
- return {
508
- User: {
509
- Username: user.Username,
510
- UserAttributes: this.formatUserAttributes(user.Attributes),
511
- UserCreateDate: user.CreatedDate,
512
- UserLastModifiedDate: user.LastModifiedDate,
513
- Enabled: user.Enabled,
514
- UserStatus: user.UserStatus
515
- }
516
- };
517
- }
518
-
519
- adminSetUserPassword(params) {
520
- const { UserPoolId, Username, Password, Permanent } = params;
521
- const user = this.findUserByUsername(Username, null, UserPoolId);
522
-
523
- if (!user) {
524
- throw new Error(`User not found: ${Username}`);
525
- }
526
-
527
- user.Password = this.hashPassword(Password);
528
- if (Permanent) {
529
- user.UserStatus = 'CONFIRMED';
530
- }
531
- user.LastModifiedDate = new Date().toISOString();
532
- this.persistUsers();
533
-
534
- return {};
535
- }
536
-
537
- adminDeleteUser(params) {
538
- const { UserPoolId, Username } = params;
539
- const user = this.findUserByUsername(Username, null, UserPoolId);
540
-
541
- if (!user) {
542
- throw new Error(`User not found: ${Username}`);
543
- }
544
-
545
- const userPool = this.userPools.get(UserPoolId);
546
- if (userPool) {
547
- const index = userPool.Users.indexOf(user.UserId);
548
- if (index !== -1) {
549
- userPool.Users.splice(index, 1);
550
- userPool.EstimatedNumberOfUsers--;
551
- }
552
- }
553
-
554
- this.users.delete(user.UserId);
555
- this.persistUsers();
556
- this.persistUserPools();
557
-
558
- return {};
559
- }
560
-
561
- // ============ Helper Methods ============
562
-
563
- findUserPoolByClientId(clientId) {
564
- for (const userPool of this.userPools.values()) {
565
- if (userPool.Clients.has(clientId)) {
566
- return userPool;
567
- }
568
- }
569
- return null;
570
- }
571
-
572
- findUserByUsername(username, clientId = null, userPoolId = null) {
573
- let targetUserPoolId = userPoolId;
574
-
575
- if (clientId && !targetUserPoolId) {
576
- const userPool = this.findUserPoolByClientId(clientId);
577
- if (userPool) {
578
- targetUserPoolId = userPool.Id;
579
- }
580
- }
581
-
582
- for (const user of this.users.values()) {
583
- if (user.Username === username && user.UserPoolId === targetUserPoolId) {
584
- return user;
585
- }
586
- }
587
-
588
- return null;
589
- }
590
-
591
- normalizeUserAttributes(attributes) {
592
- const normalized = {};
593
- for (const attr of attributes) {
594
- normalized[attr.Name] = attr.Value;
595
- }
596
- return normalized;
597
- }
598
-
599
- formatUserAttributes(attributes) {
600
- return Object.entries(attributes).map(([Name, Value]) => ({ Name, Value }));
601
- }
602
-
603
- hashPassword(password) {
604
- // Simulação de hash (não usar em produção real)
605
- return crypto.createHash('sha256').update(password).digest('hex');
606
- }
607
-
608
- verifyPassword(password, hash) {
609
- return this.hashPassword(password) === hash;
610
- }
611
-
612
- // ============ Identity Pool Operations ============
613
-
614
- createIdentityPool(params) {
615
- const { IdentityPoolName, AllowUnauthenticatedIdentities, SupportedLoginProviders, CognitoIdentityProviders } = params;
616
-
617
- const identityPoolId = `local:${IdentityPoolName}_${Date.now()}`;
618
- const identityPool = {
619
- IdentityPoolId: identityPoolId,
620
- IdentityPoolName: IdentityPoolName,
621
- AllowUnauthenticatedIdentities: AllowUnauthenticatedIdentities || false,
622
- SupportedLoginProviders: SupportedLoginProviders || {},
623
- CognitoIdentityProviders: CognitoIdentityProviders || [],
624
- Identities: new Map()
625
- };
626
-
627
- this.identityPools.set(identityPoolId, identityPool);
628
- this.persistIdentityPools();
629
-
630
- logger.debug(`✅ Identity Pool criado: ${IdentityPoolName} (${identityPoolId})`);
631
-
632
- return {
633
- IdentityPoolId: identityPoolId,
634
- IdentityPoolName: identityPoolName,
635
- AllowUnauthenticatedIdentities: identityPool.AllowUnauthenticatedIdentities
636
- };
637
- }
638
-
639
- getId(params) {
640
- const { IdentityPoolId, Logins } = params;
641
- const identityPool = this.identityPools.get(IdentityPoolId);
642
-
643
- if (!identityPool) {
644
- throw new Error(`Identity pool ${IdentityPoolId} not found`);
645
- }
646
-
647
- let identityId = null;
648
-
649
- if (Logins) {
650
- // Procura identidade existente com os logins fornecidos
651
- for (const [id, identity] of identityPool.Identities) {
652
- if (identity.Logins && this.matchesLogins(identity.Logins, Logins)) {
653
- identityId = id;
654
- break;
655
- }
656
- }
657
- }
658
-
659
- if (!identityId) {
660
- identityId = uuidv4();
661
- identityPool.Identities.set(identityId, {
662
- IdentityId: identityId,
663
- Logins: Logins || {},
664
- CreationDate: new Date().toISOString(),
665
- LastModifiedDate: new Date().toISOString()
666
- });
667
- this.persistIdentityPools();
668
- }
669
-
670
- return {
671
- IdentityId: identityId
672
- };
673
- }
674
-
675
- getCredentialsForIdentity(params) {
676
- const { IdentityId, Logins } = params;
677
- const identityPool = this.findIdentityPoolByIdentityId(IdentityId);
678
-
679
- if (!identityPool) {
680
- throw new Error(`Identity ${IdentityId} not found`);
681
- }
682
-
683
- const identity = identityPool.Identities.get(IdentityId);
684
- if (!identity) {
685
- throw new Error(`Identity ${IdentityId} not found in pool`);
686
- }
687
-
688
- // Gera credenciais temporárias (simuladas)
689
- const credentials = {
690
- AccessKeyId: `AKIA${crypto.randomBytes(16).toString('hex').toUpperCase()}`,
691
- SecretKey: crypto.randomBytes(32).toString('hex'),
692
- SessionToken: crypto.randomBytes(64).toString('base64'),
693
- Expiration: new Date(Date.now() + 3600000).toISOString()
694
- };
695
-
696
- return {
697
- Credentials: credentials,
698
- IdentityId: IdentityId
699
- };
700
- }
701
-
702
- findIdentityPoolByIdentityId(identityId) {
703
- for (const pool of this.identityPools.values()) {
704
- if (pool.Identities.has(identityId)) {
705
- return pool;
706
- }
707
- }
708
- return null;
709
- }
710
-
711
- matchesLogins(existingLogins, newLogins) {
712
- const existingKeys = Object.keys(existingLogins);
713
- const newKeys = Object.keys(newLogins);
714
-
715
- if (existingKeys.length !== newKeys.length) return false;
716
-
717
- for (const key of existingKeys) {
718
- if (existingLogins[key] !== newLogins[key]) {
719
- return false;
720
- }
721
- }
722
-
723
- return true;
724
- }
725
-
726
- // ============ Persistence ============
727
-
728
- loadUserPools() {
729
- const saved = this.store.read('__userpools__');
730
- if (saved) {
731
- for (const [id, data] of Object.entries(saved)) {
732
- // Reconstitui Maps
733
- data.Clients = new Map(Object.entries(data.Clients || {}));
734
- data.Groups = new Map(Object.entries(data.Groups || {}));
735
- data.IdentityProviders = new Map(Object.entries(data.IdentityProviders || {}));
736
- data.ResourceServers = new Map(Object.entries(data.ResourceServers || {}));
737
- this.userPools.set(id, data);
738
- }
739
- }
740
- }
741
-
742
- loadIdentityPools() {
743
- const saved = this.store.read('__identitypools__');
744
- if (saved) {
745
- for (const [id, data] of Object.entries(saved)) {
746
- data.Identities = new Map(Object.entries(data.Identities || {}));
747
- this.identityPools.set(id, data);
748
- }
749
- }
750
- }
751
-
752
- loadUsers() {
753
- const saved = this.store.read('__users__');
754
- if (saved) {
755
- for (const [id, user] of Object.entries(saved)) {
756
- this.users.set(id, user);
757
- }
758
- }
759
- }
760
-
761
- loadSessions() {
762
- const saved = this.store.read('__sessions__');
763
- if (saved) {
764
- for (const [id, session] of Object.entries(saved)) {
765
- this.sessions.set(id, session);
766
- this.accessTokens.set(session.AccessToken, session);
767
- this.refreshTokens.set(session.RefreshToken, session);
768
- }
769
- }
770
- }
771
-
772
- persistUserPools() {
773
- const poolsObj = {};
774
- for (const [id, pool] of this.userPools.entries()) {
775
- poolsObj[id] = {
776
- ...pool,
777
- Clients: Object.fromEntries(pool.Clients),
778
- Groups: Object.fromEntries(pool.Groups),
779
- IdentityProviders: Object.fromEntries(pool.IdentityProviders),
780
- ResourceServers: Object.fromEntries(pool.ResourceServers)
781
- };
782
- }
783
- this.store.write('__userpools__', poolsObj);
784
- }
785
-
786
- persistIdentityPools() {
787
- const poolsObj = {};
788
- for (const [id, pool] of this.identityPools.entries()) {
789
- poolsObj[id] = {
790
- ...pool,
791
- Identities: Object.fromEntries(pool.Identities)
792
- };
793
- }
794
- this.store.write('__identitypools__', poolsObj);
795
- }
796
-
797
- persistUsers() {
798
- const usersObj = {};
799
- for (const [id, user] of this.users.entries()) {
800
- usersObj[id] = user;
801
- }
802
- this.store.write('__users__', usersObj);
803
- }
804
-
805
- persistSessions() {
806
- const sessionsObj = {};
807
- for (const [id, session] of this.sessions.entries()) {
808
- sessionsObj[id] = session;
809
- }
810
- this.store.write('__sessions__', sessionsObj);
811
- }
812
-
813
- async reset() {
814
- this.userPools.clear();
815
- this.identityPools.clear();
816
- this.users.clear();
817
- this.sessions.clear();
818
- this.accessTokens.clear();
819
- this.refreshTokens.clear();
820
-
821
- this.persistUserPools();
822
- this.persistIdentityPools();
823
- this.persistUsers();
824
- this.persistSessions();
825
-
826
- logger.debug('Cognito: Todos os dados resetados');
827
- }
828
-
829
- // ============ Stats ============
830
-
831
- getUserPoolsCount() {
832
- return this.userPools.size;
833
- }
834
-
835
- getTotalUsersCount() {
836
- return this.users.size;
837
- }
838
-
839
- getIdentityPoolsCount() {
840
- return this.identityPools.size;
841
- }
842
-
843
- getActiveSessionsCount() {
844
- return this.sessions.size;
845
- }
846
- }
847
-
848
- module.exports = CognitoSimulator;