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
90136function 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+
192275function 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
196283function 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
247337function 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