rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper functions
function isAuthenticated() {
return request.auth != null;
}
function isAdmin() {
return isAuthenticated() &&
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
}
function belongsToOrganization(organizationId) {
return isAuthenticated() &&
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.organizationId == organizationId;
}
// Users collection
match /users/{userId} {
allow read: if isAuthenticated() &&
(request.auth.uid == userId || isAdmin());
allow write: if isAuthenticated() &&
(request.auth.uid == userId || isAdmin());
}
// Organizations collection
match /organizations/{orgId} {
allow read: if belongsToOrganization(orgId);
allow write: if isAdmin();
}
// Patients collection
match /patients/{patientId} {
allow read: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
allow create: if isAuthenticated() &&
belongsToOrganization(request.resource.data.organizationId);
allow update: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
allow delete: if isAdmin();
// Patient subcollections
match /carepaths/{carepathId} {
allow read, write: if isAuthenticated() &&
belongsToOrganization(get(/databases/$(database)/documents/patients/$(patientId)).data.organizationId);
}
match /labels/{labelId} {
allow read, write: if isAuthenticated() &&
belongsToOrganization(get(/databases/$(database)/documents/patients/$(patientId)).data.organizationId);
}
match /notes/{noteId} {
allow read, write: if isAuthenticated() &&
belongsToOrganization(get(/databases/$(database)/documents/patients/$(patientId)).data.organizationId);
}
}
// Forms and submissions
match /forms/{formId} {
allow read: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
allow write: if isAdmin();
}
match /form_submissions/{submissionId} {
allow read: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
allow create: if isAuthenticated() &&
belongsToOrganization(request.resource.data.organizationId);
allow update: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
allow delete: if isAdmin();
}
// Alerts
match /alerts/{alertId} {
allow read, write: if isAuthenticated() &&
belongsToOrganization(resource.data.organizationId);
}
// Messages and chat topics
match /messages/{messageId} {
allow read, write: if isAuthenticated();
}
match /chat_topics/{topicId} {
allow read: if isAuthenticated() &&
request.auth.uid in resource.data.participants[].userId;
allow write: if isAuthenticated() &&
request.auth.uid in resource.data.participants[].userId;
}
// Audit logs (read-only for most users)
match /audit_logs/{logId} {
allow read: if isAdmin();
allow write: if false; // Only server-side writes
}
}
}