diff --git a/server/environment.yml b/server/environment.yml new file mode 100644 index 00000000..b91cf0ab --- /dev/null +++ b/server/environment.yml @@ -0,0 +1,6 @@ +MONGO_USERNAME: +MONGO_PASSWORD: +MONGO_HOSTNAME: +MONGO_PORT: +MONGO_DB: +SENDGRID_API_KEY: \ No newline at end of file diff --git a/server/package.json b/server/package.json index 1f91c76b..afbcadd3 100644 --- a/server/package.json +++ b/server/package.json @@ -10,7 +10,11 @@ "author": "", "license": "ISC", "dependencies": { - "serverless": "^1.51.0" + "@sendgrid/mail": "^6.4.0", + "aws-sdk": "^2.528.0", + "mongoose": "^5.6.13", + "serverless": "^1.51.0", + "serverless-http": "^2.3.0" }, "devDependencies": { "@babel/core": "^7.6.0", diff --git a/server/serverless.yaml b/server/serverless.yaml index fa17c5b4..0d2c3b6b 100644 --- a/server/serverless.yaml +++ b/server/serverless.yaml @@ -1,5 +1,3 @@ -org: manojvivek -app: responsively service: responsively-server custom: @@ -10,11 +8,28 @@ provider: name: aws runtime: nodejs10.x websocketsApiName: responsively-websocket + apiName: responsively-server websocketsApiRouteSelectionExpression: $request.body.action # custom routes are selected by the value of the action property in the body + environment: ${file(environment.yml)} functions: + activateTrial: + handler: src/http/lambda.activateTrial + timeout: 15 + events: + - http: + path: activate-trial + method: get + validateLicenseHttp: + handler: src/http/lambda.validateLicense + timeout: 15 + events: + - http: + path: validate-license + method: get websocket-connection-manager: handler: src/websocket/lambda.connectionHandler + timeout: 15 events: - websocket: route: $connect @@ -22,13 +37,21 @@ functions: route: $disconnect defaultHandler: handler: src/websocket/lambda.defaultHandler + timeout: 15 events: - websocket: $default #simple event definition without extra route property pingHandler: handler: src/websocket/lambda.pingHandler + timeout: 15 events: - websocket: route: ping # will trigger if $request.body.action === "ping" + validateLicense: + handler: src/websocket/lambda.validateLicense + timeout: 15 + events: + - websocket: + route: validate # will trigger if $request.body.action === "validate" plugins: - - serverless-webpack + - serverless-webpack \ No newline at end of file diff --git a/server/sls-webpack.config.js b/server/sls-webpack.config.js index b5bd6a5d..f7707c29 100644 --- a/server/sls-webpack.config.js +++ b/server/sls-webpack.config.js @@ -3,7 +3,7 @@ const webpack = require('webpack'); process.env.NODE_ENV = slsw.lib.options.stage || 'development'; const mode = - process.env.NODE_ENV === 'development' ? 'development' : 'production'; +process.env.NODE_ENV === 'development' ? 'development' : 'production'; module.exports = { entry: slsw.lib.entries, diff --git a/server/src/app/constants/constants.js b/server/src/app/constants/constants.js new file mode 100644 index 00000000..89168bf1 --- /dev/null +++ b/server/src/app/constants/constants.js @@ -0,0 +1,24 @@ +const TRIAL_PLAN='TRIAL' + +const SUBSCRIPTION_STATUS=Object.freeze({ + ACTIVE:{ + id: 'ACTIVE' + }, + EXPIRED:{ + id:'EXPIRED' + } +}) + +const SUBSCRIPTION_DURATION=Object.freeze({ + MONTH:{ + id: 'ACTIVE' + }, + YEAR:{ + id:'EXPIRED' + } +}) + +module.exports={ + TRIAL_PLAN: TRIAL_PLAN, + SUBSCRIPTION_STATUS: SUBSCRIPTION_STATUS +} \ No newline at end of file diff --git a/server/src/app/exception/invalid-email-error.exception.js b/server/src/app/exception/invalid-email-error.exception.js new file mode 100644 index 00000000..a962ddd7 --- /dev/null +++ b/server/src/app/exception/invalid-email-error.exception.js @@ -0,0 +1,8 @@ +class InvalidEmailError extends Error{ + constructor(message){ + super(message) + this.name=this.constructor.name + } +} + +module.exports=InvalidEmailError \ No newline at end of file diff --git a/server/src/app/exception/invalid-license-error.exception.js b/server/src/app/exception/invalid-license-error.exception.js new file mode 100644 index 00000000..4b2439ea --- /dev/null +++ b/server/src/app/exception/invalid-license-error.exception.js @@ -0,0 +1,8 @@ +class InvalidLicenseError extends Error{ + constructor(message){ + super(message) + this.name=this.constructor.name + } +} + +module.exports=InvalidLicenseError \ No newline at end of file diff --git a/server/src/app/exception/invalid-subscription.exception.js b/server/src/app/exception/invalid-subscription.exception.js new file mode 100644 index 00000000..8a4635ea --- /dev/null +++ b/server/src/app/exception/invalid-subscription.exception.js @@ -0,0 +1,8 @@ +class InvalidSubscriptionError extends Error{ + constructor(message){ + super(message) + this.name=this.constructor.name + } +} + +module.exports=InvalidSubscriptionError \ No newline at end of file diff --git a/server/src/app/exception/user-exists-error.exception.js b/server/src/app/exception/user-exists-error.exception.js new file mode 100644 index 00000000..a0cfebff --- /dev/null +++ b/server/src/app/exception/user-exists-error.exception.js @@ -0,0 +1,8 @@ +class UserExistsError extends Error{ + constructor(message){ + super(message) + this.name=this.constructor.name + } +} + +module.exports=UserExistsError \ No newline at end of file diff --git a/server/src/app/model/active-connections.model.js b/server/src/app/model/active-connections.model.js new file mode 100644 index 00000000..110b4d29 --- /dev/null +++ b/server/src/app/model/active-connections.model.js @@ -0,0 +1,19 @@ +const mongoose = require('mongoose') +let Schema=mongoose.Schema + +const connectionsSchema=new Schema({ + connection_id: {type: String}, + start_time: Date +},{_id: false}) + +const activeConnectionsSchema=new Schema({ + _id: {type: String}, + connections:[connectionsSchema], + c_ts: Date, + u_ts: Date +}) + +const ACTIVE_CONNECTIONS_MODEL_NAME='ActiveConnection' +const COLLECTION_NAME='active_connections' +const ActiveConnection=mongoose.model(ACTIVE_CONNECTIONS_MODEL_NAME,activeConnectionsSchema,COLLECTION_NAME) +module.exports=ActiveConnection \ No newline at end of file diff --git a/server/src/app/model/plan.model.js b/server/src/app/model/plan.model.js new file mode 100644 index 00000000..ceddafdf --- /dev/null +++ b/server/src/app/model/plan.model.js @@ -0,0 +1,16 @@ +const mongoose = require('mongoose') +let Schema=mongoose.Schema + +const planSchema=new Schema({ + name: {type: String}, + user_limit: {type: Number}, + duration:{type: String}, + c_ts: {type: Date}, + u_ts: {type: Date}, + price: {type: String} +}) + +const PLAN_MODEL_NAME='Plan' +const COLLECTION_NAME='plans' +const Plan=mongoose.model(PLAN_MODEL_NAME,planSchema,COLLECTION_NAME) +module.exports=Plan \ No newline at end of file diff --git a/server/src/app/model/subscription.model.js b/server/src/app/model/subscription.model.js new file mode 100644 index 00000000..cac2177e --- /dev/null +++ b/server/src/app/model/subscription.model.js @@ -0,0 +1,16 @@ +const mongoose = require('mongoose') +let Schema=mongoose.Schema + +const subscriptionSchema=new Schema({ + user_id: {type: String}, + plan_id: {type: String}, + start_date:Date, + status: {type: String}, + c_ts: Date, + u_ts: Date +}) + +const SUBSCRIPTION_MODEL_NAME='Subscription' +const COLLECTION_NAME='subscriptions' +const Subscription=mongoose.model(SUBSCRIPTION_MODEL_NAME,subscriptionSchema,COLLECTION_NAME) +module.exports=Subscription \ No newline at end of file diff --git a/server/src/app/model/user.model.js b/server/src/app/model/user.model.js new file mode 100644 index 00000000..fda06dd3 --- /dev/null +++ b/server/src/app/model/user.model.js @@ -0,0 +1,15 @@ +const mongoose = require('mongoose') +let Schema=mongoose.Schema + +const userSchema=new Schema({ + name: {type: String}, + email: {type: String}, + license_key:{type: String}, + c_ts: Date, + u_ts: Date +}) + +const USER_MODEL_NAME='User' +const COLLECTION_NAME='users' +const User=mongoose.model(USER_MODEL_NAME,userSchema,COLLECTION_NAME) +module.exports=User \ No newline at end of file diff --git a/server/src/app/service/active-connections.service.js b/server/src/app/service/active-connections.service.js new file mode 100644 index 00000000..94d74625 --- /dev/null +++ b/server/src/app/service/active-connections.service.js @@ -0,0 +1,73 @@ +const ActiveConnection=require('../model/active-connections.model') +const subscriptionService=require('../service/subscription.service') +const planService=require('../service/plan.service') +const InvalidSubscriptionError=require('../exception/invalid-subscription.exception') +const InvalidLicenseError=require('../exception/invalid-license-error.exception') +const AWS=require('aws-sdk') + +async function addNewConnection(licenseKey,connectionId){ + + let responseBody={} + try{ + let subscription=await subscriptionService.getSubscriptionByLicenseKey(licenseKey) + if(!subscription){ + throw new Error('no active subscriptions found') + } + const allowedUsers=await planService.getCurrentUserLimitForPlan(subscription.start_date,subscription.plan_id) + if(allowedUsers && allowedUsers>0){ + const connectionObj={ + connection_id: connectionId, + start_time: new Date() + } + const updateObj={ + $push:{connections:connectionObj}, + $set:{u_ts:new Date()}, + $setOnInsert:{c_ts: new Date()} + } + let existingConnection=await ActiveConnection.findOneAndUpdate({_id: licenseKey},updateObj,{upsert:true}) + await removeOldConnection(allowedUsers,existingConnection) + + }else{ + throw new InvalidSubscriptionError('0 user limit found for plan') + } + }catch(err){ + console.log(err) + throw err + } +} + +async function removeOldConnection(userLimit,existingConnection){ + if(existingConnection && existingConnection.connections){ + let connections=existingConnection.connections + if(connections.length>=userLimit){ + await ActiveConnection.updateOne({_id:existingConnection._id},{$pop:{connections: -1},$set:{u_ts:new Date()}}) + } + } +} + +async function closeConnection(connectionId){ + console.log('disconnecting:'+connectionId) + await ActiveConnection.updateOne({'connections.connection_id': connectionId},{$pull:{connections:{connection_id:connectionId}}}) + console.log('disconnecting:'+connectionId+' done') +} + +async function publish(event,connectionId,data){ + console.log('publishing data to client connection:'+connectionId+',data:'+JSON.stringify(data)) + const apigwManagementApi = new AWS.ApiGatewayManagementApi({ + endpoint: event.requestContext.domainName + '/' + event.requestContext.stage + }); + await apigwManagementApi.postToConnection({ + ConnectionId: connectionId, + Data: JSON.stringify(data) + }).promise() + console.log('publishing data to client connection:'+connectionId+',data:'+data+' ..done') +} + +module.exports={ + addNewConnection, + closeConnection, + publish +} +// addNewConnection("asd","aasd").then(res=>{ +// console.log('done') +// }) \ No newline at end of file diff --git a/server/src/app/service/email.service.js b/server/src/app/service/email.service.js new file mode 100644 index 00000000..80cc091e --- /dev/null +++ b/server/src/app/service/email.service.js @@ -0,0 +1,31 @@ +const sgMail = require('@sendgrid/mail'); +const emailUtils=require('../utils/email.utils') +sgMail.setApiKey(process.env.SENDGRID_API_KEY); + +const SYSTEM_MAIL='noreply@responsively.app' +async function sendLicenseKeyMail(email,licenseKey){ + if(process.env.SEND_MAIL==='false'){ + return + } + console.log('sending license key to email:'+email) + const msg = { + to: email, + from: SYSTEM_MAIL, + subject: 'Responsively - License Key', + html: 'Please find your license key - '+licenseKey+'', + }; + await sgMail.send(msg); +} + +function validateEmailExistence(email){ + + return emailUtils.validateEmail(email) + /** + * to do check email existence, mx lookup. figure out 10min email workarounds + */ +} + +module.exports={ + sendLicenseKeyMail, + validateEmailExistence +} \ No newline at end of file diff --git a/server/src/app/service/plan.service.js b/server/src/app/service/plan.service.js new file mode 100644 index 00000000..dbe842bc --- /dev/null +++ b/server/src/app/service/plan.service.js @@ -0,0 +1,51 @@ +const Plan=require('../model/plan.model') +const mongoose=require('mongoose') + +async function getPlan(planId){ + console.log('fetching from db - planId:'+planId) + const plan=await Plan.findOne({_id: mongoose.Types.ObjectId(planId)}).exec() + console.log('plan:'+plan) + return plan +} + +async function getPlanByName(planName){ + console.log('fetching from db - planName:'+planName) + const plan=await Plan.findOne({name: planName}).exec() + console.log('plan:'+plan) + return plan +} + +async function checkIfPlanStillValidForDate(startDate, planId){ + + let plan=await getPlan(planId) + return validator(startDate,plan) + return false +} + +function validator(startDate, plan){ + if(plan && plan.duration==='MONTH'){ + console.log('calculating validity of month plan:'+plan+',startTime:'+startDate) + let endDate=new Date(startDate) + endDate.setMonth(endDate.getMonth()+1) + if(endDate.getTime()>=new Date().getTime()){ + return true + } + } + return false +} + +async function getCurrentUserLimitForPlan(startDate,planId){ + let plan=await getPlan(planId) + let valid=validator(startDate,plan) + if(valid){ + return plan.user_limit + } + return 0 + +} +module.exports={ + getPlan, + getPlanByName, + checkIfPlanStillValidForDate, + getCurrentUserLimitForPlan +} \ No newline at end of file diff --git a/server/src/app/service/subscription.service.js b/server/src/app/service/subscription.service.js new file mode 100644 index 00000000..d562eba7 --- /dev/null +++ b/server/src/app/service/subscription.service.js @@ -0,0 +1,114 @@ +const User=require('../model/user.model') +const Subscription=require('../model/subscription.model') +const userService=require('../service/user.service') +const planService=require('../service/plan.service') +const constants=require('../constants/constants') +const emailService=require('../service/email.service') +const InvalidLicenseError=require('../exception/invalid-license-error.exception') +const UserExistsError=require('../exception/user-exists-error.exception') +const mongoose=require('mongoose') + +async function createUserAndActivateTrial(email){ + + try{ + let trialPlan=await planService.getPlanByName(constants.TRIAL_PLAN) + + if(await userService.checkIfUserExists(email)){ + throw new UserExistsError('User exists') + } + let user=await userService.createUser(email) + + let subscription=new Subscription({ + user_id: user._id, + plan_id: trialPlan._id, + start_date: new Date(), + status: constants.SUBSCRIPTION_STATUS.ACTIVE.id, + }) + await insertSubscription(subscription) + await emailService.sendLicenseKeyMail(email,user.license_key) + }catch(err){ + console.log(err) + throw err + } +} + +async function insertSubscription(subscription){ + + subscription.c_ts=new Date() + subscription.u_ts=new Date() + try{ + await subscription.save() + }catch(err){ + console.log('error saving subscription'+subscription); + throw err + } +} + +async function getSubscriptionByLicenseKey(licenseKey){ + try{ + if(!licenseKey){ + throw new InvalidLicenseError('Invalid License :'+licenseKey) + } + let user=await User.findOne({license_key: licenseKey}).exec() + if(!user){ + throw new InvalidLicenseError('Invalid License:'+licenseKey) + } + let subscription= await Subscription.findOne({user_id: user._id,status: constants.SUBSCRIPTION_STATUS.ACTIVE.id}).exec() + return subscription + }catch(err){ + console.log(err) + throw err + } +} + +async function validateLicenseKey(licenseKey){ + + try{ + let subscription= await getSubscriptionByLicenseKey(licenseKey) + let licenseValid=await planService.checkIfPlanStillValidForDate(subscription.start_date,subscription.plan_id) + if(licenseValid){ + console.log('license active!'); + return true + } + console.log('license expired!'); + return false + }catch(err){ + console.log(err) + throw err + } +} + +async function constructLicenseValidationResponse(licenseKey){ + let responseBody={} + try{ + if(!licenseKey){ + throw new InvalidLicenseError('licenseKey is empty') + } + responseBody.status=await validateLicenseKey(licenseKey) + if(responseBody.status){ + responseBody.statusCode=200 + responseBody.message='success' + }else{ + responseBody.statusCode=403 + responseBody.message='license expired' + } + }catch(err){ + console.log(err) + responseBody.status=false + if(err instanceof InvalidLicenseError){ + responseBody.statusCode=403 + responseBody.message='Invalid License' + }else{ + responseBody.statusCode=500 + responseBody.message='Internal Server Error' + } + } + return responseBody +} + +module.exports={ + createUserAndActivateTrial, + validateLicenseKey, + constructLicenseValidationResponse, + getSubscriptionByLicenseKey +} \ No newline at end of file diff --git a/server/src/app/service/user.service.js b/server/src/app/service/user.service.js new file mode 100644 index 00000000..37c1dbd3 --- /dev/null +++ b/server/src/app/service/user.service.js @@ -0,0 +1,65 @@ +const User=require('../model/user.model') +const Plan=require('../model/plan.model') +const planService=require('../service/plan.service') +const constants=require('../constants/constants') +const crypto=require('crypto') +const emailService=require('../service/email.service') +const InvalidEmailError=require('../exception/invalid-email-error.exception') +const UserExistsError=require('../exception/user-exists-error.exception') +const mongoose=require('mongoose') + +async function createUser(email){ + + if(!emailService.validateEmailExistence(email)){ + throw new InvalidEmailError('Invalid Email:'+email) + } + let newUser=new User({ + email: email, + license_key:getLicenseKey() + }) + + await insertUser(newUser) + return newUser +} + +async function insertUser(newUser){ + newUser.c_ts=new Date() + newUser.u_ts=new Date() + try{ + await newUser.save() + }catch(err){ + console.log(err) + if(err.name === 'MongoError' && err.code === 11000){ + throw new UserExistsError('user already exists with email:'+newUser.email) + } + throw err + } + console.log('userInserted') + return newUser +} + +async function getUserByEmail(email){ + + return await User.findOne({email: email}) +} + +async function checkIfUserExists(email){ + + let user=await getUserByEmail(email) + console.log(user) + if(user){ + return true + } + return false +} + +function getLicenseKey(email){ + const key=crypto.randomBytes(20).toString('hex'); + return key; +} + +module.exports={ + createUser, + getUserByEmail, + checkIfUserExists +} \ No newline at end of file diff --git a/server/src/app/utils/email.utils.js b/server/src/app/utils/email.utils.js new file mode 100644 index 00000000..b2d723d5 --- /dev/null +++ b/server/src/app/utils/email.utils.js @@ -0,0 +1,8 @@ +function validateEmail(email) { + var emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegex.test(String(email).toLowerCase()); +} + +module.exports={ + validateEmail +} \ No newline at end of file diff --git a/server/src/db/db.js b/server/src/db/db.js new file mode 100644 index 00000000..36357f6d --- /dev/null +++ b/server/src/db/db.js @@ -0,0 +1,12 @@ +const mongoose = require('mongoose'); +const MONGO_USERNAME = process.env.MONGO_USERNAME +const MONGO_PASSWORD = process.env.MONGO_PASSWORD +const MONGO_HOSTNAME = process.env.MONGO_HOSTNAME +const MONGO_PORT = process.env.MONGO_PORT +const MONGO_DB = process.env.MONGO_DB +const url = `mongodb+srv://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}/${MONGO_DB}` +console.log('connecting to db'); +mongoose.connect(url,{ useNewUrlParser: true }, function(error){ + if(error){console.log(error)} + else{console.log("connection successful")} +}) diff --git a/server/src/http/lambda.js b/server/src/http/lambda.js new file mode 100644 index 00000000..d2cb4e10 --- /dev/null +++ b/server/src/http/lambda.js @@ -0,0 +1,57 @@ +const db=require('../db/db') +const subscriptionService = require('../app/service/subscription.service') +const UserExistsError=require('../app/exception/user-exists-error.exception') +const InvalidLicenseError=require('../app/exception/invalid-license-error.exception') +const InvalidEmailError=require('../app/exception/invalid-email-error.exception') + +export async function activateTrial(event, context, callback) { + let responseBody={} + let statusCode=0 + context.callbackWaitsForEmptyEventLoop = false; + try{ + const {email}=event.queryStringParameters + if(!email){ + throw new InvalidEmailError('email is empty') + } + await subscriptionService.createUserAndActivateTrial(email) + responseBody.status=true + responseBody.statusCode=200; + responseBody.message='success' + statusCode=200 + }catch(err){ + console.log(err) + responseBody.status=false + if(err instanceof UserExistsError){ + responseBody.statusCode=409 + responseBody.message='user already activated' + }else if(err instanceof InvalidEmailError){ + responseBody.statusCode=400 + responseBody.message='invalid email' + }else{ + responseBody.statusCode=500 + responseBody.message='Internal Server Error' + } + } + let response= { + statusCode: 200, + body: JSON.stringify(responseBody) + } + callback(null, response) +} + +export async function validateLicense(event, context, callback) { + let responseBody={} + let statusCode=0 + context.callbackWaitsForEmptyEventLoop = false; + try{ + const {licenseKey}=event.queryStringParameters + responseBody=await subscriptionService.constructLicenseValidationResponse(licenseKey) + }catch(err){ + console.log(err) + } + let response= { + statusCode: 200, + body: JSON.stringify(responseBody) + } + callback(null, response) + } \ No newline at end of file diff --git a/server/src/websocket/lambda.js b/server/src/websocket/lambda.js index 8299fd94..cfb646b1 100644 --- a/server/src/websocket/lambda.js +++ b/server/src/websocket/lambda.js @@ -1,14 +1,61 @@ +var db=require('../db/db') +const userService = require('../app/service/user.service') +const activeConnectionService = require('../app/service/active-connections.service') +const subscriptionService = require('../app/service/subscription.service') +const InvalidLicenseError=require('../app/exception/invalid-license-error.exception') +const InvalidSubscriptionError=require('../app/exception/invalid-subscription.exception') + export async function connectionHandler(event, context, callback) { + + let responseBody={} + const connectionId=event.requestContext.connectionId + try{ + console.log(event) + if(event.requestContext.eventType==='CONNECT'){ + const {licenseKey}=event.queryStringParameters + await activeConnectionService.addNewConnection(licenseKey, connectionId) + responseBody.status=true + responseBody.statusCode=200 + responseBody.message='connection established' + }else if(event.requestContext.eventType==='DISCONNECT'){ + await activeConnectionService.closeConnection(connectionId) + } + }catch(err){ + console.log(err) + responseBody.status=false + if(err instanceof InvalidSubscriptionError){ + responseBody.statusCode=403 + responseBody.message='invalid subscription' + }else if(err instanceof InvalidLicenseError){ + responseBody.statusCode=403 + responseBody.message='invalid license' + }else{ + responseBody.statusCode=500 + responseBody.message='server error' + } + } return { statusCode: 200, - body: 'Message recieved', + body: JSON.stringify(responseBody), }; } export async function defaultHandler(event, context, callback) { + try{ + const body=JSON.parse(event.body) + const connectionId=event.requestContext.connectionId + + if(!body.data || !body.data.licenseKey){ + throw new InvalidLicenseError('license Key is empty') + } + const licenseKey=body.data.licenseKey + activeConnectionService.closeConnection(licenseKey, connectionId) + }catch(err){ + console.log(err) + } return { statusCode: 200, - body: 'Message recieved', + body: 'Connection closed', }; } @@ -18,3 +65,30 @@ export async function pingHandler(event, context, callback) { body: 'Message recieved', }; } + +export async function validateLicense(event, context, callback) { + let responseBody={} + let statusCode=0 + context.callbackWaitsForEmptyEventLoop = false; + const connectionId=event.requestContext.connectionId + console.log(event) + try{ + const body=JSON.parse(event.body) + if(!body['data'] || !body['data']['licenseKey']){ + throw new InvalidLicenseError('licenseKey is empty') + } + const licenseKey=body['data']['licenseKey'] + responseBody=await subscriptionService.constructLicenseValidationResponse(licenseKey) + }catch(err){ + console.log(err) + responseBody.status=false + responseBody.statusCode=500 + responseBody.message='internal server error' + } + await activeConnectionService.publish(event,connectionId,responseBody) + let response= { + statusCode: 200, + body: JSON.stringify(responseBody) + } + callback(null, response) +} \ No newline at end of file