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
JavaScript
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)
})
};