Skip to content

Commit 69e30bd

Browse files
committed
Add Admin page consolidating Configure, Users, Data Management; Add Diagnostics page with Telemetry and Audit Logs
1 parent 2daf1bf commit 69e30bd

14 files changed

Lines changed: 2081 additions & 357 deletions

File tree

firestore.rules

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ service cloud.firestore {
109109
allow update, delete: if false; // Never allow modification or deletion
110110
}
111111

112+
// Telemetry - all can write (for error logging), only owners can read/delete
113+
match /telemetry/{docId} {
114+
allow create, update: if isSignedIn();
115+
allow read, delete: if isSignedIn() && isAdmin();
116+
}
117+
112118
// ============================================
113119
// DEVELOPMENT ENVIRONMENT COLLECTIONS (dev_ prefix)
114120
// Mirror all production rules for dev collections
@@ -162,5 +168,8 @@ service cloud.firestore {
162168
match /dev_settings/{docId} {
163169
allow read, write: if isSignedIn();
164170
}
171+
match /dev_telemetry/{docId} {
172+
allow read, write: if isSignedIn();
173+
}
165174
}
166175
}

www/js/auth/authentication.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ const AuthManager = {
365365
const restrictedTabs = {
366366
'financeTab': isOwnerOrManager,
367367
'analyticsTab': isOwnerOrManager,
368-
'usersTab': isOwner,
369368
'stockTab': !isStaff,
370369
'salesTab': !isStaff
371370
};
@@ -395,9 +394,15 @@ const AuthManager = {
395394
item.style.display = 'block';
396395
}
397396

398-
if (tabId === 'users' && !isOwner) {
397+
if (tabId === 'diagnostics' && !isOwner) {
399398
item.style.display = 'none';
400-
} else if (tabId === 'users' && isOwner) {
399+
} else if (tabId === 'diagnostics' && isOwner) {
400+
item.style.display = 'block';
401+
}
402+
403+
if (tabId === 'admin' && !isOwner) {
404+
item.style.display = 'none';
405+
} else if (tabId === 'admin' && isOwner) {
401406
item.style.display = 'block';
402407
}
403408

www/js/main.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import { AnalyticsManager } from './modules/analytics.js';
2222
import { CashManagementManager } from './modules/cash-management.js';
2323
import { DayManager } from './modules/day.js';
2424
import { AuditService } from './services/audit.js';
25+
import { TelemetryService } from './services/telemetry.js';
26+
import { DiagnosticsManager } from './modules/diagnostics.js';
27+
import { AdminManager } from './modules/admin.js';
2528

2629
// Import template loader utility
2730
import { TemplateLoader } from './utils/template-loader.js';
@@ -37,11 +40,28 @@ window.addEventListener('error', function(event) {
3740
const errorMsg = event.error?.message || event.message || 'Unknown error';
3841
console.error('Global error:', event.error);
3942
UIManager.showToast('An error occurred: ' + errorMsg);
43+
44+
// Log to telemetry
45+
TelemetryService.captureError({
46+
type: 'uncaught',
47+
message: errorMsg,
48+
stack: event.error?.stack,
49+
source: event.filename,
50+
line: event.lineno,
51+
column: event.colno
52+
});
4053
});
4154

4255
window.addEventListener('unhandledrejection', function(event) {
4356
const errorMsg = event.reason?.message || event.reason || 'Unknown rejection';
4457
console.error('Unhandled promise rejection:', event.reason);
58+
59+
// Log to telemetry
60+
TelemetryService.captureError({
61+
type: 'unhandledrejection',
62+
message: errorMsg,
63+
stack: event.reason?.stack
64+
});
4565
});
4666

4767
// Setup event listeners
@@ -629,6 +649,30 @@ window.app = {
629649
showChangeRoleDialog: (userId, userName, currentRole) => UsersManager.showChangeRoleDialog(userId, userName, currentRole)
630650
},
631651

652+
// Diagnostics (owner only)
653+
diagnostics: {
654+
init: () => DiagnosticsManager.init(),
655+
showTab: (tab) => DiagnosticsManager.showTab(tab),
656+
loadData: () => DiagnosticsManager.loadData(),
657+
loadAuditLogs: () => DiagnosticsManager.loadAuditLogs(),
658+
filterByType: (type) => DiagnosticsManager.filterByType(type),
659+
filterAuditLogs: (action) => DiagnosticsManager.filterAuditLogs(action),
660+
deleteError: (errorId) => DiagnosticsManager.deleteError(errorId),
661+
clearAll: () => DiagnosticsManager.clearAll()
662+
},
663+
664+
// Admin (owner only)
665+
admin: {
666+
init: () => AdminManager.init(),
667+
showTab: (tab) => AdminManager.showTab(tab),
668+
saveConfigure: () => AdminManager.saveConfigure(),
669+
approveUser: (userId) => AdminManager.approveUser(userId),
670+
rejectUser: (userId) => AdminManager.rejectUser(userId),
671+
showChangeRole: (userId, userName, currentRole) => AdminManager.showChangeRole(userId, userName, currentRole),
672+
loadStorageStats: () => AdminManager.loadStorageStats(),
673+
clearAllData: () => AdminManager.clearAllData()
674+
},
675+
632676
// UI
633677
ui: {
634678
showLoading: () => UIManager.showLoading(),

0 commit comments

Comments
 (0)