Well, there's a very simple way of doing this, and there's the right way of doing this.
The hacky way of only allowing a certain number of files to be uploaded in a certain time period is to name the files with some numerical property: say users/{userid}/0.jpg
through users/{userid}/9.jpg
(for 10 photos).
You can write a rule to check that as follows:
// Match all filenames like 0.jpg
match /users/{userId}/{photoId} {
allow write: if photoId.matches('^\d\.jpg$')
}
If you need more granularity than order of magnitude, you can do something like:
// Match all filenames like YYY.jpg where YYY is a number less than XXX
match /users/{userId}/{photoId} {
allow write: if int(photoId.split('\.')[0]) < XXX
}
That only solves half our problem though: we can restrict the number of files, but what if a user just wants to upload over them? Luckily, we can write a rule that prevents an end user from overwriting their file ever (though we've got to carve out deletions), or within a given time period. Let's explore:
// Allow files to be overwritten once a day, written if there's nothing there, or deleted as often as desired
match /users/{userId}/{photoId} {
allow write: if request.time > resource.timeCreated + duration.value(1, "d") || resource.size == 0 || request.resource.size == 0
}
These can be combined into function:
function isAllowedPhotoId(photoId) {
return int(photoId.split('\.')[0]) < XXX
}
function canOverwritePhoto() {
return request.time > resource.timeCreated + duration.value(1, "d") || resource.size == 0 || request.resource.size == 0
}
match /users/{userId}/{photoId} {
allow write: if isAllowedPhotoId(photoId) && canOverwritePhoto()
}
Long term, the solution is being able to reference Database data from within Storage, and vice-versa. Unfortunately, that world isn't here yet, but we're working towards it.