Firebase security rules: Get a document with a space in the documentID - firebase

I am writing firebase security rules, and I am attempting to get a document that may have a space in its documentID.
I have the following snippet which works well when the document does not have a space
function isAdminOfCompany(companyName) {
let company = get(/databases/$(database)/documents/Companies/$(companyName));
return company.data.authorizedUsers[request.auth.uid].access == "ADMIN;
}
Under the collection, "Companies", I have a document called "Test" and another called "Test Company" - Trying to get the document corresponding to "Test" works just fine, but "Test Company" does not seem to work, as the company variable (first line into the function) is equal to null as per the firebase security rules "playground".
My thought is that there is something to do with URL encoding, but replacing the space in a documentID to "%20" or a "+" does not change the result. Perhaps spaces are illegal characters for documentIDs (https://cloud.google.com/firestore/docs/best-practices lists a few best practices)
Any help would be appreciated!
EDIT: As per a few comments, I Will add some additional images/explanations below.
Here is the structure of my database
And here is what fields are present in the user documents
In short, the following snippet reproduces the problem (I am not actually using this, but it demonstrates the issue the same way)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Users/{user} {
allow update: if findPermission(resource.data.company) == "MASTER"
}
function findPermission(companyName) {
let c = get(path("/databases/" + database + "/documents/Companies/" + companyName));
return c.data.authorizedUsers[request.auth.uid].access;
}
}
}
When I try to update a user called test#email.com (which belongs to company "Test"), the operation is permitted, and everything works exactly as expected.
The issue arises when a user, called test2#email.com, who belongs to company "Test Company" comes along and makes the same request (with authorization email/uid updated in playground, to match what is actually found in the company structure), the request fails. The request fails, since the get() call (line 1 of the function) cannot find the Company document corresponding to "Test Company" - indicated by the variable "c" being null in the screenshot (see below) - IT IS NOT NULL WHEN LOOKING FOR "Test"
Below is a screenshot of the error message, as well as some of the relevant variables when the error occurs

Check to see what type of space just in case it is another non-printable character. You could convert it to Unicode, and check what it might be. However, it is considered bad practice to use spaces in naming variables and data structures. There are so many different types to consider.
| Unicode | HTML | Description | Example |
|---------|--------|--------------------|---------|
| U+0020 | &#32 | Space | [ ] |
| U+00A0 | &#160 | No-Break Space | [ ] |
| U+2000 | &#8192 | En Quad | [ ] |
| U+2001 | &#8193 | Em Quad | [ ] |
| U+2002 | &#8194 | En Space | [ ] |
| U+2003 | &#8195 | Em Space | [ ] |
| U+2004 | &#8196 | Three-Per-Em Space | [ ] |
| U+2005 | &#8197 | Four-Per-Em Space | [ ] |
| U+2006 | &#8198 | Six-Per-Em Space | [ ] |
| U+2007 | &#8199 | Figure Space | [ ] |
| U+2008 | &#8200 | Punctuation Space | [ ] |
| U+2009 | &#8201 | Thin Space | [ ] |
| U+200A | &#8202 | Hair Space | [ ] |

Related

Excluding data from firestore search

I'm working on a dating app. Right now we don't want to show the data of users that users have already seen.
For example, let's suppose if A has seen B and C.
now we want to show more users to A. Then B and C should be excluded from that list.
What I'm doing is getting data from firebase like [B, C, D, E, F] as B, C is already seen. So removing those we have [D, E, F].
What's the issue:
Actually getting the same data, again and again, makes more reading numbers. It also slows down the getting of data process. Like if we get a list from firebase and all the profiles in that list are already seen then the device again sends a request to firebase and gets more profiles. it does the same for the new list and if these are also seen so it makes another request again. This takes time and users have to wait until there are profiles to swipe.
Can we make something like that? We just save a list of all the seen profiles at any point and make a rule to exclude those profiles from the search result.
We don't need those profiles at one point but we need to access those profiles to show user he has seen these profiles.
Any help will be appreciated.
I got a little similar case but I didn’t understand
{
"rules": {
"Children": {
"$child_id": {
".read": "auth != null &&
root.child('Family').child(
root.child('User').child(
data.child('parentId').val()
).val()
).child('members').child(auth.uid).exists()
}
}
}
}
Update:
there are different node:
database
|
`- users
| |
| `- userId
| | |
| | `-name
| | `-id
| | `-address
| | `-..... more details
| `- userId
| | |
| | `-name
| | `-id
| | `-address
| | `-..... more details
| |
| `- more users . .
|
`- swipes
| |
| `- uniqueId
| | |
| | `- whoSwiped: id
| | `- whoIsSwiped: id
| | `- swipedType: like/dislike
| | `- createdAt: date
| `- uniqueId
| |
| `- whoSwiped: id
| `- whoIsSwiped: id
| `- swipedType: like/dislike
| `- createdAt: date
first swiped id is fetched then user from "users" node is fetched ids that are already swiped are removed from the users' list.

kusto function to parse json which is number

i could not able to parse the below json value , I tried with parse_json() and todynamic() ,I m getting the result column values to be empty
]1
the issue is that your payload includes an internal invalid JSON payload.
it is possible to "fix" it using the query language (see usages of replace() in the example below), however it'd be best if you can write a valid JSON payload to begin with.
try running this:
print s = #'{"pipelineId":"63dfc1f6-5a43-5bca-bffe-6a36a435e19d","vmId":"9252382a-814f-4d02-9b1b-305db4caa208/usl-exepipe-dev/westus/usl-exepipe-lab-dev/asuvp306563","artifactResult":{"Id":"execution-job-2","SourceName":"USL Repository","ArtifactName":"install-lcu","Status":"Succeeded","Parameters":null,"Log":"[{\"code\":\"ComponentStatus/StdOut/succeeded\",\"level\":\"Info\",\"displayStatus\":\"Provisioning succeeded\",\"message\":\"2020-06-02T14:33:04.711Z | I | Starting artifact ''install-lcu''\r\n2020-06-02T14:33:04.867Z | I | Starting Installation\r\n2020-06-02T14:33:04.899Z | I | C:\\USL\\LCU\\4556803.msu Exists.\r\n2020-06-02T14:33:04.914Z | I | Starting installation process ''C:\\USL\\LCU\\4556803.msu /quiet /norestart''\r\n2020-06-02T14:43:14.169Z | I | Process completed with exit code ''3010''\r\n2020-06-02T14:43:14.200Z | I | Need to restart computer after hotfix 4556803 installation\r\n2020-06-02T14:43:14.200Z | I | Finished Installation\r\n2020-06-02T14:43:14.200Z | I | Artifact ''install-lcu'' succeeded\r\n\",\"time\":null},{\"code\":\"ComponentStatus/StdErr/succeeded\",\"level\":\"Info\",\"displayStatus\":\"Provisioning succeeded\",\"message\":\"\",\"time\":null}]","DeploymentLog":null,"StartTime":"2020-06-02T14:32:40.9882134Z","ExecutionTime":"00:11:21.2468597","BSODCount":0},"attempt":1,"instanceId":"a301aaa0c2394e76832867bfeec04b5d:0","parentInstanceId":"78d0b036a5c548ecaafc5e47dcc76ee4:2","eventName":"Artifact Result"}'
| mv-expand log = parse_json(replace("\r\n", " ", replace(#"\\", #"\\\\", tostring(parse_json(tostring(parse_json(s).artifactResult)).Log))))
| project log.code, log.level, log.displayStatus, log.message

Firebase how to index this data to be fetched?

I have a DB with users and items.
Every user has languages, which is an array of languages, for example ['en', 'ar']
Every item has language, which is a string, for example 'en'.
How can I index my items, such that I can get a list of the last X items in an array of languages? (i.e - latest 5 items who are either 'en' or 'ar')
For a single language the solution is simple - have an index that has the language key, and array of item keys ordered by whatever.
Please note that the Firebase official documentation recommends against using arrays. IMHO, the main problem in your project is that you trying to use an array, which is an anti-pattern when it comes to Firebase. Beside that, one of the many reasons Firebase recommends against using arrays is that it makes the security rules impossible to write. Because a Firebase database is structured as pairs of key and values, the best option is to use a Map.
To achieve what you want, i recomand you using a database structure which looks like this:
Firebase-root
|
--- users
| |
| --- UID1
| | |
| | --- languages
| | |
| | --- languageId1: true
| | |
| | --- languageId2: true
| |
| --- UID2
| |
| --- languages
| |
| --- languageId3: true
| |
| --- languageId4: true
|
--- languages
| |
| --- languageId1
| | |
| | --- languageName: "en"
| | |
| | --- items
| | |
| | --- itemId1: true
| |
| --- languageId2: "ar"
| | |
| | --- languageName: "ar"
| | |
| | --- items
| | |
| | --- itemId2: true
|
--- item
|
--- itemId1
| |
| --- title: "ItemTitleEn"
| |
| --- en: true
|
--- itemId2
|
--- title: "ItemTitleAr"
|
--- ar: true
Now, with this database structure you can achieve everything you want. For example, you can query your database to display all languages from you database. You can also display all the languages of a single user.
If you want to query your database for the last x item which have the language set to en, you just need to put a listener on the items node and create a query using functions like: orderByChild(), equalsTo() and limitToLast(). Such a query should look like this:
query = rootRef.child("items")
.orderByChild("en")
.equalsTo(true)
.limitToLast(5)
.addListener(/* ... */)
EDIT: Unfortunately Firebase does not allow multiple conditions in a query. So in Firebase there is no where clause that sounds like this: WHERE language = "en" AND language = "ar". So to solve this, you need to put a listener on the other node, on languages node.
The flow is as follows:
yourRef = rootRef.child("languages"); //only one listener
yourRef.addListener(
1. Create a list
2. get items from dataSnapshot.child("languageId1").child("items").getChildren()
3. add **en** items to the list
4. get items from dataSnapshot.child("languageId2").child("items").getChildren()
5. add **ar** items to the list
6. display the list that contains data from both languages
)
Hope it helps.

Firebase security rules with external id

For some applications my team creates authenticated users with a password/email combination. This will get the user an firebase user uid. The problem with this is that the keys in firebase itself are external id's, and they do not match the auth.uid. How would I go about creating security rules then?
Sample auth.uid:
9dkad6c7-s649-9623-99e2-5a0dbgf5dfdz
Then a sample of the structure:
database
|
—— conversations
|
——{external id 1}
| |
| ——{external id 2}
| |
| {data here}
|
messages
|
——{externalid1|externalid2}
| |
| —{-KFasdahsduids}
| |
| {data here}
|
|
users
|
——{externalId}
| |
| {first name}
| {last name}
| {firebaseUID}
| {more data here}
|
——{externalId2}
|
{first name}
{lastname}
{firebaseUID}
{more data here}
The problem really is that the auth.uid is not the same as the external ones, and we really need those external id's. Can I do something with the UID that is stored in the /users/? Any suggestions?

CherryPy 3.6 - reading Multipart Post http request

I coded a java client that sends a string of meta information and a byte array through a multipart post http request to my server running cherrypy 3.6.
I need to extract both values and I coded this in python3 on the server side to find out how to manipulate the result as I can't find any relevant documentation over internet that explains how to read this html part
def controller(self, meta, data):
print("meta", meta)
print("data", type(data))
outputs :
my meta information
<class 'cherrypy._cpreqbody.Part'>
Note : the data part contains raw binary data.
How can I read the http part content into a buffer or output it to a disk file ?
Thanks for your help.
Thanks for your answer.
I'v already read this doc but unfortunately methods read-into_file and make_file, read ... it doesn't work for me. for example when trying to read a zip file sent form my java client :
Assuming data is the Http post parameter
make_file()
fp = data.make_file()
print("fp type", type(fp)) # _io.BufferedRandom
zipFile = fp.read()
outputs:
AttributeError: 'bytes' object has no attribute 'seek'
line 651, in read_lines_to_boundary raise EOFError("Illegal end of multipart body.")EOFError: Illegal end of multipart body.
read_into_file()
file = data.read_into_file()
print("file type", type(file))
zipFile = io.BytesIO(file.read())
# zipFile = file.read() # => raises same error
outputs:
line 651, in read_lines_to_boundary raise EOFError("Illegal end of multipart body.")EOFError: Illegal end of multipart body.
I don't understand what happens ...
Actually "data" is not a file like object but a cherrypy._cpreqbody.Part one. It holds a "file" file an _io.BufferedRandom class property.
Its read() method returns the whole body content in a binary form (bytes).
so to end up the straightforward solution is :
class BinReceiver(object):
def index(self, data):
zipFile = io.BytesIO(data.file.read())
path = "/tmp/data.zip"
fp = open(path)
fp.write(zipFile, 'wb')
fp.close()
print("saved data into", path, "size", len(zipFile))
index.exposed = True
and this works fine ...
fyi : I'm running python3.2
It seems like data is a file-like object which you can call .read on. In addition CherryPy provides a method read_into_file.
See the full documentation by typing help(cherrypy._cpreqbody.Part) in your REPL.
class Part(Entity)
| A MIME part entity, part of a multipart entity.
|
| Method resolution order:
| Part
| Entity
| __builtin__.object
|
| Methods defined here:
|
| __init__(self, fp, headers, boundary)
|
| default_proc(self)
| Called if a more-specific processor is not found for the
| ``Content-Type``.
|
| read_into_file(self, fp_out=None)
| Read the request body into fp_out (or make_file() if None).
|
| Return fp_out.
|
| read_lines_to_boundary(self, fp_out=None)
| Read bytes from self.fp and return or write them to a file.
|
| If the 'fp_out' argument is None (the default), all bytes read are
| returned in a single byte string.
|
| If the 'fp_out' argument is not None, it must be a file-like
| object that supports the 'write' method; all bytes read will be
| written to the fp, and that fp is returned.
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| from_fp(cls, fp, boundary) from __builtin__.type
|
| read_headers(cls, fp) from __builtin__.type
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| attempt_charsets = ['us-ascii', 'utf-8']
|
| boundary = None
|
| default_content_type = 'text/plain'
|
| maxrambytes = 1000
|
| ----------------------------------------------------------------------
| Methods inherited from Entity:
|
| __iter__(self)
|
| __next__(self)
|
| fullvalue(self)
| Return this entity as a string, whether stored in a file or not.
|
| make_file(self)
| Return a file-like object into which the request body will be read.
|
| By default, this will return a TemporaryFile. Override as needed.
| See also :attr:`cherrypy._cpreqbody.Part.maxrambytes`.
|
| next(self)
|
| process(self)
| Execute the best-match processor for the given media type.
|
| read(self, size=None, fp_out=None)
|
| readline(self, size=None)
|
| readlines(self, sizehint=None)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Entity:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| type
| A deprecated alias for :attr:`content_type<cherrypy._cpreqbody.Entity.content_type>`.
|
| ----------------------------------------------------------------------
| Data and other attributes inherited from Entity:
|
| charset = None
|
| content_type = None
|
| filename = None
|
| fp = None
|
| headers = None
|
| length = None
|
| name = None
|
| params = None
|
| part_class = <class 'cherrypy._cpreqbody.Part'>
| A MIME part entity, part of a multipart entity.
|
| parts = None
|
| processors = {'application/x-www-form-urlencoded': <function process_u...

Resources