To add/update/delete a record in Firestore, I can either run code within my app that executes this operation or I can call a cloud function that will handle the operation. Is it "safer" for my app to do it the cloud function way? It takes a bit longer this way, but I worry about Firebase being vulnerable somehow. I once read that to make a really safe app, you should assume that some malicious user has already reverse engineered your app. Should I assume that using Cloud Functions for all changes to Firestore is the safest route or is there no difference?
Using code from the client:
CollectionReference users = FirebaseFirestore.instance.collection('users');
Future<void> addUser() {
// Call the user's CollectionReference to add a new user
return users
.add({
'full_name': fullName, // John Doe
'company': company, // Stokes and Sons
'age': age // 42
})
.then((value) => print("User Added"))
.catchError((error) => print("Failed to add user: $error"));
}
Using Cloud Functions:
exports.createUser = functions.https.onCall(async (data, context) => {
const uid = context?.auth?.uid
if (!uid) {
return {result: 0, message: 'You are not authorized.'}
}
const username = data.user
const email = data.email
var result: number
var message: string
//Check to see if that username already exists
const doesUserExist = await TS_doesUserExist(username)
const createUser = await TS_createUser(uid, username, email)
if (doesUserExist[0] == 0) {
if (createUser[0] == 1) {
result = 1
message = ''
} else {
result = 0
message = createUser[1]
}
} else {
result = 0
message = doesUserExist[1]
}
return {result: result, message: message}
})
async function TS_createUser(uid: string, username: string, email: string): Promise<[number, string]> {
var result: number = 0
var message: string = ''
//Create SECURE_userinfo doc
const userInfoDoc = await admin.firestore()
.collection(usersCollPath)
.doc(uid) // use uid as document ID
.collection(secureUserInfoCollPath)
.doc()
.set({
createDate: admin.firestore.FieldValue.serverTimestamp(), //signupdate
email: email,
})
//Create stat doc
const statDoc = await admin.firestore()
.collection(usersCollPath)
.doc(uid)
.collection(statCollPath)
.doc()
.set({
stat: 1,
})
//Create username doc
const usernameDoc = await admin.firestore()
.collection(usersCollPath)
.doc(uid)
.collection(usernameCollPath)
.doc()
.set({
username: username,
})
if (userInfoDoc) {
if (statDoc) {
if (usernameDoc) {
result = 1
message = ''
} else {
result = 0
message = 'Could not create username doc'
}
} else {
result = 0
message = 'Could not create status doc'
}
} else {
result = 0
message = 'Could not create user info doc'
}
return [result, message]
}