import './routes/index.ts'; import './aura/index.ts'; import { app } from './app.ts'; import type { App } from '@kevisual/router'; import { User } from './models/user.ts'; import { createCookie, getSomeInfoFromReq } from './routes/user/me.ts'; /** * 添加auth中间件, 用于验证token * 添加 id: auth 必须需要user成功 * 添加 id: auth-can 可以不需要user成功,有则赋值 * * @param app */ export const addAuth = (app: App) => { app .route({ path: 'auth', id: 'auth', description: '验证token,必须成功, 错误返回401,正确赋值到ctx.state.tokenUser', }) .define(async (ctx) => { const token = ctx.query.token; // 已经有用户信息则直接返回,不需要重复验证 if (ctx.state.tokenUser) { return; } if (!token) { ctx.throw(401, 'Token is required'); } const user = await User.getOauthUser(token); if (!user) { ctx.throw(401, 'Token is invalid'); return; } // console.log(`auth user: ${user.username} (${user.id})`); const someInfo = getSomeInfoFromReq(ctx); if (someInfo.isBrowser && !ctx.req?.cookies?.['token']) { createCookie({ accessToken: token }, ctx); } ctx.state.tokenUser = user; }) .addTo(app); app .route({ path: 'auth', key: 'can', id: 'auth-can', description: '验证token,可以不成功,错误不返回401,正确赋值到ctx.state.tokenUser,失败赋值null', }) .define(async (ctx) => { // 已经有用户信息则直接返回,不需要重复验证 if (ctx.state.tokenUser) { return; } if (ctx.query?.token) { const token = ctx.query.token; const user = await User.getOauthUser(token); if (token) { ctx.state.tokenUser = user; const someInfo = getSomeInfoFromReq(ctx); if (someInfo.isBrowser && !ctx.req?.cookies?.['token']) { createCookie({ accessToken: token }, ctx); } } else { ctx.state.tokenUser = null; } } }) .addTo(app); }; addAuth(app); app .route({ path: 'auth', key: 'admin', id: 'auth-admin', isDebug: true, middleware: ['auth'], description: '验证token,必须是admin用户, 错误返回403,正确赋值到ctx.state.tokenAdmin', }) .define(async (ctx) => { const tokenUser = ctx.state.tokenUser; if (!tokenUser) { ctx.throw(401, 'No User For authorized'); } console.log('auth-admin tokenUser', ctx.state); if (typeof ctx.state.isAdmin !== 'undefined' && ctx.state.isAdmin === true) { return; } try { const user = await User.findOne({ id: tokenUser.id, }); if (!user) { ctx.throw(404, 'user not found'); } user.setTokenUser(tokenUser); const orgs = await user.getOrgs(); if (orgs.includes('admin')) { ctx.body = 'admin'; } else { ctx.throw(403, 'forbidden'); } ctx.state.isAdmin = true; } catch (e) { console.error(`auth-admin error`, e); console.error('tokenUser', tokenUser?.id, tokenUser?.username, tokenUser?.uid); ctx.throw(500, e.message); } }) .addTo(app); app .route({ path: 'auth-check', key: 'admin', id: 'check-auth-admin', middleware: ['auth'], }) .define(async (ctx) => { const tokenUser = ctx.state.tokenUser; if (!tokenUser) { ctx.throw(401, 'No User For authorized'); } if (typeof ctx.state.isAdmin !== 'undefined') { return; } try { const user = await User.findOne({ id: tokenUser.id, }); if (!user) { ctx.throw(404, 'user not found'); } user.setTokenUser(tokenUser); const orgs = await user.getOrgs(); if (orgs.includes('admin')) { ctx.body = 'admin'; ctx.state.isAdmin = true; ctx.state.tokenAdmin = { id: user.id, username: user.username, orgs, }; return; } else { ctx.state.isAdmin = false; } ctx.body = 'not admin'; } catch (e) { console.error(`auth-admin error`, e); console.error('tokenUser', tokenUser?.id, tokenUser?.username, tokenUser?.uid); ctx.throw(500, e.message); } }) .addTo(app); app .route({ path: 'router', key: 'list', description: '列出所有的当前的可请求的路由信息', middleware: ['auth-can'] }) .define(async (ctx) => { const tokenUser = ctx.state.tokenUser; let isUser = !!tokenUser; ctx.body = { list: app.router.routes.filter(item => { if (item.id === 'auth' || item.id === 'auth-can' || item.id === 'check-auth-admin' || item.id === 'auth-admin') { return false; } return true; }).map((item) => { return { id: item.id, path: item.path, key: item.key, description: item.description, middeleware: item.middleware, metadata: item.metadata, }; }), isUser } }) .addTo(app); app.route({ path: 'system', key: 'version' }).define(async (ctx) => { ctx.body = { version: '0.0.1', name: 'KeVisual Backend System', } }).addTo(app);