-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathfirestore.rules
More file actions
182 lines (146 loc) · 7.36 KB
/
firestore.rules
File metadata and controls
182 lines (146 loc) · 7.36 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
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
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper function: verifica se l'utente è autenticato
function isAuthenticated() {
return request.auth != null;
}
// Helper function: verifica se l'utente è il proprietario
function isOwner(userId) {
return isAuthenticated() && request.auth.uid == userId;
}
// Helper function: verifica se i dati hanno il campo userId corretto
function hasValidUserId() {
return request.resource.data.userId == request.auth.uid;
}
// Collezione users - ogni utente può leggere e scrivere solo i propri dati
match /users/{userId} {
allow read: if isOwner(userId);
allow write: if isOwner(userId);
}
// Collezione assets - ogni utente può gestire solo i propri asset
match /assets/{assetId} {
// Lettura: solo se è il proprietario
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
// Creazione: solo se autenticato e il userId corrisponde
allow create: if isAuthenticated() && hasValidUserId();
// Aggiornamento: solo se è il proprietario e non cambia il userId (se presente)
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
// Cancellazione: solo se è il proprietario
allow delete: if isOwner(resource.data.userId);
}
// Collezione monthly-snapshots - snapshot mensili del patrimonio
match /monthly-snapshots/{snapshotId} {
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
allow create: if isAuthenticated() && hasValidUserId();
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
allow delete: if isOwner(resource.data.userId);
}
// Collezione price-history - storico prezzi (può essere condiviso tra utenti)
match /price-history/{priceId} {
// Lettura pubblica per tutti gli utenti autenticati
allow read: if isAuthenticated();
// Solo il sistema (admin SDK) può scrivere
allow write: if false;
}
// Collezione portfolios - se hai portafogli separati
match /portfolios/{portfolioId} {
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
allow create: if isAuthenticated() && hasValidUserId();
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
allow delete: if isOwner(resource.data.userId);
}
// Collezione assetAllocationTargets - target di allocazione asset
match /assetAllocationTargets/{targetId} {
// Read: use targetId instead of resource.data.userId to allow reading non-existent documents
// This is needed during registration when getDoc() is called before the document exists
allow read: if isAuthenticated() && targetId == request.auth.uid;
allow create: if isAuthenticated() && hasValidUserId();
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
allow delete: if isOwner(resource.data.userId);
}
// Collezione expenses - tracciamento spese ed entrate
match /expenses/{expenseId} {
// Lettura: solo se è il proprietario
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
// Creazione: solo se autenticato e il userId corrisponde
allow create: if isAuthenticated() && hasValidUserId();
// Aggiornamento: solo se è il proprietario e non cambia il userId (se presente)
// Permette update parziali che non includono userId
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
// Cancellazione: solo se è il proprietario
allow delete: if isOwner(resource.data.userId);
}
// Collezione expenseCategories - categorie per le spese
match /expenseCategories/{categoryId} {
// Lettura: solo se è il proprietario
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
// Creazione: solo se autenticato e il userId corrisponde
allow create: if isAuthenticated() && hasValidUserId();
// Aggiornamento: solo se è il proprietario e non cambia il userId (se presente)
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
// Cancellazione: solo se è il proprietario
allow delete: if isOwner(resource.data.userId);
}
// Collezione dividends - tracciamento dividendi
match /dividends/{dividendId} {
// Lettura: solo se è il proprietario
allow read: if isAuthenticated() && resource.data.userId == request.auth.uid;
// Creazione: solo se autenticato e il userId corrisponde
allow create: if isAuthenticated() && hasValidUserId();
// Aggiornamento: solo se è il proprietario e non cambia il userId (se presente)
allow update: if isOwner(resource.data.userId) &&
(!('userId' in request.resource.data) ||
request.resource.data.userId == resource.data.userId);
// Cancellazione: solo se è il proprietario
allow delete: if isOwner(resource.data.userId);
}
// Collezione hall-of-fame - ranking personali dell'utente
match /hall-of-fame/{userId} {
// Lettura: solo il proprietario può leggere i propri ranking
allow read: if isOwner(userId);
// Scrittura: solo il proprietario può aggiornare i propri ranking
// (il document ID è uguale all'userId)
allow create, update: if isOwner(userId) &&
request.resource.data.userId == userId;
// Cancellazione: solo il proprietario
allow delete: if isOwner(userId);
}
// Collezione goalBasedInvesting - obiettivi di investimento
match /goalBasedInvesting/{userId} {
// Read: use userId (doc ID) to allow reading non-existent documents (returns null)
allow read: if isOwner(userId);
// Write: only the owner can create/update/delete their goals
allow create, update: if isOwner(userId) &&
request.resource.data.userId == userId;
// Delete: only the owner
allow delete: if isOwner(userId);
}
// Collezione budgets - configurazione budget mensili dell'utente
match /budgets/{userId} {
// Read: use userId (doc ID) to allow reading non-existent documents (returns null)
allow read: if isOwner(userId);
// Write: only the owner can create/update/delete their budget config
allow create, update: if isOwner(userId) &&
request.resource.data.userId == userId;
// Delete: only the owner
allow delete: if isOwner(userId);
}
// Blocca tutto il resto per sicurezza
match /{document=**} {
allow read, write: if false;
}
}
}