feat: add query-login

This commit is contained in:
2025-03-22 00:52:58 +08:00
parent 3d45a83129
commit 4b16ec8499
17 changed files with 530 additions and 650 deletions

View File

@@ -1,46 +1,26 @@
import MD5 from 'crypto-js/md5.js';
import { getBaseURL, query } from '../query.ts';
import { getBaseURL, queryLogin } from '../query.ts';
import { chalk } from '../chalk.ts';
import jsonwebtoken from 'jsonwebtoken';
import { BaseLoad } from '@kevisual/load';
import { getConfig, writeConfig } from '../get-config.ts';
type LoginWithWebOptions = {};
export const loginWithWeb = async (opts?: LoginWithWebOptions) => {
const baseURL = getBaseURL();
const randomId = Math.random().toString(36).substring(2, 15);
const timestamp = Date.now();
const tokenSecret = 'xiao' + randomId;
const sign = MD5(`${tokenSecret}${timestamp}`).toString();
const token = jsonwebtoken.sign({ randomId, timestamp, sign }, tokenSecret, {
// 10分钟过期
expiresIn: 60 * 10, // 10分钟
});
const config = await getConfig();
const url = `${baseURL}/api/router?path=user&key=webLogin&p&loginToken=${token}&sign=${sign}&randomId=${randomId}`;
console.log(chalk.blue(url));
return {
url,
token,
tokenSecret,
};
const res = queryLogin.loginWithWeb(baseURL, { MD5, jsonwebtoken });
console.log(chalk.blue(res.url));
return res;
};
type PollLoginOptions = {
tokenSecret: string;
saveToken?: any;
};
export const pollLoginStatus = async (token: string, opts: PollLoginOptions) => {
const load = new BaseLoad();
load.load(
async () => {
const res = await query.post({
path: 'user',
key: 'checkLoginStatus',
loginToken: token,
});
const res = await queryLogin.checkLoginStatus(token);
return res;
},
{
@@ -55,36 +35,21 @@ export const pollLoginStatus = async (token: string, opts: PollLoginOptions) =>
timeout: 60 * 3 * 1000, // 5分钟超时
});
if (res.code === 200 && res.data?.code === 200) {
const data = res.data?.data;
try {
const payload = jsonwebtoken.verify(data, opts.tokenSecret) as UserPayload;
type UserPayload = {
userToken: {
token: string;
expireTime: number;
};
user: {
id: string;
username: string;
};
};
const userToken = payload.userToken;
// console.log('token:\n\n', userToken);
console.log(chalk.green('网页登录成功', payload?.user?.username));
console.log(chalk.green('token:', userToken.token));
await opts?.saveToken(userToken.token);
console.log(chalk.green('网页登录成功'));
return;
} catch (error) {
console.log(chalk.red('登录失败'), error);
return;
}
}
console.log(chalk.red('登录失败'), res);
};
export const loginInCommand = async (saveToken: any) => {
const { url, token, tokenSecret } = await loginWithWeb();
await pollLoginStatus(token, { tokenSecret, saveToken });
return url;
export const loginInCommand = async () => {
const baseURL = getBaseURL();
const res = queryLogin.loginWithWeb(baseURL, { MD5, jsonwebtoken });
console.log(chalk.blue(res.url));
await pollLoginStatus(res.token, { tokenSecret: res.tokenSecret });
return res.url;
};
// loginInCommand();

View File

@@ -1,7 +1,9 @@
import { Query } from '@kevisual/query/query';
import { getConfig } from './get-config.ts';
import { QueryLoginNode, storage } from '@kevisual/query-login/node';
const config = getConfig();
export const baseURL = config?.baseURL || 'https://envision.xiongxiao.me';
export const baseURL = config?.baseURL || 'https://kevisual.cn';
export { storage };
export const getBaseURL = () => {
if (typeof config?.dev === 'undefined') {
return baseURL;
@@ -23,10 +25,29 @@ export const query = new Query({
query.beforeRequest = async (config) => {
if (config.headers) {
const token = await getConfig()?.token;
const token = await storage.getItem('token');
if (token) {
config.headers['Authorization'] = 'Bearer ' + token;
}
}
return config;
};
query.afterResponse = async (response, ctx) => {
if (response.code === 401) {
if (query.stop) {
return {
code: 500,
message: '登录已过期',
};
}
query.stop = true;
const res = await queryLogin.afterCheck401ToRefreshToken(response, ctx);
query.stop = false;
return res;
}
return response as any;
};
export const queryLogin = new QueryLoginNode({
query: query as any,
onLoad: async () => {},
});