Revert "添加自动登录 | feat(login): automatically restore last logged-in account (#1980)"
This reverts commit 31c45bf18e4ea2cc23f6492304fef88afb8e8302.
This commit is contained in:
@@ -87,13 +87,11 @@ export async function NCoreInitFramework (
|
||||
|
||||
// 提前启动 WebUI,使其在登录前可用,支持通过 WebUI 操控登录过程
|
||||
WebUiDataRuntime.setWorkingEnv(NapCatCoreWorkingEnv.Framework);
|
||||
await InitWebUi(logger, pathWrapper, logSubscription, statusHelperSubscription)
|
||||
.catch(e => logger.logError(e));
|
||||
InitWebUi(logger, pathWrapper, logSubscription, statusHelperSubscription).then().catch(e => logger.logError(e));
|
||||
|
||||
// 直到登录成功后,执行下一步
|
||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||
const loginContext = { isLogined: false };
|
||||
let autoLoginTriggered = false;
|
||||
|
||||
const loginListener = new NodeIKernelLoginListener();
|
||||
|
||||
@@ -107,11 +105,6 @@ export async function NCoreInitFramework (
|
||||
loginContext.isLogined = true;
|
||||
WebUiDataRuntime.setQQLoginStatus(true);
|
||||
WebUiDataRuntime.setQQLoginError('');
|
||||
try {
|
||||
await WebUiConfig.UpdateLastLoginAccount(loginResult.uin);
|
||||
} catch (error) {
|
||||
logger.logWarn('[NapCat] [Framework] 保存最近登录账号失败:', error);
|
||||
}
|
||||
await new Promise<void>(resolve => {
|
||||
registerInitCallback(() => resolve());
|
||||
});
|
||||
@@ -147,19 +140,12 @@ export async function NCoreInitFramework (
|
||||
logger.log('[NapCat] [Framework] 登录服务已连接');
|
||||
// 注册 WebUI 登录操作回调
|
||||
registerWebUiLoginCallbacks(loginService, loginContext, logger);
|
||||
if (autoLoginTriggered) return;
|
||||
autoLoginTriggered = true;
|
||||
(async () => {
|
||||
try {
|
||||
const res = await loginService.getLoginList();
|
||||
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
|
||||
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
|
||||
WebUiDataRuntime.setQQNewLoginList(list);
|
||||
} catch (error) {
|
||||
logger.logError('[NapCat] [Framework] 获取登录列表失败:', error);
|
||||
}
|
||||
await WebUiDataRuntime.runWebUiConfigQuickFunction();
|
||||
})().catch(error => logger.logError('[NapCat] [Framework] 自动登录执行失败:', error));
|
||||
// 获取历史登录列表供 WebUI 使用
|
||||
loginService.getLoginList().then((res) => {
|
||||
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
|
||||
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
|
||||
WebUiDataRuntime.setQQNewLoginList(list);
|
||||
}).catch(e => logger.logError('[NapCat] [Framework] 获取登录列表失败:', e));
|
||||
};
|
||||
|
||||
loginListener.onQRCodeSessionUserScaned = () => {
|
||||
|
||||
@@ -28,7 +28,7 @@ echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > "%NAPCAT_LO
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %*
|
||||
|
||||
REM Optional: pass the QQ number as the first argument for quick login; omit it for QR code login
|
||||
REM Example: "%~f0" 123456
|
||||
REM Optional: -q <QQ_NUMBER> for quick login, omit for QR code login
|
||||
REM Example: "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" -q 123456
|
||||
|
||||
pause
|
||||
|
||||
@@ -37,5 +37,5 @@ echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > "%NAPCAT_LO
|
||||
|
||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %*
|
||||
|
||||
REM Optional: pass the QQ number as the first argument for quick login; omit it for QR code login
|
||||
REM Example: "%~f0" 123456
|
||||
REM Optional: -q <QQ_NUMBER> for quick login, omit for QR code login
|
||||
REM Example: "%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" -q 123456
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
REM 快速登录示例脚本
|
||||
REM QQ 号参数是可选的,作为启动脚本的第一个参数传入;不传则使用二维码登录
|
||||
REM -q 参数是可选的,不传则使用二维码登录
|
||||
REM
|
||||
REM 使用方法(删掉对应系统那行的 REM):
|
||||
REM ./launcher-user.bat 123456
|
||||
|
||||
@@ -24,7 +24,7 @@ import { createHash } from 'node:crypto';
|
||||
import { LoginListItem, NodeIKernelLoginService } from 'napcat-core/services';
|
||||
import qrcode from 'napcat-qrcode/lib/main';
|
||||
import { NapCatAdapterManager } from 'napcat-adapter';
|
||||
import { InitWebUi, WebUiConfig } from 'napcat-webui-backend/index';
|
||||
import { InitWebUi } from 'napcat-webui-backend/index';
|
||||
import { WebUiDataRuntime } from 'napcat-webui-backend/src/helper/Data';
|
||||
import { napCatVersion } from 'napcat-common/src/version';
|
||||
import { NodeIO3MiscListener } from 'napcat-core/listeners/NodeIO3MiscListener';
|
||||
@@ -142,11 +142,6 @@ async function handleLogin (
|
||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||
context.isLogined = true;
|
||||
WebUiDataRuntime.setQQLoginStatus(true);
|
||||
try {
|
||||
await WebUiConfig.UpdateLastLoginAccount(loginResult.uin);
|
||||
} catch (error) {
|
||||
logger.logWarn('[NapCat] [Login] 保存最近登录账号失败:', error);
|
||||
}
|
||||
inner_resolve({
|
||||
uid: loginResult.uid,
|
||||
uin: loginResult.uin,
|
||||
@@ -486,18 +481,28 @@ async function handleLoginInner (context: { isLogined: boolean; }, logger: LogWr
|
||||
if (!success && !attempted && !context.isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
} else {
|
||||
logger.log('没有 -q 指令指定快速登录,将尝试配置账号或最近登录账号');
|
||||
logger.log('没有 -q 指令指定快速登录,将使用二维码登录方式');
|
||||
if (historyLoginList.length > 0) {
|
||||
logger.log(`可用于快速登录 of QQ:\n${historyLoginList
|
||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||
.join('\n')
|
||||
}`);
|
||||
}
|
||||
let hasAttemptedFallback = false;
|
||||
try {
|
||||
// 检查是否配置了自动登录账号,并尝试 WebUi 快速/密码回退登录。
|
||||
// 这可以避免在已经有自动登录配置的情况下过早输出二维码。
|
||||
const quickLoginList = WebUiDataRuntime.getQQQuickLoginList() || [];
|
||||
const hasAutoLogin = process.env['NAPCAT_QUICK_ACCOUNT'] || (quickLoginList.length > 0); // 假如有历史登录列表
|
||||
if (hasAutoLogin || process.env['NAPCAT_QUICK_PASSWORD'] || process.env['NAPCAT_QUICK_PASSWORD_MD5']) {
|
||||
hasAttemptedFallback = true;
|
||||
}
|
||||
await WebUiDataRuntime.runWebUiConfigQuickFunction();
|
||||
} catch (error) {
|
||||
logger.logError('WebUi 快速登录失败 执行失败', error);
|
||||
if (!context.isLogined) loginService.getQRCodePicture();
|
||||
}
|
||||
if (!hasAttemptedFallback && !context.isLogined) {
|
||||
loginService.getQRCodePicture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,8 +648,7 @@ export async function NCoreInitShell () {
|
||||
|
||||
logger.log('[NapCat] [Core] NapCat.Core Version: ' + napCatVersion);
|
||||
WebUiDataRuntime.setWorkingEnv(NapCatCoreWorkingEnv.Shell);
|
||||
await InitWebUi(logger, pathWrapper, logSubscription, statusHelperSubscription)
|
||||
.catch(e => logger.logError(e));
|
||||
InitWebUi(logger, pathWrapper, logSubscription, statusHelperSubscription).then().catch(e => logger.logError(e));
|
||||
const engine = wrapper.NodeIQQNTWrapperEngine.get();
|
||||
const loginService = wrapper.NodeIKernelLoginService.get();
|
||||
let session: NodeIQQNTWrapperSession;
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import { Value } from '@sinclair/typebox/value';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import {
|
||||
resolveAutoLoginAccount,
|
||||
WebUiConfigSchema,
|
||||
type WebUiConfigType,
|
||||
} from '../napcat-webui-backend/src/helper/config-schema';
|
||||
|
||||
describe('automatic login account selection', () => {
|
||||
test('uses explicit sources before the last successful account', () => {
|
||||
expect(resolveAutoLoginAccount('10001', '10002', '10003')).toBe('10001');
|
||||
expect(resolveAutoLoginAccount(undefined, '10002', '10003')).toBe('10002');
|
||||
expect(resolveAutoLoginAccount(undefined, undefined, '10003')).toBe('10003');
|
||||
});
|
||||
|
||||
test('ignores empty account values', () => {
|
||||
expect(resolveAutoLoginAccount(' ', '', ' 10003 ')).toBe('10003');
|
||||
expect(resolveAutoLoginAccount(undefined, '', ' ')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('WebUI login configuration migration', () => {
|
||||
test('adds an empty last account to an existing configuration', () => {
|
||||
const config = Value.Parse(WebUiConfigSchema, {
|
||||
host: '127.0.0.1',
|
||||
autoLoginAccount: '10002',
|
||||
}) as WebUiConfigType;
|
||||
|
||||
expect(config.host).toBe('127.0.0.1');
|
||||
expect(config.autoLoginAccount).toBe('10002');
|
||||
expect(config.lastLoginAccount).toBe('');
|
||||
});
|
||||
|
||||
test('preserves existing settings when the last account is updated', () => {
|
||||
const current = Value.Parse(WebUiConfigSchema, {
|
||||
host: '127.0.0.1',
|
||||
port: 7000,
|
||||
autoLoginAccount: '10002',
|
||||
}) as WebUiConfigType;
|
||||
const updated = Value.Parse(WebUiConfigSchema, {
|
||||
...current,
|
||||
lastLoginAccount: '10003',
|
||||
}) as WebUiConfigType;
|
||||
|
||||
expect(updated.host).toBe('127.0.0.1');
|
||||
expect(updated.port).toBe(7000);
|
||||
expect(updated.autoLoginAccount).toBe('10002');
|
||||
expect(updated.lastLoginAccount).toBe('10003');
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,7 @@ import { createServer } from 'http';
|
||||
import { createHash, randomUUID } from 'node:crypto';
|
||||
import { createServer as createHttpsServer } from 'https';
|
||||
import { NapCatPathWrapper } from 'napcat-common/src/path';
|
||||
import { resolveAutoLoginAccount, WebUiConfigWrapper } from '@/napcat-webui-backend/src/helper/config';
|
||||
import { WebUiConfigWrapper } from '@/napcat-webui-backend/src/helper/config';
|
||||
import { ALLRouter } from '@/napcat-webui-backend/src/router';
|
||||
import { cors } from '@/napcat-webui-backend/src/middleware/cors';
|
||||
import { createUrl, getRandomToken } from '@/napcat-webui-backend/src/utils/url';
|
||||
@@ -118,74 +118,6 @@ export async function InitWebUi (logger: ILogWrapper, pathWrapper: NapCatPathWra
|
||||
WebUiConfig = new WebUiConfigWrapper();
|
||||
let config = await WebUiConfig.GetWebUIConfig();
|
||||
|
||||
// 自动登录与 WebUI 服务是否启用无关,需要在所有提前返回之前注册。
|
||||
WebUiDataRuntime.setWebUiConfigQuickFunction(
|
||||
async () => {
|
||||
const autoLoginAccount = resolveAutoLoginAccount(
|
||||
process.env['NAPCAT_QUICK_ACCOUNT'],
|
||||
WebUiConfig.getAutoLoginAccount(),
|
||||
WebUiConfig.getLastLoginAccount()
|
||||
);
|
||||
const resolveQuickPasswordMd5 = (): string | undefined => {
|
||||
const quickPasswordMd5FromEnv = process.env['NAPCAT_QUICK_PASSWORD_MD5']?.trim();
|
||||
if (quickPasswordMd5FromEnv) {
|
||||
if (/^[a-fA-F0-9]{32}$/.test(quickPasswordMd5FromEnv)) {
|
||||
return quickPasswordMd5FromEnv.toLowerCase();
|
||||
}
|
||||
console.log('[NapCat] [WebUi] NAPCAT_QUICK_PASSWORD_MD5 格式无效(需为 32 位 MD5)');
|
||||
}
|
||||
|
||||
const quickPassword = process.env['NAPCAT_QUICK_PASSWORD'];
|
||||
if (typeof quickPassword === 'string' && quickPassword.length > 0) {
|
||||
console.log('[NapCat] [WebUi] 检测到 NAPCAT_QUICK_PASSWORD,已在内存中计算 MD5 用于回退登录');
|
||||
return createHash('md5').update(quickPassword, 'utf8').digest('hex');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
if (!autoLoginAccount) {
|
||||
await WebUiDataRuntime.refreshQRCode();
|
||||
return;
|
||||
}
|
||||
const quickPasswordMd5 = resolveQuickPasswordMd5();
|
||||
|
||||
try {
|
||||
const { result, message } = await WebUiDataRuntime.requestQuickLogin(autoLoginAccount);
|
||||
if (result) {
|
||||
console.log(`[NapCat] [WebUi] 自动快速登录成功: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
console.log(`[NapCat] [WebUi] 自动快速登录失败: ${message || '未知错误'}`);
|
||||
} catch (error) {
|
||||
console.log('[NapCat] [WebUi] 自动快速登录异常:' + error);
|
||||
}
|
||||
|
||||
if (!quickPasswordMd5) {
|
||||
console.log(`[NapCat] [WebUi] QQ ${autoLoginAccount} 未配置回退密码环境变量,建议优先使用 ACCOUNT + NAPCAT_QUICK_PASSWORD(NAPCAT_QUICK_PASSWORD_MD5 作为备用),保持二维码登录兜底`);
|
||||
await WebUiDataRuntime.refreshQRCode();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { result, message, needCaptcha, needNewDevice } = await WebUiDataRuntime.requestPasswordLogin(autoLoginAccount, quickPasswordMd5);
|
||||
if (result) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录成功: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
if (needCaptcha) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录需要验证码,请在登录页面继续完成: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
if (needNewDevice) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录需要新设备验证,请在登录页面继续完成: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录失败: ${message || '未知错误'}`);
|
||||
} catch (error) {
|
||||
console.log('[NapCat] [WebUi] 自动密码回退登录异常:' + error);
|
||||
}
|
||||
await WebUiDataRuntime.refreshQRCode();
|
||||
});
|
||||
|
||||
// 检查是否禁用WebUI(若禁用则不进行密码检测)
|
||||
if (config.disableWebUI) {
|
||||
logger.log('[NapCat] [WebUi] WebUI is disabled by configuration.');
|
||||
@@ -220,6 +152,65 @@ export async function InitWebUi (logger: ILogWrapper, pathWrapper: NapCatPathWra
|
||||
logger.log('[NapCat] [WebUi] Current WebUi is not run.');
|
||||
return;
|
||||
}
|
||||
WebUiDataRuntime.setWebUiConfigQuickFunction(
|
||||
async () => {
|
||||
const autoLoginAccount = process.env['NAPCAT_QUICK_ACCOUNT'] || WebUiConfig.getAutoLoginAccount();
|
||||
const resolveQuickPasswordMd5 = (): string | undefined => {
|
||||
const quickPasswordMd5FromEnv = process.env['NAPCAT_QUICK_PASSWORD_MD5']?.trim();
|
||||
if (quickPasswordMd5FromEnv) {
|
||||
if (/^[a-fA-F0-9]{32}$/.test(quickPasswordMd5FromEnv)) {
|
||||
return quickPasswordMd5FromEnv.toLowerCase();
|
||||
}
|
||||
console.log('[NapCat] [WebUi] NAPCAT_QUICK_PASSWORD_MD5 格式无效(需为 32 位 MD5)');
|
||||
}
|
||||
|
||||
const quickPassword = process.env['NAPCAT_QUICK_PASSWORD'];
|
||||
if (typeof quickPassword === 'string' && quickPassword.length > 0) {
|
||||
console.log('[NapCat] [WebUi] 检测到 NAPCAT_QUICK_PASSWORD,已在内存中计算 MD5 用于回退登录');
|
||||
return createHash('md5').update(quickPassword, 'utf8').digest('hex');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
if (!autoLoginAccount) {
|
||||
return;
|
||||
}
|
||||
const quickPasswordMd5 = resolveQuickPasswordMd5();
|
||||
|
||||
try {
|
||||
const { result, message } = await WebUiDataRuntime.requestQuickLogin(autoLoginAccount);
|
||||
if (result) {
|
||||
console.log(`[NapCat] [WebUi] 自动快速登录成功: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
console.log(`[NapCat] [WebUi] 自动快速登录失败: ${message || '未知错误'}`);
|
||||
} catch (error) {
|
||||
console.log('[NapCat] [WebUi] 自动快速登录异常:' + error);
|
||||
}
|
||||
|
||||
if (!quickPasswordMd5) {
|
||||
console.log(`[NapCat] [WebUi] QQ ${autoLoginAccount} 未配置回退密码环境变量,建议优先使用 ACCOUNT + NAPCAT_QUICK_PASSWORD(NAPCAT_QUICK_PASSWORD_MD5 作为备用),保持二维码登录兜底`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { result, message, needCaptcha, needNewDevice } = await WebUiDataRuntime.requestPasswordLogin(autoLoginAccount, quickPasswordMd5);
|
||||
if (result) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录成功: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
if (needCaptcha) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录需要验证码,请在登录页面继续完成: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
if (needNewDevice) {
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录需要新设备验证,请在登录页面继续完成: ${autoLoginAccount}`);
|
||||
return;
|
||||
}
|
||||
console.log(`[NapCat] [WebUi] 自动密码回退登录失败: ${message || '未知错误'}`);
|
||||
} catch (error) {
|
||||
console.log('[NapCat] [WebUi] 自动密码回退登录异常:' + error);
|
||||
}
|
||||
});
|
||||
// ------------注册中间件------------
|
||||
// 使用express的json中间件
|
||||
app.use(express.json());
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
import { themeType } from '../types/theme';
|
||||
import { getRandomToken } from '../utils/url';
|
||||
|
||||
export const WebUiConfigSchema = Type.Object({
|
||||
host: Type.String({ default: '::' }),
|
||||
port: Type.Number({ default: 6099 }),
|
||||
token: Type.String({ default: getRandomToken(12) }),
|
||||
loginRate: Type.Number({ default: 10 }),
|
||||
autoLoginAccount: Type.String({ default: '' }),
|
||||
lastLoginAccount: Type.String({ default: '' }),
|
||||
theme: themeType,
|
||||
disableWebUI: Type.Boolean({ default: false }),
|
||||
accessControlMode: Type.Union([
|
||||
Type.Literal('none'),
|
||||
Type.Literal('whitelist'),
|
||||
Type.Literal('blacklist'),
|
||||
], { default: 'none' }),
|
||||
ipWhitelist: Type.Array(Type.String(), { default: [] }),
|
||||
ipBlacklist: Type.Array(Type.String(), { default: [] }),
|
||||
enableXForwardedFor: Type.Boolean({ default: false }),
|
||||
enable2FA: Type.Boolean({ default: false }),
|
||||
totpSecret: Type.String({ default: '' }),
|
||||
});
|
||||
|
||||
export type WebUiConfigType = Static<typeof WebUiConfigSchema>;
|
||||
|
||||
export function resolveAutoLoginAccount (
|
||||
environmentAccount: string | undefined,
|
||||
configuredAccount: string | undefined,
|
||||
lastLoginAccount: string | undefined
|
||||
): string | undefined {
|
||||
return [environmentAccount, configuredAccount, lastLoginAccount]
|
||||
.map(account => account?.trim())
|
||||
.find((account): account is string => Boolean(account));
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { webUiPathWrapper, getInitialWebUiToken } from '@/napcat-webui-backend/index';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { TypeCompiler } from '@sinclair/typebox/compiler';
|
||||
import { Value } from '@sinclair/typebox/value';
|
||||
import fs, { constants } from 'node:fs/promises';
|
||||
@@ -6,9 +7,39 @@ import fs, { constants } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import { deepMerge } from '../utils/object';
|
||||
import { WebUiConfigSchema, type WebUiConfigType } from './config-schema';
|
||||
import { themeType } from '../types/theme';
|
||||
import { getRandomToken } from '../utils/url';
|
||||
|
||||
export { resolveAutoLoginAccount, WebUiConfigSchema, type WebUiConfigType } from './config-schema';
|
||||
// 限制尝试端口的次数,避免死循环
|
||||
// 定义配置的类型
|
||||
const WebUiConfigSchema = Type.Object({
|
||||
host: Type.String({ default: '::' }),
|
||||
port: Type.Number({ default: 6099 }),
|
||||
token: Type.String({ default: getRandomToken(12) }),
|
||||
loginRate: Type.Number({ default: 10 }),
|
||||
autoLoginAccount: Type.String({ default: '' }),
|
||||
theme: themeType,
|
||||
// 是否关闭WebUI
|
||||
disableWebUI: Type.Boolean({ default: false }),
|
||||
// 网络访问控制模式: 'none' | 'whitelist' | 'blacklist'
|
||||
accessControlMode: Type.Union([
|
||||
Type.Literal('none'),
|
||||
Type.Literal('whitelist'),
|
||||
Type.Literal('blacklist'),
|
||||
], { default: 'none' }),
|
||||
// IP白名单列表
|
||||
ipWhitelist: Type.Array(Type.String(), { default: [] }),
|
||||
// IP黑名单列表
|
||||
ipBlacklist: Type.Array(Type.String(), { default: [] }),
|
||||
// 是否启用 X-Forwarded-For 获取真实IP
|
||||
enableXForwardedFor: Type.Boolean({ default: false }),
|
||||
// 是否启用双因素认证(2FA)
|
||||
enable2FA: Type.Boolean({ default: false }),
|
||||
// TOTP 密钥
|
||||
totpSecret: Type.String({ default: '' }),
|
||||
});
|
||||
|
||||
export type WebUiConfigType = Static<typeof WebUiConfigSchema>;
|
||||
|
||||
// 读取当前目录下名为 webui.json 的配置文件,如果不存在则创建初始化配置文件
|
||||
export class WebUiConfigWrapper {
|
||||
@@ -211,14 +242,6 @@ export class WebUiConfigWrapper {
|
||||
await this.UpdateWebUIConfig({ autoLoginAccount: uin });
|
||||
}
|
||||
|
||||
getLastLoginAccount (): string | undefined {
|
||||
return this.WebUiConfigData?.lastLoginAccount;
|
||||
}
|
||||
|
||||
async UpdateLastLoginAccount (uin: string): Promise<void> {
|
||||
await this.UpdateWebUIConfig({ lastLoginAccount: uin });
|
||||
}
|
||||
|
||||
// 获取主题内容
|
||||
async GetTheme (): Promise<WebUiConfigType['theme']> {
|
||||
const config = await this.GetWebUIConfig();
|
||||
|
||||
Reference in New Issue
Block a user