Firebase rules to access specific child's value - ios

The childByAutoId would be useful if you want to save in a node multiple children of the same type, that way each child will have its own unique identifier.
List:{
KJHBJJHB:{
name:List-1,
owner:John Doe,
user_id:<Fire base generated User_id>
},
KhBHJBJjJ:{
name:List-2,
owner:Jane Lannister,
user_id:<Fire base generated User_id>
},
KhBHJZJjZ:{
name:List-3,
owner:John Doe,
user_id:<Fire base generated User_id>
}
}
I am trying to access the List with the help of the following code:
let ref = FIRDatabase.database().reference(withPath: "/List")
The current user logged into the app is John Doe. When the user accesses the list, I want all the List child whose owner is John Doe(i.e. List-1 & List-3) and ignore the other child values.
Do I have to do this in my application or can this be achieved via Firebase Security rules?
My current rule definition is:
"List":{
".read": "root.child('List/'+root.child('List').val()+'/user_id').val() === auth.uid" }
But this rule is not giving me any success. Any idea how to achieve the desired result?

You're trying to use security rules to filter the list. This is not possible and one of the common pitfalls for developers coming to Firebase from a SQL background. We commonly refer to it as "rules are not filters" and you can learn more about it in:
the Firebase documentation
this answer
our new video series Firebase for SQL developers
and many previous questions mentioning "rules are not filters"
The solution is almost always the same: keep a separate list of the keys of posts that each user has access to.
UserLists:{
JohnUid: {
KJHBJJHB: true,
KhBHJZJjZ: true
},
JaneUid: {
KhBHJBJjJ: true
}
}
This type of list is often referred to as an index, since it contains references to the actual post. You can also find more about this structure in the Firebase documentation on structuring data.

Related

Search Outlook Calendar Event categories for multiple hits - Microsoft Graph

I am trying to keep track of Outlook calendar events without the need to store information about them on my own systems. I decided to do this by adding the required ids as categories with their type of id before it as shown in the code sample below.
{
"#odata.etag": "",
"createdDateTime": "",
"categories": [
"ID1::abc123",
"ID2::def456"
]
}
I tried using the 'any' lambda operator and this works fine if I want to filter based on one category using the query below:
https://graph.microsoft.com/v1.0/me/events?$filter=categories/any(x:x%20eq%20'ID1::abc123')
What I need is a query that will check if an event has both ids so in this case only the events where ID1=abc123 and ID2=def456. I figured https://graph.microsoft.com/v1.0/me/events?$filter=categories/any(x:x%20eq%20'ID1::abc123')%20AND%20categories/any(x:x%20eq%20'ID2::def456') should do the trick but this keeps returning empty arrays.
Thanks in advance!
Since categories are available to the user (and this is going to look really strange in outlook), I would suggest you to use the transactionId on the events to store the external id. This will automatically deny your new event if you try to create a duplicate.
I know this isn’t the answer you were looking for, but using this solution will be much more feature proof.

Realm Swift: Question about Query-based public database

I’ve seen all around the documentation that Query-based sync is deprecated, so I’m wondering how should I got about my situation:
In my app (using Realm Cloud), I have a list of User objects with some information about each user, like their username. Upon user login (using Firebase), I need to check the whole User database to see if their username is unique. If I make this common realm using Full Sync, then all the users would synchronize and cache the whole database for each change right? How can I prevent that, if I only want the users to get a list of other users’ information at a certain point, without caching or re-synchronizing anything?
I know it's a possible duplicate of this question, but things have probably changed in four years.
The new MongoDB Realm gives you access to server level functions. This feature would allow you to query the list of existing users (for example) for a specific user name and return true if found or false if not (there are other options as well).
Check out the Functions documentation and there are some examples of how to call it from macOS/iOS in the Call a function section
I don't know the use case or what your objects look like but an example function to calculate a sum would like something like this. This sums the first two elements in the array and returns their result;
your_realm_app.functions.sum([1, 2]) { sum, error in
if let err = error {
print(err.localizedDescription)
return
}
if case let .double(x) = result {
print(x)
}
}

How to build structured realtime firebase database for iOS, swift?

I am currently setting up my realtime firebase database to my iOS application.
It is my first time trying to structure user data in a firebase database, and I am really, really struggling with understanding a few key things.
A bit of context to my application's database needs:
When a new user is created, the attributes assigned directly to the user are:
Age
Email
Username
Nationality
Later on, the user needs the option of creating personal diaries!
Each of these diaries being arrays/lists of objects... Where each object in a diary furthermore holds a few attributes in a list/array.
After reading everything I could find anywhere, I picture my database something like this:
I am terribly sorry if it becomes too specific - I will try to make the question as open as possible:
My question is:
How to create the different "children" programmatically and how to find the keys leading back to them, so I can refer to them at other times again? (when editing an attribute in a child).
A few methods I have tried:
setValue([ArrayOfObjects]) --> This creates the desired array, but I can't seem to find e.g. index 3 in this array, to allow user to change his/her email later on.
childByAutoID() --> This as well creates my array, but gives several other problems: User can only store one diary, still can't find the paths to specific indexes...
setValue(), andPriority() --> Can't seem to make the priority function. (Is this function also outdated??)
And a few more...
If anyone can tell me how to achieve just the first few steps in setting up my database structure, I will be forever grateful - I have spent literally all day on it and I am not moving forward ...
Or, at least tell me, if I am on the right track regarding my desired setup of the database. Is it flat enough? Is there a smarter way to store all these user created lists?
Thank you so much! :-)
I don't know Swift so my examples are in Dart but the methods are similar I believe.
First off, I would split the Users node into two. One to hold the user data, which is normally pretty static, and the other to hold the diaries. You would use the same uid key as reference to both. This way you have less nesting to worry about and therefore it is much easier to CRUD the data. If you are using Firebase to authenticate your users then I would use the unique key that Firebase creates for each user as the keys for these two nodes.
Then...
To create a user data node record the Dart code would be something like:
referenceUserData.child(<authenticated user id>).set({
"age": <age value>,
"email": <email value>,
"name": <name value>,
});
To create a user diary node object record the Dart code would be something like:
referenceUserData.child(<authenticated user id>).child(<diary key>).child(<diary object key>).set({
"object info value 1": <object value>,
"object info value 2": <object value>,
"object info value 3": <object value>,
});
You could also create all the object records at once by writing them as a List (array) using .set().
You also need to decide what your diary key should be. You could use Firebase to generate a unique key by using .push().set().
To read eg. the user data then your call could be:
referenceUserData
.child(<authenticated user id>)
.once()
.then(
(DataSnapshot snapshot) {
print(snapshot.key);
if (snapshot.value != null) {
print(snapshot.value);
<code to process your snapshot value>
}
};
BTW, 'priority' is legacy from the early days of Firebase RTDB so I wouldn't try to use it.

How to flag and report user in firebase firestore database?

I have application which have multiple users, one of the major thing left is to block and report users in firebase.
I am trying to look for the solution for the same by googling for it, but till now not any particular success.
I would like to know how I can achieve that. Please guide me for that,
and how the firestore security rules should be to achieve the same?
The typical approach is to have a collection that contains the blocked users, with one document for each blocked user and with the ID of that document being the UID of that user.
With that structure in place, your security rules can check for the existence of such a document and then block the user.
There's a great example of this in the blog post 7 tips on Firebase security rules and the Admin SDK (it's tip 7). The rules from there:
service cloud.firestore {
match /databases/{database}/documents {
function isBlackListed() {
return exists(/databases/$(database)/documents/blacklist/$(request.auth.uid))
}
// Collections are closed for reads and writes by default. This match block
// is included for clarity.
match /blacklist/{entry} {
allow read: if false;
allow write: if false;
}
match /posts/{postId} {
allow write: if !isBlackListed()
}
}
}

RestKit - use identificationAttributes that are not part of the response

In RestKit is it possible to use identificationAttributes that are actually not part of the JSON response?
My case is the following - I have a service that lists all articles for the currently logged-in user like http://example.com/json/articles.json
My problem is the following - since the application allows multiple users to login, I keep the articles in the database together with the userId for each article. If I set the articleMapping.identificationattributes = #["articleId"], then I have a problem if two users using the device have the same article - it will be overwritten regardless of the userId, because it is not part of the response.
To sum up the facts:
For the JSON request I do not send the userId, it is part of the
server session only, so I think that I cannot use RKRoute
I do the mapping of the article with the user manually after RestKit mapping.
I do not have the userId property as part of the JSON response, it exists only inside the ArticleManagedObject.
Is there a way to inform RestKit that during the mapping, it should check the articleId+userId combination as an identificator? I tried using identificationPredicate with no success.
EDIT:
An example response from the server, when UserA is logged in:
{
"data":{
"articles":[
{
"articleId":1,
"title":"Objective C Basics"
},
{
"articleId":2,
"title":"Xcode Basics"
}
]
}
}
and here is the response when UserB is logged in:
{
"data":{
"articles":[
{
"articleId":1,
"title":"Objective C Basics"
},
{
"articleId":3,
"title":"Java Basics"
}
]
}
}
If UserA logs in, everything is fine. But if UserB logs in from the same device, then article 1 is mapped to UserB, and from now on, the connection between UserA and article 1 is lost.
As I understand from your suggestion, the only solution is to return also the user id from the service, set RKUnionAssignmentPolicy and let RestKit take care of the mapping (currently I am manually making the mapping between articles and users after RestKit).
Another question that I have - is it possible to set the identificationAttributes or identificationPredicate so that it makes a separation between object article 1 for UserA and object article 1 for UserB.
You currently do the user to article mapping outside RestKit, this is fine, but you will need to modify this process a little.
To begin with, I'm assuming here that the article response is the full set of articles for the user. If not then things get more tricky and you'll need to modify the below to account:
Start by getting all of the existing articles for a user. With this we're going to look at what needs to be removed and what needs to be added.
As we iterate through the articles we have received we can check the existing articles for a match, if we find one we have no work to do. If we don't find a match we need to add the relationship to the existing set, which will be a union with any relationship to any other user.
Next we want to remove the list of new articles from the list of the existing articles to get the list of deletions, for these we just need to break the link, again leaving other users unchanged.

Resources