Code cleanup

This commit is contained in:
Manoj Vivek 2020-01-28 14:00:36 +05:30
parent ae46730ddb
commit 23c7dc6b97
37 changed files with 0 additions and 8160 deletions

View file

@ -5,9 +5,6 @@
},
{
"path": "website"
},
{
"path": "server"
}
],
"settings": {

4
server/.gitignore vendored
View file

@ -1,4 +0,0 @@
.serverless
setCreds.sh
node_modules
.DS_Store

View file

@ -1,13 +0,0 @@
{
"overrides": [
{
"files": [".prettierrc", ".babelrc", ".eslintrc", ".stylelintrc"],
"options": {
"parser": "json"
}
}
],
"singleQuote": true,
"bracketSpacing": false,
"trailingComma": "es5"
}

View file

@ -1,36 +0,0 @@
{
"editor.formatOnSave": true,
"files.associations": {
".babelrc": "jsonc",
".eslintrc": "jsonc",
".prettierrc": "jsonc",
".stylelintrc": "json",
".dockerignore": "ignore",
".eslintignore": "ignore",
".flowconfig": "ignore"
},
"javascript.validate.enable": false,
"javascript.format.enable": false,
"typescript.validate.enable": false,
"typescript.format.enable": false,
"flow.useNPMPackagedFlow": true,
"search.exclude": {
".git": true,
".eslintcache": true,
"app/dist": true,
"app/main.prod.js": true,
"app/main.prod.js.map": true,
"bower_components": true,
"dll": true,
"flow-typed": true,
"release": true,
"node_modules": true,
"npm-debug.log.*": true,
"test/**/__snapshots__": true,
"yarn.lock": true
}
}

View file

@ -1,49 +0,0 @@
# Responsively Server
## Dev Deployment
To deploy the app, edit the AWS credentials in the `setCreds.sh` file and run the following commands:
```
source ./setCreds.sh
yarn run deploy
```
## Rest APIs
### Activate trial
Description: To activate a trial user
Request: GET
Endpoint: `/activate-trial`
QueryParams:
```
{
email: <email-id>
}
```
Response:
```
{
status: <true|false>,
errorType: <error-code>
}
```
Sample: `/activate-trial?email=suresh@gmail.com`
### Buy License
Will have to figure out how to send the request after making a payment.
## Websocket Messages
### Validate License
Message body:
```
{
action: "VALIDATE",
body: {
licenseKey: "abcdefghijklmopqr",
}
}
```
Reply body:
```
{
valid: <true|false>
}
```

View file

@ -1,11 +0,0 @@
MONGO_USERNAME: responsively-test
MONGO_PASSWORD: abMPVW652j2ImC99
MONGO_HOSTNAME: responsively-2oqf0.mongodb.net
MONGO_PORT: 27017
MONGO_DB: app-dev
SENDGRID_API_KEY: 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
SEND_MAIL: true
RAZOR_PAY_API_KEY: rzp_test_DVeigAo0o0my9U
RAZOR_API_SECRET_KEY: SGNOlY6m4q7u10ZSs9bJSeND
RAZOR_PAY_WEBHOOK_SECRET: ye9NgW6f8cth29N3MxVNcekJw97AeD
WEBSITE_URL: https://dev.responsively.app

View file

@ -1,11 +0,0 @@
MONGO_USERNAME: responsively-test
MONGO_PASSWORD: abMPVW652j2ImC99
MONGO_HOSTNAME: responsively-2oqf0.mongodb.net
MONGO_PORT: 27017
MONGO_DB: app-prod
SENDGRID_API_KEY: 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
SEND_MAIL: true
RAZOR_PAY_API_KEY: rzp_live_MfwqMz9wLy7gQp
RAZOR_API_SECRET_KEY: LdMDhLcJsr7cCcC1USezZ3hj
RAZOR_PAY_WEBHOOK_SECRET: fk5rVJejW774NgMcm7FRsNdc6yUZqY
WEBSITE_URL: https://responsively.app

View file

@ -1,11 +0,0 @@
MONGO_USERNAME:
MONGO_PASSWORD:
MONGO_HOSTNAME:
MONGO_PORT:
MONGO_DB:
SENDGRID_API_KEY:
SEND_MAIL:
RAZOR_PAY_API_KEY:
RAZOR_API_SECRET_KEY:
RAZOR_PAY_WEBHOOK_SECRET:
WEBSITE_URL:

View file

@ -1,29 +0,0 @@
{
"name": "responsively-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"deploy": "sls deploy --stage dev",
"deploy:prod": "sls deploy --stage prod",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@sendgrid/mail": "^6.4.0",
"aws-sdk": "^2.528.0",
"axios": "^0.19.0",
"mongoose": "^5.6.13",
"razorpay": "^2.0.5",
"serverless": "^1.51.0",
"serverless-http": "^2.3.0"
},
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"babel-loader": "^8.0.6",
"serverless-webpack": "^5.3.1",
"webpack": "^4.39.3"
}
}

View file

@ -1,74 +0,0 @@
service: responsively-server
custom:
webpack:
webpackConfig: ./sls-webpack.config.js
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-${opt:stage}.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
createSubscription:
handler: src/http/lambda.createSubscription
timeout: 15
events:
- http:
path: create-subscription
method: post
cors:
origins:
- "*"
webhookHandler:
handler: src/http/lambda.webhookHandler
timeout: 15
events:
- http:
path: razor-pay-webhooks
method: post
websocket-connection-manager:
handler: src/websocket/lambda.connectionHandler
timeout: 15
events:
- websocket:
route: $connect
- websocket:
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

View file

@ -1,38 +0,0 @@
const slsw = require('serverless-webpack');
const webpack = require('webpack');
process.env.NODE_ENV = slsw.lib.options.stage || 'development';
const mode =
process.env.NODE_ENV === 'development' ? 'development' : 'production';
module.exports = {
entry: slsw.lib.entries,
mode: mode,
target: 'node',
module: {
rules: [
{
test: /\.js$/,
exclude: [/node_modules/, /__test__/, /assets/, /coverage/],
loader: 'babel-loader',
query: {
presets: [
[
'@babel/preset-env',
{
targets: {node: '10.16'}, // Node version on AWS Lambda
modules: false,
loose: true,
},
],
],
},
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
],
};

View file

@ -1,24 +0,0 @@
const TRIAL_PLAN_ID='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_ID: TRIAL_PLAN_ID,
SUBSCRIPTION_STATUS: SUBSCRIPTION_STATUS
}

View file

@ -1,3 +0,0 @@
export const RAZOR_PAY_HOST='api.razorpay.com'
export const SUBSCRIPTION_API='/v1/subscriptions'
export const SUBSCRIPTION_DURATION_MONTHS=12

View file

@ -1,8 +0,0 @@
class InvalidEmailError extends Error{
constructor(message){
super(message)
this.name=this.constructor.name
}
}
module.exports=InvalidEmailError

View file

@ -1,8 +0,0 @@
class InvalidLicenseError extends Error{
constructor(message){
super(message)
this.name=this.constructor.name
}
}
module.exports=InvalidLicenseError

View file

@ -1,8 +0,0 @@
class InvalidSubscriptionError extends Error{
constructor(message){
super(message)
this.name=this.constructor.name
}
}
module.exports=InvalidSubscriptionError

View file

@ -1,8 +0,0 @@
class PlanNotFoundError extends Error{
constructor(message){
super(message)
this.name=this.constructor.name
}
}
module.exports=PlanNotFoundError

View file

@ -1,8 +0,0 @@
class UserExistsError extends Error{
constructor(message){
super(message)
this.name=this.constructor.name
}
}
module.exports=UserExistsError

View file

@ -1,19 +0,0 @@
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

View file

@ -1,16 +0,0 @@
const mongoose = require('mongoose')
let Schema=mongoose.Schema
const planSchema=new Schema({
_id: {type: String},
name: {type: String},
user_limit: {type: Number},
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

View file

@ -1,19 +0,0 @@
const mongoose = require('mongoose')
let Schema=mongoose.Schema
const subscriptionSchema=new Schema({
_id: mongoose.Schema.Types.ObjectId,
user_id: {type: String},
plan_id: {type: String},
quantity: {type: Number},
end_date: {type: Date},
status: {type: String},
razorpay_id: {type: String},
c_ts: Date,
u_ts: Date
},{_id: false})
const SUBSCRIPTION_MODEL_NAME='Subscription'
const COLLECTION_NAME='subscriptions'
const Subscription=mongoose.model(SUBSCRIPTION_MODEL_NAME,subscriptionSchema,COLLECTION_NAME)
module.exports=Subscription

View file

@ -1,16 +0,0 @@
const mongoose = require('mongoose')
let Schema=mongoose.Schema
const userSchema=new Schema({
name: {type: String},
email: {type: String},
license_key: {type: String},
razorpay_id: {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

View file

@ -1,81 +0,0 @@
const ActiveConnection=require('../model/active-connections.model')
const subscriptionService=require('../service/subscription.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')
}
if(subscription && subscription.quantity>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(subscription.quantity,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 checkIfValidConnection(licenseKey,connectionId){
let connection=await ActiveConnection.findOne({_id: licenseKey, 'connections.connection_id':connectionId}).exec()
if(connection){
return true
}
return false
}
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,
checkIfValidConnection
}
// addNewConnection("asd","aasd").then(res=>{
// console.log('done')
// })

View file

@ -1,31 +0,0 @@
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 sendMail(email,subject,content){
if(process.env.SEND_MAIL==='false'){
return
}
console.log('sending mail to email:'+email+', subject:'+subject)
const msg = {
to: email,
from: SYSTEM_MAIL,
subject: subject,
html: content,
};
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={
sendMail,
validateEmailExistence
}

View file

@ -1,30 +0,0 @@
const planService=require('../service/plan.service')
const constants=require('../constants/constants')
const paymentConstants=require('../constants/payment.constant')
const https = require('https')
const razorpay=require('../../razorpay/razorpay')
async function createSubscription(quantity){
try{
let applicablePlan=await planService.getPlanByNumberOfUsers(quantity)
console.log(applicablePlan)
const payload={
plan_id: applicablePlan._id,
quantity: quantity,
total_count: paymentConstants.SUBSCRIPTION_DURATION_MONTHS
}
console.log(payload)
let subscriptionResponse=await razorpay.instance.subscriptions.create(payload)
return {subscriptionId: subscriptionResponse.id}
}catch(err){
console.log(err)
throw err
}
}
module.exports={
createSubscription
}

View file

@ -1,67 +0,0 @@
const Plan=require('../model/plan.model')
const constants=require('../constants/constants')
async function getPlan(planId){
console.log('fetching from db - planId:'+planId)
const plan=await Plan.findOne({_id: planId}).exec()
console.log('plan:'+plan)
return plan
}
async function getPlanById(planId){
console.log('fetching from db - planId:'+planId)
const plan=await Plan.findOne({_id: planId}).exec()
console.log('plan:'+plan)
return plan
}
async function getPlanByNumberOfUsers(quantity){
console.log('fetching plan for userCount:'+quantity)
let planList=await Plan.find({_id:{$ne: constants.TRIAL_PLAN_ID},user_limit:{"$gte":quantity}}).sort({user_limit:1}).limit(1).exec()
console.log('plan fetched:'+planList)
if(planList.length==0){
planList=await Plan.find().sort({user_limit:1}).limit(1).exec()
console.log('plan fetched:'+planList)
}
if(planList.length==0){
return {}
}
return planList[0]
}
async function checkIfPlanStillValidForDate(startDate, planId){
let plan=await getPlan(planId)
return validator(startDate,plan)
return false
}
function validator(startDate, plan){
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,
getPlanById,
checkIfPlanStillValidForDate,
getCurrentUserLimitForPlan,
getPlanByNumberOfUsers
}

View file

@ -1,199 +0,0 @@
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')
const emailTemplates=require('../utils/email.template')
async function createUserAndActivateTrial(email){
try{
if(await userService.checkIfUserExists(email)){
throw new UserExistsError('User exists')
}
let user=await userService.createUser(email, null)
let subscription=new Subscription({
_id: new mongoose.Types.ObjectId(),
user_id: user._id,
plan_id: constants.TRIAL_PLAN_ID,
end_date: getTrialEndDate(new Date()),
status: constants.SUBSCRIPTION_STATUS.ACTIVE.id,
quantity: 1,
c_ts: new Date(),
u_ts: new Date()
})
await insertSubscription(subscription)
await sendSubscriptionActivationEmail(subscription.quantity,subscription.plan_id,user)
}catch(err){
console.log(err)
throw err
}
}
function getTrialEndDate(startDate){
let endDate=new Date(startDate)
endDate.setMonth(endDate.getMonth()+1)
console.log('endDate for trial:'+endDate)
return endDate
}
async function insertSubscription(subscription){
subscription.c_ts=new Date()
subscription.u_ts=new Date()
try{
await Subscription.create(subscription)
}catch(err){
console.log('error saving subscription'+subscription);
throw err
}
}
async function upsertSubscriptionByRazorpayId(subscription){
const setOnInsertObj={
_id: new mongoose.Types.ObjectId(),
c_ts:new Date()
}
subscription.u_ts=new Date()
try{
await Subscription.update({razorpay_id: subscription.razorpay_id},{$set:subscription,$setOnInsert:setOnInsertObj},{upsert:true})
}catch(err){
console.log('error saving subscription'+subscription);
throw err
}
}
async function disableTrial(userId){
try{
console.log('disabiling trial for user:'+userId)
await Subscription.update({user_id: userId, plan_id: constants.TRIAL_PLAN_ID, status: constants.SUBSCRIPTION_STATUS.ACTIVE.id},{$set:{status: constants.SUBSCRIPTION_STATUS.EXPIRED.id,u_ts: new Date()}})
}catch(err){
console.log(err)
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,end_date:{$gt:new Date()}}).exec()
return subscription
}catch(err){
console.log(err)
throw err
}
}
async function validateLicenseKey(licenseKey){
try{
let subscription= await getSubscriptionByLicenseKey(licenseKey)
if(subscription && subscription.quantity>0){
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
}
async function processSubscriptionActivatedEvent(data){
try{
let subscriptionData= data.payload.subscription.entity
let user=await userService.getUserByRazorpayId(subscriptionData.customer_id)
if(!user){
let razorpayUserData=await userService.getUserFromRazorPay(subscriptionData.customer_id)
let userData=await userService.getUserByEmail(razorpayUserData.email)
if(userData){
user=userData
await userService.setRazorpayId(userData.email,razorpayUserData.id)
}else{
user=await userService.createUser(razorpayUserData.email,razorpayUserData.id)
}
}
await disableTrial(user._id)
let subscription=new Subscription({
user_id: user._id,
plan_id: subscriptionData.plan_id,
end_date: subscriptionData.current_end*1000+86400000*2,
quantity: subscriptionData.quantity,
status: constants.SUBSCRIPTION_STATUS.ACTIVE.id,
razorpay_id: subscriptionData.id
})
await upsertSubscriptionByRazorpayId(subscription)
if(data.event==='subscription.activated'){
await sendSubscriptionActivationEmail(subscription.quantity,subscription.plan_id,user)
}
}catch(err){
console.log(err)
throw err
}
}
async function sendSubscriptionActivationEmail(quantity,planId,user){
let plan=await planService.getPlanById(planId)
let options={
'WEBSITE':process.env.WEBSITE_URL,
'maxConcurrentDevices': quantity,
'licenseKey':user.license_key,
'planName': plan.name
}
const content=emailTemplates.getSubscriptionEmailContent(options)
await emailService.sendMail(user.email,'Responsively - License Activation',content)
}
module.exports={
createUserAndActivateTrial,
validateLicenseKey,
constructLicenseValidationResponse,
getSubscriptionByLicenseKey,
processSubscriptionActivatedEvent
}

View file

@ -1,90 +0,0 @@
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 axios=require('axios')
const Razorpay=require('../../razorpay/razorpay')
async function createUser(email, razorPayCustomerId){
if(!emailService.validateEmailExistence(email)){
throw new InvalidEmailError('Invalid Email:'+email)
}
let newUser=new User({
email: email,
license_key:getLicenseKey()
})
if(razorPayCustomerId){
newUser.razorpay_id=razorPayCustomerId
}
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 setRazorpayId(email,razorpayId){
await User.update({email: email},{$set:{razorpay_id: razorpayId}})
}
async function getUserByRazorpayId(id){
console.log('fetching user by razorpay id:'+id)
return await User.findOne({razorpay_id: id})
}
async function checkIfUserExists(email){
let user=await getUserByEmail(email)
console.log(user)
if(user){
return true
}
return false
}
async function getUserFromRazorPay(customerId){
console.log('fetching user from razorpay:'+customerId)
let user=await Razorpay.instance.customers.fetch(customerId)
console.log(user)
return user
}
function getLicenseKey(email){
const key=crypto.randomBytes(20).toString('hex');
return key;
}
module.exports={
createUser,
getUserByEmail,
checkIfUserExists,
getUserByRazorpayId,
getUserFromRazorPay,
setRazorpayId
}

View file

@ -1,496 +0,0 @@
export function getSubscriptionEmailContent(options){
let emailTemplate=`
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html style="width:100%;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;padding:0;Margin:0;">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta name="x-apple-disable-message-reformatting">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="telephone=no" name="format-detection">
<title>New email template 2019-10-25</title>
<!--[if (mso 16)]><style type="text/css"> a {text-decoration: none;} </style><![endif]-->
<!--[if gte mso 9]><style>sup { font-size: 100% !important; }</style><![endif]-->
<!--[if !mso]><!-- -->
<link href="https://fonts.googleapis.com/css?family=Montserrat:500,800" rel="stylesheet">
<!--<![endif]-->
<style type="text/css">
@media only screen and (max-width:600px) {
u+#body {
width: 100vw!important
}
p,
ul li,
ol li,
a {
font-size: 16px!important;
line-height: 150%!important
}
h1 {
font-size: 30px!important;
text-align: center;
line-height: 120%!important
}
h2 {
font-size: 26px!important;
text-align: center;
line-height: 120%!important
}
h3 {
font-size: 20px!important;
text-align: center;
line-height: 120%!important
}
h1 a {
font-size: 30px!important
}
h2 a {
font-size: 26px!important
}
h3 a {
font-size: 20px!important
}
.es-menu td a {
font-size: 16px!important
}
.es-header-body p,
.es-header-body ul li,
.es-header-body ol li,
.es-header-body a {
font-size: 16px!important
}
.es-footer-body p,
.es-footer-body ul li,
.es-footer-body ol li,
.es-footer-body a {
font-size: 16px!important
}
.es-infoblock p,
.es-infoblock ul li,
.es-infoblock ol li,
.es-infoblock a {
font-size: 12px!important
}
*[class="gmail-fix"] {
display: none!important
}
.es-m-txt-c,
.es-m-txt-c h1,
.es-m-txt-c h2,
.es-m-txt-c h3 {
text-align: center!important
}
.es-m-txt-r,
.es-m-txt-r h1,
.es-m-txt-r h2,
.es-m-txt-r h3 {
text-align: right!important
}
.es-m-txt-l,
.es-m-txt-l h1,
.es-m-txt-l h2,
.es-m-txt-l h3 {
text-align: left!important
}
.es-m-txt-r img,
.es-m-txt-c img,
.es-m-txt-l img {
display: inline!important
}
.es-button-border {
display: block!important
}
a.es-button {
font-size: 16px!important;
display: block!important;
border-left-width: 0px!important;
border-right-width: 0px!important
}
.es-btn-fw {
border-width: 10px 0px!important;
text-align: center!important
}
.es-adaptive table,
.es-btn-fw,
.es-btn-fw-brdr,
.es-left,
.es-right {
width: 100%!important
}
.es-content table,
.es-header table,
.es-footer table,
.es-content,
.es-footer,
.es-header {
width: 100%!important;
max-width: 600px!important
}
.es-adapt-td {
display: block!important;
width: 100%!important
}
.adapt-img {
width: 100%!important;
height: auto!important
}
.es-m-p0 {
padding: 0px!important
}
.es-m-p0r {
padding-right: 0px!important
}
.es-m-p0l {
padding-left: 0px!important
}
.es-m-p0t {
padding-top: 0px!important
}
.es-m-p0b {
padding-bottom: 0!important
}
.es-m-p20b {
padding-bottom: 20px!important
}
.es-mobile-hidden,
.es-hidden {
display: none!important
}
.es-desk-hidden {
display: table-row!important;
width: auto!important;
overflow: visible!important;
float: none!important;
max-height: inherit!important;
line-height: inherit!important
}
.es-desk-menu-hidden {
display: table-cell!important
}
table.es-table-not-adapt,
.esd-block-html table {
width: auto!important
}
table.es-social {
display: inline-block!important
}
table.es-social td {
display: inline-block!important
}
}
input[type="submit"] {
-webkit-appearance: none;
}
#myList div table:nth-child(2n+1),
#myList2 div table:nth-child(2n+1) {
float: left;
}
#myList div table:nth-child(2n),
#myList2 div table:nth-child(2n) {
float: right;
}
#outlook a {
padding: 0;
}
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.es-button {
mso-style-priority: 100!important;
text-decoration: none!important;
}
a[x-apple-data-detectors] {
color: inherit!important;
text-decoration: none!important;
font-size: inherit!important;
font-family: inherit!important;
font-weight: inherit!important;
line-height: inherit!important;
}
.es-desk-hidden {
display: none;
float: left;
overflow: hidden;
width: 0;
max-height: 0;
line-height: 0;
mso-hide: all;
}
a.es-button:hover {
border-color: #2CB543!important;
background: #2CB543!important;
}
a.es-secondary:hover {
border-color: #ffffff!important;
background: #ffffff!important;
}
</style>
</head>
<body style="width:100%;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;padding:0;Margin:0;">
<div class="es-wrapper-color" style="background-color:#F7F7F7;">
<!--[if gte mso 9]>
<v:background xmlns:v="urn:schemas-microsoft-com:vml" fill="t">
<v:fill type="tile" color="#F7F7F7"></v:fill>
</v:background>
<![endif]-->
<table cellpadding="0" cellspacing="0" class="es-wrapper" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;padding:0;Margin:0;width:100%;height:100%;background-repeat:repeat;background-position:center top;">
<tr style="border-collapse:collapse;">
<td valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" class="es-header" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;background-color:#1D1B26;background-repeat:repeat;background-position:center bottom;">
<tr style="border-collapse:collapse;">
<td align="left" style="Margin:0;padding-top:20px;padding-left:20px;padding-right:20px;padding-bottom:25px;">
<table width="100%" cellspacing="0" cellpadding="0" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="560" valign="top" align="center" style="padding:0;Margin:0;">
<table width="100%" cellspacing="0" cellpadding="0" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px; bottom;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<a href="${options.WEBSITE}" target="_blank" style="display:inline-block;font-weight:600;font-family:Inter UI, BlinkMacSystemFont, Segoe UI, Roboto,Helvetica Neue, Arial, sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:30px;text-decoration:none;color:#FFFFFF;">
<img src="${options.WEBSITE}/assets/img/responsively-logo.png" alt="Responsively"
title="Responsively" width="70" style="border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;"
class="adapt-img">
Responsively
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<table bgcolor="#ffffff" class="es-content-body" align="center" cellpadding="0" cellspacing="0" width="600" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
<tr class="es-visible-simple-html-only" style="border-collapse:collapse;">
<td align="left" style="Margin:0;padding-bottom:5px;padding-top:30px;padding-left:30px;padding-right:30px;background-position:center bottom;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="540" align="center" valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:16px;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;line-height:24px;color:#E06666;">
<br>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-top:20px;padding-left:30px;padding-right:30px;background-position:center bottom;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="540" align="center" valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-bottom:5px;">
<h1 style="text-align: center;Margin:0;line-height:38px;mso-line-height-rule:exactly;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;font-size:32px;font-style:normal;font-weight:bold;color:#4A4A4A;">Thank you for signing up!</h1>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr style="border-collapse:collapse;">
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-top:10px;">
<p style="text-align:center;Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:17px;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;line-height:26px;color:#4A4A4A;">Welcome to
<a target="_blank" style="-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;font-size:17px;text-decoration:underline;color:#3B2495;"
href="${options.WEBSITE}">Responsively</a>. Your license is activated.</p>
</td>
</tr>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<table bgcolor="#ffffff" class="es-content-body" align="center" cellpadding="0" cellspacing="0" width="600" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
<tr style="border-collapse:collapse;">
<td align="left" style="Margin:0;padding-left:10px;padding-top:20px;padding-bottom:20px;padding-right:20px;background-position:left top;background-color:#FFFFFF;border-radius:13px;"
bgcolor="#ffffff">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="570" align="left" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
Plan:
</td>
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
${options.planName}
</td>
</tr>
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
Max Concurrent Devices:
</td>
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
${options.maxConcurrentDevices}
</td>
</tr>
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
License Key:
</td>
<td align="left" style="padding:0;Margin:0;padding-top:5px;padding-bottom:5px;">
${options.licenseKey}
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<table class="es-content-body" width="600" cellspacing="0" cellpadding="0" bgcolor="#ffffff" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<table bgcolor="#ffffff" class="es-content-body" align="center" cellpadding="0" cellspacing="0" width="600" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" style="padding:0;Margin:0;">
<table bgcolor="#ffffff" class="es-content-body" align="center" cellpadding="0" cellspacing="0" width="600" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
<tr style="border-collapse:collapse;">
<td align="left" style="Margin:0;padding-top:15px;padding-bottom:25px;padding-left:30px;padding-right:30px;background-position:center bottom;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="540" align="center" valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="center" class="es-m-txt-l" style="padding:0;Margin:0;padding-top:10px;">
<p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:14px;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;line-height:21px;color:#4A4A4A;">If you have any questions or suggestions, please contact
<a target="_blank" style="-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;font-size:14px;text-decoration:underline;color:#3B2495;"
href="">support@responsively.app</a> or via <a href="${options.WEBSITE}">Chat</a> - we will be happy to assist you!</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" class="es-content" align="center" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;table-layout:fixed !important;width:100%;">
<tr style="border-collapse:collapse;">
<td align="center" bgcolor="#1D1B26" style="padding:0;Margin:0;background-color:#1D1B26;">
<table bgcolor="rgba(0, 0, 0, 0)" class="es-content-body" align="center" cellpadding="0" cellspacing="0" width="600" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;background-color:transparent;">
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-bottom:30px;padding-top:40px;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="600" align="center" valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="center" class="es-m-txt-c" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" class="es-table-not-adapt es-social" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="center" valign="top" style="padding:0;Margin:0;padding-right:10px;">
<img title="Facebook" src="https://esputnik.com/content/stripostatic/assets/img/social-icons/logo-white/facebook-logo-white.png"
alt="Fb" width="32" style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;">
</td>
<td align="center" valign="top" style="padding:0;Margin:0;padding-right:10px;">
<img title="Twitter" src="https://esputnik.com/content/stripostatic/assets/img/social-icons/logo-white/twitter-logo-white.png"
alt="Tw" width="32" style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;">
</td>
<td align="center" valign="top" style="padding:0;Margin:0;">
<img title="Linkedin" src="https://esputnik.com/content/stripostatic/assets/img/social-icons/logo-white/linkedin-logo-white.png"
alt="In" width="32" style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;">
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr style="border-collapse:collapse;">
<td align="left" style="padding:0;Margin:0;padding-bottom:30px;padding-left:30px;padding-right:30px;background-position:center bottom;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td width="540" align="center" valign="top" style="padding:0;Margin:0;">
<table cellpadding="0" cellspacing="0" width="100%" style="mso-table-lspace:0pt;mso-table-rspace:0pt;border-collapse:collapse;border-spacing:0px;">
<tr style="border-collapse:collapse;">
<td align="center" class="es-infoblock" style="padding:0;Margin:0;line-height:14px;font-size:12px;color:#CCCCCC;">
<p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:12px;font-family:Montserrat, Helvetica, Roboto, Arial, sans-serif;line-height:18px;color:#CCCCCC;">You are receiving this email because you have subscribed to the above plan.
Incase you did not, please ignore this mail or contact <a style="color:#ffffff">support@responsively.app</a>.</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>
`
return emailTemplate
}

View file

@ -1,8 +0,0 @@
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
}

View file

@ -1,31 +0,0 @@
const subscriptionService=require('../service/subscription.service')
const crypto=require('crypto')
const Razorpay=require('razorpay')
const mongoose=require('mongoose')
export async function processEvent(eventData){
const data=JSON.parse(eventData.body)
const signatureValid=Razorpay.validateWebhookSignature(eventData.body,eventData.headers["X-Razorpay-Signature"],process.env.RAZOR_PAY_WEBHOOK_SECRET)
if(!signatureValid){
console.log('invalid request:signature does not match');
return
}
try{
let eventData={
event_data: data,
c_ts: new Date()
}
console.log('inserting webhook event in db')
await mongoose.connection.collection('webhook_events').insert(eventData)
if(data.entity==='event'){
if(data.event==='subscription.activated' || data.event==='subscription.charged'){
await subscriptionService.processSubscriptionActivatedEvent(data)
}
}
}catch(err){
console.log(err)
throw err
}
}

View file

@ -1,12 +0,0 @@
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")}
})

View file

@ -1,113 +0,0 @@
const db=require('../db/db')
const subscriptionService = require('../app/service/subscription.service')
const paymentsService=require('../app/service/payment.service')
const UserExistsError=require('../app/exception/user-exists-error.exception')
const PlanNotFoundError=require('../app/exception/plan-not-found-error.exception')
const InvalidLicenseError=require('../app/exception/invalid-license-error.exception')
const InvalidEmailError=require('../app/exception/invalid-email-error.exception')
const razorpayWebhooks=require('../app/webhooks/main.webhooks')
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 PlanNotFoundError){
responseBody.statusCode=400
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 createSubscription(event, context, callback) {
let responseBody={}
let statusCode=0
context.callbackWaitsForEmptyEventLoop = false;
console.log(event)
try{
const reqBody=JSON.parse(event.body)
const quantity=reqBody.quantity
responseBody=await paymentsService.createSubscription(quantity)
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=400
responseBody.message='no matching plan found'
}else{
responseBody.statusCode=500
responseBody.message='Internal Server Error'
}
}
let response= {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : '*',
"Access-Control-Allow-Credentials" : true
},
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)
}
export async function webhookHandler(event, context, callback) {
let statusCode=0
context.callbackWaitsForEmptyEventLoop = false;
try{
console.log(event)
await razorpayWebhooks.processEvent(event)
}catch(err){
console.log(err)
}
let response= {
statusCode: 200,
body: 'event received'
}
callback(null, response)
}

View file

@ -1,6 +0,0 @@
const Razorpay=require('razorpay')
export const instance = new Razorpay({
key_id: process.env.RAZOR_PAY_API_KEY,
key_secret: process.env.RAZOR_API_SECRET_KEY
})

View file

@ -1,116 +0,0 @@
const 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: 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: 'Connection closed',
};
}
export async function pingHandler(event, context, callback) {
return {
statusCode: 200,
body: 'Message recieved',
};
}
export async function validateLicense(event, context, callback) {
let responseBody = { action: 'validate_response' };
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'];
let connectionStatus = await activeConnectionService.checkIfValidConnection(licenseKey, connectionId)
let data = {
status: false,
statusCode: 403,
message: 'not found in active users'
}
if (connectionStatus) {
data = {
status: true,
statusCode: 200,
message: 'valid'
}
}
responseBody.data = data;
} catch (err) {
console.log(err)
if (err instanceof InvalidLicenseError) {
responseBody.data = {
status: false,
statusCode: 403,
message: 'invalid license error',
};
} else {
responseBody.data = {
status: true, //Considering the license valid in-case of internal server error to logout valid users;
statusCode: 500,
message: 'internal server error',
};
}
}
await activeConnectionService.publish(event, connectionId, responseBody);
const response = {
statusCode: 200,
body: JSON.stringify(responseBody),
};
callback(null, response);
}

File diff suppressed because it is too large Load diff