Skip to content

Commit

Permalink
Merge pull request #105 from Amruth-Vamshi/feature/WA-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
ChakshuGautam authored Dec 11, 2024
2 parents bbddf45 + be685a9 commit 6902c78
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@sentry/minimal": "^6.19.7",
"@sentry/node": "^7.57.0",
"ajv": "^8.12.0",
"axios": "^1.7.9",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"crypto-js": "^4.1.1",
Expand Down
123 changes: 122 additions & 1 deletion src/api/api.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
ValidationPipe,
All,
Req,
HttpException,
HttpStatus,
} from '@nestjs/common';
import {
SignupResponse,
Expand Down Expand Up @@ -43,6 +45,8 @@ import { GupshupWhatsappService } from './sms/gupshupWhatsapp/gupshupWhatsapp.se
import { TelemetryService } from 'src/telemetry/telemetry.service';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const CryptoJS = require('crypto-js');
import { InjectRedis } from '@nestjs-modules/ioredis';
import Redis from 'ioredis';

CryptoJS.lib.WordArray.words;

Expand All @@ -56,7 +60,8 @@ export class ApiController {
private readonly apiService: ApiService,
private readonly configResolverService: ConfigResolverService,
private readonly gupshupWhatsappService: GupshupWhatsappService,
private readonly telemetryService: TelemetryService
private readonly telemetryService: TelemetryService,
@InjectRedis() private readonly redis: Redis
) {}

@Get()
Expand Down Expand Up @@ -438,6 +443,122 @@ export class ApiController {
return await this.apiService.logout(body.token);
}

@Get('user/search')
async searchUserFA(
@Headers('Authorization') authorization: string,
@Headers('X-FusionAuth-Application-Id') appId: string,
@Query() query: any,
@Param() params: any,
) {
if (!authorization || !appId) {
throw new HttpException(
'Authorization and X-FusionAuth-Application-Id headers are required',
HttpStatus.BAD_REQUEST,
);
}

const fusionAuthBaseUrl = this.configService.get('FUSIONAUTH_BASE_URL');
const url = new URL(`${fusionAuthBaseUrl}/api/user/search`);
// Add query params to URL
if (query) {
Object.keys(query).forEach(key => {
url.searchParams.append(key, query[key]);
});
}

// Add params to URL
if (params) {
Object.keys(params).forEach(key => {
url.searchParams.append(key, params[key]);
});
}

const cacheKey = `search_${url}`;
const cachedData = await this.redis.get(cacheKey);
if (cachedData) {
return JSON.parse(cachedData);
}

const searchData = await this.searchUserData(url, authorization, appId);

await this.redis.set(cacheKey, JSON.stringify(searchData));
return searchData;
}

@Get('user/:id')
async getUserById(
@Param('id') id: string,
@Headers('Authorization') authorization: string,
@Headers('X-FusionAuth-Application-Id') appId: string,
) {
if (!authorization || !appId) {
throw new HttpException(
'Authorization and X-FusionAuth-Application-Id headers are required',
HttpStatus.BAD_REQUEST,
);
}

const cacheKey = `user_${id}`;
const cachedData = await this.redis.get(cacheKey);
if (cachedData) {
return JSON.parse(cachedData);
}

const userData = await this.fetchUserDataFromService(id, authorization, appId);

await this.redis.set(cacheKey, JSON.stringify(userData));
return userData;
}

private async fetchUserDataFromService(id: string, authorization: string, appId: string) {
try {
const fusionAuthBaseUrl = this.configService.get('FUSIONAUTH_BASE_URL');
const url = new URL(`${fusionAuthBaseUrl}/api/user/${id}`);
const response = await fetch(
url,
{
method: "GET",
headers: {
Authorization: authorization,
'Content-Type': 'application/json',
'X-FusionAuth-Application-Id': appId,
},
},
);
return response.json();
} catch (error) {
throw new HttpException(
`Failed to fetch user data: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

private async searchUserData(
url: URL,
authorization: string,
appId: string,
) {
try {
const response = await fetch(
url,
{
headers: {
Authorization: authorization,
'Content-Type': 'application/json',
'X-FusionAuth-Application-Id': appId,
}
},
);
return response.json();
} catch (error) {
throw new HttpException(
`Failed to search user data: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

@All('*')
async defaultRoute(
@Req() request: Request,
Expand Down
11 changes: 4 additions & 7 deletions src/api/sms/gupshupWhatsapp/gupshupWhatsapp.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SMSData, SMSProvider, SMSResponse, SMSResponseStatus } from "../sms.int
import { InjectRedis } from '@nestjs-modules/ioredis';
import Redis from 'ioredis';
import { Injectable } from "@nestjs/common";

import axios from 'axios';

@Injectable()
export class GupshupWhatsappService {
Expand Down Expand Up @@ -41,8 +41,7 @@ export class GupshupWhatsappService {

let optinURL = process.env.GUPSHUP_WHATSAPP_BASEURL + '?' + optInParams.toString();

await fetch(optinURL, {
method: 'GET',
await axios.get(optinURL, {
headers: {
'Content-Type': 'application/json'
}
Expand All @@ -65,8 +64,7 @@ export class GupshupWhatsappService {

let sendOtpURL = process.env.GUPSHUP_WHATSAPP_BASEURL + '?' + sendOtpParams.toString();

const response = await fetch(sendOtpURL, {
method: 'GET',
const response = await axios.get(sendOtpURL, {
headers: {
'Content-Type': 'application/json'
}
Expand All @@ -76,7 +74,7 @@ export class GupshupWhatsappService {
// Store OTP in Redis with 30 minute expiry
await this.redis.set(`whatsapp_otp:${smsData.phone}`, otp.toString(), 'EX', 1800);

status.providerSuccessResponse = await response.text();
status.providerSuccessResponse = JSON.stringify(response.data);
status.status = SMSResponseStatus.success;
status.messageID = otp.toString();
}
Expand Down Expand Up @@ -107,7 +105,6 @@ export class GupshupWhatsappService {
try {
// Get stored OTP from Redis
const storedOTP = await this.redis.get(`whatsapp_otp:${phone}`);
console.log("storedOTP",storedOTP)

if (!storedOTP) {
status.error = {
Expand Down

0 comments on commit 6902c78

Please sign in to comment.