-
Notifications
You must be signed in to change notification settings - Fork 7
/
firestore.rules
263 lines (233 loc) · 16 KB
/
firestore.rules
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuthorized() {
return request.auth != null;
}
function readUserLocation() {
let requestedUserSpaceIds = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.space_ids;
let resourceUserSpaceIds = get(/databases/$(database)/documents/users/$(resource.data.user_id)).data.space_ids;
return requestedUserSpaceIds.hasAny(resourceUserSpaceIds);
}
match /support_requests/{docId} {
allow create : if isAuthorized() && request.auth.uid == request.resource.data.user_id &&
request.resource.data.keys().hasAll(["user_id", "title", "description", "device_name","app_version","device_os", "created_at"]) &&
request.resource.data.user_id is string &&
request.resource.data.title is string &&
request.resource.data.description is string &&
request.resource.data.device_name is string &&
request.resource.data.app_version is string &&
request.resource.data.device_os is string &&
request.resource.data.created_at is timestamp &&
request.resource.data.get('attachments', []) is list;
allow update: if false;
allow delete: if false;
allow read: if isAuthorized() && request.auth.uid == resource.data.user_id;
}
match /users/{docId} {
allow create : if isAuthorized() && request.auth.uid == docId &&
request.resource.data.keys().hasAll(["id", "auth_type", "location_enabled", "provider_firebase_id_token", "created_at"]) &&
request.resource.data.keys().hasAny(["email", "phone"]) &&
request.resource.data.id is string &&
request.resource.data.auth_type is int &&
(request.resource.data.auth_type == 1 || request.resource.data.auth_type == 2) &&
request.resource.data.location_enabled is bool &&
request.resource.data.provider_firebase_id_token is string &&
request.resource.data.created_at is int &&
request.resource.data.get('first_name', '') is string &&
request.resource.data.get('phone', '') is string &&
request.resource.data.get('email', '') is string &&
request.resource.data.get('last_name', '') is string &&
request.resource.data.get('fcm_token', '') is string &&
request.resource.data.get('profile_image', '') is string &&
request.resource.data.get('space_ids', []) is list;
allow update: if isAuthorized() && request.auth.uid == resource.data.id &&
request.resource.data.diff(resource.data).affectedKeys().hasAny(['first_name', 'last_name', 'profile_image', 'location_enabled', 'space_ids', 'phone', 'email','fcm_token', 'updated_at', 'battery_pct', 'state']) &&
request.resource.data.first_name is string &&
request.resource.data.get('last_name', '') is string &&
request.resource.data.get('fcm_token', '') is string &&
request.resource.data.location_enabled is bool &&
request.resource.data.get('space_ids', []) is list;
allow delete: if isAuthorized() && request.auth.uid == resource.data.id;
allow read: if isAuthorized();
match /user_locations/{docId} {
allow read: if isAuthorized() && (request.auth.uid == resource.data.user_id || readUserLocation());
allow update: if isAuthorized() && request.auth.uid == resource.data.user_id;
allow delete: if isAuthorized() && request.auth.uid == resource.data.user_id;
allow create: if isAuthorized() && request.auth.uid == request.resource.data.user_id &&
request.resource.data.keys().hasAll(["id", "user_id", "latitude", "longitude", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.user_id is string &&
request.resource.data.latitude is number &&
request.resource.data.longitude is number &&
request.resource.data.created_at is int;
}
match /user_journeys/{docId} {
allow read: if isAuthorized() && (request.auth.uid == resource.data.user_id || readUserLocation());
allow update: if true;
allow delete: if isAuthorized() && request.auth.uid == resource.data.user_id;
allow create: if isAuthorized() && request.auth.uid == request.resource.data.user_id &&
request.resource.data.keys().hasAll(["id", "user_id", "from_latitude", "from_longitude", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.user_id is string &&
request.resource.data.from_latitude is number &&
request.resource.data.from_longitude is number &&
request.resource.data.created_at is int;
}
match /user_sessions/{docId} {
allow read: if isAuthorized();
allow create : if isAuthorized() && request.auth.uid == request.resource.data.user_id &&
request.resource.data.keys().hasAll(["id", "user_id", "device_id", "device_name", "platform", "session_active", "app_version", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.user_id is string &&
request.resource.data.device_id is string &&
request.resource.data.device_name is string &&
request.resource.data.platform is int &&
request.resource.data.platform == 1 &&
request.resource.data.session_active is bool &&
request.resource.data.app_version is int &&
request.resource.data.created_at is int;
allow delete: if isAuthorized() && request.auth.uid == resource.data.user_id;
allow update: if isAuthorized() && request.auth.uid == resource.data.user_id;
}
}
match /users/{docId}/user_sessions/{document=**} {
allow read: if isAuthorized() && request.auth.uid == docId;
}
function isSpaceAdmin(spaceId) {
let adminId = get(/databases/$(database)/documents/spaces/$(spaceId)).data.admin_id;
return request.auth.uid == adminId;
}
function isSpaceMember(spaceId) {
let isMember = exists(/databases/$(database)/documents/spaces/$(spaceId)/space_members/$(request.auth.uid));
return isMember;
}
match /spaces/{docId} {
allow read: if true;
allow delete: if isAuthorized() && request.auth.uid == resource.data.admin_id;
allow update: if isAuthorized() && request.auth.uid == resource.data.admin_id;
allow create: if isAuthorized() &&
request.resource.data.keys().hasAll(["id", "admin_id", "name", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.admin_id is string &&
request.resource.data.name is string &&
request.resource.data.created_at is int;
}
match /{path=**}/space_places/{place} {
allow read: if isAuthorized() && isSpaceMember(resource.data.space_id);
allow write: if false;
}
match /spaces/{spaceId}/space_places/{place} {
allow read: if isAuthorized() && isSpaceMember(spaceId);
allow delete: if isAuthorized() && (isSpaceAdmin(resource.data.space_id) || request.auth.uid == resource.data.created_by);
allow update: if isAuthorized() && request.auth.uid == resource.data.created_by;
allow create: if isAuthorized() && (isSpaceAdmin(request.resource.data.space_id) || request.auth.uid == request.resource.data.created_by) &&
request.resource.data.keys().hasAll(["id", "space_id", "created_by", "latitude", "longitude", "radius", "name", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.space_id is string &&
request.resource.data.created_by is string &&
request.resource.data.latitude is number &&
request.resource.data.longitude is number &&
request.resource.data.radius is number &&
request.resource.data.name is string &&
request.resource.data.created_at is timestamp;
}
function isPlaceAdmin(spaceId, placeId) {
let created_by = get(/databases/$(database)/documents/spaces/$(spaceId)/space_places/$(place)).data.created_by;
return request.auth.uid == created_by;
}
match /spaces/{spaceId}/space_places/{place}/place_settings_by_members/{member} {
allow read: if isAuthorized() && isSpaceMember(spaceId);
allow update: if isAuthorized() && isSpaceMember(spaceId) &&
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["alert_enable", "leave_alert_for", "arrival_alert_for"]) &&
request.resource.data.arrival_alert_for is list &&
request.resource.data.leave_alert_for is list &&
request.resource.data.alert_enable is bool;
allow delete: if isAuthorized() && (request.auth.uid == resource.data.user_id || isPlaceAdmin(place));
allow create: if isAuthorized() && isSpaceMember(spaceId) &&
request.resource.data.keys().hasAll(["user_id", "place_id", "alert_enable", "leave_alert_for", "arrival_alert_for"]) &&
request.resource.data.user_id is string &&
request.resource.data.place_id is string &&
request.resource.data.get('arrival_alert_for', []) is list &&
request.resource.data.get('leave_alert_for', []) is list &&
request.resource.data.alert_enable is bool;
}
match /{path=**}/space_members/{member} {
allow read: if isAuthorized() && (request.auth.uid == resource.data.user_id || isSpaceMember(resource.data.space_id));
allow write: if false;
}
match /spaces/{spaceId}/space_members/{member} {
allow read: if isAuthorized() && (request.auth.uid == resource.data.user_id || isSpaceMember(spaceId));
allow delete: if isAuthorized() && (isSpaceAdmin(resource.data.space_id) || request.auth.uid == resource.data.user_id);
allow update: if isAuthorized() && request.auth.uid == resource.data.user_id &&
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["location_enabled"]) &&
request.resource.data.location_enabled is bool;
allow create: if isAuthorized() && (isSpaceAdmin(request.resource.data.space_id) || request.auth.uid == request.resource.data.user_id) &&
request.resource.data.keys().hasAll(["id", "space_id", "user_id", "role", "location_enabled", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.space_id is string &&
request.resource.data.user_id is string &&
request.resource.data.role is int &&
(request.resource.data.role == 1 || request.resource.data.role == 2) &&
request.resource.data.location_enabled is bool &&
request.resource.data.created_at is int;
}
match /space_invitations/{docId} {
allow read: if isAuthorized();
allow delete: if isAuthorized() && isSpaceAdmin(resource.data.space_id);
allow update: if isAuthorized() && isSpaceMember(resource.data.space_id) &&
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["code", "created_at"]) &&
request.resource.data.code is string &&
request.resource.data.code.size() == 6 &&
request.resource.data.created_at is int;
allow create: if isAuthorized() && isSpaceAdmin(request.resource.data.space_id) &&
request.resource.data.keys().hasAll(["id", "code", "space_id", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.space_id is string &&
request.resource.data.code is string &&
request.resource.data.code.size() == 6 &&
request.resource.data.created_at is int;
}
match /space_threads/{docId} {
allow read: if isAuthorized() && (isSpaceAdmin(resource.data.space_id) || isSpaceMember(resource.data.space_id));
allow delete: if isAuthorized() && isThreadAdmin(docId);
allow update: if isAuthorized() && isThreadMember(docId) &&
request.resource.data.diff(resource.data).affectedKeys().hasAny(["member_ids", "archived_for"]) &&
request.resource.data.get('member_ids', []) is list &&
request.resource.data.get('archived_for', {}) is map;
allow create: if isAuthorized() && (isSpaceMember(request.resource.data.space_id)) &&
request.resource.data.keys().hasAll(["id", "space_id", "admin_id", "member_ids", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.space_id is string &&
request.resource.data.admin_id is string &&
request.resource.data.member_ids is list &&
request.resource.data.created_at is int;
}
function isThreadMember(threadId) {
let memberIds = get(/databases/$(database)/documents/space_threads/$(threadId)).data.member_ids;
return memberIds.hasAny([request.auth.uid]);
}
function isThreadAdmin(threadId) {
let adminId = get(/databases/$(database)/documents/space_threads/$(threadId)).data.admin_id;
return adminId == request.auth.uid;
}
match /{path=**}/thread_messages/{docId} {
allow read: if isAuthorized() && isThreadMember(resource.data.thread_id);
}
match /space_threads/{threadId}/thread_messages/{docId} {
allow read: if isAuthorized() && isThreadMember(threadId);
allow delete: if isAuthorized() && (isSpaceAdmin(resource.data.space_id));
allow update: if isAuthorized() && isThreadMember(threadId) &&
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["seen_by"]) &&
request.resource.data.seen_by is list;
allow create: if isAuthorized() && isThreadMember(threadId) && request.resource.data.sender_id == request.auth.uid &&
request.resource.data.keys().hasAll(["id", "thread_id", "sender_id", "message", "seen_by", "created_at"]) &&
request.resource.data.id is string &&
request.resource.data.thread_id is string &&
request.resource.data.sender_id is string &&
request.resource.data.message is string &&
request.resource.data.seen_by is list &&
request.resource.data.created_at is timestamp;
}
}
}