The cloud_firestore API generates a random ID on the client device, so there's no guarantee the builtin CollectionReference.add
function won't overwrite your data.
The method you're currently using will ensure you're creating a new document every time, but it doesn't prevent a User from overwriting this data. If someone tried to put a document there, that write will succeed unless you explicitly deny it server-side.
The only way to guarantee this data isn't overwritten is to add Security Rules.
One way to do this is to give all of your documents creation timestamps, and ensure that the affected update rules check to make sure this field isn't modified. In the app, this would be about twice as fast as your current method, since it only involves one read/write operation.
To do this, your create function would look something like this:
import 'package:cloud_firestore/cloud_firestore.dart';
Future create(String col, Map<String, dynamic> data) {
String docId = generateID(5); // This should be longer
data = {
...data,
'cts': FieldValue.serverTimestamp(),
};
return FirebaseFirestore.instance
.collection(col)
.doc(docId)
.set(data)
}
...and your security rules would look something like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function cts_valid_for_create() {
return request.time == request.resource.data.cts;
}
function cts_valid_for_update() {
return resource.data.cts == null
&& request.resource.data.cts == resource.data.cts;
}
match /{document=**} {
allow get, delete: if true;
allow create: if cts_valid_for_create();
allow update: if cts_valid_for_update();
}
}
}
Also, it's worth noting that 5
is small enough to lead to collisions in a somewhat large collection. The odds of an ID already existing reaches 50% once there's about 30,000 documents in a collection.