forked from AP-Students/website
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfirestore.rules
More file actions
103 lines (82 loc) · 3.96 KB
/
Copy pathfirestore.rules
File metadata and controls
103 lines (82 loc) · 3.96 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
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Centralized function to check if the user is authenticated
function isAuthenticated() {
return request.auth != null;
}
// Centralized function to check if the user is an admin
function isAdmin() {
return isAuthenticated() && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.access == "admin";
}
// Centralized function to check if the user is a member or admin (role hierarchy)
function isMemberOrAdmin() {
let accessLevel = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.access;
return isAuthenticated() && (accessLevel == "admin" || accessLevel == "member");
}
function isGraderOrMemberOrAdmin() {
let accessLevel = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.access;
return isAuthenticated() && (accessLevel == "admin" || accessLevel == "member" || accessLevel == "grader");
}
// Allow read/write access to users for their own user data
match /users/{userId} {
allow read: if isAuthenticated() && request.auth.uid == userId;
allow create: if isAuthenticated() && request.auth.uid == userId && request.resource.data.access == "user";
allow update: if isAuthenticated() && request.auth.uid == userId && (!request.resource.data.diff(resource.data).affectedKeys().hasAny(['access', 'uid']));
allow delete: if isAuthenticated() && request.auth.uid == userId;
match /frqResponses/{document=**} {
allow read: if isAuthenticated() && request.auth.uid == userId;
allow create: if isAuthenticated() && request.auth.uid == userId && (request.resource.data.keys().hasAll(['responseText', 'question', 'userId', 'submittedAt'])) && (request.resource.data.keys().hasOnly(['responseText', 'question', 'userId', 'submittedAt'])) && canSubmitFrqResponse();
allow update: if isGraderOrMemberOrAdmin() && (request.resource.data.diff(resource.data).affectedKeys().hasOnly(['feedback', 'grade', 'gradedAt', 'gradedBy', 'status']));
}
match /chapterData/{document=**} {
allow read, write: if isAuthenticated() && request.auth.uid == userId;
}
}
function canSubmitFrqResponse() {
let userDoc = get(/databases/$(database)/documents/users/$(request.auth.uid));
let userData = userDoc.data;
let userDocAfter = getAfter(/databases/$(database)/documents/users/$(request.auth.uid));
let userDataAfter = userDocAfter.data;
return userData.access != "banned" && (isAdmin() || (!("lastFrqResponseAt" in userData) &&
"lastFrqResponseAt" in userDataAfter
) || (
userData.lastFrqResponseAt < (request.time - duration.value(6, 'h'))
&&
userDataAfter.lastFrqResponseAt == request.resource.data.submittedAt)
)
}
match /{somePath=**}/frqResponses/{frqResponse} {
allow read: if isGraderOrMemberOrAdmin();
}
// Admins can read/write all user documents
match /users/{document=**} {
allow read, write: if isAdmin();
}
// Subjects and pages can be accessed by members and admins
match /subjects/{subject} {
allow read: if true;
allow write: if isMemberOrAdmin();
match /units/{unit} {
allow read: if true;
allow write: if isMemberOrAdmin();
match /chapters/{chapter} {
allow read: if resource.data.isPublic == true || isMemberOrAdmin();
allow write: if isMemberOrAdmin();
}
match /tests/{test} {
allow read: if resource.data.isPublic == true || isMemberOrAdmin();
allow write: if isMemberOrAdmin();
}
}
}
match /pages/{document=**} {
allow read: if true;
allow write: if isMemberOrAdmin();
}
// Allow users to access and write to their own profiles
match /profiles/{userId} {
allow read, write: if isAuthenticated() && request.auth.uid == userId;
}
}
}