I´m building kind of a social network where users may send requests to other users.
The controller which gets loaded if the user checks his messages page:
$scope.requestedProfileTrips = Requests.getRequests(user.id).then(function (requests) {
$scope.requestedProfileTrips = [];
for (var i = 0; i < requests.length; i++) {
// this function loads additional data depending on the request from firebase
// from another database
loadProfileTrips(requests[i]);
}
});
The service which gets the requests from firebase:
getRequests: function(userId){
// get requests
var sync = $firebase(ref.child("requests").child(userId));
var requestObject = sync.$asArray();
// add requests to object
return requestObject;
}
The request object includes a userId, a messageId and so on. In the then function of the controller I get the userId from another database. This should update in realtime.
If I do:
$scope.requestedProfileTrips = Requests.getRequests(user.id);
the updating in realtime works! But I only got the user id and the message id. Is it possible to get the data from the other database which stores the usernames etc. in realtime? So everytime a request is added from firebase, the content in the then function of getRequests is triggered?
Firebase is good in real time sync but other than that as far as I know there is no ready to use database offering the same.
You could however go for a hybrid approach like manually fetching the data from tradition SQL or NoSQL database when your firebase dataset/event get updates/fired. This way you could use both realtime sync of firebase and your traditional database.
Or if you require to integrate realtime sync with traditional databases, then would suggest you look at sockets. Preferably sockets.io would let you get started pretty fast.
Related
I have an application that sends data to the firebase realtime database. Now I'm creating a dashboard to manage this data. At the moment I need to receive a notification on the dashboard when the user sends some new data to the firebase. I need to receive a message with the data id he sent and submit a notification similar to a social network.
I'm using FCM, I've already configured and tried to implement the onCreate () function. But when the bank is upgrading, this function is not being performed.
I'm implementing the code in the dashboard
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.makeUppercase = functions.database
.ref("users")
.onCreate((snapshot, context) => {
const original = snapshot.val();
console.log(original);
});
I'm actually lost on how to do this, I read the documentation, but I didn't quite understand the correct steps to follow. Is there anything I should do before that? Or is this method of doing wrong?
I build a simple react app to test google firebase. Anyone have any idea how the onSnapshot method works? I mean, it is so fast (like, instantly), even when I change network to slow 3G in devtools, it still fast. I noticed in XHR tab, when the app made request to firebase, request is still pending, but onSnapshot already fired and change the state in my react app. I thought it will wait until there's response from firebase, but that's not the case.
.firestore()
.collection("expense")
.onSnapshot((snapshot) => {
const newExpense = snapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
};
});
//set state is fired, but request is still pending
this.setState({expense: newExpense});
});
Did firebase just store the app state somewhere, or just simply read the app state and then update the state (call onSnapshot) when making request? If that's the case then you can not handle network error (or you can but that would be weird), because the app state is already changed.
Did firebase update the app state when this function (function below is to add collection to firebase database) called? and didn't even wait until request is success?
firebase.firestore().collection("expense").add(value);
firebaser here
When you write to Firestore from your application, the Firestore client in that application immediately fires events for the local listeners to that data.
So after your call to firebase.firestore().collection("expense").add(value) the Firestore client does:
Send the new data off to the server.
Calls any local listeners to /expenses straight away.
It's the second step here that makes the local chances show up instantly, as it doesn't wait for the server to complete the write operation.
This leads to a possible problem: what happens if the server rejects the write operation (for example because it conflicts with the security rules of your database)? If that happens, a few more steps are taken:
The server checks the write against the security rules and rejects it.
The client then fires reconciliation events for the local state, so it calls your onSnapshot listener again with the document removed.
Because of these extra steps, it is possible to briefly see the new document appear and then be removed, if it violates the security rules of your app.
Most likely, offline storage is enabled.
I think I found it, thanks to Aprillion for mentioning this explanation
Firebase will cache the data you get, read from that and update the state based on that data while still making network request, that's why it is instantly
I am developing an App that has a server side using Play Framework Scala, and a client side AngularJS.
I want to manage authentication only on the server side because I will have to secure both the API and the application itself and I want to keep the sessions "centralized" on my server.
But since I am not using Play Framework view templating (to keep my client side and my server side independant), I cannot pass the user profile information to the client side as it is done in the examples.
I tried to list my Cache and my Cookie keys on my Angular template but I can't seem to find anything there.
Is there any way I can grab the session information using Angular? having the session requested and managed by Play Framework ? (I cannot find it anywhere on the docs)
Here is how I render my Angular client side front page (Play framework only does the API routing and this front page routing)
def frontPage() = AuthenticatedAction {
request =>
val idToken = request.session.get("idToken").get
val profile = cache.get[JsValue](idToken + "profile").get
Ok.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html")
}
Here is how it is done on the docs example :
def index = AuthenticatedAction { request =>
val idToken = request.session.get("idToken").get
val profile = Cache.getAs[JsValue](idToken + "profile").get
Ok(views.html.user(profile))
}
I would need to get that "profile" across to my template, but I don't want to have scala html templates : I want to keep using pure Angular templates to keep my client / server sides independants (only communicating through an API)
EDIT 21/06/2016: I did not find a way to grab my session information directly from Angular, but I was able to return it by extending my API and I like that solution better ! see https://stackoverflow.com/a/37942787/4884034
You can render it to the client side with:
Ok
.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html")
.withSession(session)
or .withCookies(cookie)
So, thanks to #Simon for pointing me in the right direction.
I am now sending a session after the login :
Ok.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html").withSession("connected" -> profile.toString())
I was not able to get the session directly from Angular, so what I did instead is I updated my API to have an action returning the Session information :
def getSession = Action { request =>
request.session.get("connected").map {
user => Ok(Json.parse(user))
}.getOrElse {
Unauthorized("Oops, you are not connected")
}
}
(in routes :
## USER SESSION
GET /api/session controllers.Callback.getSession
)
That way I can call the API to get my session information on my client side, may it be Angular, a mobile app or any kind of application that reads JSON.
Example of JSON returned :
{"email":"XXX#XXX.com","email_verified":false,"clientID":"MvM2wHRX2rMKp5s3UXXXXXXXX","updated_at":"2016-06-21T10:59:49.730Z","picture":"https://s.gravatar.com/avatar/e91d5ae3XXXXXXXXXXX?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fda.png","user_id":"auth0|5XXXXXXXXX47b1b07d","name":"XXX#XXX.com","nickname":"XXX","identities":[{"user_id":"5767bea338XXXXXX","provider":"auth0","connection":"Username-Password-Authentication","isSocial":false}],"created_at":"2016-06-20T10:00:03.921Z","sub":"auth0|5767beXXXXXXX"}
I hope it will help anyone trying to have a decoupled Play Framework server side from its client side !
I'm building an app based on Firebase + AngularJS. I'm using User management service by Firebase. I'm able to get all data for Authenticated user, however, I'm not able to retrieve all user data as admin. How can I get full access to Firebase data.
Thanks!
As Frank mentioned in the comment, Firebase doesn't make user account information available to the admin. Rather, some information is available on the client after authentication and it could be sent to be stored as explicit data in Firebase.
The link Frank provide in the comment explains how to do this.
Applications do not automatically store profile or user state. To persist user data you must save it to your database. The callback function will return an object containing the data for the authenticated user, which you can then write to your database.
Here is the core of the example
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(function(authData) {
if (authData && isNewUser) {
// save the user's profile into the database so we can list users,
// use them in Security and Firebase Rules, and show profiles
ref.child("users").child(authData.uid).set({
provider: authData.provider,
name: getName(authData)
});
}
});
I'm developing a Yii2 REST API, with AngularJS for the frontend to consume.
I need a way to implement real time approach, e.g. for a chat, or to make some real time notifications.
Is this possible, how to achieve? I been reading about Ratchet, Socket.io and some other things, but I couldn't figure out how to make them fit together for REST or if this is the way to go.
Any advice would be appreciate.
You have a few options here.
Short / Long Polling (use setTimeout)
app.controller("MyController", function($scope, $timeout, $http) {
$scope.messages = [];
$timeout(callAtTimeout, 3000);
function callAtTimeout() {
console.log("Timeout occurred");
$http.get('PATH TO RESOURCE TO GET NEW MESSAGES').then(
function(res) { // update $scope.messages etc... },
function(err) { // handle error }
);
}
});
For both short and long polling on client side, you send request, wait to get a response back, then wait 3 seconds and fire again.
Short/Long polling works differently on the server side. Short polling will just return a response immediately - whether something has changed or not. Long polling, you hold the connection open and when there is a change, then you return the data. Beware of keeping too many connections open.
Socket.io (websockets)
I would recommend that you implement websockets using either something like node.js on your own web server or a hosted solution like Firebase.
The thing with Firebase is that from PHP, you can send a post request to a REST endpoint on the firebase server. Your javascript can connect to that endpoint and listen for changes and update the dom accordingly. It is possibly the simplest of all to implement.
I personally wouldnt use PHP for socket programming but it can be done.
To have real-time updates on your website, you can implement one of the following approaches depending on your requirement and how fast you need to update your frontend component.
Using a websocket
You can use a library like https://github.com/consik/yii2-websocket to implement it with Yii2. But this will act as a separate service from your REST API. Therefore you have to make sure that proper security practices are applied.
Running an Angular function with a timeout
You can continuously poll an endpoint of the REST API with a timeout of few milliseconds to receive updated values.
The second approach will create many requests to the API which will increase the server load. Therefore my preferred approach is using a websocket.