Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ let fdkExtension = setupFdk({
}
});

app.use(fdkExtension.fdkHandler);

app.use('/_healthz', (req, res, next) => {
res.json({
"ok": "ok"
});
});

app.use('/', fdkExtension.fdkHandler);
fdkExtension.apiRoutes.get("/test/routes", async (req, res, next) => {
try {
let data = await req.platformClient.lead.getTickets();
Expand Down
15 changes: 11 additions & 4 deletions express/api_routes.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
'use strict';
const { extension } = require('./extension');
const express = require('express');
const { sessionMiddleware } = require('./middleware/session_middleware');
const { ApplicationConfig, ApplicationClient } = require("@gofynd/fdk-client-javascript");


function setupProxyRoutes() {
function setupProxyRoutes(extension) {
const apiRoutes = express.Router({ mergeParams: true });
const applicationProxyRoutes = express.Router({ mergeParams: true });

applicationProxyRoutes.use(async (req, res, next) => {
applicationProxyRoutes.use(["/", "/:cluster_id"],async (req, res, next) => {
try {
const clusterId = req.params.cluster_id;
if (clusterId) {
extension = ExtensionFactory.getExtension(clusterId)
}
if(req.headers["x-user-data"]) {
req.user = JSON.parse(req.headers["x-user-data"]);
req.user.user_id = req.user._id;
Expand All @@ -30,8 +33,12 @@ function setupProxyRoutes() {
}
});

apiRoutes.use(sessionMiddleware(true), async (req, res, next) => {
apiRoutes.use(["/", "/:cluster_id"], sessionMiddleware(extension, true), async (req, res, next) => {
try {
const clusterId = req.params.cluster_id;
if (clusterId) {
extension = ExtensionFactory.getExtension(clusterId)
}
const client = await extension.getPlatformClient(req.fdkSession.company_id, req.fdkSession);
req.platformClient = client;
req.extension = extension;
Expand Down
9 changes: 8 additions & 1 deletion express/error_code.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class FdkWebhookHandlerNotFound extends Error {
}
}

class FdkInvalidCluster extends Error {
constructor(message) {
super(message);
}
}


module.exports = {
FdkInvalidExtensionConfig,
Expand All @@ -64,5 +70,6 @@ module.exports = {
FdkInvalidWebhookConfig,
FdkWebhookRegistrationError,
FdkWebhookProcessError,
FdkWebhookHandlerNotFound
FdkWebhookHandlerNotFound,
FdkInvalidCluster
};
19 changes: 12 additions & 7 deletions express/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { WebhookRegistry } = require('./webhook');
const logger = require('./logger');
const { fdkAxios } = require('@gofynd/fdk-client-javascript/sdk/common/AxiosHelper');
const { version } = require('./../package.json');
const SessionStorage = require("./session/session_storage");

class Extension {
constructor() {
Expand All @@ -18,7 +19,9 @@ class Extension {
this.access_mode = null;
this.cluster = "https://api.fynd.com";
this.webhookRegistry = null;
this.sessionStore = null;
this._isInitialized = false;
this._clusterId = null;
}

async initialize(data) {
Expand All @@ -27,6 +30,7 @@ class Extension {

this.storage = data.storage;

this.sessionStorage = new SessionStorage(this.storage);
if (!data.api_key) {
throw new FdkInvalidExtensionConfig("Invalid api_key");
}
Expand All @@ -49,6 +53,7 @@ class Extension {
throw new FdkInvalidExtensionConfig("Invalid cluster value. Invalid value: " + data.cluster);
}
this.cluster = data.cluster;
this._clusterId = this.cluster.replace("https://", "");
}
this.webhookRegistry = new WebhookRegistry();

Expand Down Expand Up @@ -80,6 +85,10 @@ class Extension {
return this._isInitialized;
}

get clusterId(){
return this._clusterId;
}

verifyScopes(scopes, extensionData) {
const missingScopes = scopes.filter(val => extensionData.scope.indexOf(val) === -1);
if (!scopes || scopes.length <= 0 || missingScopes.length) {
Expand Down Expand Up @@ -115,7 +124,6 @@ class Extension {
if (!this._isInitialized){
throw new FdkInvalidExtensionConfig('Extension not initialized due to invalid data')
}
const SessionStorage = require('./session/session_storage');

let platformConfig = this.getPlatformConfig(companyId);
platformConfig.oauthClient.setToken(session);
Expand All @@ -128,7 +136,7 @@ class Extension {
const renewTokenRes = await platformConfig.oauthClient.renewAccessToken(session.access_mode === 'offline');
renewTokenRes.access_token_validity = platformConfig.oauthClient.token_expires_at;
session.updateToken(renewTokenRes);
await SessionStorage.saveSession(session);
await this.sessionStorage.saveSession(session);
logger.debug(`Access token renewed for company ${companyId} with response ${logger.safeStringify(renewTokenRes)}`);
}
}
Expand Down Expand Up @@ -159,14 +167,11 @@ class Extension {
logger.debug(`Extension details received: ${logger.safeStringify(extensionData)}`);
return extensionData;
} catch (err) {
throw new FdkInvalidExtensionConfig("Invalid api_key or api_secret. Reason:" + err.message);
throw new FdkInvalidExtensionConfig("Invalid api_key or api_secret. Reason: " + err.message);
}
}
}


const extension = new Extension();

module.exports = {
extension
Extension
};
39 changes: 39 additions & 0 deletions express/extension_factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const { FdkInvalidCluster } = require("./error_code");
const { Extension } = require("./extension")

class ExtensionFactory {
static _extensionMap = {};
static _defaultExt = null;

static getExtension(clusterId) {
const clusterExt = ExtensionFactory._extensionMap[clusterId]
if (clusterId !== null && !clusterExt) {
throw FdkInvalidCluster(`Extension instance not found for clusterId ${clusterId}`);
}
return clusterExt;
}

static defaultExtInstance() {
return ExtensionFactory._defaultExt;
}

static async initializeExtension(clusterData, clusterId = null) {
const promises = [];
for (let extConfig of clusterData) {
const extInstance = new Extension();
if(clusterId != null && clusterId !== extConfig.cluster_id) {
continue;
}
if (!ExtensionFactory._defaultExt) {
ExtensionFactory._defaultExt = extInstance;
}
ExtensionFactory._extensionMap[extConfig.cluster_id] = extInstance;
promises.push(extInstance.initialize(extConfig))
}
return Promise.all(promises);
}
}

module.exports = {
ExtensionFactory
};
53 changes: 37 additions & 16 deletions express/index.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,77 @@
'use strict';

const { extension } = require('./extension');
const {ExtensionFactory} = require('./extension_factory');
const setupRoutes = require("./routes");
const { setupProxyRoutes } = require("./api_routes");
const Session = require("./session/session");
const SessionStorage = require("./session/session_storage");
const { ApplicationConfig, ApplicationClient } = require("@gofynd/fdk-client-javascript");
const logger = require('./logger');

function setupFdk(data, syncInitialization) {
const multiClusterMode = data.cluster_config !== undefined;
const clusterId = data.cluster.replace("https://", "").replace("http://", "");
if (data.debug) {
logger.transports[0].level = 'debug';
}
const promiseInit = extension.initialize(data)
.catch(err=>{
logger.error(err);
throw err;
});

const promiseInit = ExtensionFactory.initializeExtension(multiClusterMode? data.cluster_config: [data]).catch(err=>{
logger.error(err);
throw err;
});

const extension = !multiClusterMode? ExtensionFactory.defaultExtInstance(): ExtensionFactory.getExtension(clusterId);

let router = setupRoutes(extension);
let { apiRoutes, applicationProxyRoutes } = setupProxyRoutes();
let { apiRoutes, applicationProxyRoutes } = setupProxyRoutes(extension);

async function getPlatformClient(companyId) {
async function getPlatformClient(companyId, clusterId = null) {
let clusterExt = extension;
if (clusterId) {
clusterExt = ExtensionFactory.getExtension(clusterId)
}
let client = null;
if (!extension.isOnlineAccessMode()) {
if (!clusterExt.isOnlineAccessMode()) {
let sid = Session.generateSessionId(false, {
cluster: extension.cluster,
cluster: clusterExt.cluster,
companyId: companyId
});
let session = await SessionStorage.getSession(sid);
client = await extension.getPlatformClient(companyId, session);
let session = await clusterExt.sessionStorage.getSession(sid);
client = await clusterExt.getPlatformClient(companyId, session);
}
return client;
}

async function getApplicationClient(applicationId, applicationToken) {
async function getApplicationClient(applicationId, applicationToken, clusterId = null) {
let clusterExt = extension;
if (clusterId) {
clusterExt = ExtensionFactory.getExtension(clusterId)
}
let applicationConfig = new ApplicationConfig({
applicationID: applicationId,
applicationToken: applicationToken,
domain: extension.cluster
domain: clusterExt.cluster
});
let applicationClient = new ApplicationClient(applicationConfig);
return applicationClient;
}

function getWebhookRegistry(clusterId) {
let clusterExt = extension;
if (clusterId) {
clusterExt = ExtensionFactory.getExtension(clusterId)
}
return clusterExt.webhookRegistry;
}

const configInstance = {
fdkHandler: router,
extension: extension,
apiRoutes: apiRoutes,
webhookRegistry: extension.webhookRegistry,
applicationProxyRoutes: applicationProxyRoutes,
getPlatformClient: getPlatformClient,
getApplicationClient: getApplicationClient
getApplicationClient: getApplicationClient,
getWebhookRegistry: getWebhookRegistry
};

return syncInitialization? promiseInit.then(()=>configInstance).catch(()=>configInstance): configInstance;
Expand Down
10 changes: 7 additions & 3 deletions express/middleware/session_middleware.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
'use strict';
const { ExtensionFactory } = require('../extension_factory');
const { SESSION_COOKIE_NAME } = require('./../constants');
const SessionStorage = require("../session/session_storage");

function sessionMiddleware(strict) {
function sessionMiddleware(extension, strict) {
return async (req, res, next) => {
try {
const clusterId = req.params.cluster_id;
if (clusterId) {
extension = ExtensionFactory.getExtension(clusterId)
}
const companyId = req.headers['x-company-id'] || req.query['company_id'];
const compCookieName = `${SESSION_COOKIE_NAME}_${companyId}`
let sessionId = req.signedCookies[compCookieName];
req.fdkSession = await SessionStorage.getSession(sessionId);
req.fdkSession = await extension.sessionStorage.getSession(sessionId);

if(strict && !req.fdkSession) {
return res.status(401).json({ "message": "unauthorized" });
Expand Down
Loading