I'm currently checking whether a user is logged in client-side using:
firebase.auth().onAuthStateChanged(function (user)
{
}
However, this method takes 1-2 seconds after the page has loaded to be called and I was wondering whether there was a faster way to check if the user is signed in?
I'm using this to check that the user is authorised to enter a specific page on a website, and at the moment they are able to view the contents of it before being redirected to the homepage, which shouldn't happen. So I am hoping for a faster alternative.
You can try this method that i was using to execute certain code immediately after the user logged (avoid waiting by executing a fast loop that keeps testing for the user data) :
var int = setInterval(()=>{
firebase.auth().currentUser ?
// you can do whatever you want immediately when the user is logged
// and then clear the interval;
clearInterval(int)
: ''
}
},10)
Related
The question itself is simple: For a Firebase app, How do you get data that was previously blocked after you login and it is no longer blocked?
As for the details that lead me to ask this question:
In this particular app, I use a simple layout with 2 main sub trees of the root tree, Users and Data. The Data tree is completely readable, anyone can read it at any time. The Users tree is almost the opposite, with the only exception being if you are logged in, then you can read a specific sub tree that is yours only. This leads to the problem that when you go to the page, this data that may be very important to you is blocked until you log in, and there is no way to retrieve it directly. After you log in, however, you now have permission to get that information, but because it was previously blocked, There seems to be no way to extract it.
I have scoured the docs and found only one trigger that might be useful, onAuth(), but even though I can run stuff after login, I cant actually get any data. The best I have gotten so far was a Firebase Reference to the specific sub tree I need, but I cant find any way to actually use that reference to get the Snapshot because it is after the page load. It seems the only option I have is to refresh the page after login and check for login on page load, but that is an awful lot of overhead. Is there some other way to get the data in a tree that you previously did not have permission for after you log in and do have permission to read it? Might there be some reference in the docs I can't find or don't understand that allows me to demand a new snapshot of a fire base reference that is not through triggers that can only be defined on pageload?
Frank van puffelen is right.
It is as simple as:
// setup and other code
ref = new Firebase(URL); //The firebase reference
myuserid = null; //Storage variable
myname = null; //Storage variable
//Other code
//Start of answer code
ref.onAuth(function(authData) { //ON login status change
if (ref.getAuth()) { //Are they logged in
myuserid = authData.uid; //Stores their UID for use
userbase = 'Users/' + authData.uid; //Get path to user info
ref.child(userbase).on("value", function(snapshot, prevChildKey) {
var newData = snapshot.val(); //get data
console.log(newData); //View data, confirmed it was what I wanted
myname = newData.name; //The important data I needed
})
}
})
It seems that so long as this listener is by the other listeners, it works. It runs every time the Authentication is changed, and if they are logged in, attaching a listener to the path with the information and getting it. I am sure there are better ways and probably some problems with this code, but it works for me.
I'm using a publish to limit which data a user sees in their report
Meteor.publish("companyReport", function(){
if(!this.userId) return null;
var user = Meteor.users.findOne(this.userId);
var userCompany = user.profile.company;
var userRole = user.roles;
var userName = user.username;
if(function(){Roles.userIsInRole(Meteor.user(), ['chiefs']);})
{return ReportCollection.find({companyName:userCompany});}
else if (function(){Roles.userIsInRole(Meteor.user(), ['managers']);})
{return ReportCollection.find({companyName:userCompany, managerName:userName});}
else
{return null;}
});
Now, on the client side i can simply subscribe. It's generally working fine,except:
I noticed the following odd behaviour i don't want: if i am logged-in as a "chiefs" role user, and can see a company-wide report, if i logout and then login as a "managers" user, i can still see the data i am not supposedly allowed to see.
i know that my publications control mechanism is working ok, as when i login as a manager from another browser, i see the correct results (more limited)
i can only conclude that minimongo on the client is keeping the collection data from the old subscription as a "chiefs" user.
is this correct? if so, how do i flush this data upon logout? or?
what do people usually do to avoid this?
thanks
You probably do need to flush this data on logout, which will involve saving the subscription handle and then stopping it:
// when you subscribe
var reportHandle = Meteor.subscribe('companyReport');
// then when you want to log out
reportHandle.stop();
Meteor.logout();
UPDATE
If I understand your question, you want to make sure you're only ever flushing the minimongo when the user actually logs out:
Meteor.logout(function(err) {
if (err)
console.log(err);
else
reportHandle.stop();
});
ANOTHER UPDATE
Ah, now I see what you're asking. It depends on the package, as there's no onLogout event listener you can use for this. You can probably monkey-patch something quite easily, but I'm not sufficiently familiar with accounts-ui-bootstrap to say for sure.
When a user logs into a Meteor application a session is created. How long does it take for the session to expire after the user has closed the browser?
Does the session expire even if the browser is not closed?
Is it possible to react to the closing of a session? By invoking a callback for example.
I was looking for stale session / session timeout functionality for a meteorjs app and ran across this answer when looking for a suitable package to use.
Unfortunately the meteor-user-status package mentioned by Andrew doesn't seem to do a timeout.
I continued to look, found a couple of other packages, but couldn't get them to work for me - so I wrote a very small and simple package inspired by the others to do exactly what the questioner is asking for here i.e. force a user log out after a defined period of inactivity (whether the browser is open or not).
It does not, however, provide a callback (as it's the server that forces the logout) but this could probably be done with a Dep.autorun looking at Meteor.userId().
You can try it by typing
mrt add stale-session
And find details of how it works and how it can be configured here:
https://atmosphere.meteor.com/package/stale-session
and the code is open sourced here:
https://github.com/lindleycb/meteor-stale-session
Use the package I created that tracks user status, both overall and in several different browser sessions:
https://github.com/mizzao/meteor-user-status
With this, you can react to both sessions being closed and users logging out (see README). I've implemented it only for logged-in users, but you can do something similar if you want to track anonymous users.
I've been using zuuk:stale-session and I too initially wished it had a callback, but I solved it with an elegant solution (IMHO).
My app has a login template that get's rendered when if (! Meteor.user()) is true. It used to just run this.render('login') template which sufficed, but it still left the logged-in menu structure available. So, I switched to to Router.go('login') which has it's own layoutTemplate. So now when inactivity triggers the stale-session to delete the tokens for the user, the page goes to /login rather than just rendering the login template within whatever route was left stale.
Here's my code in router.js:
/** [requireLogin - make sure pay area is walled off with registration] */
var requireLogin = function() {
if (! Meteor.user()) {
// If user is not logged in render landingpage
//this.render('login');
Router.go('login');
this.next();
} else {
//if user is logged in render whatever route was requested
this.next();
}
}
/**
* Before any routing run the requireLogin function.
* Except in the case of "landingpage".
* Note that you can add more pages in the exceptions if you want. (e.g. About, Faq, contact...)
*/
Router.onBeforeAction(requireLogin, {
except:['terms','privacy','about','features','home']
});
I used following in my application to find the list of logged in user. It gives the list of logged in user but when i close the browser and clear the browser history, it shows the user isonline status true. Please can any one tell me where i am wrong?
When User signIn am validating user and redirect to url,
if (user != null)
{
if (Membership.ValidateUser(user.UserName, txtUserPassword.Text))
{
FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
}
}
List of logged in user code
MembershipUserCollection allUsers = Membership.GetAllUsers();
MembershipUserCollection filteredUsers = new MembershipUserCollection();
bool isOnline = true;
foreach (MembershipUser user in allUsers)
{
// if user is currently online, add to gridview list
if (user.IsOnline == isOnline)
{
filteredUsers.Add(user);
}
}
MembershipUser.IsOnline is not a very accurate check of whether or not a user is online. From the MSDN, a user is determined to be online:
if the current date and time minus the
UserIsOnlineTimeWindow property value is earlier than the
LastActivityDate for the user.
This means the user could log in and then log out 10 seconds later and still be considered online.
So in your case you were logging in, checking the count, logging out, closing the browser, clearing cache, etc., but the user's LastActivityDate still fell within the assumed window described above. What you can do is:
shorten the time window (which can produce some unwanted side
effects)
when logging the individual out, update their LastActivityDate to a
time that would make the above check invalid (e.g., the current time
UserIsOnlineTimeWindow)
update the LastActivityDate manually at certain key points (e.g.,
if your site is bookstore, maybe updating the LastActivityDate when
they add an item to the cart)
I am working on a website, where we want user to login using Javascript and not using
postback. I have few pages which user can view without logging in, but on these pages
if he wants to do something like "Add to favourite" or "Report abuse" or similar, he has to log in. I can display a div where he can log in. But I want the system to perform the task
he initially tried to do. So say if the user wants to perform "Add to favourite", he should first log in and on success othere function "Add to favourite" should be called. So logic
should know where to delegate once user is logged in.
As this loging stuff is required for many other purposes too, so I can hard code one function once log on is successful. I need something like delegation which Login Routine
should know so that it calls it back.
Help will be appritiated.
Regards
Parminder
This assumes you have some basic experience with AJAX and callbacks...
// When the user submits the login form, call the login function with
// the original call as the third parameter
function login(username, password, callback) {
// Perform AJAX call with username and password.
// Your AJAX utility should call loginResult as its callback
// Store the callback parameter on your object somewhere
}
function loginResult(result, callback) {
if (/* Check if the result contains a valid user or sessionID, etc. */) {
// Logged in, yay. Do stuff to the UI to show this.
if (callback) callback();
} else {
// Error logging in, oh no. Display error.
}
}
You could store the lastAttemptedAction in the session, and always check this upon a successful login. So the order of events would be:
User accesses site anonymously
User clicks "add to favorite"
"Add to favorite" is added to Session.lastAttemptedAction
User is asked to login
User successfully logs in
Session.lastAttemptedAction is performed/cleared
If nothing is stored in the lastAttemptedAction, then nothing will be ran. The user will silently login, and continue on his or her merry way.