@@ -14,6 +14,8 @@ import {
14
14
ValidationPipe ,
15
15
All ,
16
16
Req ,
17
+ HttpException ,
18
+ HttpStatus ,
17
19
} from '@nestjs/common' ;
18
20
import {
19
21
SignupResponse ,
@@ -43,6 +45,8 @@ import { GupshupWhatsappService } from './sms/gupshupWhatsapp/gupshupWhatsapp.se
43
45
import { TelemetryService } from 'src/telemetry/telemetry.service' ;
44
46
// eslint-disable-next-line @typescript-eslint/no-var-requires
45
47
const CryptoJS = require ( 'crypto-js' ) ;
48
+ import { InjectRedis } from '@nestjs-modules/ioredis' ;
49
+ import Redis from 'ioredis' ;
46
50
47
51
CryptoJS . lib . WordArray . words ;
48
52
@@ -56,7 +60,8 @@ export class ApiController {
56
60
private readonly apiService : ApiService ,
57
61
private readonly configResolverService : ConfigResolverService ,
58
62
private readonly gupshupWhatsappService : GupshupWhatsappService ,
59
- private readonly telemetryService : TelemetryService
63
+ private readonly telemetryService : TelemetryService ,
64
+ @InjectRedis ( ) private readonly redis : Redis
60
65
) { }
61
66
62
67
@Get ( )
@@ -438,6 +443,122 @@ export class ApiController {
438
443
return await this . apiService . logout ( body . token ) ;
439
444
}
440
445
446
+ @Get ( 'user/search' )
447
+ async searchUserFA (
448
+ @Headers ( 'Authorization' ) authorization : string ,
449
+ @Headers ( 'X-FusionAuth-Application-Id' ) appId : string ,
450
+ @Query ( ) query : any ,
451
+ @Param ( ) params : any ,
452
+ ) {
453
+ if ( ! authorization || ! appId ) {
454
+ throw new HttpException (
455
+ 'Authorization and X-FusionAuth-Application-Id headers are required' ,
456
+ HttpStatus . BAD_REQUEST ,
457
+ ) ;
458
+ }
459
+
460
+ const fusionAuthBaseUrl = this . configService . get ( 'FUSIONAUTH_BASE_URL' ) ;
461
+ const url = new URL ( `${ fusionAuthBaseUrl } /api/user/search` ) ;
462
+ // Add query params to URL
463
+ if ( query ) {
464
+ Object . keys ( query ) . forEach ( key => {
465
+ url . searchParams . append ( key , query [ key ] ) ;
466
+ } ) ;
467
+ }
468
+
469
+ // Add params to URL
470
+ if ( params ) {
471
+ Object . keys ( params ) . forEach ( key => {
472
+ url . searchParams . append ( key , params [ key ] ) ;
473
+ } ) ;
474
+ }
475
+
476
+ const cacheKey = `search_${ url } ` ;
477
+ const cachedData = await this . redis . get ( cacheKey ) ;
478
+ if ( cachedData ) {
479
+ return JSON . parse ( cachedData ) ;
480
+ }
481
+
482
+ const searchData = await this . searchUserData ( url , authorization , appId ) ;
483
+
484
+ await this . redis . set ( cacheKey , JSON . stringify ( searchData ) ) ;
485
+ return searchData ;
486
+ }
487
+
488
+ @Get ( 'user/:id' )
489
+ async getUserById (
490
+ @Param ( 'id' ) id : string ,
491
+ @Headers ( 'Authorization' ) authorization : string ,
492
+ @Headers ( 'X-FusionAuth-Application-Id' ) appId : string ,
493
+ ) {
494
+ if ( ! authorization || ! appId ) {
495
+ throw new HttpException (
496
+ 'Authorization and X-FusionAuth-Application-Id headers are required' ,
497
+ HttpStatus . BAD_REQUEST ,
498
+ ) ;
499
+ }
500
+
501
+ const cacheKey = `user_${ id } ` ;
502
+ const cachedData = await this . redis . get ( cacheKey ) ;
503
+ if ( cachedData ) {
504
+ return JSON . parse ( cachedData ) ;
505
+ }
506
+
507
+ const userData = await this . fetchUserDataFromService ( id , authorization , appId ) ;
508
+
509
+ await this . redis . set ( cacheKey , JSON . stringify ( userData ) ) ;
510
+ return userData ;
511
+ }
512
+
513
+ private async fetchUserDataFromService ( id : string , authorization : string , appId : string ) {
514
+ try {
515
+ const fusionAuthBaseUrl = this . configService . get ( 'FUSIONAUTH_BASE_URL' ) ;
516
+ const url = new URL ( `${ fusionAuthBaseUrl } /api/user/${ id } ` ) ;
517
+ const response = await fetch (
518
+ url ,
519
+ {
520
+ method : "GET" ,
521
+ headers : {
522
+ Authorization : authorization ,
523
+ 'Content-Type' : 'application/json' ,
524
+ 'X-FusionAuth-Application-Id' : appId ,
525
+ } ,
526
+ } ,
527
+ ) ;
528
+ return response . json ( ) ;
529
+ } catch ( error ) {
530
+ throw new HttpException (
531
+ `Failed to fetch user data: ${ error . message } ` ,
532
+ HttpStatus . INTERNAL_SERVER_ERROR ,
533
+ ) ;
534
+ }
535
+ }
536
+
537
+ private async searchUserData (
538
+ url : URL ,
539
+ authorization : string ,
540
+ appId : string ,
541
+ ) {
542
+ try {
543
+ const response = await fetch (
544
+ url ,
545
+ {
546
+ headers : {
547
+ Authorization : authorization ,
548
+ 'Content-Type' : 'application/json' ,
549
+ 'X-FusionAuth-Application-Id' : appId ,
550
+ }
551
+ } ,
552
+ ) ;
553
+ return response . json ( ) ;
554
+ } catch ( error ) {
555
+ throw new HttpException (
556
+ `Failed to search user data: ${ error . message } ` ,
557
+ HttpStatus . INTERNAL_SERVER_ERROR ,
558
+ ) ;
559
+ }
560
+ }
561
+
441
562
@All ( '*' )
442
563
async defaultRoute (
443
564
@Req ( ) request : Request ,
0 commit comments