修复重置登录错误次数和 tfa

This commit is contained in:
whyour 2025-01-02 23:50:20 +08:00
parent cecc5aeb15
commit 7d43b14f81
7 changed files with 81 additions and 59 deletions

View File

@ -377,4 +377,23 @@ export default (app: Router) => {
} }
}, },
); );
route.put(
'/auth/reset',
celebrate({
body: Joi.object({
retries: Joi.number().optional(),
twoFactorActivated: Joi.boolean().optional(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
try {
const userService = Container.get(UserService);
await userService.resetAuthInfo(req.body);
res.send({ code: 200, message: '更新成功' });
} catch (e) {
return next(e);
}
},
);
}; };

View File

@ -59,7 +59,6 @@ export interface AuthInfo {
token: string; token: string;
tokens: Record<string, string>; tokens: Record<string, string>;
twoFactorActivated: boolean; twoFactorActivated: boolean;
twoFactorActived: boolean;
twoFactorSecret: string; twoFactorSecret: string;
avatar: string; avatar: string;
} }

View File

@ -16,6 +16,7 @@ import { writeFile, readFile } from 'fs/promises';
import { safeJSONParse } from '../config/util'; import { safeJSONParse } from '../config/util';
import OpenService from '../services/open'; import OpenService from '../services/open';
import { shareStore } from '../shared/store'; import { shareStore } from '../shared/store';
import Logger from './logger';
export default async () => { export default async () => {
const cronService = Container.get(CronService); const cronService = Container.get(CronService);
@ -26,16 +27,13 @@ export default async () => {
const openService = Container.get(OpenService); const openService = Container.get(OpenService);
// 初始化增加系统配置 // 初始化增加系统配置
await SystemModel.findOrCreate({ const [systemConfig] = await SystemModel.findOrCreate({
where: { type: AuthDataType.systemConfig }, where: { type: AuthDataType.systemConfig },
}); });
await SystemModel.findOrCreate({ const [notifyConfig] = await SystemModel.findOrCreate({
where: { type: AuthDataType.notification }, where: { type: AuthDataType.notification },
}); });
await SystemModel.findOrCreate({ const [authConfig] = await SystemModel.findOrCreate({
where: { type: AuthDataType.authConfig },
});
const authConfig = await SystemModel.findOne({
where: { type: AuthDataType.authConfig }, where: { type: AuthDataType.authConfig },
}); });
if (!authConfig?.info) { if (!authConfig?.info) {
@ -46,25 +44,20 @@ export default async () => {
try { try {
const content = await readFile(config.authConfigFile, 'utf8'); const content = await readFile(config.authConfigFile, 'utf8');
authInfo = safeJSONParse(content); authInfo = safeJSONParse(content);
} catch (error) {} } catch (error) {
if (authConfig?.id) { Logger.warn('Failed to read auth config file, using default credentials');
await SystemModel.update( }
{ info: authInfo }, await SystemModel.upsert({
{ id: authConfig?.id,
where: { id: authConfig.id },
},
);
} else {
await SystemModel.create({
info: authInfo, info: authInfo,
type: AuthDataType.authConfig, type: AuthDataType.authConfig,
}); });
} }
}
// 初始化通知配置 // 初始化通知配置
const notifyConfig = await userService.getNotificationMode(); if (notifyConfig.info) {
await writeFile(config.systemNotifyFile, JSON.stringify(notifyConfig)); await writeFile(config.systemNotifyFile, JSON.stringify(notifyConfig.info));
}
const installDependencies = () => { const installDependencies = () => {
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖 // 初始化时安装所有处于安装中,安装成功,安装失败的依赖
@ -87,7 +80,6 @@ export default async () => {
}; };
// 初始化更新 linux/python/nodejs 镜像源配置 // 初始化更新 linux/python/nodejs 镜像源配置
const systemConfig = await systemService.getSystemConfig();
if (systemConfig.info?.pythonMirror) { if (systemConfig.info?.pythonMirror) {
systemService.updatePythonMirror({ systemService.updatePythonMirror({
pythonMirror: systemConfig.info?.pythonMirror, pythonMirror: systemConfig.info?.pythonMirror,

View File

@ -20,6 +20,8 @@ export default class OpenService {
tab.client_id = createRandomString(12, 12); tab.client_id = createRandomString(12, 12);
tab.client_secret = createRandomString(24, 24); tab.client_secret = createRandomString(24, 24);
const doc = await this.insert(tab); const doc = await this.insert(tab);
const apps = await this.find({});
await shareStore.updateApps(apps);
return { ...doc, tokens: [] }; return { ...doc, tokens: [] };
} }
@ -54,6 +56,8 @@ export default class OpenService {
public async remove(ids: number[]) { public async remove(ids: number[]) {
await AppModel.destroy({ where: { id: ids } }); await AppModel.destroy({ where: { id: ids } });
const apps = await this.find({});
await shareStore.updateApps(apps);
} }
public async resetSecret(id: number): Promise<App> { public async resetSecret(id: number): Promise<App> {
@ -136,6 +140,8 @@ export default class OpenService {
{ tokens }, { tokens },
{ where: { client_id, client_secret } }, { where: { client_id, client_secret } },
); );
const apps = await this.find({});
await shareStore.updateApps(apps);
return { return {
code: 200, code: 200,
data: { data: {
@ -153,15 +159,9 @@ export default class OpenService {
value: string; value: string;
expiration: number; expiration: number;
}> { }> {
let systemApp = (await AppModel.findOne({ const [systemApp] = await AppModel.findOrCreate({
where: { name: 'system' }, where: { name: 'system', scopes: ['crons', 'system'] },
})) as App; });
if (!systemApp) {
systemApp = await this.create({
name: 'system',
scopes: ['crons', 'system'],
} as App);
}
const { data } = await this.authToken({ const { data } = await this.authToken({
client_id: systemApp.client_id, client_id: systemApp.client_id,
client_secret: systemApp.client_secret, client_secret: systemApp.client_secret,

View File

@ -61,13 +61,9 @@ export default class UserService {
lastip, lastip,
lastaddr, lastaddr,
twoFactorActivated, twoFactorActivated,
twoFactorActived,
tokens = {}, tokens = {},
platform, platform,
} = content; } = content;
// patch old field
twoFactorActivated = twoFactorActivated || twoFactorActived;
const retriesTime = Math.pow(3, retries) * 1000; const retriesTime = Math.pow(3, retries) * 1000;
if (retries > 2 && timestamp - lastlogon < retriesTime) { if (retries > 2 && timestamp - lastlogon < retriesTime) {
const waitTime = Math.ceil( const waitTime = Math.ceil(
@ -215,20 +211,6 @@ export default class UserService {
return doc; return doc;
} }
private async initAuthInfo() {
await fs.writeFile(
config.authConfigFile,
JSON.stringify({
username: 'admin',
password: 'admin',
}),
);
return {
code: 100,
message: '未找到认证文件,重新初始化',
};
}
public async updateUsernameAndPassword({ public async updateUsernameAndPassword({
username, username,
password, password,
@ -304,7 +286,6 @@ export default class UserService {
const authInfo = await this.getAuthInfo(); const authInfo = await this.getAuthInfo();
await this.updateAuthInfo(authInfo, { await this.updateAuthInfo(authInfo, {
twoFactorActivated: false, twoFactorActivated: false,
twoFactorActived: false,
twoFactorSecret: '', twoFactorSecret: '',
}); });
return true; return true;
@ -319,7 +300,7 @@ export default class UserService {
return (doc.info || {}) as AuthInfo; return (doc.info || {}) as AuthInfo;
} }
private async updateAuthInfo(authInfo: any, info: any) { private async updateAuthInfo(authInfo: AuthInfo, info: Partial<AuthInfo>) {
const result = { ...authInfo, ...info }; const result = { ...authInfo, ...info };
await shareStore.updateAuthInfo(result); await shareStore.updateAuthInfo(result);
await this.updateAuthDb({ await this.updateAuthDb({
@ -372,4 +353,13 @@ export default class UserService {
return { code: 400, message: '通知发送失败,请检查参数' }; return { code: 400, message: '通知发送失败,请检查参数' };
} }
} }
public async resetAuthInfo(info: Partial<AuthInfo>) {
const { retries, twoFactorActivated } = info;
const authInfo = await this.getAuthInfo();
await this.updateAuthInfo(authInfo, {
retries,
twoFactorActivated,
});
}
} }

View File

@ -231,4 +231,30 @@ find_cron_api() {
fi fi
} }
update_auth_config() {
local body="$1"
local tip="$2"
local currentTimeStamp=$(date +%s)
local api=$(
curl -s --noproxy "*" "http://0.0.0.0:5600/open/system/auth/reset?t=$currentTimeStamp" \
-X 'PUT' \
-H "Accept: application/json" \
-H "Authorization: Bearer ${__ql_token__}" \
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
-H "Content-Type: application/json;charset=UTF-8" \
-H "Origin: http://0.0.0.0:5700" \
-H "Referer: http://0.0.0.0:5700/crontab" \
-H "Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7" \
--data-raw "{$body}" \
--compressed
)
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code == 200 ]]; then
echo -e "${tip}成功🎉"
else
echo -e "${tip}失败(${message})"
fi
}
get_token get_token

View File

@ -537,14 +537,10 @@ main() {
eval . $dir_shell/check.sh $cmd eval . $dir_shell/check.sh $cmd
;; ;;
resetlet) resetlet)
auth_value=$(cat $file_auth_user | jq '.retries =0' -c) eval update_auth_config "\\\"retries\\\":0" "重置登录错误次数" $cmd
echo "$auth_value" >$file_auth_user
eval echo -e "重置登录错误次数成功" $cmd
;; ;;
resettfa) resettfa)
auth_value=$(cat $file_auth_user | jq '.twoFactorActivated =false' | jq '.twoFactorActived =false' -c) eval update_auth_config "\\\"twoFactorActivated\\\":false" "禁用两步验证" $cmd
echo "$auth_value" >$file_auth_user
eval echo -e "禁用两步验证成功" $cmd
;; ;;
*) *)
eval echo -e "命令输入错误...\\\n" $cmd eval echo -e "命令输入错误...\\\n" $cmd