Skip to content

Commit ffd44d8

Browse files
Feature/delete user data (#188)
Feature/delete user data
2 parents 0715cd5 + 7123772 commit ffd44d8

File tree

6 files changed

+139
-15
lines changed

6 files changed

+139
-15
lines changed

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ This middleware plugin for [Botkit](http://howdy.ai/botkit) allows developers to
2424
+ [Intent matching](#intent-matching)
2525
- [`before` and `after`](#before-and-after)
2626
- [Dynamic workspace](#dynamic-workspace)
27-
27+
* [Information security](#information-security)
28+
+ [Labeling user data](#labeling-user-data)
29+
+ [Deleting user data](#deleting-user-data)
2830
</details>
2931

3032
## Middleware Overview
@@ -45,6 +47,7 @@ This middleware plugin for [Botkit](http://howdy.ai/botkit) allows developers to
4547
* `readContext`: used in [implementing event handlers](#implementing-event-handlers).
4648
* `before`: [pre-process](#before-and-after) requests before sending to Watson Assistant (formerly Conversation).
4749
* `after`: [post-process](#before-and-after) responses before forwarding them to Botkit.
50+
* `deleteUserData`: [deletes](#information-security) all data associated with a specified customer ID.
4851

4952

5053
## Installation
@@ -371,6 +374,36 @@ async handleHelloEvent = (bot, message) => {
371374
controller.on('hello', handleHelloEvent);
372375
```
373376

377+
## Information security
378+
379+
It may be necessary to be to able delete message logs associated with particular customer in order to comply with
380+
[GDPR or HIPPA regulations](https://cloud.ibm.com/docs/services/assistant?topic=assistant-information-security#information-security)
381+
382+
### Labeling User Data
383+
384+
Messages can be labeled with customer id by adding `x-watson-metadata` header to request in `before` hook:
385+
386+
```js
387+
watsonMiddleware.before = async (message, payload) => {
388+
// it is up to you to implement calculateCustomerId function
389+
customerId = calculateCustomerId(payload.context);
390+
payload.headers['X-Watson-Metadata'] = 'customer_id=' + customerId;
391+
392+
return payload;
393+
};
394+
```
395+
396+
### Deleting User Data
397+
398+
```js
399+
try {
400+
await watsonMiddleware.deleteUserData(customerId);
401+
//Customer data was deleted successfully
402+
} catch (e) {
403+
//Failed to delete
404+
}
405+
```
406+
374407
## License
375408

376409
This library is licensed under Apache 2.0. Full license text is available in [LICENSE](LICENSE).

lib/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,5 @@ export declare class WatsonMiddleware {
6060
updateContext(user: string, context: Context): Promise<{
6161
context: Context;
6262
}>;
63+
deleteUserData(customerId: string): Promise<void>;
6364
}

lib/index.js

Lines changed: 18 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ export class WatsonMiddleware {
6868
if (config.minimum_confidence) {
6969
this.minimumConfidence = config.minimum_confidence;
7070
}
71+
72+
debug(
73+
'Creating Assistant object with parameters: ' +
74+
JSON.stringify(this.config, null, 2),
75+
);
76+
this.conversation = new AssistantV1(this.config);
7177
}
7278

7379
public hear(patterns: string[], message: Botkit.BotkitMessage): boolean {
@@ -105,14 +111,6 @@ export class WatsonMiddleware {
105111
message: Botkit.BotkitMessage,
106112
contextDelta: ContextDelta,
107113
): Promise<void> {
108-
if (!this.conversation) {
109-
debug(
110-
'Creating Assistant object with parameters: ' +
111-
JSON.stringify(this.config, null, 2),
112-
);
113-
this.conversation = new AssistantV1(this.config);
114-
}
115-
116114
if (
117115
(!message.text && message.type !== 'welcome') ||
118116
this.ignoreType.indexOf(message.type) !== -1 ||
@@ -219,4 +217,22 @@ export class WatsonMiddleware {
219217
context: context,
220218
});
221219
}
220+
221+
public async deleteUserData(customerId: string) {
222+
const params = {
223+
customer_id: customerId,
224+
return_response: true,
225+
};
226+
try {
227+
const response = await this.conversation.deleteUserData(params);
228+
debug('deleteUserData response', response);
229+
} catch (err) {
230+
throw new Error(
231+
'Failed to delete user data, response code: ' +
232+
err.code +
233+
', message: ' +
234+
err.message,
235+
);
236+
}
237+
}
222238
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright 2016-2019 IBM Corp. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { WatsonMiddleware } from '../lib/index';
18+
import nock = require('nock');
19+
20+
//Watson Assistant params
21+
const service = {
22+
username: 'batman',
23+
password: 'bruce-wayne',
24+
url: 'http://ibm.com:80',
25+
version: '2018-07-10',
26+
};
27+
28+
const workspaceId = 'zyxwv-54321';
29+
30+
const customerId = 'XXXXXX';
31+
32+
const middleware = new WatsonMiddleware({
33+
...service,
34+
workspace_id: workspaceId,
35+
});
36+
37+
beforeEach(function() {
38+
nock.disableNetConnect();
39+
});
40+
41+
afterEach(function() {
42+
nock.cleanAll();
43+
});
44+
45+
test('makes delete request', async () => {
46+
nock(service.url)
47+
.delete(`/v1/user_data?version=2018-07-10&customer_id=${customerId}`)
48+
.reply(202, '');
49+
50+
await middleware.deleteUserData(customerId);
51+
});
52+
53+
test('throws error on unexpected response code', async () => {
54+
nock(service.url)
55+
.delete(`/v1/user_data?version=2018-07-10&customer_id=${customerId}`)
56+
.reply(404, '');
57+
58+
return await expect(middleware.deleteUserData(customerId)).rejects.toThrow(
59+
'Failed to delete user data, response code: 404, message: null',
60+
);
61+
});

0 commit comments

Comments
 (0)