Repository navigation
Expand file tree
/
Copy pathfix-admin-data-loading.js
More file actions
294 lines (244 loc) Β· 8.84 KB
/
Copy pathfix-admin-data-loading.js
File metadata and controls
294 lines (244 loc) Β· 8.84 KB
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// Fix Admin Data Loading Issues
// Run this in browser console to diagnose and fix data loading
console.log('π§ ADMIN DATA LOADING FIXER');
console.log('===========================');
class AdminDataFixer {
constructor() {
this.issues = [];
this.supabase = null;
}
// Get Supabase client from various possible sources
getSupabaseClient() {
// Try different ways to access Supabase
if (window.supabase) {
return window.supabase;
}
// Try to get from React app context
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
const reactInstances = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers;
if (reactInstances && reactInstances.size > 0) {
// This is a fallback - React DevTools might have the instance
console.log('React DevTools detected, but Supabase access limited');
}
}
// Try to access from the app's global variables
if (window.app && window.app.supabase) {
return window.app.supabase;
}
// Try to get from any global variable that might contain it
for (const key in window) {
if (key.toLowerCase().includes('supabase') && window[key] && window[key].from) {
return window[key];
}
}
return null;
}
log(message, type = 'info') {
const prefix = {
'error': 'β',
'warn': 'β οΈ',
'success': 'β
',
'info': 'βΉοΈ'
}[type] || 'βΉοΈ';
console.log(`${prefix} ${message}`);
}
// Test 1: Check if admin policies are deployed
async testAdminPolicies() {
this.log('π Testing admin policies...');
this.supabase = this.getSupabaseClient();
if (!this.supabase) {
this.log('β Supabase client not found!', 'error');
this.log('π‘ Make sure you are on the app page and Supabase is loaded', 'warn');
return false;
}
try {
// Test if is_admin function exists
const { data, error } = await this.supabase.rpc('is_admin');
if (error) {
this.log(`Admin function error: ${error.message}`, 'error');
this.log('π¨ CRITICAL: Admin policies are NOT deployed!', 'error');
return false;
}
this.log(`Admin function works. User is admin: ${data}`, data ? 'success' : 'warn');
return data;
} catch (error) {
this.log(`Admin policies test failed: ${error.message}`, 'error');
return false;
}
}
// Test 2: Check direct table access
async testDirectAccess() {
this.log('π Testing direct table access...');
if (!this.supabase) {
this.supabase = this.getSupabaseClient();
if (!this.supabase) {
this.log('β Supabase client not available', 'error');
return null;
}
}
try {
// Try to access profiles directly
const { data: profiles, error: profileError } = await this.supabase
.from('profiles')
.select('id, email, credits')
.limit(5);
if (profileError) {
this.log(`Profiles access error: ${profileError.message}`, 'error');
} else {
this.log(`β
Profiles access: Found ${profiles.length} users`, 'success');
if (profiles.length > 0) {
this.log(`Sample user: ${profiles[0].email} (${profiles[0].credits} credits)`, 'info');
}
}
// Try to access payment_history directly
const { data: payments, error: paymentError } = await this.supabase
.from('payment_history')
.select('id, customer_email, amount, payment_status')
.limit(5);
if (paymentError) {
this.log(`Payment history access error: ${paymentError.message}`, 'error');
} else {
this.log(`β
Payment history access: Found ${payments.length} payments`, 'success');
if (payments.length > 0) {
this.log(`Sample payment: ${payments[0].customer_email} - $${payments[0].amount/100}`, 'info');
}
}
return {
profiles: profiles || [],
payments: payments || [],
profileAccess: !profileError,
paymentAccess: !paymentError
};
} catch (error) {
this.log(`Direct access test failed: ${error.message}`, 'error');
return null;
}
}
// Test 3: Calculate stats manually
async calculateStats(profiles, payments) {
this.log('π Calculating stats manually...');
try {
const totalUsers = profiles.length;
const totalCredits = profiles.reduce((sum, user) => sum + (user.credits || 0), 0);
const completedPayments = payments.filter(p => p.payment_status === 'completed');
const totalRevenue = completedPayments.reduce((sum, p) => sum + (p.amount || 0), 0) / 100;
this.log(`π Manual Stats:`, 'info');
this.log(` Total Users: ${totalUsers}`, 'info');
this.log(` Total Credits: ${totalCredits}`, 'info');
this.log(` Total Revenue: $${totalRevenue.toFixed(2)}`, 'info');
this.log(` Successful Payments: ${completedPayments.length}`, 'info');
return {
totalUsers,
totalCredits,
totalRevenue,
successfulPayments: completedPayments.length
};
} catch (error) {
this.log(`Stats calculation failed: ${error.message}`, 'error');
return null;
}
}
// Fix 1: Force refresh admin data
async forceRefreshData() {
this.log('π Force refreshing admin data...');
// Trigger a page refresh of the admin dashboard
if (window.location.pathname === '/admin') {
this.log('Refreshing admin dashboard...', 'info');
window.location.reload();
} else {
this.log('Navigate to /admin first, then run this', 'warn');
}
}
// Fix 2: Provide SQL to deploy admin policies
showAdminPoliciesSQL() {
this.log('π Admin Policies SQL (Run in Supabase SQL Editor):', 'info');
console.log(`
-- COPY AND PASTE THIS INTO SUPABASE SQL EDITOR:
-- Create admin function
CREATE OR REPLACE FUNCTION is_admin()
RETURNS boolean AS $$
BEGIN
RETURN (
SELECT email FROM auth.users
WHERE id = auth.uid()
AND email = 'diogo@diogoppedro.com'
) IS NOT NULL;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Grant permissions
GRANT EXECUTE ON FUNCTION is_admin TO authenticated;
-- Create admin policies for profiles
CREATE POLICY "Admin can read all profiles"
ON profiles FOR SELECT
USING (is_admin());
-- Create admin policies for payment_history
CREATE POLICY "Admin can read all payment history"
ON payment_history FOR SELECT
USING (is_admin());
-- Test the function
SELECT is_admin();
`);
}
// Main diagnosis and fix
async diagnoseAndFix() {
this.log('π Starting admin data diagnosis...\n');
// First check if Supabase is available
this.supabase = this.getSupabaseClient();
if (!this.supabase) {
this.log('β Supabase client not found!', 'error');
this.log('π‘ Make sure you are on the app page (not just the console)', 'warn');
this.log('π‘ Try navigating to the app first, then run this script', 'warn');
return;
}
this.log('β
Supabase client found!', 'success');
// Test admin policies
const adminWorks = await this.testAdminPolicies();
if (!adminWorks) {
this.log('\nπ¨ SOLUTION: Deploy admin policies!', 'error');
this.showAdminPoliciesSQL();
return;
}
// Test direct access
const accessResult = await this.testDirectAccess();
if (!accessResult) {
this.log('\nπ¨ Database access completely failed', 'error');
return;
}
// Calculate stats manually
const stats = await this.calculateStats(accessResult.profiles, accessResult.payments);
if (stats && (stats.totalUsers > 0 || stats.successfulPayments > 0)) {
this.log('\nβ
Data exists! Issue might be with dashboard loading.', 'success');
this.log('π‘ Try refreshing the page or check browser console for errors.', 'info');
} else {
this.log('\nβ οΈ No data found in database.', 'warn');
this.log('π‘ This might be expected if no users have signed up or made payments yet.', 'info');
}
return {
adminWorks,
accessResult,
stats
};
}
}
// Create global fixer
window.adminFixer = new AdminDataFixer();
// Quick commands
window.adminQuickFix = {
diagnose: () => adminFixer.diagnoseAndFix(),
testPolicies: () => adminFixer.testAdminPolicies(),
testAccess: () => adminFixer.testDirectAccess(),
refresh: () => adminFixer.forceRefreshData(),
showSQL: () => adminFixer.showAdminPoliciesSQL()
};
console.log(`
π§ ADMIN DATA FIXER LOADED!
Quick Commands:
- adminQuickFix.diagnose() // Full diagnosis
- adminQuickFix.testPolicies() // Test admin functions
- adminQuickFix.testAccess() // Test data access
- adminQuickFix.showSQL() // Show SQL to deploy
- adminQuickFix.refresh() // Refresh dashboard
IMPORTANT: Make sure you are on the app page first!
`);
// Auto-run diagnosis
adminFixer.diagnoseAndFix();