Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

firebase storage-prevent spam

I don't understand how can I set a limit of files upload in a day. I want users to publish a maximum of 10 photos per day. On the database side I put a increment counter. If it reaches a certain size it does not allow a user to post other contents. but by the storage side this is impossible. An attacker can publish all files that he want without limits. Is there a solution to prevent this situation? Thanks in advance. At moment my security rules are:

service firebase.storage {
  match /b/projectid/o {
    match /Photo/{user}/{photo}/image.jpg {
      allow write: if request.auth != null && 
                      request.auth.uid == user && (
                      request.resource.size < 5 * 1024 * 1024 && photo.size() < 32 || 
                      request.resource == null);
      allow read: if request.auth != null && 
                     request.auth.uid == user
    }
  }
}
like image 251
DThink Avatar asked Sep 23 '16 15:09

DThink


1 Answers

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.

like image 133
Mike McDonald Avatar answered Oct 05 '22 16:10

Mike McDonald