-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathfirestore.rules
More file actions
148 lines (129 loc) · 6.64 KB
/
firestore.rules
File metadata and controls
148 lines (129 loc) · 6.64 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
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// ----------------------------------------------------------------------------------
// I. Helper Functions
// ----------------------------------------------------------------------------------
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return isAuthenticated() && request.auth.uid == userId;
}
function isAdminOrSuperAdmin() {
return isAuthenticated() && (
request.auth.token.email == '4simpleproblems@gmail.com' ||
(exists(/databases/$(database)/documents/admins/$(request.auth.uid)) &&
get(/databases/$(database)/documents/admins/$(request.auth.uid)).data.role in ['admin', 'superadmin'])
);
}
// ----------------------------------------------------------------------------------
// II. User Profiles Collection (`users`)
// ----------------------------------------------------------------------------------
match /users/{userId} {
allow read: if isAuthenticated();
allow list: if isAdminOrSuperAdmin();
allow create: if isOwner(userId)
&& request.resource.id == request.auth.uid
&& 'username' in request.resource.data;
allow update: if isOwner(userId) ||
(isAuthenticated() &&
request.resource.data.diff(resource.data).affectedKeys().hasOnly(['pending_requests', 'friends']));
allow delete: if isOwner(userId);
}
// ----------------------------------------------------------------------------------
// III. Friend Codes Collection (`friend_codes`)
// ----------------------------------------------------------------------------------
match /friend_codes/{code} {
allow read: if isAuthenticated();
allow create: if isAuthenticated()
&& request.resource.data.userId == request.auth.uid;
allow delete: if isAuthenticated() && resource.data.userId == request.auth.uid;
allow update: if false;
}
// ----------------------------------------------------------------------------------
// IV. Admin Status Collection (`admins`)
// ----------------------------------------------------------------------------------
match /admins/{userId} {
allow read: if isOwner(userId) || isAdminOrSuperAdmin();
allow list: if isAdminOrSuperAdmin();
allow create, update, delete: if isAdminOrSuperAdmin();
}
// ----------------------------------------------------------------------------------
// V. Daily Photos Collection (`daily_photos`)
// ----------------------------------------------------------------------------------
match /daily_photos/{photoId} {
allow read: if isAuthenticated();
allow create: if isAuthenticated() && request.resource.data.creatorUid == request.auth.uid;
allow update: if isAuthenticated() && (
resource.data.creatorUid == request.auth.uid ||
request.resource.data.diff(resource.data).affectedKeys().hasOnly(['hearts', 'comments'])
);
allow delete: if isAuthenticated() && resource.data.creatorUid == request.auth.uid;
}
// ----------------------------------------------------------------------------------
// VI. Legacy / Unused Collections
// ----------------------------------------------------------------------------------
match /dailyPhotos/{photoId} {
allow create: if isAuthenticated() && (
(request.resource.data.creatorUid == request.auth.uid) ||
(request.resource.data.userId == request.auth.uid)
);
allow update, delete: if isAuthenticated() && (
(resource.data.creatorUid == request.auth.uid) ||
(resource.data.userId == request.auth.uid)
);
allow read: if isAuthenticated();
}
match /friendRequests/{requestId} {
allow create: if isAuthenticated() && request.resource.data.senderId == request.auth.uid;
allow delete: if isAuthenticated() && (
(resource.data.senderId == request.auth.uid) ||
(resource.data.recipientId == request.auth.uid)
);
allow read: if isAuthenticated() && (
(resource.data.senderId == request.auth.uid) ||
(resource.data.recipientId == request.auth.uid)
);
allow update: if false;
}
// ----------------------------------------------------------------------------------
// VII. Banned Users & Bans
// ----------------------------------------------------------------------------------
match /banned_users/{userId} {
allow read, create, update, delete: if isAdminOrSuperAdmin();
}
match /bans/{userId} {
// Admins can read all, Users can read their own (to check if they are banned)
allow read: if isAdminOrSuperAdmin() || (isAuthenticated() && request.auth.uid == userId);
allow create, update, delete: if isAdminOrSuperAdmin();
}
// ----------------------------------------------------------------------------------
// VIII. Global Configuration (New)
// ----------------------------------------------------------------------------------
// Used by admin_keybinds.js and soundboard.html
match /config/{configId} {
// All authenticated users can read the config (e.g. to check explicitEnabled status)
allow read: if isAuthenticated();
// Only admins can change the config
allow write: if isAdminOrSuperAdmin();
}
// ----------------------------------------------------------------------------------
// IX. Analytics Collection (`analytics`)
// ----------------------------------------------------------------------------------
match /analytics/{sessionId} {
// Admins/SuperAdmins can read/write all analytics data
allow read, write: if isAdminOrSuperAdmin();
// Authenticated users can create/update their own session data
// For anonymous sessions, the sessionId is linked to the browser session, not a user.
// The `userId` field in the document will be 'anonymous' or the actual UID.
// So, create/update should be allowed if:
// 1. The user is anonymous AND the document's userId is 'anonymous'.
// 2. The user is authenticated AND the document's userId matches their UID.
allow create, update: if (request.auth == null && request.resource.data.userId == 'anonymous') ||
(isAuthenticated() && request.resource.data.userId == request.auth.uid);
// No one can delete analytics sessions from the client directly, only admins via backend or console.
allow delete: if false;
}
}
}