-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstorage.rules
More file actions
177 lines (147 loc) · 5.8 KB
/
storage.rules
File metadata and controls
177 lines (147 loc) · 5.8 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
rules_version = '2';
// ============================================================
// SPARKTECH DESIGNS - FIREBASE STORAGE SECURITY RULES
// Building & Construction Company Website
// ============================================================
//
// Storage Structure:
// /projects/{projectId}/...
// /properties/{propertyId}/...
// /services/{serviceId}/...
// /blog/{postId}/...
// /team/{memberId}.jpg
// /users/{userId}/avatar.jpg
// /applications/{appId}/resume.pdf
// /general/...
// ============================================================
service firebase.storage {
match /b/{bucket}/o {
// ========================================
// HELPER FUNCTIONS
// ========================================
// Check if user is authenticated
function isAuthenticated() {
return request.auth != null;
}
// Check if user is admin (requires Firestore lookup)
function isAdmin() {
return isAuthenticated() &&
firestore.exists(/databases/(default)/documents/user_roles/$(request.auth.uid)) &&
firestore.get(/databases/(default)/documents/user_roles/$(request.auth.uid)).data.role == 'admin';
}
// Check file size (max 10MB for images, 20MB for documents)
function isValidImageSize() {
return request.resource.size < 10 * 1024 * 1024;
}
function isValidDocumentSize() {
return request.resource.size < 20 * 1024 * 1024;
}
// Check file type
function isImage() {
return request.resource.contentType.matches('image/.*');
}
function isPDF() {
return request.resource.contentType == 'application/pdf';
}
// ========================================
// PROJECT IMAGES (Public Read, Admin Write)
// ========================================
match /projects/{projectId}/{allPaths=**} {
// Anyone can view project images
allow read: if true;
// Only admins can upload/modify project images
allow write: if isAdmin() && isImage() && isValidImageSize();
}
// ========================================
// PROPERTY IMAGES (Public Read, Admin Write)
// ========================================
match /properties/{propertyId}/{allPaths=**} {
// Anyone can view property images
allow read: if true;
// Only admins can upload/modify property images
allow write: if isAdmin() && (isImage() || isPDF()) && isValidImageSize();
}
// ========================================
// SERVICE IMAGES (Public Read, Admin Write)
// ========================================
match /services/{serviceId}/{allPaths=**} {
// Anyone can view service images
allow read: if true;
// Only admins can upload/modify service images
allow write: if isAdmin() && isImage() && isValidImageSize();
}
// ========================================
// BLOG IMAGES (Public Read, Admin Write)
// ========================================
match /blog/{postId}/{allPaths=**} {
// Anyone can view blog images
allow read: if true;
// Only admins can upload/modify blog images
allow write: if isAdmin() && isImage() && isValidImageSize();
}
// ========================================
// TEAM PHOTOS (Public Read, Admin Write)
// ========================================
match /team/{fileName} {
// Anyone can view team photos
allow read: if true;
// Only admins can upload/modify team photos
allow write: if isAdmin() && isImage() && isValidImageSize();
}
// ========================================
// USER AVATARS (Public Read, Owner Write)
// ========================================
match /users/{userId}/avatar.jpg {
// Anyone can view avatars (for display in comments, etc.)
allow read: if true;
// Users can only upload their own avatar
allow write: if isAuthenticated() &&
request.auth.uid == userId &&
isImage() &&
request.resource.size < 5 * 1024 * 1024; // 5MB max for avatars
}
// User folder - additional files
match /users/{userId}/{fileName} {
// Only owner can access their files
allow read: if isAuthenticated() && request.auth.uid == userId;
allow write: if isAuthenticated() &&
request.auth.uid == userId &&
isValidImageSize();
}
// ========================================
// JOB APPLICATION RESUMES (Private)
// ========================================
match /applications/{appId}/{fileName} {
// Only admins can read application files
allow read: if isAdmin();
// Anyone can upload (during application submission)
// Limited to PDFs and reasonable size
allow create: if isPDF() && isValidDocumentSize();
// No updates or deletes from users
allow update, delete: if isAdmin();
}
// ========================================
// GENERAL ASSETS (Public Read, Admin Write)
// ========================================
match /general/{fileName} {
// Anyone can view general assets
allow read: if true;
// Only admins can modify
allow write: if isAdmin() && isValidImageSize();
}
// ========================================
// TEMPORARY UPLOADS (For processing)
// ========================================
match /temp/{userId}/{fileName} {
// Users can manage their own temp files
allow read, write: if isAuthenticated() && request.auth.uid == userId;
// Auto-cleanup should be handled by Cloud Functions
}
// ========================================
// CATCH-ALL: Deny everything else
// ========================================
match /{allPaths=**} {
allow read, write: if false;
}
}
}