Connection management now id based rather than type based
This commit is contained in:
@@ -5,10 +5,7 @@ const db = new Database('./src/lib/server/db/users.db', { verbose: console.info
|
||||
db.pragma('foreign_keys = ON')
|
||||
const initUsersTable = 'CREATE TABLE IF NOT EXISTS Users(id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(64) UNIQUE NOT NULL, password VARCHAR(72) NOT NULL)'
|
||||
const initUserConnectionsTable =
|
||||
'CREATE TABLE IF NOT EXISTS UserConnections(id INTEGER PRIMARY KEY AUTOINCREMENT, userId INTEGER NOT NULL, serviceName VARCHAR(64) NOT NULL, accessToken TEXT, refreshToken TEXT, expiry DATETIME, FOREIGN KEY(userId) REFERENCES Users(id))'
|
||||
const initJellyfinAuthTable = 'CREATE TABLE IF NOT EXISTS JellyfinConnections(id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT, accesstoken TEXT, serverid TEXT)'
|
||||
const initYouTubeMusicConnectionsTable = ''
|
||||
const initSpotifyConnectionsTable = ''
|
||||
'CREATE TABLE IF NOT EXISTS UserConnections(id INTEGER PRIMARY KEY AUTOINCREMENT, userId INTEGER NOT NULL, serviceType VARCHAR(64) NOT NULL, accessToken TEXT, refreshToken TEXT, expiry INTEGER, connectionInfo TEXT, FOREIGN KEY(userId) REFERENCES Users(id))'
|
||||
db.exec(initUsersTable)
|
||||
db.exec(initUserConnectionsTable)
|
||||
|
||||
@@ -30,41 +27,29 @@ export class Users {
|
||||
export class UserConnections {
|
||||
static validServices = Object.keys(Services)
|
||||
|
||||
static getConnections = (userId, serviceNames = null) => {
|
||||
if (!serviceNames) {
|
||||
const connections = db.prepare('SELECT * FROM UserConnections WHERE userId = ?').all(userId)
|
||||
if (connections.length === 0) return null
|
||||
return connections
|
||||
}
|
||||
|
||||
if (!Array.isArray(serviceNames)) {
|
||||
if (typeof serviceNames !== 'string') throw new Error('Service names must be a string or array of strings')
|
||||
serviceNames = [serviceNames]
|
||||
}
|
||||
|
||||
serviceNames = serviceNames.filter((service) => this.validServices.includes(service))
|
||||
|
||||
const placeholders = serviceNames.map(() => '?').join(', ') // This is SQL-injection safe, the placeholders are just ?, ?, ?....
|
||||
const connections = db.prepare(`SELECT * FROM UserConnections WHERE userId = ? AND serviceName IN (${placeholders})`).all(userId, ...serviceNames)
|
||||
static getConnections = (userId) => {
|
||||
const connections = db.prepare(`SELECT * FROM UserConnections WHERE userId = ?`).all(userId)
|
||||
if (connections.length === 0) return null
|
||||
return connections
|
||||
}
|
||||
|
||||
// May want to give accessToken a default of null in the future if one of the services does not use access tokens
|
||||
static setConnection = (userId, serviceName, accessToken, refreshToken = null, expiry = null) => {
|
||||
if (!this.validServices.includes(serviceName)) throw new Error(`Service name ${serviceName} is invalid`)
|
||||
static addConnection = (userId, serviceType, accessToken, options = {}) => {
|
||||
const { refreshToken = null, expiry = null, connectionInfo = null } = options
|
||||
|
||||
const existingConnection = this.getConnections(userId, serviceName)
|
||||
if (existingConnection) {
|
||||
db.prepare('UPDATE UserConnections SET accessToken = ?, refreshToken = ?, expiry = ? WHERE userId = ? AND serviceName = ?').run(accessToken, refreshToken, expiry, userId, serviceName)
|
||||
} else {
|
||||
db.prepare('INSERT INTO UserConnections(userId, serviceName, accessToken, refreshToken, expiry) VALUES(?, ?, ?, ?, ?)').run(userId, serviceName, accessToken, refreshToken, expiry)
|
||||
}
|
||||
// return this.getConnections(userId, serviceName) <--- Uncomment this if want to return new connection data after update
|
||||
if (!this.validServices.includes(serviceType)) throw new Error(`Service name ${serviceType} is invalid`)
|
||||
|
||||
if (connectionInfo) JSON.parse(connectionInfo) // Aditional validation, if connectionInfo is not stringified valid json it will throw an error
|
||||
|
||||
const commandInfo = db
|
||||
.prepare('INSERT INTO UserConnections(userId, serviceType, accessToken, refreshToken, expiry, connectionInfo) VALUES(?, ?, ?, ?, ?, ?)')
|
||||
.run(userId, serviceType, accessToken, refreshToken, expiry, connectionInfo)
|
||||
return commandInfo.lastInsertRowid
|
||||
}
|
||||
|
||||
static deleteConnection = (userId, serviceName) => {
|
||||
const info = db.prepare('DELETE FROM UserConnections WHERE userId = ? AND serviceName = ?').run(userId, serviceName)
|
||||
if (!info.changes === 0) throw new Error(`User does not have connection: ${serviceName}`)
|
||||
static deleteConnection = (userId, serviceId) => {
|
||||
const commandInfo = db.prepare('DELETE FROM UserConnections WHERE userId = ? AND id = ?').run(userId, serviceId)
|
||||
if (!commandInfo.changes === 0) throw new Error(`User does not have connection with id: ${serviceId}`)
|
||||
return serviceId
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user