feat(auth): add authentication routes and user token handling
- Implemented user authentication routes in `auth.ts` for fetching current user info and admin verification. - Added caching mechanism for user tokens to improve performance. - Created middleware for admin authentication. feat(opencode): create OpenCode client route - Added `opencode-cnb` route for creating OpenCode clients with session management. - Integrated OpenCode SDK for client operations and session handling. refactor(client): encapsulate OpenCode client creation - Created a utility function `getClient` in `client.ts` to initialize OpenCode clients. test(opencode): add tests for OpenCode routes - Implemented test cases for OpenCode routes in `list.ts` to validate functionality. - Created common utilities for testing in `common.ts`.
This commit is contained in:
119
assistant/src/routes/auth.ts
Normal file
119
assistant/src/routes/auth.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { app, assistantConfig } from '../app.ts';
|
||||
import { authCache } from '@/module/cache/auth.ts';
|
||||
|
||||
import { logger } from '@/module/logger.ts';
|
||||
const getTokenUser = async (token: string) => {
|
||||
const query = assistantConfig.query
|
||||
const res = await query.post({
|
||||
path: 'user',
|
||||
key: 'me',
|
||||
token: token,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
export const getTokenUserCache = async (token: string) => {
|
||||
const tokenUser = await authCache.get(token);
|
||||
if (tokenUser) {
|
||||
return {
|
||||
code: 200,
|
||||
data: tokenUser,
|
||||
};
|
||||
}
|
||||
const res = await getTokenUser(token);
|
||||
if (res.code === 200) {
|
||||
authCache.set(token, res.data);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
export const checkAuth = async (ctx: any, isAdmin = false) => {
|
||||
const config = assistantConfig.getConfig();
|
||||
const { auth = {} } = config;
|
||||
const token = ctx.query.token;
|
||||
logger.debug('checkAuth', ctx.query, { token });
|
||||
if (!token) {
|
||||
return {
|
||||
code: 401,
|
||||
message: '未登录',
|
||||
}
|
||||
}
|
||||
// 鉴权代理
|
||||
let tokenUser = await authCache.get(token);
|
||||
if (!tokenUser) {
|
||||
const tokenUserRes = await getTokenUser(token);
|
||||
if (tokenUserRes.code !== 200) {
|
||||
return {
|
||||
code: tokenUserRes.code,
|
||||
message: '验证失败' + tokenUserRes.message,
|
||||
}
|
||||
} else {
|
||||
tokenUser = tokenUserRes.data;
|
||||
}
|
||||
authCache.set(token, tokenUser);
|
||||
}
|
||||
ctx.state = {
|
||||
...ctx.state,
|
||||
token,
|
||||
tokenUser,
|
||||
};
|
||||
const { username } = tokenUser;
|
||||
if (!auth.username) {
|
||||
// 初始管理员账号
|
||||
auth.username = username;
|
||||
assistantConfig.setConfig({ auth });
|
||||
}
|
||||
if (isAdmin && auth.username) {
|
||||
const admins = config.auth?.admin || [];
|
||||
let isCheckAdmin = false;
|
||||
const admin = auth.username;
|
||||
if (admin === username) {
|
||||
isCheckAdmin = true;
|
||||
}
|
||||
if (!isCheckAdmin && admins.length > 0 && admins.includes(username)) {
|
||||
isCheckAdmin = true;
|
||||
}
|
||||
if (!isCheckAdmin) {
|
||||
return {
|
||||
code: 403,
|
||||
message: '非管理员用户',
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
code: 200,
|
||||
data: { tokenUser, token }
|
||||
}
|
||||
};
|
||||
app
|
||||
.route({
|
||||
path: 'auth',
|
||||
id: 'auth',
|
||||
description: '获取当前登录用户信息, 第一个登录的用户为管理员用户',
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
if (!ctx.query?.token && ctx.appId === app.appId) {
|
||||
return;
|
||||
}
|
||||
const authResult = await checkAuth(ctx);
|
||||
if (authResult.code !== 200) {
|
||||
ctx.throw(authResult.code, authResult.message);
|
||||
}
|
||||
})
|
||||
.addTo(app);
|
||||
app
|
||||
.route({
|
||||
path: 'auth-admin',
|
||||
id: 'auth-admin',
|
||||
description: '管理员鉴权, 获取用户信息,并验证是否为管理员。',
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
// logger.debug('query', ctx.query);
|
||||
if (!ctx.query?.token && ctx.appId === app.appId) {
|
||||
return;
|
||||
}
|
||||
ctx.state.isAdmin = true;
|
||||
const authResult = await checkAuth(ctx, true);
|
||||
if (authResult.code !== 200) {
|
||||
ctx.throw(authResult.code, authResult.message);
|
||||
}
|
||||
})
|
||||
.addTo(app);
|
||||
Reference in New Issue
Block a user