Add Nocturne debug web UI, core process control, and web QR login
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Veskslop daemon — auth state for the web UI.
|
||||
*
|
||||
* Owns at most one QR login session. The terminal tool and the web UI share
|
||||
* the session class. The token file stays the single credential store.
|
||||
*/
|
||||
|
||||
import { existsSync } from "node:fs";
|
||||
|
||||
import { isTerminalQrState, QrLoginSession, type QrLoginState, type QrLoginUpdate } from "./qr-session.js";
|
||||
|
||||
export interface AuthSessionSnapshot {
|
||||
state: QrLoginState;
|
||||
url?: string;
|
||||
user?: object;
|
||||
error?: string;
|
||||
captcha?: object;
|
||||
}
|
||||
|
||||
export interface AuthStatus {
|
||||
tokenFile: string;
|
||||
hasToken: boolean;
|
||||
session: AuthSessionSnapshot | null;
|
||||
}
|
||||
|
||||
export class AuthService {
|
||||
private session?: QrLoginSession;
|
||||
private snapshot: AuthSessionSnapshot | null = null;
|
||||
private freshLogin = false;
|
||||
|
||||
constructor(
|
||||
private readonly tokenFile: string,
|
||||
private readonly onUpdate?: (update: QrLoginUpdate) => void
|
||||
) {}
|
||||
|
||||
status(): AuthStatus {
|
||||
return {
|
||||
tokenFile: this.tokenFile,
|
||||
hasToken: existsSync(this.tokenFile),
|
||||
session: this.snapshot ? structuredClone(this.snapshot) : null
|
||||
};
|
||||
}
|
||||
|
||||
startQr(): AuthStatus {
|
||||
if (this.session && !isTerminalQrState(this.session.state)) return this.status();
|
||||
|
||||
this.snapshot = { state: "connecting" };
|
||||
this.session = new QrLoginSession({
|
||||
tokenFile: this.tokenFile,
|
||||
debug: process.env.DEBUG === "1",
|
||||
onUpdate: update => {
|
||||
this.snapshot = { ...update };
|
||||
if (update.state === "finished") this.freshLogin = true;
|
||||
this.onUpdate?.(update);
|
||||
}
|
||||
});
|
||||
this.session.start();
|
||||
|
||||
return this.status();
|
||||
}
|
||||
|
||||
cancelQr(): AuthStatus {
|
||||
this.session?.cancel();
|
||||
return this.status();
|
||||
}
|
||||
|
||||
submitCaptcha(key: string): boolean {
|
||||
return this.session?.submitCaptcha(key) ?? false;
|
||||
}
|
||||
|
||||
/** True once after a successful login. Used to force the new token on start. */
|
||||
consumeFreshLogin(): boolean {
|
||||
const value = this.freshLogin;
|
||||
this.freshLogin = false;
|
||||
return value;
|
||||
}
|
||||
|
||||
clearFreshLogin(): void {
|
||||
this.freshLogin = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user