mira-app-server
Version:
Mira Server - standalone server application using mira-app-core
251 lines • 11.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserRouter = void 0;
const express_1 = require("express");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
class UserRouter {
constructor(authRouter, dataDir = './data') {
this.router = (0, express_1.Router)();
this.authRouter = authRouter;
this.dataDir = dataDir;
this.setupRoutes();
}
setupRoutes() {
// 获取用户信息路由 - 符合vben框架标准 (/api/user/info)
this.router.get('/info', async (req, res) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
code: 401,
message: '未提供认证令牌',
data: null
});
}
const authService = this.authRouter.getAuthService();
const user = await authService.validateToken(token);
if (user) {
const userInfo = authService.getUserInfo(user);
// 根据用户角色生成权限码
let permissions = [];
let userGroup = '';
switch (userInfo.role) {
case 'super':
permissions = ['*']; // 超级管理员拥有所有权限
userGroup = '超级管理员';
break;
case 'admin':
permissions = [
'AC_100100', // 系统管理权限
'AC_100010', // 资源库管理权限
'AC_100020', // 用户管理权限
'AC_200000', // 数据库访问权限
'AC_300000' // 设备管理权限
];
userGroup = '管理员';
break;
default:
permissions = ['AC_000100']; // 基础权限
userGroup = '普通用户';
}
// 符合vben标准的用户信息格式
const vbenUserInfo = {
...userInfo,
realName: userInfo.username, // vben期望的真实姓名字段
roles: [userInfo.role], // vben期望的角色数组
permissions: permissions, // 权限码数组
userGroup: userGroup, // 用户组信息
registrationDate: userInfo.created_at,
// 添加更多用户信息字段以符合vben标准
avatar: `/api/user/avatar/${user.id}`,
desc: userGroup, // 用户描述使用用户组
homePath: '/mira/overview', // 默认首页路径
};
res.json({
code: 0,
message: '获取用户信息成功',
data: vbenUserInfo
});
}
else {
res.status(401).json({
code: 401,
message: '无效或过期的认证令牌',
data: null
});
}
}
catch (error) {
console.error('Get user info error:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',
data: null
});
}
});
// 修改密码
this.router.put('/change-password', async (req, res) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ code: 401, message: '未提供认证令牌', data: null });
}
const { oldPassword, newPassword } = req.body;
if (!oldPassword || !newPassword) {
return res.status(400).json({ code: 400, message: '旧密码和新密码不能为空', data: null });
}
const authService = this.authRouter.getAuthService();
const user = await authService.validateToken(token);
if (!user) {
return res.status(401).json({ code: 401, message: '无效或过期的认证令牌', data: null });
}
const userStorage = this.authRouter.getUserStorage();
const fullUser = await userStorage.findUserByUsername(user.username);
if (!fullUser || !userStorage.verifyPasswordDirect(oldPassword, fullUser.password)) {
return res.status(400).json({ code: 400, message: '旧密码不正确', data: null });
}
await userStorage.updateUser(user.id, { password: newPassword });
res.json({ code: 0, message: '密码修改成功', data: null });
}
catch (error) {
console.error('Change password error:', error);
res.status(500).json({ code: 500, message: '服务器内部错误', data: null });
}
});
// 更新用户信息路由
this.router.put('/info', async (req, res) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
code: 401,
message: '未提供认证令牌',
data: null
});
}
const authService = this.authRouter.getAuthService();
const user = await authService.validateToken(token);
if (user) {
// 这里可以添加更新用户信息的逻辑
// 目前返回成功消息
res.json({
code: 0,
message: '用户信息更新成功',
data: null
});
}
else {
res.status(401).json({
code: 401,
message: '无效或过期的认证令牌',
data: null
});
}
}
catch (error) {
console.error('Update user info error:', error);
res.status(500).json({
code: 500,
message: '服务器内部错误',
data: null
});
}
});
// 上传头像
this.router.post('/avatar', async (req, res) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ code: 401, message: '未提供认证令牌', data: null });
}
const authService = this.authRouter.getAuthService();
const user = await authService.validateToken(token);
if (!user) {
return res.status(401).json({ code: 401, message: '无效或过期的认证令牌', data: null });
}
const { image } = req.body;
if (!image) {
return res.status(400).json({ code: 400, message: '请提供图片数据', data: null });
}
const userDir = path.join(this.dataDir, 'users', user.id.toString());
await fs.promises.mkdir(userDir, { recursive: true });
const avatarPath = path.join(userDir, 'avatar.jpg');
const base64Data = image.replace(/^data:image\/\w+;base64,/, '');
await fs.promises.writeFile(avatarPath, Buffer.from(base64Data, 'base64'));
res.json({
code: 0,
message: '头像上传成功',
data: { avatar: `/api/user/avatar/${user.id}` }
});
}
catch (error) {
console.error('Upload avatar error:', error);
res.status(500).json({ code: 500, message: '服务器内部错误', data: null });
}
});
// 获取头像
this.router.get('/avatar/:userId', async (req, res) => {
try {
const { userId } = req.params;
const avatarPath = path.join(this.dataDir, 'users', userId, 'avatar.jpg');
if (fs.existsSync(avatarPath)) {
return res.sendFile(path.resolve(avatarPath));
}
// 默认头像:生成 SVG
const userStorage = this.authRouter.getUserStorage();
const user = await userStorage.findUserById(parseInt(userId));
const initial = (user?.username || '?')[0].toUpperCase();
const colors = ['#4f46e5', '#0891b2', '#059669', '#d97706', '#dc2626', '#7c3aed', '#db2777'];
const color = colors[parseInt(userId) % colors.length];
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="128" height="128" rx="64" fill="${color}"/><text x="64" y="64" dy=".35em" text-anchor="middle" fill="white" font-size="48" font-family="sans-serif">${initial}</text></svg>`;
res.setHeader('Content-Type', 'image/svg+xml');
res.setHeader('Cache-Control', 'public, max-age=300');
res.send(svg);
}
catch (error) {
console.error('Get avatar error:', error);
res.status(500).json({ code: 500, message: '服务器内部错误', data: null });
}
});
}
getRouter() {
return this.router;
}
}
exports.UserRouter = UserRouter;
//# sourceMappingURL=UserRouter.js.map