Files
v-hono/auth_routes.v

268 lines
7.1 KiB
V

module hono
import x.json2
import net.http
// 登录请求结构
pub struct LoginRequest {
pub:
username string
password string
}
// 注册请求结构
pub struct RegisterRequest {
pub:
username string
email string
password string
role string
}
// 菜单创建请求结构
pub struct MenuCreateRequest {
pub:
name string
path string
icon string
parent_id int
sort_order int
permissions []string
}
// 响应结构体
struct ErrorResponseBody {
error string
}
struct LoginResponseBody {
token string
expires_at string
}
struct RegisterResponseBody {
user_id string
username string
email string
role string
}
struct MessageResponseBody {
message string
}
struct ProfileResponseBody {
user_id string
username string
email string
role string
active string
}
struct MenusResponseBody {
menus []MenuItem
}
struct MenuCreateResponseBody {
menu_id string
name string
path string
icon string
parent_id string
sort_order string
permissions string
active string
}
// 认证中间件(只做校验,不注入 user)
pub fn auth_middleware(auth_manager AuthManager) ContextMiddleware {
return fn [auth_manager] (mut c Context, next fn (mut Context) http.Response) http.Response {
token := c.req.header.get_custom('Authorization') or { '' }
if token == '' {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Authorization token required'
}))
}
_ := auth_manager.verify_token(token) or {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid or expired token'
}))
}
return next(mut c)
}
}
// 权限检查中间件(直接校验 token 权限)
pub fn permission_middleware(auth_manager AuthManager, required_permission string) ContextMiddleware {
return fn [auth_manager, required_permission] (mut c Context, next fn (mut Context) http.Response) http.Response {
token := c.req.header.get_custom('Authorization') or { '' }
user := auth_manager.verify_token(token) or {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid or expired token'
}))
}
if !auth_manager.check_permission(user, required_permission) {
c.status(403)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Insufficient permissions'
}))
}
return next(mut c)
}
}
// 注册认证路由
pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
// 登录路由
app.post('/api/auth/login', fn [mut auth_manager] (mut c Context) http.Response {
body := c.body
login_req := json2.decode[LoginRequest](body) or {
c.status(400)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid request body'
}))
}
session := auth_manager.login(login_req.username, login_req.password) or {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[LoginResponseBody](LoginResponseBody{
token: session.token.str()
expires_at: session.expires_at.str()
}))
})
// 注册路由
app.post('/api/auth/register', fn [mut auth_manager] (mut c Context) http.Response {
body := c.body
register_req := json2.decode[RegisterRequest](body) or {
c.status(400)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid request body'
}))
}
role := match register_req.role {
'admin' { UserRole.admin }
'manager' { UserRole.manager }
'user' { UserRole.user }
'guest' { UserRole.guest }
else { UserRole.user }
}
user := auth_manager.create_user(register_req.username, register_req.email, register_req.password, role) or {
c.status(400)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[RegisterResponseBody](RegisterResponseBody{
user_id: user.id.str()
username: user.username
email: user.email
role: user.role.str()
}))
})
// 注销路由
app.post('/api/auth/logout', fn [mut auth_manager] (mut c Context) http.Response {
token := c.req.header.get_custom('Authorization') or { '' }
if token == '' {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Authorization token required'
}))
}
auth_manager.logout(token) or {
c.status(500)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[MessageResponseBody](MessageResponseBody{
message: 'Logged out successfully'
}))
})
// 获取用户信息路由
app.get('/api/auth/profile', fn [auth_manager] (mut c Context) http.Response {
token := c.req.header.get_custom('Authorization') or { '' }
user := auth_manager.verify_token(token) or {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid or expired token'
}))
}
return c.json(json2.encode[ProfileResponseBody](ProfileResponseBody{
user_id: user.id.str()
username: user.username
email: user.email
role: user.role.str()
active: user.status.str()
}))
})
// 获取用户菜单路由
app.get('/api/auth/menus', fn [auth_manager] (mut c Context) http.Response {
token := c.req.header.get_custom('Authorization') or { '' }
user := auth_manager.verify_token(token) or {
c.status(401)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid or expired token'
}))
}
menus := auth_manager.get_user_menus(user) or {
c.status(500)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[MenusResponseBody](MenusResponseBody{
menus: menus
}))
})
// 创建菜单项路由 (需要管理员权限)
app.post('/api/auth/menus', fn [mut auth_manager] (mut c Context) http.Response {
body := c.body
menu_req := json2.decode[MenuCreateRequest](body) or {
c.status(400)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: 'Invalid request body'
}))
}
menu := auth_manager.create_menu_item(menu_req.name, menu_req.path, menu_req.icon, menu_req.parent_id, menu_req.sort_order, menu_req.permissions) or {
c.status(400)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[MenuCreateResponseBody](MenuCreateResponseBody{
menu_id: menu.id.str()
name: menu.name
path: menu.path
icon: menu.icon
parent_id: menu.parent_id.str()
sort_order: menu.sort_order.str()
permissions: json2.encode[[]string](menu.permissions)
active: menu.status.str()
}))
})
// 获取所有菜单项路由 (需要管理员权限)
app.get('/api/auth/menus/all', fn [auth_manager] (mut c Context) http.Response {
menus := auth_manager.get_all_menu_items() or {
c.status(500)
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
error: err.msg()
}))
}
return c.json(json2.encode[MenusResponseBody](MenusResponseBody{
menus: menus
}))
})
}