@soundworks/core 4.0.0-alpha.5 → 4.0.0-alpha.7

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.
@@ -0,0 +1,36 @@
1
+ import BaseSharedStateCollection from '../common/BaseSharedStateCollection.js';
2
+
3
+ // this file exists only for documentation purposesSharedStateCollection.js
4
+
5
+ /**
6
+ * @callback server.SharedStateCollection~onUpdateCallback
7
+ * @param {server.SharedState} state - State that triggered the update.
8
+ * @param {Object} newValues - Key / value pairs of the updates that have been
9
+ * applied to the state.
10
+ * @param {Object} oldValues - Key / value pairs of the updated params before
11
+ * the updates has been applied to the state.
12
+ * @param {Mixed} [context=null] - Optionnal context object that has been passed
13
+ * with the values updates in the `set` call.
14
+ */
15
+
16
+ /**
17
+ * The `SharedStateCollection` interface represent a collection of all states
18
+ * created from a given schema name on the network, at the execption of the ones
19
+ * created by the current node.
20
+ *
21
+ * ```
22
+ * const collection = await server.stateManager.getCollection('my-schema');
23
+ * const allValues = collection.getValues();
24
+ * collection.onUpdate((state, newValues, oldValues, context) => {
25
+ * // do something
26
+ * });
27
+ * ```
28
+ * @memberof server
29
+ * @extends BaseSharedStateCollection
30
+ * @inheritdoc
31
+ * @hideconstructor
32
+ */
33
+ class SharedStateCollection extends BaseSharedStateCollection {}
34
+
35
+ export default SharedStateCollection;
36
+
@@ -2,9 +2,9 @@ import { Worker } from 'node:worker_threads';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
 
5
+ import querystring from 'querystring';
5
6
  import { WebSocketServer } from 'ws';
6
7
  import WebSocket from 'ws';
7
- import querystring from 'querystring';
8
8
 
9
9
  import Socket from './Socket.js';
10
10
 
@@ -69,13 +69,13 @@ class Sockets {
69
69
 
70
70
  // init ws server
71
71
  this._wss = new WebSocketServer({
72
- server: server.httpServer,
72
+ noServer: true,
73
73
  path: `/${config.path}`, // @note - update according to existing config files (aka cosima-apps)
74
74
  });
75
75
 
76
76
  this._wss.on('connection', (ws, req) => {
77
77
  const queryString = querystring.decode(req.url.split('?')[1]);
78
- const { role, key } = queryString;
78
+ const { role, key, token } = queryString;
79
79
  const binary = !!(parseInt(queryString.binary));
80
80
 
81
81
  if (binary) {
@@ -96,8 +96,29 @@ class Sockets {
96
96
  socket.addToRoom('*');
97
97
  socket.addToRoom(role);
98
98
 
99
- onConnectionCallback(role, socket);
99
+ onConnectionCallback(role, socket, token);
100
+ }
101
+ });
102
+
103
+ // check if client can connect
104
+ server.httpServer.on('upgrade', async (req, socket, head) => {
105
+ const queryString = querystring.decode(req.url.split('?')[1]);
106
+
107
+ const { role, token } = queryString;
108
+
109
+ if (server.isProtected(role)) {
110
+ // we don't have any ip in the upgrade request, so we just check the
111
+ // connection token is pending
112
+ const allowed = server.isValidConnectionToken(token);
113
+
114
+ if (!allowed) {
115
+ socket.destroy('not allowed');
116
+ }
100
117
  }
118
+
119
+ this._wss.handleUpgrade(req, socket, head, (ws) => {
120
+ this._wss.emit('connection', ws, req);
121
+ });
101
122
  });
102
123
  }
103
124
 
@@ -359,7 +359,9 @@ class StateManager extends BaseStateManager {
359
359
  client.transport.emit(CREATE_RESPONSE, reqId, stateId, remoteId, schemaName, sendedSchema, currentValues);
360
360
 
361
361
  this._observers.forEach(observer => {
362
- observer.transport.emit(OBSERVE_NOTIFICATION, [schemaName, stateId, nodeId]);
362
+ if (observer.id !== nodeId) {
363
+ observer.transport.emit(OBSERVE_NOTIFICATION, schemaName, stateId, nodeId);
364
+ }
363
365
  });
364
366
  } catch (err) {
365
367
  client.transport.emit(CREATE_ERROR, reqId, err.message);
@@ -428,7 +430,7 @@ class StateManager extends BaseStateManager {
428
430
  const { schemaName, id, _creatorId } = state;
429
431
  // only track application states
430
432
  // (e.g. do not propagate infos about audit state)
431
- if (!PRIVATE_STATES.includes(schemaName)) {
433
+ if (!PRIVATE_STATES.includes(schemaName) && _creatorId !== client.id) {
432
434
  statesInfos.push([schemaName, id, _creatorId]);
433
435
  }
434
436
  });
@@ -0,0 +1,38 @@
1
+ import crypto from 'node:crypto';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+
4
+ // adapted from https://dev.to/jobizil/encrypt-and-decrypt-data-in-nodejs-using-aes-256-cbc-2l6d
5
+ // generate a new key and init vector each time the server restart, we don't need
6
+ // any persistency here
7
+ const secretKey = uuidv4();
8
+ const secretIv = uuidv4();
9
+ const encryptionMethod = 'aes-256-cbc';
10
+
11
+ const key = crypto
12
+ .createHash('sha512')
13
+ .update(secretKey)
14
+ .digest('hex')
15
+ .substring(0, 32);
16
+
17
+ const encryptionIV = crypto
18
+ .createHash('sha512')
19
+ .update(secretIv)
20
+ .digest('hex')
21
+ .substring(0, 16);
22
+
23
+
24
+ export function encryptData(obj) {
25
+ const data = JSON.stringify(obj);
26
+ const cipher = crypto.createCipheriv(encryptionMethod, key, encryptionIV)
27
+ return Buffer.from(
28
+ cipher.update(data, 'utf8', 'hex') + cipher.final('hex')
29
+ ).toString('base64')
30
+ }
31
+
32
+ export function decryptData(encryptedData) {
33
+ const buff = Buffer.from(encryptedData, 'base64')
34
+ const decipher = crypto.createDecipheriv(encryptionMethod, key, encryptionIV)
35
+
36
+ const decrypted = `${decipher.update(buff.toString('utf8'), 'hex', 'utf8')}${decipher.final('utf8')}`
37
+ return JSON.parse(decrypted);
38
+ }
@@ -1,15 +0,0 @@
1
- name: "Unit Tests"
2
- on: push
3
-
4
- jobs:
5
- test:
6
- runs-on: ubuntu-latest
7
- steps:
8
- - name: Checkout
9
- uses: actions/checkout@v3.3.0
10
- - name: 'Install Node'
11
- uses: actions/setup-node@v3.6.0
12
- - name: Install dependencies
13
- run: npm install
14
- - name: "Run Test"
15
- run: npm test -- tests/**.spec.js