| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 |
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
3×
3×
3×
1×
1×
| 'use strict';
const csgrant = require('./index')
const util = require('util');
exports.showLog = false
const log = exports.showLog? console.log: ()=>{}
// returns true if any of users is in identities
function AnyOfUsersInIdentities(users, identities){
var intersection = identities.filter(function(n) {
// true if users has this identity
return users.indexOf(n) > -1
})
// if this array is not empty, we have at least
// one of the users in the identities list
return intersection.length > 0
}
// Fast lookup of sockets per user.
function SocketDict() {
// keep a list of active sockets
this.sockets = []
// a reference to the socket.io library
this.io = null;
// add new socket
this._addSocket = function (socket) {
// is socket already in the list?
const index = this.sockets.indexOf(socket)
if (index > -1)
return
// new socket
this.sockets.push(socket)
log('add socket: ', this.sockets.length , 'identities:', socket.identities)
}
// remove socket
this._removeSocket = function (socket) {
// is socket already in the list?
const index = this.sockets.indexOf(socket)
if (index > -1) {
// remove
log('remove socket: ', index)
this.sockets.splice(index,1)
return
}
}
// Notifies a list of users, if they are in any socket
this.notifyUsers = function (users, channel, data) {
log('\nnotify users:', users, channel, data)
log(' -# sockets:', this.sockets.length)
for (let socket of this.sockets) {
log(' -socket identities:', socket.identities)
if (AnyOfUsersInIdentities(users, socket.identities)) {
log(' --notifying', socket.identities)
csgrant.verifyToken(socket.token, function(err) {
if (err) {
console.error('Error verifying token: ' + err )
return
}
log(' --emit channel:', channel, 'data:', data)
socket.emit(channel, data)
})
}
}
log('end notify\n')
}
// Notify everybody....
this.notifyAll = function (channel, msg) {
this.io.sockets.emit(channel, msg);
}
}
// Initialise the socket.io library
// server:
exports.init = function(server, events) {
Eif (!server) {
log('No server available, socket connections will not be established')
return
}
const io = require('socket.io')(server)
userSockets.io = io
log('Init sockets')
// authorization middleware
io.use(function(socket, next) {
const handshakeData = socket.request
const token = handshakeData._query['token']
if(!token) {
const error = 'missing token in the socket'
console.log(error)
socket.emit('unauthorized', error, function() {
socket.disconnect('unauthorized')
return
})
}
socket.token = token
csgrant.verifyToken(socket.token, function(err, decoded) {
// function to call when unauthorized
var unauthorizedAccess = function(error) {
console.error('unauthorizedAccess:', error)
socket.emit('unauthorized', error, function() {
socket.disconnect('unauthorized');
});
}
// verify the token
let error
if (err) {
console.error('Error: ' + err.message);
error = {"message": "unauthorized"};
unauthorizedAccess(error);
return;
}
log(util.inspect(decoded))
if (!decoded.identities || decoded.identities.length == 0) {
console.error('Invalid token. No identities provided')
error = {"message": "no identities provided"}
unauthorizedAccess(error)
return
}
socket.identities = decoded.identities
next()
})
})
events.on('resource', function(resource, operation, users) {
const data = {resource: resource, operation: operation}
// notify the users on sockets with appropriate identities
userSockets.notifyUsers(users, 'resource', data)
})
io.on('connection', function (socket) {
log(' socket connection: ' + socket.identities[0])
userSockets._addSocket(socket)
socket.on('disconnect', function() {
log(' socket disconnect: ' + socket.identities[0])
userSockets._removeSocket(socket)
})
})
// allow others to send/receive messages
return io
}
// global variable for list of sockets
const userSockets = new SocketDict()
// global function to access sockets
exports.getUserSockets = function () {
return userSockets
}
|