diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index f8cf671..aea7e8b 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -291,11 +291,32 @@ const auth: FastifyPluginAsync = async (fastify) => { const stored = await redis.get(`refresh:${refreshToken}`) if (!stored) return reply.code(401).send({ error: 'Invalid or expired refresh token' }) - const payload = JSON.parse(stored) as JwtPayload - const accessToken = fastify.jwt.sign(payload, { - expiresIn: config.jwt.accessExpiry, - }) + const cached = JSON.parse(stored) as JwtPayload + // Re-read role and active status from DB so role changes take effect immediately + const { rows } = await db.query( + `SELECT u.role, u.active, h.slug AS hotel_slug + FROM users u + LEFT JOIN hotels h ON h.id = u.hotel_id + WHERE u.id = $1`, + [cached.sub], + ) + if (!rows[0] || !rows[0].active) { + await redis.del(`refresh:${refreshToken}`) + reply.clearCookie('refresh_token', { path: '/api/auth' }) + return reply.code(401).send({ error: 'Account inactive or not found' }) + } + + const payload: JwtPayload = { + ...cached, + role: rows[0].role, + hotelSlug: rows[0].hotel_slug ?? cached.hotelSlug, + } + // Update Redis with fresh payload + const ttl = await redis.ttl(`refresh:${refreshToken}`) + if (ttl > 0) await redis.set(`refresh:${refreshToken}`, JSON.stringify(payload), 'EX', ttl) + + const accessToken = fastify.jwt.sign(payload, { expiresIn: config.jwt.accessExpiry }) return { access_token: accessToken } }) diff --git a/src/pages/UsersPage.tsx b/src/pages/UsersPage.tsx index a962dc8..337dae9 100644 --- a/src/pages/UsersPage.tsx +++ b/src/pages/UsersPage.tsx @@ -1025,10 +1025,8 @@ export function UsersPage() { } } - const stats = { - total: users.length, - active: users.filter(u => u.isActive).length, - } + const totalUsers = users.length + const activeUsers = users.filter(u => u.isActive).length return (
{stats.total} пользователей · {stats.active} активных
+{totalUsers} пользователей · {activeUsers} активных