2

There is this page showing how to convert a string to an int:

int("2") == 2
int(2.0) == 2

But how can I know before doing the conversion whether it will work or throw an exception?

For instance how can I implement the following:

IF x can be cast to an integer THEN return int(x) < 10
ELSE IF y can be cast to an integer THEN return int(y) < 10
ELSE return false
l1b3rty
  • 3,333
  • 14
  • 32
  • Firebase doesn't expose type information a priori, but you can usually determine this after you get the value. What language are you using? – Frank van Puffelen Apr 07 '21 at 21:17
  • I use the Web SDK, but my question is about the rules. I won't trust any check on the client side – l1b3rty Apr 07 '21 at 21:20
  • Shouldn't there be an `int.tryParse`, which returns null if it's not parsable? – Huthaifa Muayyad Apr 07 '21 at 21:42
  • Oh, got it. I missed the fact that it's about security rules. The rules for RTDB do have explicit type check functions. For Firestore those are in the `is` keyword. See https://stackoverflow.com/questions/63273066/firestore-security-rule-check-if-a-field-is-an-integer. I'm not sure how you can check whether the value can be parsed though. – Frank van Puffelen Apr 07 '21 at 21:45

1 Answers1

4

You can use the cast_as_int function defined below:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    function cast_as_int(x) {
      let pattern = '[+-]?([0-9]*[.])?[0-9]+';
      return (
        (x is float)
        || (x is int)
        || (x is string) && (x.matches(pattern))
      ) ? int(float(x)) : null;
    }

    // All gets will succeed
    match /{document=**} {
      allow get: if cast_as_int(1) == 1
        && cast_as_int('2') == 2
        && cast_as_int('3.14') == 3
        && cast_as_int(4.44) == 4
        && cast_as_int("5!") != 5;
    }
  }
}

The function takes in an variable and returns either an Integer or null. Firestore does not allow statements to evaluate to multiple types, so the function can only return Integer or null (not false as requested).

The function assumes you want to convert from (Integer or Float) to Integer. If you only want to convert from Integer to Integer, then replace int(float(x)) with int(x).

The regex for let pattern = '[+-]?([0-9]*[.])?[0-9]+' was taken this StackOverflow Question

touch my body
  • 1,634
  • 22
  • 36