I'm planning to use firebase, but I have security related question.
My documents have creation_date property and it is filled with ServerValue.TIMESTAMP when document created.
Can I be sure that user will not reverse engineer my webapp to somehow insert fake date? And protect this field from future edits.
You can use the request.time variable in the security rules for validating the value of the timestamp. From the reference documentation:
The time variable contains a timestamp representing the current server time a request is being evaluated at. You can use this to provide time-based access to files, such as: only allowing files to be uploaded until a certain date, or only allowing files to be read up to an hour after they were uploaded.
// Allow a read if the file was created less than one hour ago
allow read: if request.time < resource.data.timeCreated + duration.value(1, 'h');
Many functions are provided to write rules using timestamps and durations.
Related
In my current application, I store a value in Firestore for each user something along the lines of this:
User1Doc - hasUsedFeatureToday = true
User2Doc - hasUsedFeatureToday = false
...
At the end of the day, I run a scheduled function that resets all of these to false. This was fine while my application was relatively small, but does not scale very effectively as I'm sure you can imagine.
Each user can only use this aspect of my app once per day, so the only time this field is read is when they try to use it.
I would like to change this system to store a timestamp in the user's document when they use the feature and then check if this timestamp is the same day (Europe/London time) if someone tries to use it again.
Does Firebase offer a way to get a "timezoned" timestamp like this and store/check it with the Firestore?
You can just store a timestamp (UTC). Whenever users logs in to your app, just check the timestamp and update the same. You can always use libraries like Luxon to get local time from the UTC time.
If you want to allow the user to update this timestamp only once, you can use security rules to restrict the same. However, user may try to prevent the timestamp from being updated at first place.
You can instead use Cloud Function to serve the data only when the user requests it. This will be better than updating documents of all users even if they won't be using the feature every day.
I made a game with JavaScript in which the user takes a specific amount of time to complete it. Then I want to create a document in a collection named scores on Firestone with that time. My problem is that the user can create an infinite amount of documents with a random time by simply copy & pasting the code and entering their own values. Is there a way that the user can only create once a document with the correct time at the end of the game? Here is the code that I used:
db.collection('score').add({
time: 122,
});
You have two requirements I think:
The user should only be able to create one document.
The time in the document must be the current time at the end of the game.
Allow only one document per user
The first one is easiest to do by using Firebase Authentication to sign the user in, so that they have an identity. If you don't want the user to enter any credentials, you can sign them in using anonymous authentication.
No matter how you sign them in, this gives them a unique UID (user identifier), which you can then use as the document ID:
let uid = firebase.auth().currentUser.uid;
db.collection('score').doc(uid).set({
time: 122,
});
So instead of calling add() (which generates a new document each time you call it), we create a document with the user's UID as its name. That way the user will always be writing to the same document.
You can then enforce that the user can only write their own document with Firebase's server-side security rules. See for an example of this, the documentation on content-owner only access.
Ensure the time can't be spoofed
To prevent the user from writing just any value they wish into the database, we can use Firestore's built-in FieldValue.serverTimestamp marker value. When you use this in your code, the Firestore server automatically writes in the current value from the server:
let uid = firebase.auth().currentUser.uid;
db.collection('score').doc(uid).set({
time: firebase.firestore.FieldValue.serverTimestamp(),
});
Here too, you can then use Firebase's server-side security rules to ensure that a malicious user can't pass their own value. To do that, compare the value that is being written (request.data.time) with the built-in variable for the current time (request.time).
I need a validation rule that checks if the end date is after the start date, so the period is valid. I have found a couple resources, but I couldn't use them to get what I need. Perhaps for someone else it is of some use.
https://medium.com/#khreniak/advanced-examples-of-using-cloud-firestore-security-rules-9e641d023c7e
End-date greater than start-date validation android
Basically, I have document coming in in cloud firestore and I need to check if the value dateEnd > dateStart. Both come from the same request. I would rather store the values as day/month/year instead of storing them as a timestamp value. However, if there is no other solution than to use timestamps, I could use that.
I can't get any further than this:
match /organisations/{orgID}/people/{userID} {
allow create: if(dateEnd > dateStart)
}
Thanks in advance for your help
If you use a date format like YYYYMMDD (which allows to lexicographic order dates), the following should do the trick. It would also work with timestamps in milliseconds.
match /organisations/{orgID}/people/{userID}
allow create: if request.resource.data.dateEnd > request.resource.data.dateStart;
}
As explained in the doc, "When writing data ... the request.resource variable contains the future state of the document".
I would suggest you watch the official video about security rules, a must watch...
If you absolutely need to store the values as DD/MM/YYYY in the Firestore document you should have two pairs of fields: a dateEnd/dateStart pair of field with format DD/MM/YYYY, and another pair of fields, e.g. dateEndForRules/dateStartForRules with format YYYYMMDD that you only use in the Security rules.
I am using Firebase FireStore database for the first time and I have the following question.
I have created a calendar collection. This collection will contains document representing events that have to be shown into a Calendar implemented by an Angular application.
So I am defining the following fields for these documents:
id: int. It is a unique identifier of the specific document\event.
title: string. It is the event title.
start_date_time: string. It specifies the date and the time at which the event starts.
end_date_time: string. It specifies the date and the time at which the event ends.
And here I have some doubts:
Is the id field required? From what I know I will have the document UID that will ensure the uniqueness of the document. If not strongly required adopt an id field can be convenient have something like an auto increment field? (I know that I have to handle in some other way the auto increment because FireStore is not a relational DB and doesn't automatically handle it). For example I was thinking that can be useful to order my document from the first inserted one to the last inserted one.
It seems to me that FireStore doesn't handle DateTime field (as done for example by a traditional relational database). Is this assumption correct? How can I correctly handle my start_date_time and end_date_time fields? These field have to contains the date time used by my Angular application? So for example I was thinking that I can define it as string field and put into these fields values as 2020-07-20T07:00:00 representing a specific date and a specific time. It could be considered a valid approach to the problem or not?
Is the id field required?
No fields are required. Firestore is schema-less. The only thing a document requires is a string ID that is unique to the collection where it lives.
There is no autoincrement of IDs. That doesn't scale massively the way Firestore requires. If you need ordering, you will have to define that for yourself according to your needs.
In general, you are supposed to accept the randomly generated IDs that the Firebase client APIs will generate for you. Ordering is typically defined using a field in the document.
It seems to me that FireStore doesn't handle DateTime field
Firestore has a timestamp field type that stores moments in time to nanosecond precision. There is no need to store a formatted string, unless that's something you require for other reasons.
In my flutter application I want to prevent users to enter their nominations after the cutoff date.
For example, there is an exam nomination with cutoff date 31st March 2020. I am inserting the nomination data from my flutter app to the Firebase database. In app I'm checking the current date should be before the 31st March and then only allow to enter the data. However if the user changes the mobile data to backward the the app will allow to enter the nominations for the exam.
I know if I write the Firebase Cloud Function and move my insert code there it will solve the issue. But I have lot of code that I will have to rewrite :-(. Is there any other solution that will allow me to know the actual current date? What if the internet is off?
Thanking you in advance
You could maybe write a small amount of backend code to read the Firebase server timestamp and use that to check the cutoff. See this code:
exports.currentTime = functions.https.onRequest((req, res) => {
res.send({"timestamp":new Date().getTime()})
})
I got this from this SO answer so don't ask me for more details :-)
How to save the current date/time when I add new value to Firebase Realtime Database
Not sure about how to handle the Internet off... but if you can't read the server date, they can't submit the results.
Your only option that doesn't involve writing backend code is to use security rules to restrict database writes based on the current date. What you will have to do is set up a rule on the collection that should be restricted, and it will have a line that looks something like this:
allow write: if request.time < timestamp.date(yyyy, mm, dd);
Where yyyy, mm, and dd are the components of the date. If you want something more specific, read the security rules API docs for timestamp functions - you will have to provide an time in epoch milliseconds. Note that timestamps in security rules are always measured in UTC.