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.
@@ -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
+ };