All files / middleware auth.js

0% Statements 0/53
0% Branches 0/21
0% Functions 0/6
0% Lines 0/52

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101                                                                                                                                                                                                         
const jwt = require('jsonwebtoken');
const { User } = require('../models');
const logger = require('../utils/logger');
 
// Verify JWT token
const authenticate = async (req, res, next) => {
  try {
    const token = req.headers.authorization?.replace('Bearer ', '');
    
    if (!token) {
      return res.status(401).json({ error: 'Authentication required' });
    }
 
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    const user = await User.findByPk(decoded.userId);
 
    if (!user || !user.isActive) {
      return res.status(401).json({ error: 'Invalid authentication' });
    }
 
    req.user = user;
    req.userId = user.id;
    next();
  } catch (error) {
    logger.error('Authentication error:', error);
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
};
 
// Verify wallet signature
const verifySignature = async (req, res, next) => {
  try {
    const { message, signature, walletAddress } = req.body;
    
    if (!message || !signature || !walletAddress) {
      return res.status(400).json({ error: 'Missing required fields' });
    }
 
    const ethers = require('ethers');
    const recoveredAddress = ethers.utils.verifyMessage(message, signature);
 
    if (recoveredAddress.toLowerCase() !== walletAddress.toLowerCase()) {
      return res.status(401).json({ error: 'Invalid signature' });
    }
 
    req.walletAddress = walletAddress;
    next();
  } catch (error) {
    logger.error('Signature verification error:', error);
    return res.status(401).json({ error: 'Signature verification failed' });
  }
};
 
// Check admin role
const isAdmin = async (req, res, next) => {
  try {
    if (!req.user || req.user.role !== 'admin') {
      return res.status(403).json({ error: 'Admin access required' });
    }
    next();
  } catch (error) {
    logger.error('Admin check error:', error);
    return res.status(403).json({ error: 'Access denied' });
  }
};
 
// Rate limit per user
const userRateLimit = (maxRequests, windowMs) => {
  const requests = new Map();
 
  return (req, res, next) => {
    const userId = req.userId;
    const now = Date.now();
    
    if (!requests.has(userId)) {
      requests.set(userId, []);
    }
 
    const userRequests = requests.get(userId);
    const recentRequests = userRequests.filter(time => now - time < windowMs);
 
    if (recentRequests.length >= maxRequests) {
      return res.status(429).json({ 
        error: 'Too many requests, please try again later' 
      });
    }
 
    recentRequests.push(now);
    requests.set(userId, recentRequests);
    next();
  };
};
 
module.exports = {
  authenticate,
  verifySignature,
  isAdmin,
  userRateLimit
};