Skip to content

Commit 1f73cce

Browse files
authored
Merge pull request #1 from Moesif/companyIdFix
Feature parity with moesif-express
2 parents 7c68b4b + f59cc7d commit 1f73cce

File tree

5 files changed

+381
-188
lines changed

5 files changed

+381
-188
lines changed

index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
* Created by derric on 8/23/17.
32
* This file is an example AWS Lambda function.
3+
* The Moesif AWS Lambda SDK is in the ./lib directory
44
*/
55

66
const moesif = require('./lib');

lib/index.js

+146-50
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
/**
2-
* Created by derric on 8/22/17.
3-
*/
41
'use strict'
5-
var _ = require('lodash');
6-
var url = require('url');
7-
var moesifapi = require('moesifapi');
8-
var EventModel = moesifapi.EventModel;
9-
var requestIp = require('request-ip');
10-
var logData = {};
11-
logData.request = {};
12-
logData.response = {};
13-
logData.request.time = Date.now();
2+
const _ = require('lodash');
3+
const url = require('url');
4+
const moesifapi = require('moesifapi');
5+
const requestIp = require('request-ip');
6+
const moesifConfigManager = require('./moesifConfigManager');
7+
const EventModel = moesifapi.EventModel;
8+
const UserModel = moesifapi.UserModel;
9+
const CompanyModel = moesifapi.CompanyModel;
10+
var startTime = Date.now();
1411

1512
//
1613
// ### function moesifExpress(options)
@@ -39,9 +36,19 @@ module.exports = function (options, handler) {
3936
(event.requestContext && event.requestContext.identity && event.requestContext.identity.user) ||
4037
event.user;
4138
};
39+
40+
options.identifyCompany = options.identifyCompany || function() {};
41+
4242
options.getSessionToken = options.getSessionToken || function (event, context) {
43-
return (event.requestContext && event.requestContext.identity && event.requestContext.identity.apiKey) ;
43+
return (event.requestContext && event.requestContext.identity && event.requestContext.identity.apiKey);
4444
};
45+
options.getMetadata = options.getMetadata || function (event, context) {
46+
const metadata = {};
47+
metadata.trace_id = context.awsRequestId;
48+
metadata.function_name = context.functionName;
49+
metadata.request_context = event && event.requestContext;
50+
return metadata;
51+
};
4552
options.getTags = options.getTags || function () {
4653
return undefined;
4754
};
@@ -58,29 +65,68 @@ module.exports = function (options, handler) {
5865
return false;
5966
};
6067

68+
var logBody = true;
69+
if (typeof options.logBody !== 'undefined' && options.logBody !== null) {
70+
logBody = Boolean(options.logBody);
71+
}
72+
options.logBody = logBody;
73+
6174
ensureValidOptions(options);
6275

6376
// config moesifapi
6477
var config = moesifapi.configuration;
65-
config.ApplicationId = options.applicationId || process.env.MOESIF_APPLICATION_ID;
78+
config.ApplicationId = options.applicationId || options.ApplicationId || process.env.MOESIF_APPLICATION_ID;
79+
config.BaseUri = options.baseUri || options.BaseUri || config.BaseUri;
6680
var moesifController = moesifapi.ApiController;
6781

6882
var moesifMiddleware = function (event, context, callback) {
6983
logMessage(options.debug, 'moesifMiddleware', 'start');
84+
moesifConfigManager.tryGetConfig();
7085

71-
var next = function (err, result) {
72-
logEvent(event, context, err, result, options, moesifController);
73-
callback(err, result)
74-
};
86+
var next = function (err, result) {
87+
logEvent(event, context, err, result, options, moesifController);
88+
callback(err, result)
89+
};
7590

76-
handler(event, context, next);
91+
handler(event, context, next);
7792
};
7893

79-
moesifMiddleware.updateUser = function (userModel, cb) {
94+
moesifMiddleware.updateUser = function(userModel, cb) {
95+
const user = new UserModel(userModel);
8096
logMessage(options.debug, 'updateUser', 'userModel=' + JSON.stringify(userModel));
81-
ensureValidUserModel(userModel);
97+
ensureValidUserModel(user);
8298
logMessage(options.debug, 'updateUser', 'userModel valid');
83-
moesifController.updateUser(userModel, cb);
99+
moesifController.updateUser(user, cb);
100+
};
101+
102+
moesifMiddleware.updateUsersBatch = function(usersBatchModel, cb) {
103+
usersBatch = [];
104+
for (let userModel of usersBatchModel) {
105+
usersBatch.push(new UserModel(userModel));
106+
}
107+
logMessage(options.debug, 'updateUsersBatch', 'usersBatchModel=' + JSON.stringify(usersBatchModel));
108+
ensureValidUsersBatchModel(usersBatch);
109+
logMessage(options.debug, 'updateUsersBatch', 'usersBatchModel valid');
110+
moesifController.updateUsersBatch(usersBatch, cb);
111+
};
112+
113+
moesifMiddleware.updateCompany = function(companyModel, cb) {
114+
const company = new CompanyModel(companyModel);
115+
logMessage(options.debug, 'updateCompany', 'companyModel=' + JSON.stringify(companyModel));
116+
ensureValidCompanyModel(company);
117+
logMessage(options.debug, 'updateCompany', 'companyModel valid');
118+
moesifController.updateCompany(company, cb);
119+
}
120+
121+
moesifMiddleware.updateCompaniesBatch = function(companiesBatchModel, cb) {
122+
companiesBatch = [];
123+
for (let companyModel of companiesBatchModel) {
124+
companiesBatch.push(new CompanyModel(companyModel));
125+
}
126+
logMessage(options.debug, 'updateCompaniesBatch', 'companiesBatchModel=' + JSON.stringify(companiesBatchModel));
127+
ensureValidCompaniesBatchModel(companiesBatch);
128+
logMessage(options.debug, 'updateCompaniesBatch', 'companiesBatchModel valid');
129+
moesifController.updateCompaniesBatch(companiesBatch, cb);
84130
};
85131

86132
logMessage(options.debug, 'moesifInitiator', 'returning moesifMiddleware Function');
@@ -89,10 +135,6 @@ module.exports = function (options, handler) {
89135

90136
function mapResponseHeaders(event, context, result) {
91137
const headers = result.headers || {}; // NOTE: Mutating event.headers; prefer deep clone of event.headers
92-
93-
headers['x-amzn-trace-id'] = context.awsRequestId;
94-
headers['x-amzn-function-name'] = context.functionName;
95-
headers['x-apigateway-trace-id'] = (event && event.requestContext && event.requestContext.requestId) || (context && context.requestContext && context.requestContext.requestId);
96138
return headers;
97139
}
98140

@@ -104,41 +146,45 @@ function logEvent(event, context, err, result, options, moesifController) {
104146
return;
105147
}
106148

149+
var logData = {};
150+
logData.request = {};
151+
logData.response = {};
152+
logData.request.time = event && event.requestContext && event.requestContext.requestTimeEpoch ?
153+
new Date(event && event.requestContext && event.requestContext.requestTimeEpoch) :
154+
startTime;
155+
107156
logData.request.uri = getPathWithQueryStringParams(event);
108157
logData.request.verb = event.httpMethod;
109158
logData.request.apiVerion = options.getApiVersion(event, context);
110159
logData.request.ipAddress = requestIp.getClientIp(event) || (event.requestContext && event.requestContext.identity && event.requestContext.identity.sourceIp);
111160
logData.request.headers = event.headers || {};
161+
logData.metadata = options.getMetadata(event, context);
112162

113-
if (event.body) {
163+
if (options.logBody && event.body) {
114164
if (event.isBase64Encoded) {
115-
logData.request.transferEncoding = 'base64';
116-
logData.request.body = bodyToBase64(event.body);
165+
logData.request.body = event.body;
166+
logData.request.transferEncoding = 'base64';
117167
} else {
118-
try {
119-
logData.request.body = JSON.parse(event.body);
120-
} catch (err) {
121-
logData.request.body = event.body;
122-
}
168+
const bodyWrapper = safeJsonParse(event.body);
169+
logData.request.body = bodyWrapper.body
170+
logData.request.transferEncoding = bodyWrapper.transferEncoding
123171
}
124172
}
125173

126174
logMessage(options.debug, 'logEvent', 'created request: \n' + JSON.stringify(logData.request));
127175
var safeRes = result || {};
128-
logData.response.time = Date.now();
176+
logData.response.time = new Date(Math.max(logData.request.time.getTime(), Date.now()));
129177
logData.response.status = safeRes.statusCode ? parseInt(safeRes.statusCode) : 599;
130178
logData.response.headers = mapResponseHeaders(event, context, safeRes);
131179

132-
if (safeRes.body) {
180+
if (options.logBody && safeRes.body) {
133181
if (safeRes.isBase64Encoded) {
134-
logData.response.transferEncoding = 'base64';
135-
logData.response.body = bodyToBase64(safeRes.body);
182+
logData.response.body = safeRes.body;
183+
logData.response.transferEncoding = 'base64';
136184
} else {
137-
try {
138-
logData.response.body = JSON.parse(safeRes.body);
139-
} catch (err) {
140-
logData.response.body = safeRes.body;
141-
}
185+
const bodyWrapper = safeJsonParse(safeRes.body);
186+
logData.response.body = bodyWrapper.body
187+
logData.response.transferEncoding = bodyWrapper.transferEncoding
142188
}
143189
}
144190

@@ -147,6 +193,7 @@ function logEvent(event, context, err, result, options, moesifController) {
147193
logData = options.maskContent(logData);
148194

149195
logData.userId = options.identifyUser(event, context);
196+
logData.companyId = options.identifyCompany(event, context);
150197
logData.sessionToken = options.getSessionToken(event, context);
151198
logData.tags = options.getTags(event, context);
152199

@@ -155,7 +202,7 @@ function logEvent(event, context, err, result, options, moesifController) {
155202
ensureValidLogData(logData);
156203

157204
// This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
158-
if (!options.skip(event, context)) {
205+
if (!options.skip(event, context) && moesifConfigManager.shouldSend(logData && logData.userId, logData && logData.companyId)) {
159206
logMessage(options.debug, 'logEvent', 'sending data invoking moesifAPI');
160207

161208
moesifController.createEvent(new EventModel(logData), function(err) {
@@ -189,8 +236,48 @@ function bodyToBase64(body) {
189236
}
190237
}
191238

239+
function safeJsonParse(body) {
240+
try {
241+
if (!Buffer.isBuffer(body) &&
242+
(typeof body === 'object' || Array.isArray(body))) {
243+
return {
244+
body: body,
245+
transferEncoding: undefined
246+
}
247+
}
248+
return {
249+
body: JSON.parse(body.toString()),
250+
transferEncoding: undefined
251+
}
252+
} catch (e) {
253+
return {
254+
body: bodyToBase64(body),
255+
transferEncoding: 'base64'
256+
}
257+
}
258+
}
259+
260+
function bodyToBase64(body) {
261+
if (!body) {
262+
return body;
263+
}
264+
if (Buffer.isBuffer(body)) {
265+
return body.toString('base64');
266+
} else if (typeof body === 'string') {
267+
return Buffer.from(body).toString('base64');
268+
} else if (typeof body.toString === 'function') {
269+
return Buffer.from(body.toString()).toString('base64');
270+
} else {
271+
return '';
272+
}
273+
}
274+
192275
function getPathWithQueryStringParams(event) {
193-
return url.format({ pathname: event.path, query: event.queryStringParameters })
276+
try {
277+
return url.format({ pathname: event.path, query: event.queryStringParameters });
278+
} catch (err) {
279+
return '/';
280+
}
194281
}
195282

196283
function ensureValidOptions(options) {
@@ -199,14 +286,20 @@ function ensureValidOptions(options) {
199286
if (options.identifyUser && !_.isFunction(options.identifyUser)) {
200287
throw new Error('identifyUser should be a function');
201288
}
289+
if (options.identifyCompany && !_.isFunction(options.identifyCompany)) {
290+
throw new Error('identifyCompany should be a function');
291+
}
202292
if (options.getSessionToken && !_.isFunction(options.getSessionToken)) {
203293
throw new Error('getSessionToken should be a function');
204294
}
295+
if (options.getMetadata && !_.isFunction(options.getMetadata)) {
296+
throw new Error('getMetadata should be a function');
297+
}
205298
if (options.getTags && !_.isFunction(options.getTags)) {
206299
throw new Error('getTags should be a function');
207300
}
208301
if (options.getApiVersion && !_.isFunction(options.getApiVersion)) {
209-
throw new Error('identifyUser should be a function');
302+
throw new Error('getApiVersion should be a function');
210303
}
211304
if (options.maskContent && !_.isFunction(options.maskContent)) {
212305
throw new Error('maskContent should be a function');
@@ -235,17 +328,20 @@ function ensureValidLogData(logData) {
235328
throw new Error('For Moesif events, request and response objects are required. Please check your maskContent function do not remove this');
236329
}
237330
else {
238-
// if (!logData.response.body) {
239-
// throw new Error('for log events, response body objects is required but can be empty object');
240-
// }
241331
if (!logData.request.time) {
242332
throw new Error('For Moesif events, response time is required. The middleware should populate it automatically. Please check your maskContent function do not remove this');
243333
}
244334
}
245335
}
246336

247337
function ensureValidUserModel(userModel) {
248-
if (!userModel.userId) {
338+
if (!userModel || !userModel.userId) {
249339
throw new Error('To update user, a userId field is required');
250340
}
251341
}
342+
343+
function ensureValidCompanyModel(companyModel) {
344+
if (!companyModel || !companyModel.companyId) {
345+
throw new Error('To update company, a companyId field is required');
346+
}
347+
}

0 commit comments

Comments
 (0)