fix: VIP activation not reflecting due to stale session-status token; add missing routes
This commit is contained in:
45
src/index.ts
45
src/index.ts
@@ -91,9 +91,25 @@ app.get('/api/qrcode/public/current', (req, res) => {
|
|||||||
res.json({ success: true, data: { qrcode: null, url: '' } });
|
res.json({ success: true, data: { qrcode: null, url: '' } });
|
||||||
});
|
});
|
||||||
|
|
||||||
// 弹窗
|
// 弹窗 (通用参数化路由)
|
||||||
app.get('/api/popups/', (req, res) => {
|
app.get('/api/popups/:name', (req, res) => {
|
||||||
res.json({ success: true, data: [] });
|
const { name } = req.params;
|
||||||
|
const popups: Record<string, any> = {
|
||||||
|
test_beta_01: { id: 'test_beta_01', title: '测试弹窗', content: '', shown: false },
|
||||||
|
};
|
||||||
|
res.json({ success: true, data: popups[name] ?? null });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 嘉豪弹窗
|
||||||
|
app.get('/api/jiahao', (req, res) => {
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
enabled: false,
|
||||||
|
message: '',
|
||||||
|
imageUrl: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 售后教程弹窗
|
// 售后教程弹窗
|
||||||
@@ -172,6 +188,29 @@ app.get('/api/avatars', (req, res) => {
|
|||||||
res.json({ success: true, data: [] });
|
res.json({ success: true, data: [] });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 更新服务 (electron-updater)
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// 更新配置
|
||||||
|
app.get('/update-config.json', (req, res) => {
|
||||||
|
res.json({
|
||||||
|
version: '7.0.4',
|
||||||
|
url: '',
|
||||||
|
notes: '',
|
||||||
|
mandatory: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// latest.yml (electron-updater 标准格式)
|
||||||
|
app.get('/latest.yml', (req, res) => {
|
||||||
|
res.type('text/yaml');
|
||||||
|
res.send(`version: 7.0.4
|
||||||
|
files: []
|
||||||
|
releaseDate: '2024-01-01T00:00:00.000Z'
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 错误处理
|
// 错误处理
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@@ -211,14 +211,57 @@ router.post('/login', async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 会话状态
|
// 会话状态 (从数据库查询最新状态,避免 token 缓存导致 isVip 过期)
|
||||||
// ============================================
|
// ============================================
|
||||||
router.get('/session-status', authMiddleware, async (req: Request, res: Response) => {
|
router.get('/session-status', authMiddleware, async (req: Request, res: Response) => {
|
||||||
res.json({
|
try {
|
||||||
success: true,
|
const user = await prisma.user.findUnique({
|
||||||
valid: true,
|
where: { id: req.user!.userId },
|
||||||
user: req.user,
|
select: {
|
||||||
});
|
id: true,
|
||||||
|
username: true,
|
||||||
|
email: true,
|
||||||
|
avatar: true,
|
||||||
|
isVip: true,
|
||||||
|
vipExpireAt: true,
|
||||||
|
vipLevel: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({
|
||||||
|
success: false,
|
||||||
|
message: '用户不存在',
|
||||||
|
code: 'USER_NOT_FOUND',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 VIP 是否过期
|
||||||
|
let isVip = user.isVip;
|
||||||
|
if (user.vipExpireAt && new Date() > user.vipExpireAt) {
|
||||||
|
isVip = false;
|
||||||
|
await prisma.user.update({
|
||||||
|
where: { id: user.id },
|
||||||
|
data: { isVip: false },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
valid: true,
|
||||||
|
user: {
|
||||||
|
userId: user.id,
|
||||||
|
username: user.username,
|
||||||
|
email: user.email,
|
||||||
|
avatar: user.avatar,
|
||||||
|
isVip,
|
||||||
|
vipLevel: user.vipLevel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Session status error:', error);
|
||||||
|
res.status(500).json({ success: false, message: '获取会话状态失败' });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@@ -100,6 +100,46 @@ router.post('/', authMiddleware, async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 更新滤镜 (PUT)
|
||||||
|
// ============================================
|
||||||
|
router.put('/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { title, description, category, filterContent, contentFormat = 'MQTS1', brand, author } = req.body;
|
||||||
|
|
||||||
|
const filter = await prisma.filterShare.findUnique({
|
||||||
|
where: { id },
|
||||||
|
select: { userId: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!filter) {
|
||||||
|
return res.status(404).json({ success: false, message: '滤镜不存在' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.userId !== req.user!.userId) {
|
||||||
|
return res.status(403).json({ success: false, message: '无权修改此滤镜' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData: any = {};
|
||||||
|
if (title !== undefined) updateData.title = title;
|
||||||
|
if (description !== undefined) updateData.description = description;
|
||||||
|
if (category !== undefined) updateData.category = category;
|
||||||
|
if (filterContent !== undefined) updateData.filterContent = filterContent;
|
||||||
|
if (contentFormat !== undefined) updateData.contentFormat = contentFormat;
|
||||||
|
|
||||||
|
const updated = await prisma.filterShare.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateData,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({ success: true, message: '滤镜已更新', data: updated });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Update filter_share error:', error);
|
||||||
|
res.status(500).json({ success: false, message: '更新失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 删除滤镜
|
// 删除滤镜
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Router, Request, Response } from 'express';
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { authMiddleware } from '../middleware/auth';
|
import { authMiddleware } from '../middleware/auth';
|
||||||
|
import { generateToken } from '../utils/jwt';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
@@ -89,8 +90,18 @@ router.post('/activate-vip', authMiddleware, async (req: Request, res: Response)
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 生成新 token(包含最新的 VIP 状态)
|
||||||
|
const token = generateToken({
|
||||||
|
userId: updatedUser.id,
|
||||||
|
username: updatedUser.username,
|
||||||
|
email: updatedUser.email,
|
||||||
|
isVip: true,
|
||||||
|
vipLevel: updatedUser.vipLevel,
|
||||||
|
});
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
|
token,
|
||||||
isVip: true,
|
isVip: true,
|
||||||
vipExpireAt: newExpireAt,
|
vipExpireAt: newExpireAt,
|
||||||
vipLevel: updatedUser.vipLevel,
|
vipLevel: updatedUser.vipLevel,
|
||||||
|
|||||||
Reference in New Issue
Block a user