1 | const interceptor = require('./lib/interceptor');
|
2 | const Logger = require('./lib/logger');
|
3 | const utils = require('./lib/utils');
|
4 | const LogStatusType = require('../utils/log-status-type');
|
5 | const _ = require('lodash');
|
6 |
|
7 | const logger = new Logger();
|
8 | const baseConfig = {
|
9 | serviceName: '',
|
10 | protectedFields: [
|
11 | 'password',
|
12 | 'currentPassword',
|
13 | 'newPassword',
|
14 | 'confirmationNewPassword',
|
15 | ],
|
16 | skip: []
|
17 | };
|
18 | let config;
|
19 |
|
20 | const getType = (req) => {
|
21 | const createMethods = [ 'POST' ];
|
22 | const updateMethods = [ 'PUT', 'PATCH' ];
|
23 | const deleteMethods = [ 'DELETE' ];
|
24 | const readMethods = [ 'GET' ];
|
25 | switch (true) {
|
26 | case createMethods.indexOf(req.method) >= 0:
|
27 | return 'Service Create';
|
28 | case updateMethods.indexOf(req.method) >= 0:
|
29 | return 'Service Update';
|
30 | case deleteMethods.indexOf(req.method) >= 0:
|
31 | return 'Service Delete';
|
32 | case readMethods.indexOf(req.method) >= 0:
|
33 | return 'Service Read';
|
34 | default:
|
35 | return 'Service Read';
|
36 | }
|
37 | };
|
38 |
|
39 | const getData = req => {
|
40 | return Object.assign({},
|
41 | req.query,
|
42 | req.params,
|
43 | req.body
|
44 | );
|
45 | };
|
46 |
|
47 |
|
48 | const mongoiseKeys = data => {
|
49 | return Object.keys(data).reduce((accumulator, key) => {
|
50 | const objKey = (key.indexOf('.') >= 0) ? _.kebabCase(key) : key
|
51 | accumulator[objKey] = data[key];
|
52 |
|
53 | return accumulator;
|
54 | }, {});
|
55 | };
|
56 |
|
57 | const clearProtectedData = data => {
|
58 | return _.omit(data, config.protectedFields);
|
59 | };
|
60 |
|
61 | const normalizeData = _.flow(
|
62 | mongoiseKeys,
|
63 | clearProtectedData
|
64 | );
|
65 |
|
66 | const shouldLog = req => {
|
67 | const allowedAction = req.method !== 'OPTIONS';
|
68 | const allowedPath = !config.skip.some(pathToSkip => new RegExp(pathToSkip).test(req.originalUrl));
|
69 | return allowedAction && allowedPath;
|
70 | }
|
71 |
|
72 | const logRequest = (req, res) => {
|
73 | if (!shouldLog(req)) {
|
74 | return false;
|
75 | }
|
76 |
|
77 | const type = getType(req);
|
78 | const data = getData(req);
|
79 | const result = 'trying';
|
80 | const reason = `${config.serviceName} - ${req.originalUrl}`;
|
81 | const system_id = req.system_id || _.get(req, 'user.system_id');
|
82 | const contractorId = req.contractor_id;
|
83 |
|
84 | if (!system_id) {
|
85 | console.warn('you must pass system_id to be able to log it', req.originalUrl);
|
86 | return false;
|
87 | }
|
88 |
|
89 | const promise = contractorId ?
|
90 | logger.log(type, reason, normalizeData(data), result, system_id, contractorId) :
|
91 | logger.broadcast(type, reason, normalizeData(data), result, system_id);
|
92 |
|
93 | return promise.catch(error => handleError(error, config));
|
94 | };
|
95 |
|
96 | const logResponse = (req, response, result) => {
|
97 | if (!shouldLog(req)) {
|
98 | return false;
|
99 | }
|
100 |
|
101 | const type = getType(req);
|
102 | const data = typeof response === 'object' ? response : { response };
|
103 | const reason = `${config.serviceName} - ${req.originalUrl}`;
|
104 | const system_id = req.system_id || _.get(req, 'user.system_id');
|
105 | const contractorId = req.contractor_id || _.get(data, 'contractor_id');
|
106 |
|
107 | if (!system_id) {
|
108 | console.warn('you must pass system_id to be able to log it', req.originalUrl);
|
109 | return false;
|
110 | }
|
111 |
|
112 |
|
113 | const promise = contractorId ?
|
114 | logger.log(type, reason, normalizeData(data), result, system_id, contractorId) :
|
115 | logger.broadcast(type, reason, normalizeData(data), result, system_id);
|
116 |
|
117 | return promise.catch(error => handleError(error, config));
|
118 | };
|
119 |
|
120 | const configureLogResponse = (req, res) => {
|
121 | interceptor.getResponseBody(res).then(responseBody => {
|
122 | const response = utils.parseResponse(responseBody);
|
123 | const responseStatus = _.get(response, 'statusLog[0].type') || LogStatusType.SUCCESS;
|
124 | const data = _.get(response, 'data') || _.get(response, 'statusLog[0]') || response;
|
125 |
|
126 | const status = responseStatus === LogStatusType.SUCCESS ? 'success' : 'error';
|
127 | logResponse(req, data, status);
|
128 | });
|
129 | };
|
130 |
|
131 | const configure = customConfig => (req, res, next) => {
|
132 | try {
|
133 | config = Object.assign({}, baseConfig, customConfig);
|
134 |
|
135 | logger.setRequestMetaData(interceptor.getRequestMetadata(req));
|
136 | logRequest(req, res);
|
137 | configureLogResponse(req, res);
|
138 | } catch (error) {
|
139 | handleError(error, config);
|
140 | }
|
141 |
|
142 | next();
|
143 | };
|
144 |
|
145 | const handleError = (error, config) => {
|
146 | const errorCode = _.get(error, 'code');
|
147 | console.error(`there was an error when logging ${config.serviceName}. code:`, errorCode);
|
148 | };
|
149 |
|
150 | module.exports = {
|
151 | configure,
|
152 | logger,
|
153 | };
|