mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-07-10 09:24:56 +02:00
Update:Auth to use new user model
- Express requests include userNew to start migrating API controllers to new user model
This commit is contained in:
parent
59370cae81
commit
202ceb02b5
14 changed files with 626 additions and 392 deletions
|
@ -3,11 +3,20 @@ const Logger = require('./Logger')
|
|||
const Database = require('./Database')
|
||||
const Auth = require('./Auth')
|
||||
|
||||
/**
|
||||
* @typedef SocketClient
|
||||
* @property {string} id socket id
|
||||
* @property {SocketIO.Socket} socket
|
||||
* @property {number} connected_at
|
||||
* @property {import('./models/User')} user
|
||||
*/
|
||||
|
||||
class SocketAuthority {
|
||||
constructor() {
|
||||
this.Server = null
|
||||
this.io = null
|
||||
|
||||
/** @type {Object.<string, SocketClient>} */
|
||||
this.clients = {}
|
||||
}
|
||||
|
||||
|
@ -18,27 +27,29 @@ class SocketAuthority {
|
|||
*/
|
||||
getUsersOnline() {
|
||||
const onlineUsersMap = {}
|
||||
Object.values(this.clients).filter(c => c.user).forEach(client => {
|
||||
if (onlineUsersMap[client.user.id]) {
|
||||
onlineUsersMap[client.user.id].connections++
|
||||
} else {
|
||||
onlineUsersMap[client.user.id] = {
|
||||
...client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions),
|
||||
connections: 1
|
||||
Object.values(this.clients)
|
||||
.filter((c) => c.user)
|
||||
.forEach((client) => {
|
||||
if (onlineUsersMap[client.user.id]) {
|
||||
onlineUsersMap[client.user.id].connections++
|
||||
} else {
|
||||
onlineUsersMap[client.user.id] = {
|
||||
...client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions),
|
||||
connections: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
return Object.values(onlineUsersMap)
|
||||
}
|
||||
|
||||
getClientsForUser(userId) {
|
||||
return Object.values(this.clients).filter(c => c.user && c.user.id === userId)
|
||||
return Object.values(this.clients).filter((c) => c.user?.id === userId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits event to all authorized clients
|
||||
* @param {string} evt
|
||||
* @param {any} data
|
||||
* @param {string} evt
|
||||
* @param {any} data
|
||||
* @param {Function} [filter] optional filter function to only send event to specific users
|
||||
*/
|
||||
emitter(evt, data, filter = null) {
|
||||
|
@ -67,7 +78,7 @@ class SocketAuthority {
|
|||
// Emits event to all admin user clients
|
||||
adminEmitter(evt, data) {
|
||||
for (const socketId in this.clients) {
|
||||
if (this.clients[socketId].user && this.clients[socketId].user.isAdminOrUp) {
|
||||
if (this.clients[socketId].user?.isAdminOrUp) {
|
||||
this.clients[socketId].socket.emit(evt, data)
|
||||
}
|
||||
}
|
||||
|
@ -75,16 +86,14 @@ class SocketAuthority {
|
|||
|
||||
/**
|
||||
* Closes the Socket.IO server and disconnect all clients
|
||||
*
|
||||
* @param {Function} callback
|
||||
*
|
||||
* @param {Function} callback
|
||||
*/
|
||||
close(callback) {
|
||||
Logger.info('[SocketAuthority] Shutting down')
|
||||
// This will close all open socket connections, and also close the underlying http server
|
||||
if (this.io)
|
||||
this.io.close(callback)
|
||||
else
|
||||
callback()
|
||||
if (this.io) this.io.close(callback)
|
||||
else callback()
|
||||
}
|
||||
|
||||
initialize(Server) {
|
||||
|
@ -93,7 +102,7 @@ class SocketAuthority {
|
|||
this.io = new SocketIO.Server(this.Server.server, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ["GET", "POST"]
|
||||
methods: ['GET', 'POST']
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -144,7 +153,7 @@ class SocketAuthority {
|
|||
// admin user can send a message to all authenticated users
|
||||
// displays on the web app as a toast
|
||||
const client = this.clients[socket.id] || {}
|
||||
if (client.user && client.user.isAdminOrUp) {
|
||||
if (client.user?.isAdminOrUp) {
|
||||
this.emitter('admin_message', payload.message || '')
|
||||
} else {
|
||||
Logger.error(`[SocketAuthority] Non-admin user sent the message_all_users event`)
|
||||
|
@ -162,8 +171,8 @@ class SocketAuthority {
|
|||
/**
|
||||
* When setting up a socket connection the user needs to be associated with a socket id
|
||||
* for this the client will send a 'auth' event that includes the users API token
|
||||
*
|
||||
* @param {SocketIO.Socket} socket
|
||||
*
|
||||
* @param {SocketIO.Socket} socket
|
||||
* @param {string} token JWT
|
||||
*/
|
||||
async authenticateSocket(socket, token) {
|
||||
|
@ -176,6 +185,7 @@ class SocketAuthority {
|
|||
Logger.error('Cannot validate socket - invalid token')
|
||||
return socket.emit('invalid_token')
|
||||
}
|
||||
|
||||
// get the user via the id from the decoded jwt.
|
||||
const user = await Database.userModel.getUserByIdOrOldId(token_data.userId)
|
||||
if (!user) {
|
||||
|
@ -196,18 +206,13 @@ class SocketAuthority {
|
|||
|
||||
client.user = user
|
||||
|
||||
if (!client.user.toJSONForBrowser) {
|
||||
Logger.error('Invalid user...', client.user)
|
||||
return
|
||||
}
|
||||
|
||||
Logger.debug(`[SocketAuthority] User Online ${client.user.username}`)
|
||||
|
||||
this.adminEmitter('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions))
|
||||
|
||||
// Update user lastSeen without firing sequelize bulk update hooks
|
||||
user.lastSeen = Date.now()
|
||||
await Database.userModel.updateFromOld(user, false)
|
||||
await user.save({ hooks: false })
|
||||
|
||||
const initialPayload = {
|
||||
userId: client.user.id,
|
||||
|
@ -224,4 +229,4 @@ class SocketAuthority {
|
|||
this.Server.cancelLibraryScan(id)
|
||||
}
|
||||
}
|
||||
module.exports = new SocketAuthority()
|
||||
module.exports = new SocketAuthority()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue