Update data in firebase using nodejs - javascript

I have the following problem, I am sending data every minute to a firebase
database in a cron tab that is running in nodejs, I only send the information when there are changes, but when there are no changes the database continues to receive information, This is my code
let admin = require('firebase-admin');
let prev_res = {};
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'mydburl'
});
cron.schedule('* * * * *', function(){
let connection = mysql.createConnection({
host : 'myhost',
user : 'myuser',
password : 'mypass',
database : 'mydb'
});
connection.query("MY QUERY", function(err, rows, fields){
if (!err){
if(JSON.stringify(rows) != JSON.stringify(prev_res)){
let db = admin.database();
let ref = db.ref('path');
ref.set(rows);
console.log("Updated data");
} else {
console.log("without changes");
}
prev_res = rows;
}
});
});
Does the firebase admin have some kind of cache or something like that?

This is actually a strange problem with Firebase Authentication.
The issue resides in the permissions for the user you are including in your credentials.
Besides creating a Service Account with the correct permissions, you need to add this user to your IAM Accounts with the editor role.
Restart your App after doing this and you should stop seeing:
"FIREBASE WARNING: Provided authentication credentials are invalid.
This usually indicates your FirebaseApp instance was not initialized
correctly."

Related

Send CloudWatch logs to database

I am attempting to save our Cloudwatch logs in an on-premise Postgres database. I'm currently exporting logs to S3 and save in DynamoDB. My requirement now is to persist it in our DB, using node and AWS js-SDK. I'm not very strong on node and js-SDK, so I'll greatly appreciate any idea.
I tried a simple implementation.
const pools = require('../src/common/db'),
const AWS = require('aws-sdk');
// set the cwl
let cwl = new AWS.CloudWatchLogs({
region: 'us-east-1',
accessKeyId: 'ABCD1234',
secretAccessKey: 'MNBV76543',
Bucket: 'My_bucket'
});
// Get the events
cwl.getLogEvents({
logGroupName: 'OurLogGroupname',
logStreamName: 'specifiedLogstream'
}, (error, success ) =>{
if(error){
console.log(error)
}
console.log(success)
})
// Try saving to db
let sql = ''
pools.query_db('abc', 'INSERT INTO logging.aws_logs(request_id, duration, billed_duration) VALUES (?,?,?)', function(err, res){
if(err) return callback(err);
callback();
})
I would prefer the following way, if you really want to store all messages from Cloudwatch into a database:
Add a subscription to your Cloudwatch LogGroup
This subscription can be configured to trigger a Lambda
The Lambda will have the following logic:
extract the message from the event variable
prepare your SQL statement
connect to database (retry if not possible)
execute the SQL statement (retry if not possible)
done
One good example on how to extract the message of a Cloudwatch Subscription invocation would the one for sending those logs to Opensearch (search the blueprints)

"Request is missing authentication credential" error when calling firebase.messaging.getToken()

I am following the tutorial to add push notifications to a web app, including calling firebase.messaging.usePublicVapidKey with the VAPID key. However, when I'm calling getToken I get the following error:
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project
I am already using VAPID key and nowhere in the tutorial did Google say that a Google OAuth login was required. How can I fix this?
var messaging = firebase.messaging();
messaging.usePublicVapidKey('redacted');
function obtenerToken() {
messaging.getToken().then(function (nuevoToken) {
if (nuevoToken) {
token = nuevoToken;
} else {
messaging.requestPermission().then(obtenerToken)
.catch(function (err) { console.log('La web no tiene permiso para recibir notificaciones ', err); });
}
}).catch(function (err) { console.log('Error al obtener token de Firebase ', err); });
}
obtenerToken();
Clear your site data!
After struggling with this for some time I cleared my site data and the auth error did not occur again. We use Firestore with custom auth tokens to retrieve realtime data in another part of the site and I suspect it caused the problem.
Did you initialize with a Firebase configuration object?
import firebase from "firebase/app";
import "firebase/messaging";
const firebaseConfig = {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: "sender-id",
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
let messaging;
try {
messaging = firebase.messaging();
messaging.usePublicVapidKey("publicVapidKey");
} catch (e) {
messaging = null;
}
Have you set whitelist your production domain for browser API keys and client IDs in the Google Developer Console?
Did you setup firebase-messaging-sw.js file?
Like this.
// change your using firebase version
importScripts("https://www.gstatic.com/firebasejs/5.10.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/5.10.0/firebase-messaging.js");
const messagingSenderId = "your sender id here";
firebase.initializeApp({ messagingSenderId });
try {
const messaging = firebase.messaging();
} catch (e) {}
See:
https://firebase.google.com/docs/web/setup
https://firebase.google.com/support/guides/launch-checklist
https://github.com/firebase/quickstart-js/tree/master/messaging
https://github.com/firebase/quickstart-js/blob/master/messaging/firebase-messaging-sw.js
If does not work then you should try quickstart.
Managed to fix the issue. It turns out I copied the config from one project and the VAAPI key from another project. D'oh!
I ran into the same issue, for a different reason. We are using two Firebase projects (one dev, one production). The two apps are configured in the same config file. I just learned that the firebase.messaging() function can accept one parameter: the initialized Firebase App. Without this parameter, const devMessaging was configuring with the default app settings, in my case production. Here is the fixed code:
export const app = firebase.initializeApp(config);
export const devApp = firebase.initializeApp(devConfig, "secondary");
const devMessaging = firebase.messaging(devApp);
devMessaging.usePublicVapidKey("this_is_private");
devMessaging.getToken().then(() => {
// continue with the rest of the code
});
resource: https://firebase.google.com/docs/reference/js/firebase.messaging

Having trouble connecting to my Firebase database - Node & Express

I am still learning programming in general so sorry if I don't make sense.
I am trying to connect to my firebase database but I get a PERMISSION_DENIED error. The database in my firebase is set to Test mode so anyone should be able to access it.
I have added all the npm packages needed based on the firebase docs as well.
Let me know if I need to provide more information.
I am not sure what I am doing wrong here. Would anyone know? Any help is appreciated.
Here is my module file
var express = require('express');
var firebase = require('firebase');
// Initialize Firebase
var config = {
apiKey: "apikey",
authDomain: "authdomain",
databaseURL: "databaseurl",
storageBucket: "storagebucket"
};
firebase.initializeApp(config);
var db = firebase.database();
var ref = db.ref("/users");
ref.on("value", function(snapshot) {
console.log(snapshot.val());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
var index = require('./routes/index');
app.use('/', index);
module.exports = app;
Here is my routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'The Title' });
});
module.exports = router;
Asynchronous listeners: Data stored in a Firebase Realtime Database is retrieved by attaching an asynchronous listener to a
database reference. The listener is triggered once for the initial
state of the data and again anytime the data changes. An event
listener may receive several different types of events.
Helpful link https://firebase.google.com/docs/database/admin/retrieve-data
You need to create a reference variable that corresponds to your database path
var ref = db.ref("server/saving-data/fireblog/posts");
and then you'll attach an asynchronous callback to read the data at the reference
ref.on("value", function(snapshot) {
console.log(snapshot.val());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
I believe your issue with PERMISSION_DENIED is that you're using
var db = firebase.database();
instead of
var db = admin.database();
So I figured out a way to properly connect to my firebase database. I am not sure if this is the best way but the first thing I did was delete the current database and recreated it (not sure if this helped or was needed but I just wanted a fresh install just in-case something was wrong before.)
Then inside my database dashboard in firebase I went to the "Gear Icon => Project Settings" next to "Project Overview" header on the upper left of the dashboard screen. From here under Firebase Admin SDK I clicked "Generate New Private Key" button on the bottom.
This gave me a .json file which was downloaded onto my computer. I changed the downloaded files name to something more simple like myfirstapp-firebase-db.json. I added this file into the folder where my node js is being stored.
Before I started writing the code to connect to my firebase database, I had to make sure that my "Database => Rules" were set to true for read & write privileges in my firebase project.
Database Rules setup:
{
"rules": {
".read": true,
".write": true
}
}
After everything needed to configure firebase was taken care of, I simply configured my module.js file to properly connect. Below is the code necessary to connect to firebase. The two important things were "serviceAccount" and "databaseURL".....
var firebase = require('firebase');
// Initialize firebase
firebase.initializeApp({
serviceAccount: "./<your-service-account-url>-firebase-db.json",
databaseURL: "https://<your-database-url>.firebaseio.com/"
});
var db = firebase.database();
var ref = db.ref("/users");
..... The "serviceAccount" is a route to the .json file downloaded from the step "Generate New Private Key" above. You can find the databaseURL inside the "Database" dashboard on the top of the white block inside firebase. I simply copied and pasted that url into the databaseURL.
Then I put firebase.database() into a var = db and then specified the ref.
At this point my connection was successful and when I did a node modules.js it showed me in the console everything that is in the ref database. Make sure to have some pre populated fields in the database for the console to show you all the items inside. I hope this may be helpful to someone and if anyone knows of a better way of doing this I would love to know your suggestions!

Send notification using Cloud Functions for Firebase to specific user

I'm using Cloud Functions for Firebase to send notifications to the user. I'm able to get the notification but the problem is that everyone is getting the notification, I'm trying to send the notification to a particular user. I'm saving user's device id in Firebase's database and then send that particular person the notification. Here is my code:
To save user's data, which is actually working fine:
DatabaseReference root = FirebaseDatabase.getInstance().getReference();
DatabaseReference groupsRef = root.child("users").child(Settings.Secure
.getString(ctx.getContentResolver(), Settings.Secure.ANDROID_ID));
groupsRef.child("isLogin").setValue(2);
In first activity subscribing to the topic:
FirebaseMessaging.getInstance().subscribeToTopic("android");
And finally javascript code(something I know very little about):
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users')
.onWrite(event => {
var eventSnapshot = event.data;
var str = "This is notification"
console.log(str);
var topic = "android";
var payload = {
data: {
isLogin: eventSnapshot.child("975af90b767584c5").child("isLogin").val()
}
};
return admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
Here instead of "975af90b767584c5" which is hardcoded right now, I want to send device id, which I don't know how to do in javascript. Or if there is any other way.
Any help is appreciated, thanks.
First in app, get User FCM token by
String Token = FirebaseInstanceId.getInstance().getToken();
Now, send this token to your server and save it with other user details in Database.
Then when you want to send Notification to specific use, fetch that user's FCM token from Database via user id or something else.If you want to send notification to multiple user then fetch multiple user FCM token from database and put it in arrayList.
Now for main part, call fcm endpoint with your KEY, notification content
and most important: token or token array.
In your case, do not use sendToTopic, use send to: Token/Array
You can google for java script syntax, but this is main logic.For more info:
https://firebase.google.com/docs/cloud-messaging/admin/send-messages

Cant get Firebase in Node JS app to run

I am trying to setup firebase JS client with NodeJS. So far here is my code
var firebase = require('firebase/app');
require('firebase/database');
var config = {
apiKey: "MY_SECRET_KEY_fhcWICPI",
authDomain: "my_fir_app.firebaseapp.com",
databaseURL: "https://my_fir_app.firebaseio.com",
};
var firApp = firebase.initializeApp(config);
firebase.database.enableLogging(true)
// Get a reference to the database service
var database = firebase.database();
Then here is one of my Firebase functions to save data to the real time database.
/**
* This will save the authors of stories in Firebase
* #param {String} id The ID of the author
* #param {String} firstName The authors first name
* #param {String} lastName The authors last name
* #param {Timestamp} dateCreated The unix time stamp when the author was created
*/
function saveStoryAuthor(id, firstName, lastName, dateCreated) {
database.ref('mystoriesdb/authors/' + id).set({
first_name: firstName,
last_name: lastName,
date_created : dateCreated
});
}
Finally, somewhere in the middle of my code am calling this function as
...
saveStoryAuthor('MZ8XWXNrkG', 'Dennis', 'Richie')
...
However, this is what I get in the logs (since I have enabled logging)
$ node index.js
p:0: Browser went online.
p:0: Making a connection attempt
getToken() completed. Creating connection.
c:0:0: Connection created
p:0: Failed to get token: Error: No transports available
p:0: data client disconnected
p:0: Trying to reconnect in 326.9669258513522ms
0: onDisconnectEvents
p:0: Making a connection attempt
getToken() completed. Creating connection.
c:0:1: Connection created
p:0: Failed to get token: Error: No transports available
I am probably doing something wrong. Could someone help.
It seems you havent created a service account in order to add firebase to your project with node js
Check out the documentation here.
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
You need to change
var firebase = require('firebase/app');
to
var firebase = require('firebase');
Solution: Add the following to the root of your Webpack configuration:
resolve: {
mainFields: ['main']
}
Explanation:
The firebase/database package defines different entry points: main, browser, and module. NodeJS uses main. Webpack is a hipster and uses module.
The Firebase guys made some NodeJS-specific configuration (such as setting up WebSocket as a transport layer) in the entry point defined by main. So, after bundling, that special NodeJS-specific code isn't set up, so it errors out. Telling Webpack to just use main like Node resolves this issue.

Categories

Resources