Files
code-center/src/route.ts

202 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);