Skip to content

Commit

Permalink
Merge pull request #45 from tgoyal63/development
Browse files Browse the repository at this point in the history
Fix bugs and update dependencies
  • Loading branch information
Teoriya committed Feb 4, 2024
2 parents a4a9b7a + 2f0e5a0 commit 814bcf0
Show file tree
Hide file tree
Showing 14 changed files with 318 additions and 174 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/jsonwebtoken": "^9.0.4",
"@types/mongoose": "^5.11.97",
"@types/node": "^20.8.7",
"@types/node-cron": "^3.0.11",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"eslint": "^8.56.0",
Expand Down Expand Up @@ -43,6 +44,7 @@
"googleapis": "^128.0.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^7.6.3",
"node-cron": "^3.0.3",
"zod": "^3.22.4",
"zod-express-middleware": "^1.4.0"
}
Expand Down
6 changes: 5 additions & 1 deletion src/controllers/service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ export const getServicesController = ApiHandler(
const services = await getServicesOfDiscordGuilds(guildIds);
const servicesWithGuilds = services.map((service) => {
const guild = guilds.find((guild) => guild.id === service.guildId);
if (!guild) throw new Error("Guild not found");
return {
...service,
guild:{...guild,icon:`https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp`},
guild: {
...guild,
icon: `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp`,
},
};
});
return res.send({
Expand Down
40 changes: 22 additions & 18 deletions src/customSolutions/customIntegrations/tagMango/apiWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import axios from "axios";
import { createCredential, getCredential } from "./models/tmCredential.model";
import {
createCredential,
getCredential,
} from "./services/tmCredential.service";

export const getOtp = async (
data: { phone: number; userAgent: string },
Expand Down Expand Up @@ -32,6 +35,7 @@ export const verifyOtp = async (
},
customerId: string,
domain: string,
serviceId: string,
) => {
const config = {
method: "post",
Expand All @@ -43,7 +47,7 @@ export const verifyOtp = async (
},
data: {
...data,
logoutAll: true,
// logoutAll: true,
},
};
const response = await axios(config);
Expand All @@ -57,24 +61,24 @@ export const verifyOtp = async (
refreshToken: result.refreshToken,
phone: data.phone,
domain,
serviceId,
});
if (!credential.acknowledged) {
throw new Error("Error in creating credential");
}
return true;
};

export const getAccessToken = async (customerId: string) => {
const credential = await getCredential(customerId);
export const getAccessToken = async (serviceId: string) => {
const credential = await getCredential(serviceId);
if (!credential) throw new Error("Credential not found");

// If token is valid for more than 80 minutes, return it
// If token updated in less than 80 minutes, return it
// if (credential.updatedAt.getTime() + 80 * 60 * 1000 > Date.now())
// return {
// accessToken: credential.accessToken,
// domain: credential.domain,
// };

const { refreshToken } = credential;
const config = {
method: "post",
Expand All @@ -94,11 +98,11 @@ export const getAccessToken = async (customerId: string) => {
throw new Error("Error in getting access token");

const data = await createCredential({
customerId,
accessToken: result.accessToken,
refreshToken: result.refreshToken,
phone: credential.phone,
domain: credential.domain,
serviceId,
});
if (!data.acknowledged)
throw new Error("Error in updating credential with new token");
Expand All @@ -112,9 +116,9 @@ export const getAccessToken = async (customerId: string) => {
export const getSubscribers = async ({
page = 1,
type = "all",
pageSize = 25,
pageSize,
mangoes,
customerId,
serviceId,
term,
startDate,
endDate,
Expand All @@ -123,12 +127,12 @@ export const getSubscribers = async ({
type?: "all" | "active" | "inactive" | "revoked";
pageSize?: number;
mangoes: string;
customerId: string;
serviceId: string;
term?: string | number;
startDate?: string;
endDate?: string;
}) => {
const credential = await getAccessToken(customerId);
const credential = await getAccessToken(serviceId);
const config = {
method: "get",
maxBodyLength: Infinity,
Expand All @@ -137,7 +141,7 @@ export const getSubscribers = async ({
"x-whitelabel-host": credential.domain,
"Content-Type": "application/json",
authorization: `Bearer ${credential.accessToken}`,
"x-whitelabel-creator": await getHostDetails(customerId),
"x-whitelabel-creator": await getHostDetails(serviceId),
},
params: {
page,
Expand All @@ -147,7 +151,7 @@ export const getSubscribers = async ({
term,
startDate,
endDate,
spreadSubscribers: true,
// spreadSubscribers: true,
},
};
const response = await axios(config);
Expand All @@ -159,15 +163,15 @@ export const getSubscribers = async ({
throw result;
};

export const getAllActiveMangoes = async (customerId: string) => {
const credential = await getAccessToken(customerId);
export const getAllActiveMangoes = async (serviceId: string) => {
const credential = await getAccessToken(serviceId);
const config = {
method: "get",
maxBodyLength: Infinity,
url: "https://api-prod-new.tagmango.com/get-all-active-mangoes",
headers: {
"x-whitelabel-host": credential.domain,
"x-whitelabel-creator": await getHostDetails(customerId),
"x-whitelabel-creator": await getHostDetails(serviceId),
authorization: `Bearer ${credential.accessToken}`,
},
};
Expand All @@ -180,8 +184,8 @@ export const getAllActiveMangoes = async (customerId: string) => {
throw result;
};

export const getHostDetails = async (customerId: string) => {
const credential = await getAccessToken(customerId);
export const getHostDetails = async (serviceId: string) => {
const credential = await getAccessToken(serviceId);
const config = {
method: "get",
maxBodyLength: Infinity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export type TmSubscriberDocument = mongoose.Document & {
country: string;
linkedDiscord: boolean;
discordLinkTimestamp: Date;
updatedAt: Date;
createdAt: Date;
};

const TmSubscriberSchema = new mongoose.Schema(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import mongoose from "mongoose";
import { CustomerDocument } from "../../../../models/mongoDB/customer.model";
import { CustomerDocument } from "@/models/mongoDB/customer.model";
import { ServiceDocument } from "@/models/mongoDB/service.model";

export type TmCredentialDocument = mongoose.Document & {
customer: mongoose.PopulatedDoc<CustomerDocument & mongoose.Document>;
accessToken: string; // 1.5 hours
refreshToken: string; // 1 month
phone: number;
domain: string;
service: mongoose.PopulatedDoc<ServiceDocument & mongoose.Document>;
createdAt: Date;
updatedAt: Date;
};
Expand All @@ -17,12 +19,16 @@ const TmCredentialSchema = new mongoose.Schema(
type: mongoose.Schema.Types.ObjectId,
ref: "customer",
required: true,
unique: true,
},
accessToken: { type: String, required: true },
refreshToken: { type: String, required: true },
phone: { type: Number, required: true },
domain: { type: String, required: true },
service: {
type: mongoose.Schema.Types.ObjectId,
ref: "service",
required: true,
},
},
{ timestamps: true },
);
Expand All @@ -31,31 +37,3 @@ const model = mongoose.model<TmCredentialDocument>(
TmCredentialSchema,
);
export default model;

export const createCredential = async ({
customerId,
accessToken,
refreshToken,
phone,
domain,
}: {
customerId: string;
accessToken: string;
refreshToken: string;
phone: number;
domain: string;
}) => {
const credential = await model
.updateOne(
{ customer: customerId },
{ accessToken, refreshToken, phone, domain },
{ upsert: true },
)
.exec();
return credential;
};

export const getCredential = async (customerId: string) => {
const credential = await model.findOne({ customer: customerId }).exec();
return credential;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export type TmMapperDocument = mongoose.Document & {
TmCredentialDocument & mongoose.Document
>;
customer: mongoose.PopulatedDoc<CustomerDocument & mongoose.Document>;
xWhiteLabelHost: string;
metadata: object;
customIntegrationId: string;
};
Expand Down Expand Up @@ -39,52 +38,3 @@ const TmMapperSchema = new mongoose.Schema(
);
const model = mongoose.model<TmMapperDocument>("tmMapper", TmMapperSchema);
export default model;

export const createMapper = async ({
mango,
serviceId,
tmCredentialId,
customerId,
metadata,
customIntegrationId,
}: {
mango: string;
serviceId: string;
tmCredentialId: string;
customerId: string;
metadata: object;
customIntegrationId: string;
}) => {
const mapper = await model.create({
mango,
service: serviceId,
tmCredential: tmCredentialId,
customer: customerId,
metadata,
customIntegrationId,
});
return mapper;
};

export const getMapper = async (
{
mango,
serviceId,
customerId,
}: {
mango?: string;
serviceId?: string;
customerId?: string;
},
populated = true,
) => {
const mapper = await model
.findOne({
mango,
service: serviceId,
customer: customerId,
})
.populate(populated ? ["service", "tmCredential", "customer"] : [])
.exec();
return mapper;
};
30 changes: 20 additions & 10 deletions src/customSolutions/customIntegrations/tagMango/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import serviceModel from "@/models/mongoDB/service.model";
import { Router } from "express";
import { getAllActiveMangoes, getOtp, verifyOtp } from "../apiWrapper";
import { getCredential } from "../models/tmCredential.model";
import { createMapper } from "../models/tmMapper.model";
import { getCredential } from "../services/tmCredential.service";
import { createMapper } from "../services/tmMapper.service";
const router = Router();

// Get OTP
Expand Down Expand Up @@ -37,13 +37,18 @@ router.post("/getOtp", async (req, res) => {
// Verify OTP
router.post("/verifyOtp", async (req, res) => {
try {
const { phone, otp, domain } = req.body;
const { phone, otp, domain, serviceId } = req.body;
const data = {
phone,
otp,
userAgent: req.headers["user-agent"] || "",
};
const verified = await verifyOtp(data, req.customer.id, domain);
const verified = await verifyOtp(
data,
req.customer.id,
domain,
serviceId,
);
if (verified) {
res.status(200).send({
message: "OTP verified successfully",
Expand All @@ -64,9 +69,12 @@ router.post("/verifyOtp", async (req, res) => {

router.get("/mangoes", async (req, res) => {
try {
const credential = await getCredential(req.customer.id);
if (!req.query.serviceId) throw new Error("ServiceId not found");
const credential = await getCredential(req.query.serviceId as string);
if (!credential) throw new Error("Credential not found");
const mangoes = await getAllActiveMangoes(req.customer.id);
const mangoes = await getAllActiveMangoes(
req.query.serviceId as string,
);
if (!mangoes) throw new Error("No mangoes found");

const data = mangoes.map((mango: any) => {
Expand Down Expand Up @@ -99,22 +107,24 @@ router.post("/addCustomSolution", async (req, res) => {
const service = await serviceModel.findById(serviceId).exec();
if (!service) throw new Error("Service not found");

const mangoes = await getAllActiveMangoes(req.customer.id);
const mangoes = await getAllActiveMangoes(serviceId);
if (!mangoes.find((m: any) => m._id === mango))
throw new Error("Mango not found in TagMango");

const mapper = await createMapper({
mango,
serviceId,
customerId: req.customer.id,
tmCredentialId: (await getCredential(req.customer.id))?._id,
tmCredentialId: (await getCredential(serviceId))?._id,
metadata: {},
customIntegrationId: service.customIntegrationId,
});
res.status(200).send({
if (!mapper) throw new Error("Error in creating mapper");

return res.status(200).send({
message: "Custom TagMango Service created successfully",
});
} catch (error) {
} catch (error: any) {
if (error.name === "MongoServerError") {
if (error.code === 11000) {
return res.status(400).send({
Expand Down

0 comments on commit 814bcf0

Please sign in to comment.