Remove node from Firebase with Functions - javascript

I'm trying to remove a node from Firebase using cronjob and i have this function but when it gets executed I get an error saying "Error: could not handle the request" and the log says: "database is not defined"
This is my function:
exports.cleanStatsOnRequest = functions.https.onRequest((req, res) => {
const ref1 = firebase.database.ref;
const dbref = ref1.child(`/dailystats`);
console.log('removing dailystats');
return dbref.remove
.then(() => {
res.send('dailystats removed');
})
.catch(error => {
res.send(error);
});
});
What am I doing wrong? What is the right way to define the database?

You need to use the Firebase Admin SDK to access the Realtime Database from an HTTP trigger Cloud Function. This documentation shows you how to read from the database. This example shows writing to the database, which would be similar to deleting.

Try this. database,ref and remove are functions. Read this guide.
Also you should not return dbref.remove() as remove() will return a promise.
exports.cleanStatsOnRequest = functions.https.onRequest((req, res) => {
const ref1 = firebase.database().ref(); // changes here
const dbref = ref1.child('/dailystats');
console.log('removing dailystats');
return dbref.remove() // changes here
.then(() => {
res.send('dailystats removed');
})
.catch(error => {
res.send(error);
});
});

Related

Firebase functions.auth.user().onCreate no triggering

i am trying create user with custom claim. I am using Firebase Cloud Functions. The problem is, when i create (Sign Up) an user, the onCreate not trigger. I am following this tutorial of provided by google. https://firebase.google.com/docs/auth/admin/custom-claims
I Deployed my functions and the region is us-central1
Cloud functions version :
firebase-admin": "^8.9.0
firebase-functions": "^3.3.0
I am using Vue JS as Front-end
My functions/Index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.ProccessSignUp = functions.auth.user().onCreate(async (user) =>{
console.log("Email"+user.email);
if (user.email){
const customClaims = {
admin:true
};
return admin.auth().setCustomUserClaims(user.uid,customClaims)
.then(() =>{
const metadataRef = admin.database().ref('metadata/' +user.uid);
return metadataRef.set({refeshTime:new Date().getTime()})
}).catch(err =>{
console.log(err.message)
})
}
});
My SignUpWithEmailAndPassword
userSignUp({dispatch},payload){
firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(user =>{
user.user.sendEmailVerification()
.then(() =>
alert('Your account has been created! Please, verify your account'),
dispatch('userSignOut'),
).catch(err =>{
console.log(err.message)
})
}).catch(err =>{
console.log(err.message)
})
},
oAuthStateChanged
router.beforeEach(async (to, from, next) => {
const user = await new Promise((resolve) => {
firebase.auth().onAuthStateChanged(async user => {
await store.dispatch("autoSignIn", user);
resolve(user)
});
});
const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth) {
if (!user){
next(false)
}else {
if (user.emailVerified){
next();
}else {
alert('Please verify your account')
await store.dispatch("userSignOut", user);
}
}
} else {
next()
}
});
As explained in the doc, with Cloud Functions you can "emit a log line from your function, use standard JavaScript logging calls such as console.log and console.error".
Then the Cloud Functions logs are viewable either in the Firebase console, Stackdriver Logging UI, or via the firebase command-line tool.
So you should be able to confirm that your Cloud Function runs correctly (or not) by looking at, for exemple, the Firebase console.
I had the same situation while running cloud funtions locally. My user().onCreate() trigger function was also not triggering.
export const addNewUser = auth
.user()
.onCreate((user) => {
// Do something
})
I tried many things but everything was looking fine. Finally I updated my firebase-tools to latest version by running this command and it started working as a charm.
npm install -g firebase-tools#latest
Hope this helps someone.

Set on firebase and then set firebase claims

So i working with firebase auth and database in order to set new user to data base, if set successful i want to set claims for that user.
So it means i have a promise within a promise:
function setUser(user){
// no need for the database code before this, but userRef is set properly
return userRef.set(user)
.then(succ => {
return firebase.firebase.auth().setCustomUserClaims(user.key, {admin: true})
.then(() => {
console.log("setting claims")
return true;
});
})
.catch(err => {
return err
})
}
calling function:
app.post("/register_user",jsonParser,async (req, res) => {
var user = req.body.user;
let result = await fireBase.setUser(user);
res.send(result);
})
What happens is that i get the set on the database but claims are not set nor i can i see the log. I know its a js question and not firebase one. I tried many different ways (with await) but non worked.
firebase.firebase does not seem correct. You need to be using the admin object which can be initialised using const admin = require('firebase-admin'); This is not part of the firebase db sdk, but the admin one. You can also use the userRef.uid as that gives you the id of the document of the user, if that is what you want, else use your user.key
return admin.auth().setCustomUserClaims(userRef.uid, {
admin: true
}).then(() => {
//on success
});

firebase set/initialize values to zero dynamically

I'm looking a good and right way to set/ initalize values with http trigger.
what I did is ref to the node in firebase and get data then update it.
module.exports.initializeAnswers = functions.https.onRequest(async(req,res)=>{
try{
// i want to initalize each key
await firebase.ref('/CurrentGame').once('value',snapshot=>{
snapshot.forEach((childSnapshot)=>{
if(childSnapshot !=null){
childSnapshot.update(0)
}
return false
});
})
}catch(e){
console.info(e)
return res.status(400).send({error:0})
}
})
I'm looking for a right way and not by the 'update' function
I want to initalize each value to zero with http trigger
I understand that you will have several children (variable number) under the "answers" node and only one "rightAnswer" node. If my understanding is correct, the following code will do the trick:
exports.initializeAnswers = functions.https.onRequest((req, res) => {
admin.database().ref('/CurrentGame/answers').once('value', snapshot => {
const updates = {};
snapshot.forEach((child) => {
updates['/answers/' + child.key] = 0;
});
updates['/rightAnswer'] = 0;
return admin.database().ref('/CurrentGame').update(updates);
}).then(() => {
res.status(200).end();
}).catch((err) => {
console.log(err);
res.status(500).send(err);
});
});
You can use Firebase Cloud Functions to initialize the values on HTTP trigger. check this link

Cloud Functions for Firebase: how to use a Transaction promise?

I am trying to write a function in Cloud Functions that triggers every time a user gets created and which then saves that user into a list of users and finally increments a user counter.
However I am not sure if I am using promises correctly.
exports.saveUser = functions.auth.user().onCreate(event => {
const userId = event.data.uid
const saveUserToListPromise = db.collection("users").doc(userId).set({
"userId" : userId
})
var userCounterRef = db.collection("users").doc("userCounter");
const transactionPromise = db.runTransaction(t => {
return t.get(userCounterRef)
.then(doc => {
// Add one user to the userCounter
var newUserCounter = doc.data().userCounter + 1;
t.update(userCounterRef, { userCounter: newUserCounter });
});
})
.then(result => {
console.log('Transaction success!');
})
.catch(err => {
console.log('Transaction failure:', err);
});
return Promise.all([saveUserToListPromise, transactionPromise])
})
I want to make sure that even if many users register at once that my userCounter is still correct and that the saveUser function won't be terminated before the transaction and the save to the list has happened.
So I tried this out and it works just fine however I don't know if this is the correct way of achieving the functionality that I want and I also don't know if this still works when there are actually many users triggering that function at once.
Hope you can help me.
Thanks in advance.
The correct way to perform multiple writes atomically in a transaction is to perform all the writes with the Transaction object (t here) inside the transaction block. This ensures at all of the writes succeed, or none.
exports.saveUser = functions.auth.user().onCreate(event => {
const userId = event.data.uid
return db.runTransaction(t => {
const userCounterRef = db.collection("users").doc("userCounter")
return t.get(userCounterRef).then(doc => {
// Add one user to the userCounter
t.update(userCounterRef, { userCounter: FirebaseFirestore.FieldValue.increment(1) })
// And update the user's own doc
const userDoc = db.collection("users").doc(userId)
t.set(userDoc, { "userId" : userId })
})
})
.then(result => {
console.info('Transaction success!')
})
.catch(err => {
console.error('Transaction failure:', err)
})
})

Firestore query not working

Shown above is my firestore collection.
I am attempting to get data from this collection using a Google Cloud Function that I have deployed:
const admin = require('firebase-admin')
const functions = require('firebase-functions')
module.exports= function(request, response){
let results = []
admin.firestore().collection('news_stories')
.get()
.then(docs => docs.map(doc => results.push(doc.data())))
.catch(e => resoponse.status(400).send(e))
response.status(200).send(results)
}
When I run the above function I get an:
Error: could not handle the request
I also tried running the function this way to see if it would work.
module.exports= function(request, response){
let ref = admin.firestore().collection('news_stories')
.get()
.then(docs => response.status(200).send(docs))
.catch(e => resoponse.status(400).send(e))
}
This function returned a this JSON object:
There is no information regarding data or any of the docs.
I uploaded the collection to the firestore DB using this function:
const functions = require('firebase-functions')
const admin = require('firebase-admin')
module.exports = function(request,response){
if(!request.body.data){
response.status(422).send({error: 'missing data'})
}
let data = request.body.data
data.map(item => {
admin.firestore().collection('news_stories').add({item})
})
response.status(200).send('success!')
}
Not sure what I am doing wrong. Why is the function not returning any of the documents?
Data is retrieved from Firestore asynchronously. By the time your send you response back to the caller, the results haven't been retrieved from Firestore yet.
It's easiest to see this by replacing the bulk of the code with three log statements:
console.log("Before starting get");
admin.firestore().collection('news_stories')
.get()
.then(() => {
console.log("In then()");
});
console.log("After starting get");
It's best if you run the above in a regular node.js command, instead of in the Cloud Functions environment, since the latter may actually kill the command before the data is loaded.
The output of the above is:
Before starting get
After starting get
In then()
That is probably not the order that you expected. But because the data is loaded from Firestore asynchronously, the code after the callback function is allowed to continue straight away. Then when the data comes back from Firestore, your callback is invoked and can use the data as it needs to.
The solution is to move all the code that requires the data into the then() handler:
const admin = require('firebase-admin')
const functions = require('firebase-functions')
module.exports= function(request, response){
admin.firestore().collection('news_stories')
.get()
.then(docs => {
let results = []
docs.map(doc => results.push(doc.data()))
response.status(200).send(results)
})
.catch(e => resoponse.status(400).send(e))
}
So after some trouble shooting I found the source of the problem . For some reason if you use .map on the return object the server will respond with a 500 status...
change the .map to forEach and the function works
this will work ...
admin.firestore().collection('news_stories')
.get()
.then(docs => {
let data = []
docs.forEach(doc => data.push(doc.data()))
response.status(200).send(data)
})
yet this wont ...
admin.firestore().collection('news_stories')
.get()
.then(docs => {
let data = []
docs.map(doc => data.push(doc.data()))
response.status(200).send(data)
})

Categories

Resources