authentication with cookies.

This commit is contained in:
Miroslav Šedivý 2021-01-29 23:14:59 +01:00
parent a5a82077c5
commit eac56533e6
4 changed files with 74 additions and 25 deletions

View File

@ -1,22 +1,22 @@
import * as Api from '../api' import * as Api from '../api'
export class NekoApi { export class NekoApi {
api_configuration = new Api.Configuration() api_configuration = new Api.Configuration({
basePath: location.href.replace(/\/+$/, ''),
})
public connect(url: string, id: string, secret: string) { public setUrl(url: string) {
this.api_configuration = new Api.Configuration({ this.api_configuration = new Api.Configuration({
basePath: url, basePath: url.replace(/\/+$/, ''),
baseOptions: {
auth: {
username: id,
password: secret,
},
},
}) })
} }
public disconnect() { get url(): string {
this.api_configuration = new Api.Configuration() return this.api_configuration.basePath || location.href.replace(/\/+$/, '')
}
get session(): SessionApi {
return new Api.SessionApi(this.api_configuration)
} }
get room(): RoomApi { get room(): RoomApi {
@ -28,5 +28,6 @@ export class NekoApi {
} }
} }
export type SessionApi = Api.SessionApi
export type RoomApi = Api.RoomApi export type RoomApi = Api.RoomApi
export type MembersApi = Api.MembersApi export type MembersApi = Api.MembersApi

View File

@ -29,14 +29,14 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
return typeof this._ws !== 'undefined' && this._ws.readyState === WebSocket.OPEN return typeof this._ws !== 'undefined' && this._ws.readyState === WebSocket.OPEN
} }
public connect(url: string, id: string, secret: string) { public connect(url: string) {
if (this.connected) { if (this.connected) {
throw new Error('attempting to create websocket while connection open') throw new Error('attempting to create websocket while connection open')
} }
this.emit('connecting') this.emit('connecting')
this._ws = new WebSocket(`${url}/ws?id=${encodeURIComponent(id)}&secret=${encodeURIComponent(secret)}`) this._ws = new WebSocket(url)
this._log.info(`connecting`) this._log.info(`connecting`)
this._ws.onopen = this.onConnected.bind(this) this._ws.onopen = this.onConnected.bind(this)

View File

@ -80,6 +80,7 @@
///////////////////////////// /////////////////////////////
public state = { public state = {
connection: { connection: {
authenticated: false,
websocket: 'disconnected', websocket: 'disconnected',
webrtc: 'disconnected', webrtc: 'disconnected',
type: 'none', type: 'none',
@ -116,6 +117,10 @@
members: {}, members: {},
} as NekoState } as NekoState
public get authenticated() {
return this.state.connection.authenticated
}
public get connected() { public get connected() {
return this.state.connection.websocket == 'connected' return this.state.connection.websocket == 'connected'
} }
@ -140,25 +145,61 @@
///////////////////////////// /////////////////////////////
// Public methods // Public methods
///////////////////////////// /////////////////////////////
public connect(url: string, id: string, secret: string) { public async setUrl(url: string) {
if (this.connected) {
throw new Error('client already connected')
}
const wsURL = url.replace(/^http/, 'ws').replace(/\/$|\/ws\/?$/, '')
this.websocket.connect(wsURL, id, secret)
const httpURL = url.replace(/^ws/, 'http').replace(/\/$|\/ws\/?$/, '') const httpURL = url.replace(/^ws/, 'http').replace(/\/$|\/ws\/?$/, '')
this.api.connect(httpURL, id, secret) this.api.setUrl(httpURL)
} }
public disconnect() { public async login(id: string, secret: string) {
if (this.authenticated) {
throw new Error('client already authenticated')
}
try {
await this.api.session.login({ id, secret })
Vue.set(this.state.connection, 'authenticated', true)
this.websocketConnect()
} catch (e) {
throw e
}
}
public async logout() {
if (!this.authenticated) {
throw new Error('client not authenticated')
}
try {
this.websocketDisconnect()
await this.api.session.logout()
Vue.set(this.state.connection, 'authenticated', false)
} catch (e) {
throw e
}
}
public websocketConnect() {
if (!this.authenticated) {
throw new Error('client not authenticated')
}
if (this.connected) {
throw new Error('client already connected to websocket')
}
this.websocket.connect(this.api.url.replace(/^http/, 'ws') + '/api/ws')
}
public websocketDisconnect() {
if (!this.authenticated) {
throw new Error('client not authenticated')
}
if (!this.connected) { if (!this.connected) {
throw new Error('client not connected') throw new Error('client not connected to websocket')
} }
this.websocket.disconnect() this.websocket.disconnect()
this.api.disconnect()
} }
public webrtcConnect() { public webrtcConnect() {
@ -348,6 +389,12 @@
Vue.set(this.state.connection, 'type', 'webrtc') Vue.set(this.state.connection, 'type', 'webrtc')
Vue.set(this.state.connection, 'can_watch', this.webrtc.supported) Vue.set(this.state.connection, 'can_watch', this.webrtc.supported)
Vue.set(this.state.connection, 'can_control', this.webrtc.supported) Vue.set(this.state.connection, 'can_control', this.webrtc.supported)
// check if is user logged in
this.api.session.whoami().then(() => {
Vue.set(this.state.connection, 'authenticated', true)
this.websocketConnect()
})
} }
beforeDestroy() { beforeDestroy() {

View File

@ -11,6 +11,7 @@ export default interface State {
// Connection // Connection
///////////////////////////// /////////////////////////////
export interface Connection { export interface Connection {
authenticated: boolean
websocket: 'disconnected' | 'connecting' | 'connected' websocket: 'disconnected' | 'connecting' | 'connected'
webrtc: 'disconnected' | 'connecting' | 'connected' webrtc: 'disconnected' | 'connecting' | 'connected'
type: 'webrtc' | 'fallback' | 'none' type: 'webrtc' | 'fallback' | 'none'