@webex/internal-plugin-board 3.0.0-beta.9 → 3.0.0-bnr.2
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/README.md +1 -3
- package/dist/board.js +28 -108
- package/dist/board.js.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/index.js +7 -28
- package/dist/index.js.map +1 -1
- package/dist/realtime-channel-collection.js +2 -8
- package/dist/realtime-channel-collection.js.map +1 -1
- package/dist/realtime-channel.js +1 -5
- package/dist/realtime-channel.js.map +1 -1
- package/dist/realtime.js +38 -82
- package/dist/realtime.js.map +1 -1
- package/dist/types/board.d.ts +2 -0
- package/dist/types/config.d.ts +11 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/realtime-channel-collection.d.ts +2 -0
- package/dist/types/realtime-channel.d.ts +2 -0
- package/dist/types/realtime.d.ts +7 -0
- package/package.json +14 -14
- package/src/board.js +257 -205
- package/src/config.js +2 -2
- package/src/index.js +19 -21
- package/src/realtime-channel-collection.js +2 -2
- package/src/realtime-channel.js +8 -9
- package/src/realtime.js +109 -93
- package/test/integration/spec/board.js +347 -221
- package/test/integration/spec/realtime.js +82 -56
- package/test/integration/spec/sharing-mercury.js +154 -73
- package/test/unit/spec/board.js +301 -215
- package/test/unit/spec/encryption.js +152 -120
- package/test/unit/spec/realtime.js +131 -89
package/src/config.js
CHANGED
package/src/index.js
CHANGED
|
@@ -50,7 +50,7 @@ registerInternalPlugin('board', Board, {
|
|
|
50
50
|
|
|
51
51
|
extract(options) {
|
|
52
52
|
return Promise.resolve(options.body);
|
|
53
|
-
}
|
|
53
|
+
},
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
name: 'encryptChannel',
|
|
@@ -68,8 +68,8 @@ registerInternalPlugin('board', Board, {
|
|
|
68
68
|
|
|
69
69
|
extract(options) {
|
|
70
70
|
return Promise.resolve(options.body);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
73
|
],
|
|
74
74
|
transforms: [
|
|
75
75
|
{
|
|
@@ -77,29 +77,27 @@ registerInternalPlugin('board', Board, {
|
|
|
77
77
|
direction: 'inbound',
|
|
78
78
|
|
|
79
79
|
fn(ctx, object) {
|
|
80
|
-
return ctx.webex.internal.board.decryptContents(object)
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
80
|
+
return ctx.webex.internal.board.decryptContents(object).then((decryptedContents) => {
|
|
81
|
+
object.items = decryptedContents;
|
|
82
|
+
});
|
|
83
|
+
},
|
|
85
84
|
},
|
|
86
85
|
{
|
|
87
86
|
name: 'encryptChannel',
|
|
88
87
|
direciton: 'outbound',
|
|
89
88
|
fn(ctx, object) {
|
|
90
|
-
return ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1})
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
89
|
+
return ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => {
|
|
90
|
+
const key = keys[0];
|
|
91
|
+
|
|
92
|
+
object.defaultEncryptionKeyUrl = key.uri;
|
|
93
|
+
object.kmsMessage.keyUris.push(key.uri);
|
|
94
|
+
|
|
95
|
+
return ctx.transform('encryptKmsMessage', object);
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
103
101
|
});
|
|
104
102
|
|
|
105
103
|
export {default} from './board';
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
import AmpCollection from 'ampersand-collection';
|
|
8
8
|
|
|
9
|
-
import RealtimeChannel from './realtime-channel
|
|
9
|
+
import RealtimeChannel from './realtime-channel';
|
|
10
10
|
|
|
11
11
|
const RealtimeChannelCollection = AmpCollection.extend({
|
|
12
12
|
mainIndex: 'channelId',
|
|
13
13
|
model: RealtimeChannel,
|
|
14
14
|
|
|
15
|
-
namespace: 'Board'
|
|
15
|
+
namespace: 'Board',
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
export default RealtimeChannelCollection;
|
package/src/realtime-channel.js
CHANGED
|
@@ -12,30 +12,29 @@ const RealtimeChannel = Mercury.extend({
|
|
|
12
12
|
props: {
|
|
13
13
|
channelId: {
|
|
14
14
|
type: 'string',
|
|
15
|
-
required: true
|
|
15
|
+
required: true,
|
|
16
16
|
},
|
|
17
17
|
socketUrl: {
|
|
18
|
-
type: 'string'
|
|
18
|
+
type: 'string',
|
|
19
19
|
},
|
|
20
20
|
binding: {
|
|
21
|
-
type: 'string'
|
|
22
|
-
}
|
|
21
|
+
type: 'string',
|
|
22
|
+
},
|
|
23
23
|
},
|
|
24
24
|
|
|
25
25
|
session: {
|
|
26
26
|
isSharingMercury: {
|
|
27
27
|
type: 'boolean',
|
|
28
|
-
default: false
|
|
28
|
+
default: false,
|
|
29
29
|
},
|
|
30
30
|
socket: {
|
|
31
|
-
type: 'object'
|
|
32
|
-
}
|
|
31
|
+
type: 'object',
|
|
32
|
+
},
|
|
33
33
|
},
|
|
34
34
|
|
|
35
35
|
send(data) {
|
|
36
36
|
return this.socket.send(data);
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
export default RealtimeChannel;
|
|
41
|
-
|
package/src/realtime.js
CHANGED
|
@@ -6,7 +6,7 @@ import uuid from 'uuid';
|
|
|
6
6
|
import {tap} from '@webex/common';
|
|
7
7
|
import {WebexPlugin} from '@webex/webex-core';
|
|
8
8
|
|
|
9
|
-
import RealtimeChannelCollection from './realtime-channel-collection
|
|
9
|
+
import RealtimeChannelCollection from './realtime-channel-collection';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @class
|
|
@@ -17,42 +17,48 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
17
17
|
namespace: 'Board',
|
|
18
18
|
|
|
19
19
|
collections: {
|
|
20
|
-
realtimeChannels: RealtimeChannelCollection
|
|
20
|
+
realtimeChannels: RealtimeChannelCollection,
|
|
21
21
|
},
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
* Sends the message via the socket. Assumes that the message is already properly formatted
|
|
25
|
+
* @memberof Board.RealtimeService
|
|
26
|
+
* @param {Board~Channel} channel
|
|
27
|
+
* @param {string} message Contains the un-encrypted message to send.
|
|
28
|
+
* @returns {Promise<Board~Content>}
|
|
29
|
+
*/
|
|
30
30
|
publish(channel, message) {
|
|
31
31
|
let encryptionPromise;
|
|
32
32
|
let contentType = 'STRING';
|
|
33
33
|
|
|
34
34
|
if (message.payload.file) {
|
|
35
35
|
contentType = 'FILE';
|
|
36
|
-
encryptionPromise = this.webex.internal.board.encryptSingleFileContent(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
encryptionPromise = this.webex.internal.board.encryptSingleFileContent(
|
|
37
|
+
channel.defaultEncryptionKeyUrl,
|
|
38
|
+
message.payload
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
encryptionPromise = this.webex.internal.board.encryptSingleContent(
|
|
42
|
+
channel.defaultEncryptionKeyUrl,
|
|
43
|
+
message.payload
|
|
44
|
+
);
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
return encryptionPromise
|
|
43
|
-
|
|
47
|
+
return encryptionPromise.then((encryptedPayloadAndKeyUrl) =>
|
|
48
|
+
this.publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType)
|
|
49
|
+
);
|
|
44
50
|
},
|
|
45
51
|
|
|
46
52
|
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
* Sends the message via the socket. The message should already have been
|
|
54
|
+
* encrypted
|
|
55
|
+
* @memberof Board.RealtimeService
|
|
56
|
+
* @param {Board~Channel} channel
|
|
57
|
+
* @param {object} encryptedPayloadAndKeyUrl
|
|
58
|
+
* @param {string} contentType - provides hint for decryption. Defaults to
|
|
59
|
+
* `STRING`, and could also be `FILE`
|
|
60
|
+
* @returns {Promise<Board~Content>}
|
|
61
|
+
*/
|
|
56
62
|
publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType) {
|
|
57
63
|
const realtimeChannel = this.realtimeChannels.get(channel.channelId);
|
|
58
64
|
|
|
@@ -63,27 +69,29 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
63
69
|
const data = {
|
|
64
70
|
id: uuid.v4(),
|
|
65
71
|
type: 'publishRequest',
|
|
66
|
-
recipients: [
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
recipients: [
|
|
73
|
+
{
|
|
74
|
+
alertType: 'none',
|
|
75
|
+
route: realtimeChannel.binding,
|
|
76
|
+
headers: {},
|
|
77
|
+
},
|
|
78
|
+
],
|
|
71
79
|
data: {
|
|
72
80
|
eventType: 'board.activity',
|
|
73
81
|
contentType,
|
|
74
82
|
payload: encryptedPayloadAndKeyUrl.payload,
|
|
75
83
|
envelope: {
|
|
76
84
|
encryptionKeyUrl: encryptedPayloadAndKeyUrl.encryptionKeyUrl,
|
|
77
|
-
channelId: channel.channelId
|
|
78
|
-
}
|
|
79
|
-
}
|
|
85
|
+
channelId: channel.channelId,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
80
88
|
};
|
|
81
89
|
|
|
82
90
|
// provide a hint for decryption
|
|
83
91
|
if (contentType === 'FILE') {
|
|
84
92
|
data.data.payload = {
|
|
85
93
|
file: encryptedPayloadAndKeyUrl.file,
|
|
86
|
-
payload: encryptedPayloadAndKeyUrl.payload
|
|
94
|
+
payload: encryptedPayloadAndKeyUrl.payload,
|
|
87
95
|
};
|
|
88
96
|
}
|
|
89
97
|
|
|
@@ -94,49 +102,46 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
94
102
|
const requestBindings = [this._boardChannelIdToMercuryBinding(channel.channelId)];
|
|
95
103
|
const bindingObj = {bindings: requestBindings};
|
|
96
104
|
|
|
97
|
-
return this.webex.internal.board.register(bindingObj)
|
|
98
|
-
.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
binding: bindings[0]
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
return this.realtimeChannels.get(channel.channelId);
|
|
105
|
+
return this.webex.internal.board.register(bindingObj).then(({webSocketUrl, bindings}) => {
|
|
106
|
+
this.realtimeChannels.add({
|
|
107
|
+
channelId: channel.channelId,
|
|
108
|
+
socketUrl: webSocketUrl,
|
|
109
|
+
binding: bindings[0],
|
|
106
110
|
});
|
|
111
|
+
|
|
112
|
+
return this.realtimeChannels.get(channel.channelId);
|
|
113
|
+
});
|
|
107
114
|
},
|
|
108
115
|
|
|
109
116
|
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
* Open new mercury connection
|
|
118
|
+
* @memberof Board.RealtimeService
|
|
119
|
+
* @param {Board~Channel} channel
|
|
120
|
+
* @returns {Promise}
|
|
121
|
+
*/
|
|
115
122
|
connectByOpenNewMercuryConnection(channel) {
|
|
116
123
|
let promise = Promise.resolve();
|
|
117
124
|
let realtimeChannel = this.realtimeChannels.get(channel.channelId);
|
|
118
125
|
|
|
119
126
|
if (!realtimeChannel) {
|
|
120
127
|
this.logger.info('board realtime: realtime channel not found, creating new channel');
|
|
121
|
-
promise = this.createRealtimeChannel(channel)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.logger.info('board realtime: realtime channel created');
|
|
128
|
+
promise = this.createRealtimeChannel(channel).then((rc) => {
|
|
129
|
+
realtimeChannel = rc;
|
|
130
|
+
this.logger.info('board realtime: realtime channel created');
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
return realtimeChannel;
|
|
133
|
+
});
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
return promise
|
|
131
|
-
.then(() => realtimeChannel.connect(realtimeChannel.socketUrl));
|
|
136
|
+
return promise.then(() => realtimeChannel.connect(realtimeChannel.socketUrl));
|
|
132
137
|
},
|
|
133
138
|
|
|
134
139
|
/**
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
* Disconnect connection
|
|
141
|
+
* @memberof Board.RealtimeService
|
|
142
|
+
* @param {Board~Channel} channel
|
|
143
|
+
* @returns {Promise}
|
|
144
|
+
*/
|
|
140
145
|
disconnectMercuryConnection(channel) {
|
|
141
146
|
const realtimeChannel = this.realtimeChannels.get(channel.channelId);
|
|
142
147
|
|
|
@@ -144,10 +149,13 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
144
149
|
return Promise.reject(new Error('Realtime Channel not found!'));
|
|
145
150
|
}
|
|
146
151
|
|
|
147
|
-
return
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
return (
|
|
153
|
+
realtimeChannel
|
|
154
|
+
.disconnect()
|
|
155
|
+
// even if we can't remove the channels from the collection, we can still
|
|
156
|
+
// continue on execution
|
|
157
|
+
.then(tap(() => this.realtimeChannels.remove(channel.channelId)))
|
|
158
|
+
);
|
|
151
159
|
},
|
|
152
160
|
|
|
153
161
|
/**
|
|
@@ -169,33 +177,39 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
169
177
|
* @returns {Promise<Board~Registration>}
|
|
170
178
|
*/
|
|
171
179
|
connectToSharedMercury(channel) {
|
|
172
|
-
return this.webex.internal.board.registerToShareMercury(channel)
|
|
173
|
-
.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const realtimeChannel = this.realtimeChannels.get(channel.channelId);
|
|
181
|
-
|
|
182
|
-
if (!res.sharedWebSocket) {
|
|
183
|
-
return realtimeChannel.connect(realtimeChannel.socketUrl)
|
|
184
|
-
.then(() => res);
|
|
185
|
-
}
|
|
180
|
+
return this.webex.internal.board.registerToShareMercury(channel).then((res) => {
|
|
181
|
+
this.realtimeChannels.add({
|
|
182
|
+
channelId: channel.channelId,
|
|
183
|
+
binding: res.binding,
|
|
184
|
+
socketUrl: res.webSocketUrl,
|
|
185
|
+
});
|
|
186
186
|
|
|
187
|
-
|
|
188
|
-
realtimeChannel.socket = this.webex.internal.mercury.socket;
|
|
189
|
-
// refresh socket reference when mercury is reconnected
|
|
190
|
-
this.webex.internal.mercury.off('online', this.refreshMercurySocketReference, this);
|
|
191
|
-
this.webex.internal.mercury.on('online', this.refreshMercurySocketReference, this);
|
|
187
|
+
const realtimeChannel = this.realtimeChannels.get(channel.channelId);
|
|
192
188
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
if (!res.sharedWebSocket) {
|
|
190
|
+
return realtimeChannel.connect(realtimeChannel.socketUrl).then(() => res);
|
|
191
|
+
}
|
|
196
192
|
|
|
197
|
-
|
|
198
|
-
|
|
193
|
+
realtimeChannel.isSharingMercury = true;
|
|
194
|
+
realtimeChannel.socket = this.webex.internal.mercury.socket;
|
|
195
|
+
// refresh socket reference when mercury is reconnected
|
|
196
|
+
this.webex.internal.mercury.off('online', this.refreshMercurySocketReference, this);
|
|
197
|
+
this.webex.internal.mercury.on('online', this.refreshMercurySocketReference, this);
|
|
198
|
+
|
|
199
|
+
// make sure there's only one handler
|
|
200
|
+
this.webex.internal.mercury.off(
|
|
201
|
+
'event:board.activity',
|
|
202
|
+
this.handleBoardActivityMessages,
|
|
203
|
+
this
|
|
204
|
+
);
|
|
205
|
+
this.webex.internal.mercury.on(
|
|
206
|
+
'event:board.activity',
|
|
207
|
+
this.handleBoardActivityMessages,
|
|
208
|
+
this
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
return res;
|
|
212
|
+
});
|
|
199
213
|
},
|
|
200
214
|
|
|
201
215
|
handleBoardActivityMessages(event) {
|
|
@@ -225,12 +239,14 @@ const RealtimeService = WebexPlugin.extend({
|
|
|
225
239
|
return this.disconnectMercuryConnection(channel);
|
|
226
240
|
}
|
|
227
241
|
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
242
|
+
return (
|
|
243
|
+
this.webex.internal.board
|
|
244
|
+
.unregisterFromSharedMercury(channel, realtimeChannel.binding)
|
|
245
|
+
// tap suppress errors but we can still go on if the channel can't be
|
|
246
|
+
// removed from the collection
|
|
247
|
+
.then(tap(() => this.realtimeChannels.remove(channel.channelId)))
|
|
248
|
+
);
|
|
249
|
+
},
|
|
234
250
|
});
|
|
235
251
|
|
|
236
252
|
export default RealtimeService;
|