diff --git a/index.js b/index.js index 57bdf03..10467f3 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,7 @@ const PORT = process.env.DEEMIX_SERVER_PORT || argv.port process.env.DEEMIX_SERVER_PORT = PORT process.env.DEEMIX_HOST = argv.host -const server = new DeemixServer(argv.host, PORT) +const server = new DeemixServer(argv.host, PORT, false) server.init() let win diff --git a/server/src/helpers/loginStorage.ts b/server/src/helpers/loginStorage.ts new file mode 100644 index 0000000..d034b18 --- /dev/null +++ b/server/src/helpers/loginStorage.ts @@ -0,0 +1,45 @@ +import fs from 'fs' +// @ts-expect-error +import deemix from 'deemix' +import { LoginFile } from '../types' + +const configFolder = deemix.utils.localpaths.getConfigFolder() + +const DEFAULTS: LoginFile = { + accessToken: null, + arl: null +} + +let loginData: LoginFile = { + accessToken: null, + arl: null +} + +export function loadLoginCredentials() { + if (!fs.existsSync(configFolder)) fs.mkdirSync(configFolder) + if (!fs.existsSync(configFolder + 'login.json')) resetLoginCredentials() + + try { + loginData = JSON.parse(fs.readFileSync(configFolder + 'login.json').toString()) + } catch (e) { + if (e.name === 'SyntaxError') resetLoginCredentials() + } +} + +export function getLoginCredentials(): LoginFile { + if (!loginData.arl) loadLoginCredentials() + return loginData +} + +export function saveLoginCredentials(newLogin: LoginFile) { + if (newLogin.arl) loginData.arl = newLogin.arl + if (newLogin.accessToken) loginData.accessToken = newLogin.accessToken + if (!fs.existsSync(configFolder)) fs.mkdirSync(configFolder) + fs.writeFileSync(configFolder + 'login.json', JSON.stringify(loginData, null, 2)) +} + +export function resetLoginCredentials() { + if (!fs.existsSync(configFolder)) fs.mkdirSync(configFolder) + fs.writeFileSync(configFolder + 'login.json', JSON.stringify(DEFAULTS, null, 2)) + loginData = JSON.parse(JSON.stringify(DEFAULTS)) +} diff --git a/server/src/index.ts b/server/src/index.ts index f24d03a..96a6865 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -10,13 +10,15 @@ if (!isModule) { // TODO: Remove type assertion while keeping correct types const argv = yargs(hideBin(process.argv)).options({ port: { type: 'string', default: '6595' }, - host: { type: 'string', default: '127.0.0.1' } + host: { type: 'string', default: '127.0.0.1' }, + singleuser: { type: 'boolean', default: false } }).argv as Arguments const DEEMIX_SERVER_PORT = process.env.DEEMIX_SERVER_PORT ?? argv.port const DEEMIX_HOST = process.env.DEEMIX_HOST ?? argv.host + const IS_SINGLE_USER = !!argv.singleuser - const server = new DeemixServer(DEEMIX_HOST, DEEMIX_SERVER_PORT) + const server = new DeemixServer(DEEMIX_HOST, DEEMIX_SERVER_PORT, IS_SINGLE_USER) server.init() } diff --git a/server/src/routes/api/post/loginArl.ts b/server/src/routes/api/post/loginArl.ts index cf5ef6e..92f649b 100644 --- a/server/src/routes/api/post/loginArl.ts +++ b/server/src/routes/api/post/loginArl.ts @@ -4,6 +4,7 @@ import { Deezer } from 'deezer-js' import { sessionDZ } from '../../../app' import { ApiHandler } from '../../../types' import { logger } from '../../../helpers/logger' +import { saveLoginCredentials, resetLoginCredentials } from '../../../helpers/loginStorage' export interface RawLoginArlBody { arl: string @@ -24,6 +25,7 @@ const handler: RequestHandler<{}, {}, RawLoginArlBody, {}> = async (req, res, _) if (!sessionDZ[req.session.id]) sessionDZ[req.session.id] = new Deezer() const deemix = req.app.get('deemix') const dz = sessionDZ[req.session.id] + const isSingleUser = req.app.get('isSingleUser') if (!req.body) { return res.status(400).send() @@ -69,7 +71,14 @@ const handler: RequestHandler<{}, {}, RawLoginArlBody, {}> = async (req, res, _) currentChild: dz.selected_account } - if (response !== LoginStatus.NOT_AVAILABLE && response !== LoginStatus.FAILED) deemix.startQueue(dz) + if (response !== LoginStatus.NOT_AVAILABLE && response !== LoginStatus.FAILED) { + deemix.startQueue(dz) + if (isSingleUser) + saveLoginCredentials({ + accessToken: null, + arl: returnValue.arl + }) + } else if (isSingleUser) resetLoginCredentials() return res.status(200).send(returnValue) } diff --git a/server/src/routes/api/post/loginEmail.ts b/server/src/routes/api/post/loginEmail.ts index e2bf143..256c254 100644 --- a/server/src/routes/api/post/loginEmail.ts +++ b/server/src/routes/api/post/loginEmail.ts @@ -1,9 +1,11 @@ import { ApiHandler } from '../../../types' import { getAccessToken, getArlFromAccessToken } from '../../../app' +import { saveLoginCredentials } from '../../../helpers/loginStorage' const path = '/loginEmail' const handler: ApiHandler['handler'] = async (req, res) => { + const isSingleUser = req.app.get('isSingleUser') const { email, password } = req.body let accessToken = req.body.accessToken @@ -14,6 +16,12 @@ const handler: ApiHandler['handler'] = async (req, res) => { let arl if (accessToken) arl = await getArlFromAccessToken(accessToken) + if (isSingleUser && accessToken) + saveLoginCredentials({ + accessToken, + arl: arl || null + }) + res.send({ accessToken, arl }) } diff --git a/server/src/routes/api/post/logout.ts b/server/src/routes/api/post/logout.ts index 0fb5e08..0e975c0 100644 --- a/server/src/routes/api/post/logout.ts +++ b/server/src/routes/api/post/logout.ts @@ -2,12 +2,14 @@ import { Deezer } from 'deezer-js' import { ApiHandler } from '../../../types' import { sessionDZ } from '../../../app' +import { resetLoginCredentials } from '../../../helpers/loginStorage' const path: ApiHandler['path'] = '/logout' const handler: ApiHandler['handler'] = (req, res) => { sessionDZ[req.session.id] = new Deezer() res.send({ logged_out: true }) + if (req.app.get('isSingleUser')) resetLoginCredentials() } const apiHandler: ApiHandler = { path, handler } diff --git a/server/src/routes/index.ts b/server/src/routes/index.ts index 1a44ee2..89bb249 100644 --- a/server/src/routes/index.ts +++ b/server/src/routes/index.ts @@ -2,6 +2,7 @@ import express from 'express' // @ts-expect-error import { Deezer } from 'deezer-js' import { logger } from '../helpers/logger' +import { getLoginCredentials } from '../helpers/loginStorage' import { sessionDZ, deemixVersion, currentVersion } from '../app' const router = express.Router() @@ -11,6 +12,7 @@ router.get('/connect', async (req, res) => { if (!sessionDZ[req.session.id]) sessionDZ[req.session.id] = new Deezer() const dz = sessionDZ[req.session.id] const deemix = req.app.get('deemix') + const isSingleUser = req.app.get('isSingleUser') if (!update) { logger.info(`Currently running deemix-gui version ${currentVersion}`) @@ -30,6 +32,8 @@ router.get('/connect', async (req, res) => { settingsData: deemix.getSettings() } + if (isSingleUser && result.autologin) result.singleUser = getLoginCredentials() + if (result.settingsData.settings.autoCheckForUpdates) result.checkForUpdates = true const queue = deemix.getQueue() diff --git a/server/src/server.ts b/server/src/server.ts index 3e0cc37..1550cf9 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -10,6 +10,7 @@ import { getErrorCb, getListeningCb } from './helpers/server-callbacks' import { registerApis } from './routes/api/register' import { registerWebsocket } from './websocket' import { logger, removeOldLogs } from './helpers/logger' +import { loadLoginCredentials } from './helpers/loginStorage' import { Port, Listener } from './types' import { DeemixApp } from './app' import { normalizePort } from './helpers/port' @@ -17,15 +18,17 @@ import { normalizePort } from './helpers/port' export class DeemixServer { host: string port: Port + isSingleUser: boolean wss: WsServer app: Application server: Server deemixApp: DeemixApp - constructor(host: string, port: string) { + constructor(host: string, port: string, singleuser: boolean = false) { this.host = host this.port = normalizePort(port) + this.isSingleUser = singleuser this.wss = new WsServer({ noServer: true }) this.app = express() @@ -45,11 +48,13 @@ export class DeemixServer { } this.deemixApp = new DeemixApp(listener) + if (this.isSingleUser) loadLoginCredentials() } init() { const debug = initDebug('deemix-gui:server') this.app.set('deemix', this.deemixApp) + this.app.set('isSingleUser', this.isSingleUser) /* === Middlewares === */ registerMiddlewares(this.app) diff --git a/server/src/types.ts b/server/src/types.ts index 40bd990..9d12134 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -243,3 +243,8 @@ export interface Arguments { export interface Listener { send: (key: string, data?: any) => void } + +export interface LoginFile { + arl: string | null + accessToken: string | null +} diff --git a/webui b/webui index 283bb5f..f4f4deb 160000 --- a/webui +++ b/webui @@ -1 +1 @@ -Subproject commit 283bb5fa0df7042c78919f64c1c6638996ca6ac8 +Subproject commit f4f4debf7f905ab1c64a0af5f393e554ddfb427e