wingbot 3.24.4 → 3.26.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -0
- package/package.json +1 -1
- package/src/BotApp.js +51 -7
- package/src/BotAppSender.js +33 -2
- package/src/CallbackAuditLog.js +145 -0
- package/src/Responder.js +1 -1
- package/src/graphApi/GraphApi.js +50 -3
- package/src/graphApi/conversationTestApi.js +2 -0
- package/src/graphApi/conversationsApi.js +4 -0
- package/src/graphApi/postBackApi.js +1 -0
- package/src/graphApi/validateBotApi.js +1 -0
- package/src/utils/getUpdate.js +3 -0
- package/src/utils/headersToAuditMeta.js +12 -0
package/index.js
CHANGED
|
@@ -21,6 +21,7 @@ const { asserts } = require('./src/testTools');
|
|
|
21
21
|
const BuildRouter = require('./src/BuildRouter');
|
|
22
22
|
const MockAiModel = require('./src/MockAiModel');
|
|
23
23
|
const ReturnSender = require('./src/ReturnSender');
|
|
24
|
+
const CallbackAuditLog = require('./src/CallbackAuditLog');
|
|
24
25
|
const Plugins = require('./src/Plugins');
|
|
25
26
|
const NotificationsStorage = require('./src/notifications/NotificationsStorage');
|
|
26
27
|
const Notifications = require('./src/notifications/Notifications');
|
|
@@ -70,6 +71,7 @@ module.exports = {
|
|
|
70
71
|
bufferloader,
|
|
71
72
|
asserts,
|
|
72
73
|
MemoryStateStorage,
|
|
74
|
+
CallbackAuditLog,
|
|
73
75
|
MemoryBotConfigStorage,
|
|
74
76
|
CachedModel,
|
|
75
77
|
CustomEntityDetectionModel,
|
package/package.json
CHANGED
package/src/BotApp.js
CHANGED
|
@@ -9,6 +9,7 @@ const crypto = require('crypto');
|
|
|
9
9
|
const BotAppSender = require('./BotAppSender');
|
|
10
10
|
const Processor = require('./Processor');
|
|
11
11
|
const ReturnSender = require('./ReturnSender');
|
|
12
|
+
const headersToAuditMeta = require('./utils/headersToAuditMeta');
|
|
12
13
|
|
|
13
14
|
const DEFAULT_API_URL = 'https://orchestrator-api.wingbot.ai';
|
|
14
15
|
|
|
@@ -20,6 +21,9 @@ const DEFAULT_API_URL = 'https://orchestrator-api.wingbot.ai';
|
|
|
20
21
|
/** @typedef {import('./Responder')} Responder */
|
|
21
22
|
/** @typedef {import('./Processor').Plugin} Plugin */
|
|
22
23
|
|
|
24
|
+
/** @typedef {import('./CallbackAuditLog')} AuditLog */
|
|
25
|
+
/** @typedef {import('./BotAppSender').TlsOptions} TlsOptions */
|
|
26
|
+
|
|
23
27
|
/**
|
|
24
28
|
* @typedef {object} BotAppOptions
|
|
25
29
|
* @prop {string|Promise<string>} secret
|
|
@@ -28,6 +32,8 @@ const DEFAULT_API_URL = 'https://orchestrator-api.wingbot.ai';
|
|
|
28
32
|
* @prop {Function} [fetch]
|
|
29
33
|
* @prop {ChatLogStorage} [chatLogStorage]
|
|
30
34
|
* @prop {boolean} [preferSynchronousResponse]
|
|
35
|
+
* @prop {AuditLog} [auditLog]
|
|
36
|
+
* @prop {TlsOptions} [tls]
|
|
31
37
|
*
|
|
32
38
|
* @typedef {ProcessorOptions & BotAppOptions} Options
|
|
33
39
|
*/
|
|
@@ -58,12 +64,16 @@ class BotApp {
|
|
|
58
64
|
fetch = null,
|
|
59
65
|
appId = null,
|
|
60
66
|
preferSynchronousResponse = false,
|
|
67
|
+
auditLog = null,
|
|
68
|
+
tls = null,
|
|
61
69
|
...processorOptions
|
|
62
70
|
} = options;
|
|
63
71
|
|
|
64
72
|
this._secret = Promise.resolve(secret);
|
|
65
73
|
this._fetch = fetch; // mock
|
|
66
74
|
this._appId = appId;
|
|
75
|
+
this._auditLog = auditLog;
|
|
76
|
+
this._tls = tls;
|
|
67
77
|
|
|
68
78
|
let { apiUrl } = options;
|
|
69
79
|
|
|
@@ -140,13 +150,44 @@ class BotApp {
|
|
|
140
150
|
};
|
|
141
151
|
}
|
|
142
152
|
|
|
143
|
-
|
|
153
|
+
/**
|
|
154
|
+
* @param {ReturnSender} sender
|
|
155
|
+
* @param {string} senderId
|
|
156
|
+
* @param {string} pageId
|
|
157
|
+
* @param {object} headers
|
|
158
|
+
*/
|
|
159
|
+
async _processSenderResponses (sender, senderId, pageId, headers) {
|
|
160
|
+
if (!this._auditLog) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
await Promise.all(
|
|
164
|
+
sender.tracking.events.map(async (event) => {
|
|
165
|
+
if (!['audit', 'report'].includes(event.type)) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
await this._auditLog.log(
|
|
170
|
+
event,
|
|
171
|
+
{ senderId, pageId },
|
|
172
|
+
headersToAuditMeta(headers),
|
|
173
|
+
this._auditLog.defaultWid,
|
|
174
|
+
'Info',
|
|
175
|
+
event.type === 'audit' ? 'Important' : 'Debug'
|
|
176
|
+
);
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async _processIncommingMessage (
|
|
182
|
+
message, senderId, pageId, appId, secret, sync = false, headers = {}
|
|
183
|
+
) {
|
|
144
184
|
const { mid = null } = message;
|
|
145
185
|
|
|
146
186
|
if (sync || this._preferSynchronousResponse) {
|
|
147
187
|
const sender = new ReturnSender({}, senderId, message, this._senderLogger);
|
|
148
188
|
sender.propagatesWaitEvent = true;
|
|
149
189
|
const res = await this._processor.processMessage(message, pageId, sender, { appId });
|
|
190
|
+
await this._processSenderResponses(sender, senderId, pageId, headers);
|
|
150
191
|
|
|
151
192
|
return {
|
|
152
193
|
status: res.status,
|
|
@@ -174,11 +215,13 @@ class BotApp {
|
|
|
174
215
|
appId,
|
|
175
216
|
secret,
|
|
176
217
|
mid,
|
|
177
|
-
fetch: this._fetch
|
|
218
|
+
fetch: this._fetch,
|
|
219
|
+
tls: this._tls
|
|
178
220
|
};
|
|
179
221
|
|
|
180
222
|
const sender = new BotAppSender(options, senderId, message, this._senderLogger);
|
|
181
223
|
const res = await this._processor.processMessage(message, pageId, sender, { appId });
|
|
224
|
+
await this._processSenderResponses(sender, senderId, pageId, headers);
|
|
182
225
|
|
|
183
226
|
return {
|
|
184
227
|
status: res.status,
|
|
@@ -280,7 +323,7 @@ class BotApp {
|
|
|
280
323
|
|
|
281
324
|
const body = JSON.parse(rawBody);
|
|
282
325
|
|
|
283
|
-
const entry = await this._processEntries(appId, secret, body.entry);
|
|
326
|
+
const entry = await this._processEntries(appId, secret, body.entry, rawHeaders);
|
|
284
327
|
|
|
285
328
|
return {
|
|
286
329
|
statusCode: 200,
|
|
@@ -293,7 +336,7 @@ class BotApp {
|
|
|
293
336
|
};
|
|
294
337
|
}
|
|
295
338
|
|
|
296
|
-
async _processEntries (appId, secret, entry = []) {
|
|
339
|
+
async _processEntries (appId, secret, entry = [], headers = {}) {
|
|
297
340
|
return Promise.all(
|
|
298
341
|
entry.map(async (event) => {
|
|
299
342
|
const {
|
|
@@ -308,7 +351,8 @@ class BotApp {
|
|
|
308
351
|
...standby.map((e) => ({ ...e, isStandby: true }))
|
|
309
352
|
];
|
|
310
353
|
|
|
311
|
-
const responses = await this
|
|
354
|
+
const responses = await this
|
|
355
|
+
._processMessaging(events, pageId, appId, secret, sync, headers);
|
|
312
356
|
|
|
313
357
|
return {
|
|
314
358
|
id: pageId,
|
|
@@ -318,7 +362,7 @@ class BotApp {
|
|
|
318
362
|
);
|
|
319
363
|
}
|
|
320
364
|
|
|
321
|
-
async _processMessaging (process, pageId, appId, secret, sync) {
|
|
365
|
+
async _processMessaging (process, pageId, appId, secret, sync, headers) {
|
|
322
366
|
const eventsBySenderId = new Map();
|
|
323
367
|
process.forEach((e) => this._processMessagingArrayItem(e, eventsBySenderId));
|
|
324
368
|
|
|
@@ -329,7 +373,7 @@ class BotApp {
|
|
|
329
373
|
|
|
330
374
|
for (const message of messaging) {
|
|
331
375
|
const res = await this._processIncommingMessage(
|
|
332
|
-
message, senderId, pageId, appId, secret, sync
|
|
376
|
+
message, senderId, pageId, appId, secret, sync, headers
|
|
333
377
|
);
|
|
334
378
|
|
|
335
379
|
responses.push(res);
|
package/src/BotAppSender.js
CHANGED
|
@@ -6,17 +6,25 @@
|
|
|
6
6
|
const jwt = require('jsonwebtoken');
|
|
7
7
|
const { default: fetch, Headers } = require('node-fetch');
|
|
8
8
|
const crypto = require('crypto');
|
|
9
|
+
const { Agent } = require('https');
|
|
9
10
|
const { promisify } = require('util');
|
|
10
11
|
const ReturnSender = require('./ReturnSender');
|
|
11
12
|
|
|
12
13
|
/** @typedef {import('./ReturnSender').ReturnSenderOptions} ReturnSenderOptions */
|
|
13
14
|
/** @typedef {import('./ReturnSender').ChatLogStorage} ChatLogStorage */
|
|
14
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} TlsOptions
|
|
18
|
+
* @prop {string|Promise<string>} key
|
|
19
|
+
* @prop {string|Promise<string>} cert
|
|
20
|
+
*/
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* @typedef {object} BotAppSenderOptions
|
|
17
24
|
* @prop {string} apiUrl
|
|
18
25
|
* @prop {string} pageId
|
|
19
26
|
* @prop {string} appId
|
|
27
|
+
* @prop {TlsOptions} [tls]
|
|
20
28
|
* @prop {string} [mid]
|
|
21
29
|
* @prop {Function} [fetch]
|
|
22
30
|
* @prop {string|Promise<string>} secret
|
|
@@ -47,6 +55,9 @@ class BotAppSender extends ReturnSender {
|
|
|
47
55
|
|
|
48
56
|
this._secret = Promise.resolve(options.secret);
|
|
49
57
|
|
|
58
|
+
this._tls = options.tls;
|
|
59
|
+
this._agent = null;
|
|
60
|
+
|
|
50
61
|
this._fetch = options.fetch || fetch;
|
|
51
62
|
}
|
|
52
63
|
|
|
@@ -65,6 +76,21 @@ class BotAppSender extends ReturnSender {
|
|
|
65
76
|
}, goodSecret);
|
|
66
77
|
}
|
|
67
78
|
|
|
79
|
+
async _getAgent () {
|
|
80
|
+
if (!this._tls) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (!this._agent) {
|
|
84
|
+
const [key, cert] = await Promise.all([
|
|
85
|
+
Promise.resolve(this._tls.key), Promise.resolve(this._tls.cert)
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
this._agent = new Agent({ cert, key });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return this._agent;
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
async _send (payload) {
|
|
69
95
|
// attach sender
|
|
70
96
|
if (typeof payload.sender === 'undefined') {
|
|
@@ -78,14 +104,19 @@ class BotAppSender extends ReturnSender {
|
|
|
78
104
|
|
|
79
105
|
const body = JSON.stringify(payload);
|
|
80
106
|
|
|
81
|
-
const token = await
|
|
107
|
+
const [token, agent] = await Promise.all([
|
|
108
|
+
BotAppSender.signBody(body, this._secret, this._appId),
|
|
109
|
+
this._getAgent()
|
|
110
|
+
]);
|
|
82
111
|
|
|
83
112
|
const headers = new Headers();
|
|
84
113
|
|
|
85
114
|
headers.set('Authorization', token);
|
|
86
115
|
headers.set('Content-Type', 'application/json');
|
|
87
116
|
|
|
88
|
-
const response = await this._fetch(this._apiUrl, {
|
|
117
|
+
const response = await this._fetch(this._apiUrl, {
|
|
118
|
+
headers, body, agent, method: 'POST'
|
|
119
|
+
})
|
|
89
120
|
.then((r) => r.json());
|
|
90
121
|
|
|
91
122
|
const { request, errors = null } = response;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author wingbot.ai
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const LEVEL_CRITICAL = 'Critical';
|
|
7
|
+
const LEVEL_IMPORTANT = 'Important';
|
|
8
|
+
const LEVEL_DEBUG = 'Debug';
|
|
9
|
+
|
|
10
|
+
const TYPE_ERROR = 'Error';
|
|
11
|
+
const TYPE_WARN = 'Warn';
|
|
12
|
+
const TYPE_INFO = 'Info';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {object} TrackingEvent
|
|
16
|
+
* @prop {string} [type='audit']
|
|
17
|
+
* @prop {string} category
|
|
18
|
+
* @prop {string} action
|
|
19
|
+
* @prop {string} [label]
|
|
20
|
+
* @prop {object} [payload]
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {object} User
|
|
25
|
+
* @prop {string} [id]
|
|
26
|
+
* @prop {string} [senderId]
|
|
27
|
+
* @prop {string} [pageId]
|
|
28
|
+
* @prop {string} [jwt] - jwt to check the authorship
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {object} Meta
|
|
33
|
+
* @prop {string} [ip]
|
|
34
|
+
* @prop {string} [ua]
|
|
35
|
+
* @prop {string} [ro] - referrer || origin
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {object} Logger
|
|
40
|
+
* @prop {Function} log
|
|
41
|
+
* @prop {Function} error
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {object} AuditLogEntry
|
|
46
|
+
* @prop {string} date - ISO date
|
|
47
|
+
* @prop {string} [eventType='audit']
|
|
48
|
+
* @prop {string} category
|
|
49
|
+
* @prop {string} action
|
|
50
|
+
* @prop {string} [label]
|
|
51
|
+
* @prop {object} [payload]
|
|
52
|
+
* @prop {string} level - (Critical|Important|Debug)
|
|
53
|
+
* @prop {string} type - (Error|Warn|Info)
|
|
54
|
+
* @prop {User} user
|
|
55
|
+
* @prop {string} wid - workspace id
|
|
56
|
+
* @prop {Meta} meta
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Audit Log Callback
|
|
61
|
+
*
|
|
62
|
+
* @callback AuditLogCallback
|
|
63
|
+
* @param {AuditLogEntry} entry
|
|
64
|
+
* @returns {Promise}
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Just a simple auditlog interface
|
|
69
|
+
*/
|
|
70
|
+
class CallbackAuditLog {
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @param {AuditLogCallback} callback
|
|
75
|
+
* @param {Logger} log
|
|
76
|
+
*/
|
|
77
|
+
constructor (callback = null, log = console) {
|
|
78
|
+
this._log = log;
|
|
79
|
+
this.defaultWid = '0';
|
|
80
|
+
|
|
81
|
+
this.LEVEL_CRITICAL = LEVEL_CRITICAL;
|
|
82
|
+
this.LEVEL_IMPORTANT = LEVEL_IMPORTANT;
|
|
83
|
+
this.LEVEL_DEBUG = LEVEL_DEBUG;
|
|
84
|
+
|
|
85
|
+
this.TYPE_ERROR = TYPE_ERROR;
|
|
86
|
+
this.TYPE_WARN = TYPE_WARN;
|
|
87
|
+
this.TYPE_INFO = TYPE_INFO;
|
|
88
|
+
|
|
89
|
+
/** @type {AuditLogCallback} */
|
|
90
|
+
this.callback = callback || (async (e) => {
|
|
91
|
+
const {
|
|
92
|
+
category,
|
|
93
|
+
action,
|
|
94
|
+
...rest
|
|
95
|
+
} = e;
|
|
96
|
+
log.log(`AuditLog: ${category} - ${action}`, rest);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Add a log
|
|
102
|
+
*
|
|
103
|
+
* @param {TrackingEvent} event
|
|
104
|
+
* @param {User} user
|
|
105
|
+
* @param {Meta} [meta]
|
|
106
|
+
* @param {string} [wid] - workspace ID
|
|
107
|
+
* @param {string} [type]
|
|
108
|
+
* @param {string} [level]
|
|
109
|
+
* @param {Date} [date]
|
|
110
|
+
* @returns {Promise}
|
|
111
|
+
*/
|
|
112
|
+
async log (
|
|
113
|
+
event,
|
|
114
|
+
user = {},
|
|
115
|
+
meta = {},
|
|
116
|
+
wid = this.defaultWid,
|
|
117
|
+
type = TYPE_INFO,
|
|
118
|
+
level = LEVEL_IMPORTANT,
|
|
119
|
+
date = new Date()
|
|
120
|
+
) {
|
|
121
|
+
const {
|
|
122
|
+
type: eventType = 'audit',
|
|
123
|
+
...rest
|
|
124
|
+
} = event;
|
|
125
|
+
const entry = {
|
|
126
|
+
date: date.toISOString(),
|
|
127
|
+
eventType,
|
|
128
|
+
...rest,
|
|
129
|
+
level,
|
|
130
|
+
meta,
|
|
131
|
+
type,
|
|
132
|
+
user,
|
|
133
|
+
wid
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await this.callback(entry);
|
|
138
|
+
} catch (e) {
|
|
139
|
+
this._log.error('Failed to send AuditLog', e, entry);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = CallbackAuditLog;
|
package/src/Responder.js
CHANGED
|
@@ -190,7 +190,7 @@ class Responder {
|
|
|
190
190
|
* Events are aggregated within ReturnSender and can be caught
|
|
191
191
|
* within Processor's `interaction` event (event.tracking.events)
|
|
192
192
|
*
|
|
193
|
-
* @param {string} type
|
|
193
|
+
* @param {string} type - (log,report,conversation,audit,user)
|
|
194
194
|
* @param {string} category
|
|
195
195
|
* @param {string} [action]
|
|
196
196
|
* @param {string} [label]
|
package/src/graphApi/GraphApi.js
CHANGED
|
@@ -8,6 +8,7 @@ const { graphql, buildSchema } = require('graphql');
|
|
|
8
8
|
const WingbotApiConnector = require('./WingbotApiConnector');
|
|
9
9
|
// @ts-ignore
|
|
10
10
|
const packageJson = require('../../package.json');
|
|
11
|
+
const headersToAuditMeta = require('../utils/headersToAuditMeta');
|
|
11
12
|
|
|
12
13
|
const DEFAULT_GROUPS = ['botEditor', 'botAdmin', 'appToken'];
|
|
13
14
|
const KEYS_URL = 'https://api.wingbot.ai/keys';
|
|
@@ -19,6 +20,8 @@ const DEFAULT_CACHE = 86400000; // 24 hours
|
|
|
19
20
|
* @param {object[]} [errors]
|
|
20
21
|
*/
|
|
21
22
|
|
|
23
|
+
/** @typedef {import('../CallbackAuditLog')} AuditLog */
|
|
24
|
+
|
|
22
25
|
/**
|
|
23
26
|
* Experimental chatbot API
|
|
24
27
|
*/
|
|
@@ -32,6 +35,7 @@ class GraphApi {
|
|
|
32
35
|
* @param {string} [options.appToken] - public token
|
|
33
36
|
* @param {string[]} [options.groups] - list of allowed bot groups
|
|
34
37
|
* @param {boolean} [options.useBundledGql] - uses library bundled graphql definition
|
|
38
|
+
* @param {AuditLog} [options.auditLog]
|
|
35
39
|
*/
|
|
36
40
|
constructor (apis, options) {
|
|
37
41
|
this._root = {
|
|
@@ -44,7 +48,16 @@ class GraphApi {
|
|
|
44
48
|
token: null,
|
|
45
49
|
groups: DEFAULT_GROUPS,
|
|
46
50
|
keysUrl: KEYS_URL,
|
|
47
|
-
cacheKeys: DEFAULT_CACHE
|
|
51
|
+
cacheKeys: DEFAULT_CACHE,
|
|
52
|
+
auditLog: {
|
|
53
|
+
async callback () {
|
|
54
|
+
// noop
|
|
55
|
+
},
|
|
56
|
+
defaultWid: '0',
|
|
57
|
+
async log () {
|
|
58
|
+
// noop
|
|
59
|
+
}
|
|
60
|
+
}
|
|
48
61
|
};
|
|
49
62
|
|
|
50
63
|
Object.assign(opts, options);
|
|
@@ -57,6 +70,10 @@ class GraphApi {
|
|
|
57
70
|
|
|
58
71
|
this._defaultGroups = opts.groups;
|
|
59
72
|
|
|
73
|
+
/** @type {AuditLog} */
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
this.auditLog = opts.auditLog;
|
|
76
|
+
|
|
60
77
|
this._apiConnector = new WingbotApiConnector({
|
|
61
78
|
token: opts.token,
|
|
62
79
|
appToken: opts.appToken,
|
|
@@ -75,6 +92,10 @@ class GraphApi {
|
|
|
75
92
|
* @param {object} headers
|
|
76
93
|
* @param {string} [headers.Authorization]
|
|
77
94
|
* @param {string} [headers.authorization]
|
|
95
|
+
* @param {string} [headers.Origin]
|
|
96
|
+
* @param {string} [headers.origin]
|
|
97
|
+
* @param {string} [headers.Referer]
|
|
98
|
+
* @param {string} [headers.referer]
|
|
78
99
|
* @param {string} [wingbotToken]
|
|
79
100
|
* @returns {Promise<GraphQlResponse>}
|
|
80
101
|
*/
|
|
@@ -83,13 +104,39 @@ class GraphApi {
|
|
|
83
104
|
assert.equal(typeof body.query, 'string', 'GraphQL request should contain a query property');
|
|
84
105
|
|
|
85
106
|
const authHeader = headers.Authorization || headers.authorization;
|
|
86
|
-
|
|
107
|
+
let token = {};
|
|
108
|
+
|
|
109
|
+
const audit = async (action, payload = {}, important = false, warn = false) => {
|
|
110
|
+
await this.auditLog.log(
|
|
111
|
+
{
|
|
112
|
+
category: 'API',
|
|
113
|
+
action,
|
|
114
|
+
payload
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: token.id,
|
|
118
|
+
jwt: token.id && authHeader.replace(/^bearer\s/i, '')
|
|
119
|
+
},
|
|
120
|
+
headersToAuditMeta(headers),
|
|
121
|
+
this.auditLog.defaultWid,
|
|
122
|
+
warn ? 'Warn' : 'Info',
|
|
123
|
+
important ? 'Important' : 'Debug'
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
token = await this._apiConnector.verifyToken(authHeader, wingbotToken);
|
|
129
|
+
} catch (e) {
|
|
130
|
+
await audit('authorization failed', { message: e.message, authHeader }, true, true);
|
|
131
|
+
throw e;
|
|
132
|
+
}
|
|
87
133
|
|
|
88
134
|
const schema = await this._schema();
|
|
89
135
|
|
|
90
136
|
const ctx = {
|
|
91
137
|
token,
|
|
92
|
-
groups: this._defaultGroups
|
|
138
|
+
groups: this._defaultGroups,
|
|
139
|
+
audit
|
|
93
140
|
};
|
|
94
141
|
|
|
95
142
|
// @ts-ignore
|
|
@@ -42,6 +42,8 @@ function conversationTestApi (testsSource, botFactory, options, acl) {
|
|
|
42
42
|
|
|
43
43
|
const { bot: validationRequestBody, step = null, lang = null } = args;
|
|
44
44
|
|
|
45
|
+
await ctx.audit('conversationTest', args);
|
|
46
|
+
|
|
45
47
|
return test.test(validationRequestBody, step, lang);
|
|
46
48
|
}
|
|
47
49
|
};
|
|
@@ -131,6 +131,8 @@ function conversationsApi (
|
|
|
131
131
|
condition
|
|
132
132
|
} = args;
|
|
133
133
|
|
|
134
|
+
await ctx.audit('conversations', args);
|
|
135
|
+
|
|
134
136
|
const { data, lastKey: nextKey } = await stateStorage
|
|
135
137
|
.getStates(condition || {}, limit, lastKey);
|
|
136
138
|
|
|
@@ -154,6 +156,8 @@ function conversationsApi (
|
|
|
154
156
|
senderId
|
|
155
157
|
} = args;
|
|
156
158
|
|
|
159
|
+
await ctx.audit('conversation', args);
|
|
160
|
+
|
|
157
161
|
const state = await stateStorage.getState(senderId, pageId);
|
|
158
162
|
|
|
159
163
|
if (!state) {
|
package/src/utils/getUpdate.js
CHANGED
|
@@ -168,6 +168,9 @@ function getSetState (setState = {}, req, res = null, useState = null) {
|
|
|
168
168
|
if (entity && (!rear || req.entities.some((e) => e.entity === entity))) {
|
|
169
169
|
values = req.entities.filter((e) => e.entity === entity)
|
|
170
170
|
.map((e) => e.value);
|
|
171
|
+
if (values.length === 0 && useState && useState[`@${entity}`]) {
|
|
172
|
+
values = [useState[`@${entity}`]];
|
|
173
|
+
}
|
|
171
174
|
} else if (variable) {
|
|
172
175
|
values = toArray(getValue(variable, state));
|
|
173
176
|
} else if (value === '' || value === null || value === undefined) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author wingbot.ai
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
module.exports = function headersToAuditMeta (headers) {
|
|
7
|
+
return {
|
|
8
|
+
ua: headers['User-Agent'] || headers['user-agent'] || headers['User-agent'],
|
|
9
|
+
ro: headers.Referer || headers.referer || headers.Origin || headers.origin,
|
|
10
|
+
ip: headers['X-Forwarded-For'] || headers['x-forwarded-for'] || headers['X-Azure-ClientIP'] || headers['x-azure-clientip']
|
|
11
|
+
};
|
|
12
|
+
};
|