@cocreate/socket-server 1.7.7 → 1.8.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +3 -3
  3. package/src/index.js +311 -306
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## [1.8.1](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.8.0...v1.8.1) (2023-05-20)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Refactor socket server code to re check permissions using platformId when organization.dbUrl is false. ([e0cae7a](https://github.com/CoCreate-app/CoCreate-socket-server/commit/e0cae7a0a2eb9c740f36a3306fc038a9c68329ab))
7
+ * updated dependencies to their latest versions ([84d2f1d](https://github.com/CoCreate-app/CoCreate-socket-server/commit/84d2f1d0a67b021682f5b9b543ededb995830231))
8
+
9
+ # [1.8.0](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.7.7...v1.8.0) (2023-05-19)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * Refactor index.js to remove unused code and improve readability ([8b71373](https://github.com/CoCreate-app/CoCreate-socket-server/commit/8b71373fc453d247389b786530c491754f8104d5))
15
+ * SocketServer class methods and properties ([9dd6f1d](https://github.com/CoCreate-app/CoCreate-socket-server/commit/9dd6f1d25b7bbe6a107d9076db31b73ac8a464b3))
16
+
17
+
18
+ ### Features
19
+
20
+ * handle dbUrl false session ([61f64d2](https://github.com/CoCreate-app/CoCreate-socket-server/commit/61f64d2d02327ef3bec2821e8f3f083cc449a753))
21
+
1
22
  ## [1.7.7](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.7.6...v1.7.7) (2023-05-11)
2
23
 
3
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/socket-server",
3
- "version": "1.7.7",
3
+ "version": "1.8.1",
4
4
  "description": "CoCreate-socket-server",
5
5
  "keywords": [
6
6
  "cocreate-socket",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "homepage": "https://cocreate.app/docs/CoCreate-socket-server",
42
42
  "dependencies": {
43
- "@cocreate/docs": "^1.5.13",
44
- "@cocreate/uuid": "^1.2.61"
43
+ "@cocreate/docs": "^1.7.11",
44
+ "@cocreate/uuid": "^1.4.10"
45
45
  },
46
46
  "devDependencies": {
47
47
  "express": "^4.17.1",
package/src/index.js CHANGED
@@ -4,312 +4,317 @@ const EventEmitter = require("events").EventEmitter;
4
4
  const AsyncMessage = require("./AsyncMessage")
5
5
  const uid = require('@cocreate/uuid')
6
6
 
7
- class SocketServer extends EventEmitter{
8
- constructor(prefix) {
9
- super();
10
-
11
- this.clients = new Map();
12
- this.asyncMessages = new Map();
13
-
14
- this.prefix = prefix || "crud";
15
-
16
- //. websocket server
17
- this.wss = new WebSocket.Server({noServer: true});
18
- this.permissionInstance = null;
19
- this.authInstance = null;
20
- }
21
-
22
- setPermission(instance) {
23
- this.permissionInstance = instance;
24
- }
25
-
26
- setAuth(instance) {
27
- this.authInstance = instance
28
- }
29
-
30
- handleUpgrade(req, socket, head) {
31
- const self = this;
32
- const pathname = url.parse(req.url).pathname;
33
- const config = this.getKeyFromUrl(pathname)
34
- if (config.type == this.prefix) {
35
- self.wss.handleUpgrade(req, socket, head, function(socket) {
36
- socket.config = config
37
- self.onWebSocket(req, socket);
38
- })
39
- return true;
40
- }
41
- return false;
42
- }
43
-
44
- onWebSocket(req, socket) {
45
- const self = this;
46
-
47
- this.addClient(socket);
48
-
49
- socket.on('message', async (message) => {
50
- self.onMessage(req, socket, message);
51
- })
52
-
53
- socket.on('close', function () {
54
- self.removeClient(socket)
55
- })
56
-
57
- socket.on("error", () => {
58
- self.removeClient(socket)
59
- });
60
-
61
- this.send(socket, 'connect', socket.config.key);
62
-
63
- }
64
-
65
- addClient(socket) {
66
- let organization_id = socket.config.organization_id
67
- let user_id = socket.config.user_id
68
- let key = socket.config.key
69
- let room_clients = this.clients.get(key);
70
- if (room_clients) {
71
- room_clients.push(socket);
72
- } else {
73
- room_clients = [socket];
74
- }
75
- this.clients.set(key, room_clients);
76
- // this.addAsyncMessage(key)
77
-
78
- let asyncMessage = this.asyncMessages.get(key)
79
- if (!asyncMessage) {
80
- this.asyncMessages.set(key, new AsyncMessage(key));
81
- }
82
-
83
- if (user_id)
84
- this.emit('userStatus', socket, {user_id, userStatus: 'on', organization_id});
85
-
86
- //. add metrics
87
- let total_cnt = 0;
88
- this.clients.forEach((c) => total_cnt += c.length)
89
-
90
- this.emit("createMetrics", null, {
91
- organization_id,
92
- client_cnt: room_clients.length,
93
- total_cnt: total_cnt
94
- });
95
- }
96
-
97
- removeClient(socket) {
98
- let organization_id = socket.config.organization_id
99
- let user_id = socket.config.user_id
100
- let key = socket.config.key
101
- let room_clients = this.clients.get(key)
102
- const index = room_clients.indexOf(socket);
103
-
104
- if (index > -1) {
105
- room_clients.splice(index, 1);
106
- }
107
-
108
- if (room_clients.length == 0) {
109
- if (user_id)
110
- this.emit('userStatus', socket, {user_id, status: 'off', organization_id});
111
-
112
- this.emit("deleteMetrics", null, { organization_id });
113
- this.emit("deletePermissions", organization_id );
114
- this.emit('disconnect', organization_id)
115
- this.asyncMessages.delete(key);
116
- } else {
117
- let total_cnt = 0;
118
- this.clients.forEach((c) => total_cnt += c.length)
119
-
120
- this.emit("changeCountMetrics", null, {
121
- organization_id,
122
- total_cnt,
123
- client_cnt: room_clients.length
124
- });
125
- }
126
-
127
- }
128
-
129
- async onMessage(req, socket, message) {
130
- try {
131
- const organization_id = socket.config.organization_id
132
-
133
- // ToDo: remove
134
- // if (message instanceof Buffer) {
135
- // this.emit('importFile2DB', socket, message);
136
- // console.log('importFile2DB', socket, message);
137
- // return;
138
- // }
139
-
140
- const {action, data} = JSON.parse(message)
141
-
142
- if (action) {
143
- this.recordTransfer('in', message, organization_id)
144
-
145
- let user_id = null;
146
- if (this.authInstance)
147
- user_id = await this.authInstance.getUserId(req);
148
-
149
- if (this.permissionInstance) {
150
- const permission = await this.permissionInstance.check(action, data, req, user_id)
151
- if (!permission || permission.error) {
152
- // if (action == 'syncServer' && permission.database === true)
153
- // if (action == 'syncServer')
154
- // this.emit('createDocument', socket, data);
155
- // else
156
- if (action !== 'createOrg')
157
- return this.send(socket, 'Access Denied', {action, permission, ...data})
158
- else
159
- this.send(socket, 'Access Denied', {action, permission})
160
-
161
- }
162
- }
163
-
164
- if (user_id) {
165
- if (!socket.config.user_id ) {
166
- socket.config.user_id = user_id
167
- this.emit('userStatus', socket, {user_id, userStatus: 'on', organization_id});
168
- }
169
- } else {
170
- this.send(socket, 'updateUserStatus', {userStatus: 'off', clientId: data.clientId, organization_id})
171
- }
172
-
173
- //. checking async status....
174
- if (data.async == true) {
175
- console.log('async true')
176
- const asyncMessage = this.asyncMessages.get(socket.config.key);
177
- socket.config.asyncId = uid.generate();
178
- if (asyncMessage) {
179
- asyncMessage.defineMessage(socket.config.asyncId);
180
- }
181
- }
182
-
183
- this.emit(action, socket, data);
184
- }
185
-
186
- } catch(e) {
187
- console.log(e);
188
- }
189
- }
190
-
191
- broadcast(socket, action, data) {
192
- const self = this;
193
- if (!data.uid)
194
- data.uid = uid.generate()
195
- const responseData = JSON.stringify({
196
- action,
197
- data
198
- });
199
-
200
- const asyncId = socket.config.asyncId
201
- let isAsync = false;
202
- let asyncData = [];
203
- if (asyncId && socket.config && socket.config.key) {
204
- isAsync = true;
205
- }
206
-
207
- let organization_id = socket.config.organization_id;
208
- let url = `/${this.prefix}/${organization_id}`;
209
-
210
- let namespace = data.namespace;
211
- if (namespace) {
212
- url += `/${namespace}`
213
- }
214
-
215
- let rooms = data.room;
216
- if (rooms) {
217
- if (!rooms.isArray())
218
- rooms = [rooms]
219
- for (let room of rooms) {
220
- let url = url;
221
- url += `/${room}`;
222
-
223
- const clients = this.clients.get(url);
224
- if (clients) {
225
- clients.forEach((client) => {
226
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
227
- if (isAsync) {
228
- asyncData.push({socket: client, message: responseData})
229
- } else {
230
- client.send(responseData);
231
- }
232
- self.recordTransfer('out', responseData, organization_id)
233
- }
234
- })
235
- }
236
- }
237
-
238
- } else {
239
- this.clients.forEach((value, key) => {
240
- if (key.includes(url)) {
241
- value.forEach(client => {
242
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
243
- if (isAsync) {
244
- asyncData.push({socket: client, message: responseData})
245
- } else {
246
- client.send(responseData);
247
- }
248
- self.recordTransfer('out', responseData, organization_id)
249
- }
250
- })
251
- }
252
- })
253
- }
254
-
255
- //. set async processing
256
- if (isAsync) {
257
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, asyncData)
258
- }
259
-
260
- }
261
-
262
- send(socket, action, data){
263
- const asyncId = socket.config.asyncId
264
- let responseData = JSON.stringify({
265
- action,
266
- data
267
- });
268
-
269
- if (asyncId && socket.config && socket.config.key) {
270
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, [{socket, message: responseData}]);
271
- } else {
272
- socket.send(responseData);
273
- }
274
-
275
- if (socket.config && socket.config.organization_id)
276
- this.recordTransfer('out', responseData, socket.config.organization_id)
277
-
278
- }
279
-
280
- // addAsyncMessage(key) {
281
- // let asyncMessage = this.asyncMessages.get(key)
282
- // if (!asyncMessage) {
283
- // this.asyncMessages.set(key, new AsyncMessage(key));
284
- // }
285
- // }
286
-
287
- getKeyFromUrl(pathname) {
288
- var path = pathname.split("/");
289
- var params = {
290
- type: null,
291
- key: pathname
292
- }
293
- if (path.length > 0) {
294
- params.type = path[1];
295
- params.organization_id = path[2]
296
- }
297
- return params
298
- }
299
-
300
-
301
- sendBinary(socket, data, organization_id) {
302
- socket.send(data, {binary: true});
303
- this.recordTransfer('out', data, organization_id)
304
- }
305
-
306
- recordTransfer(type, data, organization_id) {
307
- this.emit("setBandwidth", null, {
308
- type,
309
- data,
310
- organization_id
311
- });
312
- }
7
+ class SocketServer extends EventEmitter {
8
+ constructor(prefix) {
9
+ super();
10
+
11
+ this.clients = new Map();
12
+ this.asyncMessages = new Map();
13
+
14
+ this.prefix = prefix || "crud";
15
+
16
+ //. websocket server
17
+ this.wss = new WebSocket.Server({ noServer: true });
18
+ this.permissionInstance = null;
19
+ this.authInstance = null;
20
+ }
21
+
22
+ setPermission(instance) {
23
+ this.permissionInstance = instance;
24
+ }
25
+
26
+ setAuth(instance) {
27
+ this.authInstance = instance
28
+ }
29
+
30
+ handleUpgrade(req, socket, head) {
31
+ const self = this;
32
+ const pathname = url.parse(req.url).pathname;
33
+ const config = this.getKeyFromUrl(pathname)
34
+ if (config.type == this.prefix) {
35
+ self.wss.handleUpgrade(req, socket, head, function (socket) {
36
+ socket.config = config
37
+ self.onWebSocket(req, socket);
38
+ })
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+
44
+ onWebSocket(req, socket) {
45
+ const self = this;
46
+
47
+ this.addClient(socket);
48
+
49
+ socket.on('message', async (message) => {
50
+ self.onMessage(req, socket, message);
51
+ })
52
+
53
+ socket.on('close', function () {
54
+ self.removeClient(socket)
55
+ })
56
+
57
+ socket.on("error", () => {
58
+ self.removeClient(socket)
59
+ });
60
+
61
+ this.send(socket, 'connect', socket.config.key);
62
+
63
+ }
64
+
65
+ addClient(socket) {
66
+ let organization_id = socket.config.organization_id
67
+ let user_id = socket.config.user_id
68
+ let key = socket.config.key
69
+ let room_clients = this.clients.get(key);
70
+ if (room_clients) {
71
+ room_clients.push(socket);
72
+ } else {
73
+ room_clients = [socket];
74
+ }
75
+ this.clients.set(key, room_clients);
76
+ // this.addAsyncMessage(key)
77
+
78
+ let asyncMessage = this.asyncMessages.get(key)
79
+ if (!asyncMessage) {
80
+ this.asyncMessages.set(key, new AsyncMessage(key));
81
+ }
82
+
83
+ if (user_id)
84
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
85
+
86
+ //. add metrics
87
+ let total_cnt = 0;
88
+ this.clients.forEach((c) => total_cnt += c.length)
89
+
90
+ this.emit("createMetrics", null, {
91
+ organization_id,
92
+ client_cnt: room_clients.length,
93
+ total_cnt: total_cnt
94
+ });
95
+ }
96
+
97
+ removeClient(socket) {
98
+ let organization_id = socket.config.organization_id
99
+ let user_id = socket.config.user_id
100
+ let key = socket.config.key
101
+ let room_clients = this.clients.get(key)
102
+ const index = room_clients.indexOf(socket);
103
+
104
+ if (index > -1) {
105
+ room_clients.splice(index, 1);
106
+ }
107
+
108
+ if (room_clients.length == 0) {
109
+ if (user_id)
110
+ this.emit('userStatus', socket, { user_id, status: 'off', organization_id });
111
+
112
+ this.emit("deleteMetrics", null, { organization_id });
113
+ this.emit("deletePermissions", organization_id);
114
+ this.emit('disconnect', organization_id)
115
+ this.asyncMessages.delete(key);
116
+ } else {
117
+ let total_cnt = 0;
118
+ this.clients.forEach((c) => total_cnt += c.length)
119
+
120
+ this.emit("changeCountMetrics", null, {
121
+ organization_id,
122
+ total_cnt,
123
+ client_cnt: room_clients.length
124
+ });
125
+ }
126
+
127
+ }
128
+
129
+ async onMessage(req, socket, message) {
130
+ try {
131
+ const organization_id = socket.config.organization_id
132
+
133
+ // TODO: remove
134
+ // if (message instanceof Buffer) {
135
+ // this.emit('importFile2DB', socket, message);
136
+ // console.log('importFile2DB', socket, message);
137
+ // return;
138
+ // }
139
+
140
+ const { action, data } = JSON.parse(message)
141
+
142
+ if (action) {
143
+ this.recordTransfer('in', message, organization_id)
144
+
145
+ let user_id = null;
146
+ if (this.authInstance)
147
+ user_id = await this.authInstance.getUserId(req);
148
+
149
+ if (this.permissionInstance) {
150
+ const permission = await this.permissionInstance.check(action, data, req, user_id)
151
+ if (!permission || permission.error) {
152
+ // if (action == 'syncServer' && permission.database === true)
153
+ // if (action == 'syncServer')
154
+ // this.emit('createDocument', socket, data);
155
+ // else
156
+ if (permission.dbUrl === false) {
157
+ data.database = process.env.organization_id
158
+ data.organization_id = process.env.organization_id
159
+
160
+ const permission2 = await this.permissionInstance.check(action, data, req, user_id)
161
+ if (!permission2 || permission2.error) {
162
+ return this.send(socket, 'Access Denied', { action, permission2, ...data })
163
+ }
164
+ } else
165
+ return this.send(socket, 'Access Denied', { action, permission, ...data })
166
+ }
167
+ }
168
+
169
+ if (user_id) {
170
+ if (!socket.config.user_id) {
171
+ socket.config.user_id = user_id
172
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
173
+ }
174
+ } else {
175
+ this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
176
+ }
177
+
178
+ //. checking async status....
179
+ if (data.async == true) {
180
+ console.log('async true')
181
+ const asyncMessage = this.asyncMessages.get(socket.config.key);
182
+ socket.config.asyncId = uid.generate();
183
+ if (asyncMessage) {
184
+ asyncMessage.defineMessage(socket.config.asyncId);
185
+ }
186
+ }
187
+
188
+ this.emit(action, socket, data);
189
+ }
190
+
191
+ } catch (e) {
192
+ console.log(e);
193
+ }
194
+ }
195
+
196
+ broadcast(socket, action, data) {
197
+ const self = this;
198
+ if (!data.uid)
199
+ data.uid = uid.generate()
200
+ const responseData = JSON.stringify({
201
+ action,
202
+ data
203
+ });
204
+
205
+ const asyncId = socket.config.asyncId
206
+ let isAsync = false;
207
+ let asyncData = [];
208
+ if (asyncId && socket.config && socket.config.key) {
209
+ isAsync = true;
210
+ }
211
+
212
+ let organization_id = socket.config.organization_id;
213
+ let url = `/${this.prefix}/${organization_id}`;
214
+
215
+ let namespace = data.namespace;
216
+ if (namespace) {
217
+ url += `/${namespace}`
218
+ }
219
+
220
+ let rooms = data.room;
221
+ if (rooms) {
222
+ if (!rooms.isArray())
223
+ rooms = [rooms]
224
+ for (let room of rooms) {
225
+ let url = url;
226
+ url += `/${room}`;
227
+
228
+ const clients = this.clients.get(url);
229
+ if (clients) {
230
+ clients.forEach((client) => {
231
+ if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
232
+ if (isAsync) {
233
+ asyncData.push({ socket: client, message: responseData })
234
+ } else {
235
+ client.send(responseData);
236
+ }
237
+ self.recordTransfer('out', responseData, organization_id)
238
+ }
239
+ })
240
+ }
241
+ }
242
+
243
+ } else {
244
+ this.clients.forEach((value, key) => {
245
+ if (key.includes(url)) {
246
+ value.forEach(client => {
247
+ if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
248
+ if (isAsync) {
249
+ asyncData.push({ socket: client, message: responseData })
250
+ } else {
251
+ client.send(responseData);
252
+ }
253
+ self.recordTransfer('out', responseData, organization_id)
254
+ }
255
+ })
256
+ }
257
+ })
258
+ }
259
+
260
+ //. set async processing
261
+ if (isAsync) {
262
+ this.asyncMessages.get(socket.config.key).setMessage(asyncId, asyncData)
263
+ }
264
+
265
+ }
266
+
267
+ send(socket, action, data) {
268
+ const asyncId = socket.config.asyncId
269
+ let responseData = JSON.stringify({
270
+ action,
271
+ data
272
+ });
273
+
274
+ if (asyncId && socket.config && socket.config.key) {
275
+ this.asyncMessages.get(socket.config.key).setMessage(asyncId, [{ socket, message: responseData }]);
276
+ } else {
277
+ socket.send(responseData);
278
+ }
279
+
280
+ if (socket.config && socket.config.organization_id)
281
+ this.recordTransfer('out', responseData, socket.config.organization_id)
282
+
283
+ }
284
+
285
+ // addAsyncMessage(key) {
286
+ // let asyncMessage = this.asyncMessages.get(key)
287
+ // if (!asyncMessage) {
288
+ // this.asyncMessages.set(key, new AsyncMessage(key));
289
+ // }
290
+ // }
291
+
292
+ getKeyFromUrl(pathname) {
293
+ var path = pathname.split("/");
294
+ var params = {
295
+ type: null,
296
+ key: pathname
297
+ }
298
+ if (path.length > 0) {
299
+ params.type = path[1];
300
+ params.organization_id = path[2]
301
+ }
302
+ return params
303
+ }
304
+
305
+
306
+ sendBinary(socket, data, organization_id) {
307
+ socket.send(data, { binary: true });
308
+ this.recordTransfer('out', data, organization_id)
309
+ }
310
+
311
+ recordTransfer(type, data, organization_id) {
312
+ this.emit("setBandwidth", null, {
313
+ type,
314
+ data,
315
+ organization_id
316
+ });
317
+ }
313
318
  }
314
319
 
315
320