@@ -12,168 +12,166 @@ import policy from "./policies";
12
12
const server = http . createServer ( app . callback ( ) ) ;
13
13
let io ;
14
14
15
- if ( process . env . WEBSOCKETS_ENABLED === "true" ) {
16
- const { can } = policy ;
17
-
18
- io = IO ( server , {
19
- path : "/realtime" ,
20
- serveClient : false ,
21
- cookie : false ,
22
- } ) ;
23
-
24
- io . adapter (
25
- socketRedisAdapter ( {
26
- pubClient : client ,
27
- subClient : subscriber ,
28
- } )
29
- ) ;
30
-
31
- SocketAuth ( io , {
32
- authenticate : async ( socket , data , callback ) => {
33
- const { token } = data ;
34
-
35
- try {
36
- const user = await getUserForJWT ( token ) ;
37
- socket . client . user = user ;
38
-
39
- // store the mapping between socket id and user id in redis
40
- // so that it is accessible across multiple server nodes
41
- await client . hset ( socket . id , "userId" , user . id ) ;
42
-
43
- return callback ( null , true ) ;
44
- } catch ( err ) {
45
- return callback ( err ) ;
46
- }
47
- } ,
48
- postAuthenticate : async ( socket , data ) => {
49
- const { user } = socket . client ;
50
-
51
- // the rooms associated with the current team
52
- // and user so we can send authenticated events
53
- let rooms = [ `team-${ user . teamId } ` , `user-${ user . id } ` ] ;
54
-
55
- // the rooms associated with collections this user
56
- // has access to on connection. New collection subscriptions
57
- // are managed from the client as needed through the 'join' event
58
- const collectionIds = await user . collectionIds ( ) ;
59
- collectionIds . forEach ( collectionId =>
60
- rooms . push ( `collection-${ collectionId } ` )
61
- ) ;
62
-
63
- // join all of the rooms at once
64
- socket . join ( rooms ) ;
65
-
66
- // allow the client to request to join rooms
67
- socket . on ( "join" , async event => {
68
- // user is joining a collection channel, because their permissions have
69
- // changed, granting them access.
70
- if ( event . collectionId ) {
71
- const collection = await Collection . scope ( {
72
- method : [ "withMembership" , user . id ] ,
73
- } ) . findByPk ( event . collectionId ) ;
74
-
75
- if ( can ( user , "read" , collection ) ) {
76
- socket . join ( `collection-${ event . collectionId } ` ) ;
77
- }
78
- }
15
+ const { can } = policy ;
79
16
80
- // user is joining a document channel, because they have navigated to
81
- // view a document.
82
- if ( event . documentId ) {
83
- const document = await Document . findByPk ( event . documentId , {
84
- userId : user . id ,
85
- } ) ;
17
+ io = IO ( server , {
18
+ path : "/realtime" ,
19
+ serveClient : false ,
20
+ cookie : false ,
21
+ } ) ;
86
22
87
- if ( can ( user , "read" , document ) ) {
88
- const room = `document-${ event . documentId } ` ;
23
+ io . adapter (
24
+ socketRedisAdapter ( {
25
+ pubClient : client ,
26
+ subClient : subscriber ,
27
+ } )
28
+ ) ;
29
+
30
+ SocketAuth ( io , {
31
+ authenticate : async ( socket , data , callback ) => {
32
+ const { token } = data ;
33
+
34
+ try {
35
+ const user = await getUserForJWT ( token ) ;
36
+ socket . client . user = user ;
37
+
38
+ // store the mapping between socket id and user id in redis
39
+ // so that it is accessible across multiple server nodes
40
+ await client . hset ( socket . id , "userId" , user . id ) ;
41
+
42
+ return callback ( null , true ) ;
43
+ } catch ( err ) {
44
+ return callback ( err ) ;
45
+ }
46
+ } ,
47
+ postAuthenticate : async ( socket , data ) => {
48
+ const { user } = socket . client ;
49
+
50
+ // the rooms associated with the current team
51
+ // and user so we can send authenticated events
52
+ let rooms = [ `team-${ user . teamId } ` , `user-${ user . id } ` ] ;
53
+
54
+ // the rooms associated with collections this user
55
+ // has access to on connection. New collection subscriptions
56
+ // are managed from the client as needed through the 'join' event
57
+ const collectionIds = await user . collectionIds ( ) ;
58
+ collectionIds . forEach ( collectionId =>
59
+ rooms . push ( `collection-${ collectionId } ` )
60
+ ) ;
61
+
62
+ // join all of the rooms at once
63
+ socket . join ( rooms ) ;
64
+
65
+ // allow the client to request to join rooms
66
+ socket . on ( "join" , async event => {
67
+ // user is joining a collection channel, because their permissions have
68
+ // changed, granting them access.
69
+ if ( event . collectionId ) {
70
+ const collection = await Collection . scope ( {
71
+ method : [ "withMembership" , user . id ] ,
72
+ } ) . findByPk ( event . collectionId ) ;
73
+
74
+ if ( can ( user , "read" , collection ) ) {
75
+ socket . join ( `collection-${ event . collectionId } ` ) ;
76
+ }
77
+ }
89
78
90
- await View . touch ( event . documentId , user . id , event . isEditing ) ;
91
- const editing = await View . findRecentlyEditingByDocument (
92
- event . documentId
93
- ) ;
79
+ // user is joining a document channel, because they have navigated to
80
+ // view a document.
81
+ if ( event . documentId ) {
82
+ const document = await Document . findByPk ( event . documentId , {
83
+ userId : user . id ,
84
+ } ) ;
94
85
95
- socket . join ( room , ( ) => {
96
- // let everyone else in the room know that a new user joined
97
- io . to ( room ) . emit ( "user.join" , {
98
- userId : user . id ,
99
- documentId : event . documentId ,
100
- isEditing : event . isEditing ,
101
- } ) ;
86
+ if ( can ( user , "read" , document ) ) {
87
+ const room = `document-${ event . documentId } ` ;
102
88
103
- // let this user know who else is already present in the room
104
- io . in ( room ) . clients ( async ( err , sockets ) => {
105
- if ( err ) throw err ;
106
-
107
- // because a single user can have multiple socket connections we
108
- // need to make sure that only unique userIds are returned. A Map
109
- // makes this easy.
110
- let userIds = new Map ( ) ;
111
- for ( const socketId of sockets ) {
112
- const userId = await client . hget ( socketId , "userId" ) ;
113
- userIds . set ( userId , userId ) ;
114
- }
115
- socket . emit ( "document.presence" , {
116
- documentId : event . documentId ,
117
- userIds : Array . from ( userIds . keys ( ) ) ,
118
- editingIds : editing . map ( view => view . userId ) ,
119
- } ) ;
120
- } ) ;
121
- } ) ;
122
- }
123
- }
124
- } ) ;
89
+ await View . touch ( event . documentId , user . id , event . isEditing ) ;
90
+ const editing = await View . findRecentlyEditingByDocument (
91
+ event . documentId
92
+ ) ;
125
93
126
- // allow the client to request to leave rooms
127
- socket . on ( "leave" , event => {
128
- if ( event . collectionId ) {
129
- socket . leave ( `collection-${ event . collectionId } ` ) ;
130
- }
131
- if ( event . documentId ) {
132
- const room = `document-${ event . documentId } ` ;
133
- socket . leave ( room , ( ) => {
134
- io . to ( room ) . emit ( "user.leave" , {
94
+ socket . join ( room , ( ) => {
95
+ // let everyone else in the room know that a new user joined
96
+ io . to ( room ) . emit ( "user.join" , {
135
97
userId : user . id ,
136
98
documentId : event . documentId ,
99
+ isEditing : event . isEditing ,
137
100
} ) ;
138
- } ) ;
139
- }
140
- } ) ;
141
101
142
- socket . on ( "disconnecting" , ( ) => {
143
- const rooms = Object . keys ( socket . rooms ) ;
144
-
145
- rooms . forEach ( room => {
146
- if ( room . startsWith ( "document-" ) ) {
147
- const documentId = room . replace ( "document-" , "" ) ;
148
- io . to ( room ) . emit ( "user.leave" , {
149
- userId : user . id ,
150
- documentId,
102
+ // let this user know who else is already present in the room
103
+ io . in ( room ) . clients ( async ( err , sockets ) => {
104
+ if ( err ) throw err ;
105
+
106
+ // because a single user can have multiple socket connections we
107
+ // need to make sure that only unique userIds are returned. A Map
108
+ // makes this easy.
109
+ let userIds = new Map ( ) ;
110
+ for ( const socketId of sockets ) {
111
+ const userId = await client . hget ( socketId , "userId" ) ;
112
+ userIds . set ( userId , userId ) ;
113
+ }
114
+ socket . emit ( "document.presence" , {
115
+ documentId : event . documentId ,
116
+ userIds : Array . from ( userIds . keys ( ) ) ,
117
+ editingIds : editing . map ( view => view . userId ) ,
118
+ } ) ;
151
119
} ) ;
152
- }
153
- } ) ;
154
- } ) ;
120
+ } ) ;
121
+ }
122
+ }
123
+ } ) ;
155
124
156
- socket . on ( "presence" , async event => {
125
+ // allow the client to request to leave rooms
126
+ socket . on ( "leave" , event => {
127
+ if ( event . collectionId ) {
128
+ socket . leave ( `collection-${ event . collectionId } ` ) ;
129
+ }
130
+ if ( event . documentId ) {
157
131
const room = `document-${ event . documentId } ` ;
132
+ socket . leave ( room , ( ) => {
133
+ io . to ( room ) . emit ( "user.leave" , {
134
+ userId : user . id ,
135
+ documentId : event . documentId ,
136
+ } ) ;
137
+ } ) ;
138
+ }
139
+ } ) ;
158
140
159
- if ( event . documentId && socket . rooms [ room ] ) {
160
- const view = await View . touch (
161
- event . documentId ,
162
- user . id ,
163
- event . isEditing
164
- ) ;
165
- view . user = user ;
141
+ socket . on ( "disconnecting" , ( ) => {
142
+ const rooms = Object . keys ( socket . rooms ) ;
166
143
167
- io . to ( room ) . emit ( "user.presence" , {
144
+ rooms . forEach ( room => {
145
+ if ( room . startsWith ( "document-" ) ) {
146
+ const documentId = room . replace ( "document-" , "" ) ;
147
+ io . to ( room ) . emit ( "user.leave" , {
168
148
userId : user . id ,
169
- documentId : event . documentId ,
170
- isEditing : event . isEditing ,
149
+ documentId,
171
150
} ) ;
172
151
}
173
152
} ) ;
174
- } ,
175
- } ) ;
176
- }
153
+ } ) ;
154
+
155
+ socket . on ( "presence" , async event => {
156
+ const room = `document-${ event . documentId } ` ;
157
+
158
+ if ( event . documentId && socket . rooms [ room ] ) {
159
+ const view = await View . touch (
160
+ event . documentId ,
161
+ user . id ,
162
+ event . isEditing
163
+ ) ;
164
+ view . user = user ;
165
+
166
+ io . to ( room ) . emit ( "user.presence" , {
167
+ userId : user . id ,
168
+ documentId : event . documentId ,
169
+ isEditing : event . isEditing ,
170
+ } ) ;
171
+ }
172
+ } ) ;
173
+ } ,
174
+ } ) ;
177
175
178
176
server . on ( "error" , err => {
179
177
throw err ;
0 commit comments