|
|
@@ -1,4 +1,4 @@
|
|
1
|
|
-import { RPCServer, Socket } from "rpclibrary";
|
|
|
1
|
+import { RPCServer, Socket, RPCInterface } from "rpclibrary";
|
|
2
|
2
|
import { Inject, Injectable } from "../../Injector/ServiceDecorator";
|
|
3
|
3
|
import { FrontworkAdmin } from "../../Admin/Admin";
|
|
4
|
4
|
import { GuildManager } from "../Guild/GuildManager";
|
|
|
@@ -23,10 +23,9 @@ const uuid = require('uuid/v4')
|
|
23
|
23
|
const salt = "6pIbc6yjSN"
|
|
24
|
24
|
const ONE_WEEK = 604800000
|
|
25
|
25
|
|
|
26
|
|
-type Serverstate = {
|
|
27
|
|
- server: RPCServer,
|
|
|
26
|
+type Serverstate<SubresT, InterfaceT extends RPCInterface> = {
|
|
|
27
|
+ server: RPCServer<SubresT, InterfaceT>,
|
|
28
|
28
|
port : number,
|
|
29
|
|
- allowed: string[]
|
|
30
|
29
|
};
|
|
31
|
30
|
|
|
32
|
31
|
|
|
|
@@ -51,8 +50,9 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
51
|
50
|
private character : CharacterManager
|
|
52
|
51
|
|
|
53
|
52
|
exporters :any[] = []
|
|
54
|
|
- rankServers : {[rank in Rank] : Serverstate}
|
|
|
53
|
+ rankServer : Serverstate<{}, FrontcraftFeatureIfc>
|
|
55
|
54
|
userLogins : {[username in string] : UserRecord} = {}
|
|
|
55
|
+ allowed: string[] = []
|
|
56
|
56
|
|
|
57
|
57
|
exportRPCs = () => [
|
|
58
|
58
|
this.login,
|
|
|
@@ -145,19 +145,11 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
145
|
145
|
}
|
|
146
|
146
|
})))
|
|
147
|
147
|
|
|
148
|
|
- //start rankServers
|
|
149
|
|
- let rankServers = { } as any
|
|
150
|
|
- await Promise.all(_Rank.map(async (r,i) => {
|
|
151
|
|
- const port = 20001 + i
|
|
152
|
|
- const rankServer = await this.startRankServer(r, port)
|
|
153
|
|
- rankServers[r] = {
|
|
154
|
|
- server: rankServer,
|
|
155
|
|
- port: port,
|
|
156
|
|
- allowed: []
|
|
157
|
|
- }
|
|
158
|
|
- }))
|
|
159
|
|
- this.rankServers = rankServers
|
|
160
|
|
- getLogger('UserManager').debug(Object.values(this.rankServers).length+" rank servers started")
|
|
|
148
|
+ const rankServer = await this.startRankServer(20001)
|
|
|
149
|
+ this.rankServer = {
|
|
|
150
|
+ server: rankServer,
|
|
|
151
|
+ port: 20001
|
|
|
152
|
+ }
|
|
161
|
153
|
setInterval(this.checkExpiredSessions, 600_000)
|
|
162
|
154
|
}
|
|
163
|
155
|
|
|
|
@@ -166,20 +158,17 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
166
|
158
|
Object.values(x.connections).forEach(c => c.destroy())
|
|
167
|
159
|
})
|
|
168
|
160
|
|
|
169
|
|
- Object.values(this.rankServers)
|
|
170
|
|
- .map(state => {
|
|
171
|
|
- try{
|
|
172
|
|
- return state.server.destroy()
|
|
173
|
|
- }catch(e){
|
|
174
|
|
- getLogger('UserManager').warn(e)
|
|
175
|
|
- }
|
|
176
|
|
- })
|
|
|
161
|
+ try{
|
|
|
162
|
+ return this.rankServer.server.destroy()
|
|
|
163
|
+ }catch(e){
|
|
|
164
|
+ //getLogger('UserManager').warn(e)
|
|
|
165
|
+ }
|
|
177
|
166
|
}
|
|
178
|
167
|
|
|
179
|
168
|
checkExpiredSessions = () => {
|
|
180
|
169
|
Object.values(this.userLogins).map(userLogin => {
|
|
181
|
170
|
const auth = userLogin.auth
|
|
182
|
|
- if(!this.checkToken(auth.token.value, auth.user.rank)){
|
|
|
171
|
+ if(!this.checkToken(auth.token.value)){
|
|
183
|
172
|
this.logout(auth.user.username, auth.token.value)
|
|
184
|
173
|
}
|
|
185
|
174
|
})
|
|
|
@@ -232,6 +221,13 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
232
|
221
|
await this.admin.knex('rpcpermissions')
|
|
233
|
222
|
.where('rpcname', '=', permission.rpcname)
|
|
234
|
223
|
.update(permission)
|
|
|
224
|
+
|
|
|
225
|
+ await Promise.all(
|
|
|
226
|
+ Object.entries(this.userLogins).map(([username, record]) => {
|
|
|
227
|
+ if(record.user.rank === "ADMIN") return
|
|
|
228
|
+ return this.adminLogout(username)
|
|
|
229
|
+ })
|
|
|
230
|
+ )
|
|
235
|
231
|
}
|
|
236
|
232
|
|
|
237
|
233
|
getPermissions = async () : Promise<RPCPermission[]> => {
|
|
|
@@ -313,15 +309,10 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
313
|
309
|
await sock.call('kick')
|
|
314
|
310
|
}))
|
|
315
|
311
|
|
|
316
|
|
- Object.values(this.rankServers)
|
|
317
|
|
- .forEach(state => {
|
|
318
|
|
- state.allowed = state.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value)
|
|
319
|
|
- })
|
|
|
312
|
+ this.allowed = this.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value)
|
|
320
|
313
|
delete this.userLogins[username]
|
|
321
|
314
|
}
|
|
322
|
|
- }catch(e){
|
|
323
|
|
- getLogger('UserManager').warn(e)
|
|
324
|
|
- }
|
|
|
315
|
+ }catch(e){}
|
|
325
|
316
|
}
|
|
326
|
317
|
|
|
327
|
318
|
wipeCurrency = async () => {
|
|
|
@@ -356,11 +347,11 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
356
|
347
|
const userAuth : Auth = {
|
|
357
|
348
|
token: token,
|
|
358
|
349
|
user: user,
|
|
359
|
|
- port: this.rankServers[user.rank].port
|
|
|
350
|
+ port: this.rankServer.port
|
|
360
|
351
|
}
|
|
361
|
352
|
|
|
362
|
353
|
this.userLogins[user.username] = {connections: {}, auth: userAuth, user:user}
|
|
363
|
|
- this.rankServers[user.rank].allowed.push(token.value)
|
|
|
354
|
+ this.allowed.push(token.value)
|
|
364
|
355
|
return userAuth
|
|
365
|
356
|
}
|
|
366
|
357
|
|
|
|
@@ -378,49 +369,43 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|
378
|
369
|
return
|
|
379
|
370
|
}
|
|
380
|
371
|
|
|
381
|
|
- startRankServer = async (rank : Rank, port: number) : Promise<RPCServer> => {
|
|
382
|
|
-
|
|
383
|
|
- const allowedRPCs = await this.getRPCForRank(rank)
|
|
384
|
|
- let rpcServer
|
|
385
|
|
- let n = 0
|
|
386
|
|
- while(!rpcServer){
|
|
387
|
|
- n++
|
|
388
|
|
- await Promise.race([
|
|
389
|
|
- new Promise((res, rej) => {
|
|
390
|
|
- rpcServer = new RPCServer(port, allowedRPCs, {
|
|
391
|
|
- closeHandler: (socket) => {
|
|
392
|
|
- Object.values(this.userLogins)
|
|
393
|
|
- .forEach(login => delete login.connections[socket.port])
|
|
394
|
|
-
|
|
395
|
|
- },
|
|
396
|
|
- connectionHandler: (socket) => {
|
|
397
|
|
- this.checkConnection(socket).then(res => {
|
|
398
|
|
- if(!res){
|
|
399
|
|
- socket.destroy();
|
|
400
|
|
- }
|
|
401
|
|
- }).catch((e) => {
|
|
402
|
|
- socket.destroy();
|
|
403
|
|
- getLogger('UserManager').warn(e);
|
|
404
|
|
- })
|
|
405
|
|
- },
|
|
406
|
|
- errorHandler: (socket, e, rpcName, args) => {
|
|
407
|
|
- getLogger('UserManager').error(rpcName, args, e);
|
|
408
|
|
- },
|
|
409
|
|
- sesame: (sesame) => this.checkToken(sesame, rank),
|
|
410
|
|
- visibility: '0.0.0.0'
|
|
411
|
|
- })
|
|
412
|
|
- res()
|
|
413
|
|
- }),
|
|
414
|
|
- new Promise((res, rej) => setTimeout(res, 500))
|
|
415
|
|
- ])
|
|
416
|
|
- if(!rpcServer && n>1)
|
|
417
|
|
- getLogger('UserManager').warn("createServer retry nr.", n, 'port', port)
|
|
418
|
|
- }
|
|
|
372
|
+ startRankServer = async (port: number) : Promise<RPCServer<{},FrontcraftFeatureIfc>> => {
|
|
|
373
|
+ let rpcs = [
|
|
|
374
|
+ ...this.exportRPCFeatures(),
|
|
|
375
|
+ ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
|
|
|
376
|
+ ]
|
|
|
377
|
+ let rpcServer = new RPCServer<{},FrontcraftFeatureIfc>(port, rpcs, {
|
|
|
378
|
+ accessFilter: async (sesame, exporter) => {
|
|
|
379
|
+ const record = this.getUserRecordByToken(sesame!)
|
|
|
380
|
+ if(!record) return false
|
|
|
381
|
+ return await this.getPermission(exporter.name, record.user.rank)
|
|
|
382
|
+ },
|
|
|
383
|
+ closeHandler: (socket) => {
|
|
|
384
|
+ Object.values(this.userLogins)
|
|
|
385
|
+ .forEach(login => delete login.connections[socket.port])
|
|
|
386
|
+
|
|
|
387
|
+ },
|
|
|
388
|
+ connectionHandler: (socket) => {
|
|
|
389
|
+ this.checkConnection(socket).then(res => {
|
|
|
390
|
+ if(!res){
|
|
|
391
|
+ socket.destroy();
|
|
|
392
|
+ }
|
|
|
393
|
+ }).catch((e) => {
|
|
|
394
|
+ socket.destroy();
|
|
|
395
|
+ })
|
|
|
396
|
+ },
|
|
|
397
|
+ errorHandler: (socket, e, rpcName, args) => {
|
|
|
398
|
+ getLogger('UserManager').error(rpcName, args, e);
|
|
|
399
|
+ },
|
|
|
400
|
+ sesame: (sesame) => this.checkToken(sesame),
|
|
|
401
|
+ visibility: '0.0.0.0'
|
|
|
402
|
+ })
|
|
|
403
|
+
|
|
419
|
404
|
return rpcServer
|
|
420
|
405
|
}
|
|
421
|
406
|
|
|
422
|
|
- checkToken = (token: string, rank: Rank) : boolean => this.rankServers[rank].allowed.includes(token)
|
|
423
|
|
- && Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
|
|
|
407
|
+ checkToken = (token: string) : boolean => this.allowed.includes(token)
|
|
|
408
|
+ && Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
|
|
424
|
409
|
|
|
425
|
410
|
checkTokenOwnedByUser = (username: string, tokenValue: string) => {
|
|
426
|
411
|
username = username.toLowerCase()
|