UNPKG

spaps

Version:

Sweet Potato Authentication & Payment Service CLI - Zero-config local development with built-in admin middleware and permission utilities

238 lines (202 loc) 6.4 kB
const chalk = require('chalk'); /** * Admin middleware for SPAPS applications * Provides built-in admin role checking and permission validation */ // Default admin configuration const DEFAULT_ADMIN_ACCOUNTS = { email: 'buildooor@gmail.com', wallets: { ethereum: '0xa72bb7CeF1e4B2Cc144373d8dE0Add7CCc8DF4Ba', solana: 'HVEbdiYU3Rr34NHBSgKs7q8cvdTeZLqNL77Z1FB2vjLy', } }; /** * Check if an identifier (email/wallet) is an admin account */ function isAdminAccount(identifier, customAdmins = []) { if (!identifier) return false; const normalized = identifier.toLowerCase(); // Check default admin accounts if (normalized === DEFAULT_ADMIN_ACCOUNTS.email.toLowerCase() || normalized === DEFAULT_ADMIN_ACCOUNTS.wallets.ethereum.toLowerCase() || normalized === DEFAULT_ADMIN_ACCOUNTS.wallets.solana.toLowerCase()) { return true; } // Check custom admin accounts return customAdmins.some(admin => { if (typeof admin === 'string') { return admin.toLowerCase() === normalized; } if (admin.email && admin.email.toLowerCase() === normalized) { return true; } if (admin.wallet_address && admin.wallet_address.toLowerCase() === normalized) { return true; } return false; }); } /** * Get user role based on identifier */ function getUserRole(identifier, customAdmins = []) { if (isAdminAccount(identifier, customAdmins)) { return 'admin'; } return 'user'; } /** * Get role-aware error message */ function getRoleAwareErrorMessage(requiredRole, userRole, action = 'perform this action') { const messages = { admin: { user: `🔒 Admin privileges required to ${action}. Please authenticate with an admin account.`, guest: `🔐 Authentication required. Please sign in with an admin account to ${action}.` }, user: { guest: `🔐 Authentication required. Please sign in to ${action}.` } }; return messages[requiredRole]?.[userRole] || `Access denied. Required role: ${requiredRole}, current role: ${userRole}`; } /** * Express middleware for admin authentication */ function requireAdmin(options = {}) { const { customAdmins = [], errorMessage, onUnauthorized, allowLocalBypass = true } = options; return (req, res, next) => { // Check if in local development mode if (allowLocalBypass && req.isLocalMode) { console.log(chalk.yellow('🏠 Local mode: Admin check bypassed')); req.isAdmin = true; req.userRole = 'admin'; return next(); } // Extract user information from request const userEmail = req.user?.email || req.body?.email; const walletAddress = req.user?.wallet_address || req.body?.wallet_address; const identifier = userEmail || walletAddress; if (!identifier) { const message = errorMessage || getRoleAwareErrorMessage('admin', 'guest'); if (onUnauthorized) { return onUnauthorized(req, res, { reason: 'no_identifier', message }); } return res.status(401).json({ success: false, error: { code: 'AUTHENTICATION_REQUIRED', message } }); } const isAdmin = isAdminAccount(identifier, customAdmins); const userRole = getUserRole(identifier, customAdmins); if (!isAdmin) { const message = errorMessage || getRoleAwareErrorMessage('admin', userRole); if (onUnauthorized) { return onUnauthorized(req, res, { reason: 'insufficient_privileges', message, userRole, identifier }); } return res.status(403).json({ success: false, error: { code: 'INSUFFICIENT_PRIVILEGES', message } }); } // Add admin information to request req.isAdmin = true; req.userRole = userRole; req.adminAccount = identifier; console.log(chalk.green(`👑 Admin authenticated: ${identifier}`)); next(); }; } /** * Permission checking utility */ function hasPermission(user, requiredPermissions, customAdmins = []) { if (!user) return false; const identifier = user.email || user.wallet_address; const userRole = getUserRole(identifier, customAdmins); // Admins have all permissions if (userRole === 'admin') { return true; } // Check specific permissions if (Array.isArray(requiredPermissions)) { return requiredPermissions.every(permission => user.permissions?.includes(permission) ); } return user.permissions?.includes(requiredPermissions); } /** * Express middleware for permission checking */ function requirePermission(permissions, options = {}) { const { customAdmins = [], errorMessage, onUnauthorized } = options; return (req, res, next) => { const user = req.user; const hasRequiredPermission = hasPermission(user, permissions, customAdmins); if (!hasRequiredPermission) { const userRole = user ? getUserRole(user.email || user.wallet_address, customAdmins) : 'guest'; const message = errorMessage || getRoleAwareErrorMessage('permission', userRole, `access this resource`); if (onUnauthorized) { return onUnauthorized(req, res, { reason: 'insufficient_permissions', message, requiredPermissions: permissions, userPermissions: user?.permissions || [] }); } return res.status(403).json({ success: false, error: { code: 'INSUFFICIENT_PERMISSIONS', message, details: { required: permissions, current: user?.permissions || [] } } }); } next(); }; } module.exports = { // Middleware functions requireAdmin, requirePermission, // Utility functions isAdminAccount, getUserRole, hasPermission, getRoleAwareErrorMessage, // Constants DEFAULT_ADMIN_ACCOUNTS, // Helper for client-side checking createPermissionChecker: (customAdmins = []) => ({ isAdmin: (identifier) => isAdminAccount(identifier, customAdmins), getRole: (identifier) => getUserRole(identifier, customAdmins), hasPermission: (user, permissions) => hasPermission(user, permissions, customAdmins), getErrorMessage: (requiredRole, userRole, action) => getRoleAwareErrorMessage(requiredRole, userRole, action) }) };