spaps 0.4.3 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -35
- package/bin/spaps.js +5 -312
- package/package.json +11 -8
- package/src/ai-helper.js +20 -20
- package/src/cli-dispatcher.js +139 -0
- package/src/config.js +5 -0
- package/src/docs-system.js +78 -129
- package/src/handlers.js +155 -0
- package/src/help-system.js +5 -3
- package/src/index.js +42 -0
- package/src/middleware/admin.js +238 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Admin middleware for SPAPS applications
|
|
5
|
+
* Provides built-in admin role checking and permission validation
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Default admin configuration
|
|
9
|
+
const DEFAULT_ADMIN_ACCOUNTS = {
|
|
10
|
+
email: 'buildooor@gmail.com',
|
|
11
|
+
wallets: {
|
|
12
|
+
ethereum: '0xa72bb7CeF1e4B2Cc144373d8dE0Add7CCc8DF4Ba',
|
|
13
|
+
solana: 'HVEbdiYU3Rr34NHBSgKs7q8cvdTeZLqNL77Z1FB2vjLy',
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if an identifier (email/wallet) is an admin account
|
|
19
|
+
*/
|
|
20
|
+
function isAdminAccount(identifier, customAdmins = []) {
|
|
21
|
+
if (!identifier) return false;
|
|
22
|
+
|
|
23
|
+
const normalized = identifier.toLowerCase();
|
|
24
|
+
|
|
25
|
+
// Check default admin accounts
|
|
26
|
+
if (normalized === DEFAULT_ADMIN_ACCOUNTS.email.toLowerCase() ||
|
|
27
|
+
normalized === DEFAULT_ADMIN_ACCOUNTS.wallets.ethereum.toLowerCase() ||
|
|
28
|
+
normalized === DEFAULT_ADMIN_ACCOUNTS.wallets.solana.toLowerCase()) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check custom admin accounts
|
|
33
|
+
return customAdmins.some(admin => {
|
|
34
|
+
if (typeof admin === 'string') {
|
|
35
|
+
return admin.toLowerCase() === normalized;
|
|
36
|
+
}
|
|
37
|
+
if (admin.email && admin.email.toLowerCase() === normalized) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (admin.wallet_address && admin.wallet_address.toLowerCase() === normalized) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get user role based on identifier
|
|
49
|
+
*/
|
|
50
|
+
function getUserRole(identifier, customAdmins = []) {
|
|
51
|
+
if (isAdminAccount(identifier, customAdmins)) {
|
|
52
|
+
return 'admin';
|
|
53
|
+
}
|
|
54
|
+
return 'user';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get role-aware error message
|
|
59
|
+
*/
|
|
60
|
+
function getRoleAwareErrorMessage(requiredRole, userRole, action = 'perform this action') {
|
|
61
|
+
const messages = {
|
|
62
|
+
admin: {
|
|
63
|
+
user: `🔒 Admin privileges required to ${action}. Please authenticate with an admin account.`,
|
|
64
|
+
guest: `🔐 Authentication required. Please sign in with an admin account to ${action}.`
|
|
65
|
+
},
|
|
66
|
+
user: {
|
|
67
|
+
guest: `🔐 Authentication required. Please sign in to ${action}.`
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return messages[requiredRole]?.[userRole] || `Access denied. Required role: ${requiredRole}, current role: ${userRole}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Express middleware for admin authentication
|
|
76
|
+
*/
|
|
77
|
+
function requireAdmin(options = {}) {
|
|
78
|
+
const {
|
|
79
|
+
customAdmins = [],
|
|
80
|
+
errorMessage,
|
|
81
|
+
onUnauthorized,
|
|
82
|
+
allowLocalBypass = true
|
|
83
|
+
} = options;
|
|
84
|
+
|
|
85
|
+
return (req, res, next) => {
|
|
86
|
+
// Check if in local development mode
|
|
87
|
+
if (allowLocalBypass && req.isLocalMode) {
|
|
88
|
+
console.log(chalk.yellow('🏠 Local mode: Admin check bypassed'));
|
|
89
|
+
req.isAdmin = true;
|
|
90
|
+
req.userRole = 'admin';
|
|
91
|
+
return next();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Extract user information from request
|
|
95
|
+
const userEmail = req.user?.email || req.body?.email;
|
|
96
|
+
const walletAddress = req.user?.wallet_address || req.body?.wallet_address;
|
|
97
|
+
const identifier = userEmail || walletAddress;
|
|
98
|
+
|
|
99
|
+
if (!identifier) {
|
|
100
|
+
const message = errorMessage || getRoleAwareErrorMessage('admin', 'guest');
|
|
101
|
+
|
|
102
|
+
if (onUnauthorized) {
|
|
103
|
+
return onUnauthorized(req, res, { reason: 'no_identifier', message });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return res.status(401).json({
|
|
107
|
+
success: false,
|
|
108
|
+
error: {
|
|
109
|
+
code: 'AUTHENTICATION_REQUIRED',
|
|
110
|
+
message
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const isAdmin = isAdminAccount(identifier, customAdmins);
|
|
116
|
+
const userRole = getUserRole(identifier, customAdmins);
|
|
117
|
+
|
|
118
|
+
if (!isAdmin) {
|
|
119
|
+
const message = errorMessage || getRoleAwareErrorMessage('admin', userRole);
|
|
120
|
+
|
|
121
|
+
if (onUnauthorized) {
|
|
122
|
+
return onUnauthorized(req, res, {
|
|
123
|
+
reason: 'insufficient_privileges',
|
|
124
|
+
message,
|
|
125
|
+
userRole,
|
|
126
|
+
identifier
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return res.status(403).json({
|
|
131
|
+
success: false,
|
|
132
|
+
error: {
|
|
133
|
+
code: 'INSUFFICIENT_PRIVILEGES',
|
|
134
|
+
message
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Add admin information to request
|
|
140
|
+
req.isAdmin = true;
|
|
141
|
+
req.userRole = userRole;
|
|
142
|
+
req.adminAccount = identifier;
|
|
143
|
+
|
|
144
|
+
console.log(chalk.green(`👑 Admin authenticated: ${identifier}`));
|
|
145
|
+
next();
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Permission checking utility
|
|
151
|
+
*/
|
|
152
|
+
function hasPermission(user, requiredPermissions, customAdmins = []) {
|
|
153
|
+
if (!user) return false;
|
|
154
|
+
|
|
155
|
+
const identifier = user.email || user.wallet_address;
|
|
156
|
+
const userRole = getUserRole(identifier, customAdmins);
|
|
157
|
+
|
|
158
|
+
// Admins have all permissions
|
|
159
|
+
if (userRole === 'admin') {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Check specific permissions
|
|
164
|
+
if (Array.isArray(requiredPermissions)) {
|
|
165
|
+
return requiredPermissions.every(permission =>
|
|
166
|
+
user.permissions?.includes(permission)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return user.permissions?.includes(requiredPermissions);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Express middleware for permission checking
|
|
175
|
+
*/
|
|
176
|
+
function requirePermission(permissions, options = {}) {
|
|
177
|
+
const {
|
|
178
|
+
customAdmins = [],
|
|
179
|
+
errorMessage,
|
|
180
|
+
onUnauthorized
|
|
181
|
+
} = options;
|
|
182
|
+
|
|
183
|
+
return (req, res, next) => {
|
|
184
|
+
const user = req.user;
|
|
185
|
+
const hasRequiredPermission = hasPermission(user, permissions, customAdmins);
|
|
186
|
+
|
|
187
|
+
if (!hasRequiredPermission) {
|
|
188
|
+
const userRole = user ? getUserRole(user.email || user.wallet_address, customAdmins) : 'guest';
|
|
189
|
+
const message = errorMessage || getRoleAwareErrorMessage('permission', userRole, `access this resource`);
|
|
190
|
+
|
|
191
|
+
if (onUnauthorized) {
|
|
192
|
+
return onUnauthorized(req, res, {
|
|
193
|
+
reason: 'insufficient_permissions',
|
|
194
|
+
message,
|
|
195
|
+
requiredPermissions: permissions,
|
|
196
|
+
userPermissions: user?.permissions || []
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return res.status(403).json({
|
|
201
|
+
success: false,
|
|
202
|
+
error: {
|
|
203
|
+
code: 'INSUFFICIENT_PERMISSIONS',
|
|
204
|
+
message,
|
|
205
|
+
details: {
|
|
206
|
+
required: permissions,
|
|
207
|
+
current: user?.permissions || []
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
next();
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
module.exports = {
|
|
218
|
+
// Middleware functions
|
|
219
|
+
requireAdmin,
|
|
220
|
+
requirePermission,
|
|
221
|
+
|
|
222
|
+
// Utility functions
|
|
223
|
+
isAdminAccount,
|
|
224
|
+
getUserRole,
|
|
225
|
+
hasPermission,
|
|
226
|
+
getRoleAwareErrorMessage,
|
|
227
|
+
|
|
228
|
+
// Constants
|
|
229
|
+
DEFAULT_ADMIN_ACCOUNTS,
|
|
230
|
+
|
|
231
|
+
// Helper for client-side checking
|
|
232
|
+
createPermissionChecker: (customAdmins = []) => ({
|
|
233
|
+
isAdmin: (identifier) => isAdminAccount(identifier, customAdmins),
|
|
234
|
+
getRole: (identifier) => getUserRole(identifier, customAdmins),
|
|
235
|
+
hasPermission: (user, permissions) => hasPermission(user, permissions, customAdmins),
|
|
236
|
+
getErrorMessage: (requiredRole, userRole, action) => getRoleAwareErrorMessage(requiredRole, userRole, action)
|
|
237
|
+
})
|
|
238
|
+
};
|