mobizt / Firebase-ESP-Client

[DEPRECATED]🔥Firebase Arduino Client Library for ESP8266, ESP32 and RP2040 Pico. The complete, fast, secured and reliable Firebase Arduino client library that supports RTDB, Cloud Firestore, Firebase and Google Cloud Storage, Cloud Messaging and Cloud Functions for Firebase.
MIT License
471 stars 100 forks source link

RTDB.setQueryIndex() fails with "security rules is not a valid JSON" #566

Closed SPuntte closed 12 months ago

SPuntte commented 12 months ago

Hi, big thanks for all the hard work on this library.

I was going through the examples when RTDB/DataRetaining yielded this.

Describe the bug

Connecting to Wi-Fi..................
Connected with IP: 192.168.1.137

Firebase Client v4.4.8

Token info: type = id token (GITKit token), status = on request
Token info: type = id token (GITKit token), status = ready
Set query index in database rules... security rules is not a valid JSON
Push data... ok
Delete history data older than 10 minutes... Index not defined, add \".indexOn\": \"ts\", for path \"/test/log\", to the rules
Push data... ok

etc.

To Reproduce examples/RTDB/DataRetaining/DataRetaining.ino, with appropriate WiFi and Firebase secrets.

Expected behavior Database rules modified succesfully.

IDE and its version: Arduino CLI 0.32.2 via VS Code Arduino extension

ESP8266 Arduino Core SDK version 3.1.2

Additional context Board: WEMOS D1 mini (clone?) based on ESP-12F

mobizt commented 12 months ago

It's not issue. It is library intended error to warn user that his security rule can't be processed.

As the error shown you should make your security rules valid JSON before using this function.

mobizt commented 12 months ago

Copy your security rules and paste into this tool and check what causes your rules invalid. https://jsonformatter.curiousconcept.com/

SPuntte commented 12 months ago

It seems as if you assume my rules are actually invalid JSON. I don't think that holds.

The initial report used these rules

{
  "rules": {
    ".read": "auth != null", 
    ".write": "auth != null"
  }
}

Even if I change them to

{
  "rules": {
    "test": {
      "log": {
        ".indexOn": "ts",
        ".read": "auth != null",
        ".write": "auth != null",
      }
    }
  }
}

Said example still gives me the error:

Connecting to Wi-Fi........
Connected with IP: 192.168.1.137

Firebase Client v4.4.8

Token info: type = id token (GITKit token), status = on request
Token info: type = id token (GITKit token), status = ready
Set query index in database rules... security rules is not a valid JSON
Push data... ok
Delete history data older than 10 minutes... ok
Push data... ok
Push data... ok
Delete history data older than 10 minutes... ok
Push data... ok

etc.

mobizt commented 12 months ago

I confirm that everything is ok.

Result of DataRetaining example

Connecting to Wi-Fi.....
Connected with IP: 192.168.71.141

Firebase Client v4.4.8

Token info: type = id token (GITKit token), status = on request
Token info: type = id token (GITKit token), status = ready
Set query index in database rules... ok
Push data... ok
Delete history data older than 10 minutes... ok
Push data... ok
Push data... ok
Delete history data older than 10 minutes... ok
Push data... ok
Push data... ok
Delete history data older than 10 minutes... ok
Push data... ok
Push data... ok

Result of DataFilter example

Connecting to Wi-Fi.....
Connected with IP: 192.168.71.141

Firebase Client v4.4.8

Token info: type = id token (GITKit token), status = on request
Token info: type = id token (GITKit token), status = ready
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... ok
Push json... 
Push json... ok
Push json... ok
Push json... ok
Push json... 
Push json... ok
Push json... ok
Push json... ok
Push json... 
Push json... ok
Push json... ok
Push json... ok
Push json... 
Push json... ok
Push json... ok
Push json... ok
Push json... 
Push json... ok
Push json... ok
Push json... ok
Push json... 

Get json... ok
Pretty printed JSON data:
{
        "-NeOKGyEM5gAZvNONNaG": {
                "Data1": 20,
                "Data2": 119
        },
        "-NeOKGzIEeIRUOta6USe": {
                "Data1": 21,
                "Data2": 120
        },
        "-NeOKaWwgfi0mHEBO41J": {
                "Data1": 19,
                "Data2": 118
        },
        "-NeOKaY3hEWyaISGMmop": {
                "Data1": 20,
                "Data2": 119
        },
        "-NeOKaZHwzX88lAqFJ8H": {
                "Data1": 21,
                "Data2": 120
        },
        "-NeOM41OatWnYwXGLIP-": {
                "Data1": 19,
                "Data2": 118
        },
        "-NeOM42NNlmOEXJZ6BbV": {
                "Data1": 20,
                "Data2": 119
        },
        "-NeOM43oGLOJvSDM-FTf": {
                "Data1": 21,
                "Data2": 120
        }
}
Iterate JSON data:

0, Type: object, Name: -NeOKGyEM5gAZvNONNaG, Value: {"Data1":20,"Data2":119}
1, Type: object, Name: Data1, Value: 20
2, Type: object, Name: Data2, Value: 119
3, Type: object, Name: -NeOKGzIEeIRUOta6USe, Value: {"Data1":21,"Data2":120}
4, Type: object, Name: Data1, Value: 21
5, Type: object, Name: Data2, Value: 120
6, Type: object, Name: -NeOKaWwgfi0mHEBO41J, Value: {"Data1":19,"Data2":118}
7, Type: object, Name: Data1, Value: 19
8, Type: object, Name: Data2, Value: 118
9, Type: object, Name: -NeOKaY3hEWyaISGMmop, Value: {"Data1":20,"Data2":119}
10, Type: object, Name: Data1, Value: 20
11, Type: object, Name: Data2, Value: 119
12, Type: object, Name: -NeOKaZHwzX88lAqFJ8H, Value: {"Data1":21,"Data2":120}
13, Type: object, Name: Data1, Value: 21
14, Type: object, Name: Data2, Value: 120
15, Type: object, Name: -NeOM41OatWnYwXGLIP-, Value: {"Data1":19,"Data2":118}
16, Type: object, Name: Data1, Value: 19
17, Type: object, Name: Data2, Value: 118
18, Type: object, Name: -NeOM42NNlmOEXJZ6BbV, Value: {"Data1":20,"Data2":119}
19, Type: object, Name: Data1, Value: 20
20, Type: object, Name: Data2, Value: 119
21, Type: object, Name: -NeOM43oGLOJvSDM-FTf, Value: {"Data1":21,"Data2":120}
22, Type: object, Name: Data1, Value: 21
23, Type: object, Name: Data2, Value: 120

Database security rules.

{
    "rules": {
        ".read": "auth != null",
        ".write": "auth != null",
        "test": {
            "log": {
                ".indexOn": "ts"
            },
            "push": {
                ".indexOn": "Data2"
            }
        }
    }
}
mobizt commented 12 months ago

Please make sure you set the SSL buffer properly. https://github.com/mobizt/Firebase-ESP-Client/blob/4622d57db62811db4e66f2cafd3831d1ff1b01c4/examples/RTDB/DataRetaining/DataRetaining.ino#L122-L124

SPuntte commented 12 months ago

Oh, I see... trailing commas are not JSON in the RFC 8259 sense. Not very helpful as Firebase console defaults to using them :facepalm:

README, under The authenication credentials and prerequisites:

The Firebase RTDB security rules are JSON-based rules which it should valid to used with this library RTDB functions that involved the security rules modification and reading, otherwise the rules wont be changed or read by these functions.

Clarifying this might benefit future users stumbling on this. How about something like this instead?

The Firebase RTDB security rules are JSON-based rules modifiable through the Firebase console and the REST API. While the Firebase console defaults to a less strict JSON syntax, In order to read or modify the rules with this library, rules already present need to adhere to RFC 8259, i.e. no trailing commas allowed.

mobizt commented 12 months ago

Your database rules are invalid in FirebaseJson implementation and it is not allowing incomplete, extra character other than key-value pair that should be and well-formed data.

mobizt commented 12 months ago

Security rules are similar to JSON but not JSON especially in Firestore then we can't assume it to be JSON but the rules for RTDB are simpler and are very similar to JSON and if user need to use the function to modify rules, he should make his rules valid JSON.

SPuntte commented 12 months ago

Alright, In hindsight, I should have created a discussions thread instead to figure out the conflicting comma.

FWIW, I still think clarifying the README would be beneficial, especially as the screenshots1, 2 depict the unfortunate decision on Firebase's part to default to nonstandard JSON. Although I now understand the intended meaning, the sentence I quoted above does not parse very well according to my understanding of the English language.

Maybe all RTDB examples operating on the security rules could also have a comment mention that the default rules provided by Firebase will result in an error.

If you think these points are worth acting on, I can definitely donate a bit of my time to make a PR.

Thanks for your quick responses and my apologies for the hassle.

mobizt commented 12 months ago

I appreciate your time for contribution.

The new version 5 is coming with breaking changes which affected to the feature you used.

The new asynchronous operation, code size, program footprint and variety of functions that provided by the library development in the past are the keys for code refactoring and cutting in version 5.

Here is the information of all changes that break the old version compatibility and will be stated on Readme.

Breaking Changes from version 4

To keep support only necessary options and features that provided by Firebase which can be reduced the program footprint, there are some functions removed from this library in version 5.

Note that, the following changes applied for Firebase-ESP-Client, Firebase-ESP8266 and Firebase-ESP32 libraries.

The functions removal.

The enums and struct removal

This removal is for proper naming.

Note that, you can replace the enums fb_esp_xxx with firebase_xxx.

Note that, mem_storage_type_undefined, mem_storage_type_flash, and mem_storage_type_sd was used instead.

The platform and its features removal.

Because of no benefit we gain from using FreeRTOS in Raspberry Pi Pico platform in this library and limited resources and C++ functions supported in AVR platform, the following are changes.

To bring back the removed functions.

You should copy the relevant function you used in the source code of version 4 (mostly in FB_RTDB.h and FB_RTDB.cpp) to your sketch.

The removed functions implemented using the library public functions and some private helper functions.