Support periodic auth checks in SecurityContext on web socket connections

This commit is contained in:
2022-08-09 23:49:25 -05:00
parent efb9726470
commit e339ec718d
10 changed files with 137 additions and 2 deletions

View File

@@ -17,6 +17,8 @@ import {WebSocketCloseEvent} from '../../http/lifecycle/WebSocketCloseEvent'
import {apiEvent, error} from '../../http/response/api'
import {AsyncResource, executionAsyncId} from 'async_hooks'
import {Session} from '../../http/session/Session'
import {Config} from '../../service/Config'
import {WebSocketHealthCheckEvent} from '../../http/lifecycle/WebSocketHealthCheckEvent'
@Injectable()
export class WebSocketBus implements EventBus, AwareOfContainerLifecycle {
@@ -50,6 +52,9 @@ export class WebSocketBus implements EventBus, AwareOfContainerLifecycle {
@Inject()
protected readonly session!: Session
@Inject()
protected readonly config!: Config
public readonly uuid = uuid4()
private connected = false
@@ -125,7 +130,7 @@ export class WebSocketBus implements EventBus, AwareOfContainerLifecycle {
}
}
up(): void {
async up(): Promise<void> {
const resource = new AsyncResource('WebSocketBus', {
triggerAsyncId: executionAsyncId(),
requireManualDestroy: false,
@@ -147,10 +152,53 @@ export class WebSocketBus implements EventBus, AwareOfContainerLifecycle {
})
})
this.ws.on('close', () => this.bus.push(new WebSocketCloseEvent()))
this.ws.on('error', () => this.bus.push(new WebSocketCloseEvent()))
await this.registerHealthCheck()
this.connected = true
}
/**
* Set up an interval that fires a `WebSocketHealthCheckEvent` on the request bus.
* This can be used, e.g., to check if the user is still logged in.
* You can control the interval by setting the `server.socket.healthCheckIntervalSeconds`
* config option. Set the option to 0 to disable the interval.
* @protected
*/
protected async registerHealthCheck(): Promise<void> {
const interval = this.config.safe('server.socket.healthCheckIntervalSeconds')
.or(60)
.integer()
if ( interval === 0 ) {
return
}
const handle = setInterval(() => {
if ( !this.isConnected() ) {
return
}
return this.bus.push(new WebSocketHealthCheckEvent())
}, interval * 1000)
await this.bus.subscribe(WebSocketCloseEvent, () => {
clearInterval(handle)
})
}
down(): void {
if ( this.connected ) {
try {
this.ws.close()
} catch (e) {
this.logging.error('Error closing socket:')
this.logging.error(e)
}
}
this.connected = false
}