Ctrl K
ComunidadGuías…

middleware/auth.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
const jwt = require('jsonwebtoken');
const { pool } = require('../config/database');
const JWT_SECRET = require('../config/jwt-secret');

const ROLES = {
  user: 0,
  reviewer: 1,
  radio_admin: 1,
  admin: 2,
  super_admin: 3
};

const ROLE_NAMES = {
  user: '普通用户',
  reviewer: '审核员',
  radio_admin: '广播管理员',
  admin: '管理员',
  super_admin: '超级管理员'
};

const ROLE_PERMISSIONS = {
  user: [],
  reviewer: ['posts:review'],
  radio_admin: ['songs:review', 'songs:delete', 'slots:manage', 'stats:view'],
  admin: ['posts:review', 'posts:delete', 'songs:review', 'songs:delete', 'slots:manage', 'users:view', 'users:status', 'notices:manage', 'feedbacks:manage'],
  super_admin: ['posts:review', 'posts:delete', 'songs:review', 'songs:delete', 'slots:manage', 'users:view', 'users:status', 'users:role', 'admin:manage', 'stats:view', 'logs:view', 'notices:manage', 'settings:view', 'feedbacks:manage', 'stories:review', 'post-views:view', 'wechat:review']
};

const auth = async (req, res, next) => {
  try {
    const token = req.headers.authorization?.split(' ')[1] || req.cookies?.token;
    if (!token) {
      return res.status(401).json({ code: 401, message: '请先登录' });
    }
    const decoded = jwt.verify(token, JWT_SECRET);
    const [users] = await pool.execute('SELECT id, username, nickname, avatar, role, status FROM users WHERE id = ?', [decoded.id]);
    if (users.length === 0) {
      return res.status(401).json({ code: 401, message: '用户不存在' });
    }
    if (users[0].status === 0) {
      return res.status(403).json({ code: 403, message: '账号已被禁用' });
    }
    req.user = users[0];
    req.user.roleName = ROLE_NAMES[users[0].role] || '普通用户';
    req.user.permissions = ROLE_PERMISSIONS[users[0].role] || [];
    next();
  } catch (err) {
    if (err && ['TokenExpiredError', 'JsonWebTokenError', 'NotBeforeError'].includes(err.name)) {
      return res.status(401).json({ code: 401, message: '登录已过期,请重新登录' });
    }
    console.error('[Auth] 用户状态查询失败:', err && (err.code || err.message));
    return res.status(503).json({ code: 503, message: '服务暂时不可用,请稍后重试' });
  }
};

const optionalAuth = async (req, res, next) => {
  try {
    const token = req.headers.authorization?.split(' ')[1] || req.cookies?.token;
    if (token) {
      const decoded = jwt.verify(token, JWT_SECRET);
      const [users] = await pool.execute('SELECT id, username, nickname, avatar, role, status FROM users WHERE id = ?', [decoded.id]);
      if (users.length > 0 && users[0].status === 1) {
        req.user = users[0];
        req.user.roleName = ROLE_NAMES[users[0].role] || '普通用户';
        req.user.permissions = ROLE_PERMISSIONS[users[0].role] || [];
      }
    }
  } catch (err) {
  }
  next();
};

const isStaff = (req, res, next) => {
  if (!req.user || ROLES[req.user.role] < 1) {
    return res.status(403).json({ code: 403, message: '无管理权限' });
  }
  next();
};

const adminOnly = (req, res, next) => {
  if (!req.user || ROLES[req.user.role] < 2) {
    return res.status(403).json({ code: 403, message: '需要管理员权限' });
  }
  next();
};

const superAdminOnly = (req, res, next) => {
  if (!req.user || req.user.role !== 'super_admin') {
    return res.status(403).json({ code: 403, message: '需要超级管理员权限' });
  }
  next();
};

const requirePermission = (permission) => {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ code: 401, message: '请先登录' });
    }
    if (req.user.role === 'super_admin' || (req.user.permissions && req.user.permissions.includes(permission))) {
      return next();
    }
    return res.status(403).json({ code: 403, message: '权限不足' });
  };
};

function isStaffRole(role) {
  return role && ROLES[role] >= 1;
}

module.exports = { auth, optionalAuth, adminOnly, isStaff, superAdminOnly, requirePermission, isStaffRole, ROLES, ROLE_NAMES, ROLE_PERMISSIONS };