feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality - Implement territory management with manager performance tracking - Add seatmap components for venue layout management - Create customer management features with modal interface - Add advanced hooks for dashboard flags and territory data - Implement seat selection and venue management utilities - Add type definitions for ticketing and seatmap systems 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
94
reactrebuild0825/firestore.rules
Normal file
94
reactrebuild0825/firestore.rules
Normal file
@@ -0,0 +1,94 @@
|
||||
rules_version = '2';
|
||||
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
// Helper functions
|
||||
function inOrg(orgId) {
|
||||
return request.auth != null && request.auth.token.orgId == orgId;
|
||||
}
|
||||
|
||||
function canWriteOrg(orgId) {
|
||||
return inOrg(orgId) && (request.auth.token.role in ['superadmin', 'orgAdmin']);
|
||||
}
|
||||
|
||||
function territoryOK(resOrgId, resTerritoryId) {
|
||||
return inOrg(resOrgId) && (
|
||||
request.auth.token.role in ['superadmin', 'orgAdmin'] ||
|
||||
(request.auth.token.role == 'territoryManager' && (resTerritoryId in request.auth.token.territoryIds)) ||
|
||||
request.auth.token.role == 'staff' // staff sees entire org; can narrow later
|
||||
);
|
||||
}
|
||||
|
||||
function canReadTerritory(resOrgId, resTerritoryId) {
|
||||
return inOrg(resOrgId) && (
|
||||
request.auth.token.role in ['superadmin', 'orgAdmin'] ||
|
||||
(request.auth.token.role == 'territoryManager' && (resTerritoryId in request.auth.token.territoryIds)) ||
|
||||
request.auth.token.role == 'staff'
|
||||
);
|
||||
}
|
||||
|
||||
// Organizations collection
|
||||
match /orgs/{orgId} {
|
||||
allow read, write: if inOrg(orgId);
|
||||
allow create: if request.auth != null;
|
||||
}
|
||||
|
||||
// Users collection for organization membership tracking
|
||||
match /users/{userId} {
|
||||
// Users can read their own document, or admins can read within their org
|
||||
allow read: if (request.auth != null && request.auth.uid == userId) ||
|
||||
(request.auth != null && inOrg(resource.data.orgId));
|
||||
|
||||
// Only orgAdmins and superadmins can write user documents
|
||||
allow write: if request.auth != null &&
|
||||
canWriteOrg(request.resource.data.orgId);
|
||||
}
|
||||
|
||||
// Territories collection
|
||||
match /territories/{territoryId} {
|
||||
allow read: if inOrg(resource.data.orgId);
|
||||
allow write: if canWriteOrg(request.resource.data.orgId);
|
||||
}
|
||||
|
||||
// Events collection with territory scoping
|
||||
match /events/{eventId} {
|
||||
allow read: if canReadTerritory(resource.data.orgId, resource.data.territoryId);
|
||||
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
|
||||
}
|
||||
|
||||
// Ticket types collection with territory inheritance
|
||||
match /ticket_types/{ticketTypeId} {
|
||||
allow read: if inOrg(resource.data.orgId);
|
||||
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
|
||||
}
|
||||
|
||||
// Tickets collection with territory inheritance
|
||||
match /tickets/{ticketId} {
|
||||
// Scanning/reporting needs org-wide reads; can narrow if required
|
||||
allow read: if inOrg(resource.data.orgId);
|
||||
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
|
||||
}
|
||||
|
||||
// Scans collection - append-only audit trail for ticket scanning
|
||||
match /scans/{scanId} {
|
||||
// Staff and above can read scans within their org for reporting/analytics
|
||||
allow read: if inOrg(resource.data.orgId) &&
|
||||
request.auth.token.role in ['staff', 'territoryManager', 'orgAdmin', 'superadmin'];
|
||||
|
||||
// Only create operations allowed - append-only pattern
|
||||
// Staff and above can create scan records within their org
|
||||
allow create: if inOrg(request.resource.data.orgId) &&
|
||||
request.auth.token.role in ['staff', 'territoryManager', 'orgAdmin', 'superadmin'];
|
||||
|
||||
// Explicitly deny updates and deletes to enforce append-only pattern
|
||||
allow update, delete: if false;
|
||||
}
|
||||
|
||||
// Legacy support for old organization membership model
|
||||
function isOrgMember(orgId) {
|
||||
return request.auth != null &&
|
||||
exists(/databases/$(database)/documents/users/$(request.auth.uid)) &&
|
||||
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.orgs[orgId] != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user