I am trying to set up some polling on the Front End to check for inactive users and boot them to the login screen if they stay inactive for too long. The problem is, every time I make the ajax call, it is reseting the session and acting as if the user is active, even if I remain inactive in the app. It seems as though the ajax call is causing the session to act as if the user is active. Is there a way to made an AJAX call without it reseting the session like that? I tried to add the route in my api.php routes but if I check for Auth via those routes I just get false every time (cannot access Auth::user()). Any work arounds to this issue.
Code & Information:
Using SESSION_DRIVER=file (I know one work around is to use the database driver but I'd rather try and keep it file if possible)
UserController.php
public function userLoginPoll(Request $request)
{
$statusArray = [
'logged_in' => Auth::check()
];
return $statusArray;
}
web.php
Route::get('/users_api/userLoginPoll', 'UserController#userLoginPoll');
poll.js
$.poll(3000, function(retry){
$.get('/users_api/userLoginPoll', function(data){
if(data.logged_in){
retry();
}else{
window.location = '/login';
}
});
});
Using This Polling JQ Plugin
Related
I'm trying to fix one mistake which one of the previous developer has did. Currently in project we have half-bookmarkable pages. Why half? Because if token has expired user will be redirect to resourse where he has to provide his credentials and on success he will be redirect to previous resource which he has used before. Sounds good for now. The problem here is next, some of resources have server side filtering and highly complicated logic which comes in the end to the one object like this:
param = {
limit: 10,
offset: 0,
orderBy: 'value',
query: 'string query can include 10 more filters'
};
then thru the service it sends a request to the end point
var custom = {};
function data(param) {
custom.params = param;
return $http.get('/data_endpoint', custom)
.then(function (response) {
return response.data;
});
From this part request works fine and response is correct but url isn't. User cannot store current url with search params because url doesn't have it and if user will try to get back to previous page with applied filters he won't be able to do that.
Also there is interceptor in this application, which add one more query param to every api request, because every api request requires some specific validation. This param is always the same.
I have tried to add $location.search(param) exactly to this data service but it breaks the app with infinity loop of login / logout looping, because interceptor stops working and all other request are sending without special query param
Then I thought to add this params inside interceptor like this:
config.params.hasOwnProperty('query') ? $location.search(config.params) : $location.search();
But it still breaks app to infinity loop.
This method adds query to url but doesn't allow to modify it, so if user applied additional filtering, it doesn't send new modified request but sends old one.
if (config.params.hasOwnProperty('query')){
for (var key in config.params){
$location.search(key, config.params[key])
}
}
That's why I decided to ask question here, probably somebody gives an advice how to solve this problem. Thanks in advance.
I want to remove user stored data in my database when the user exits the page. A window dialog box will come up asking if the user really wishes to exit the page. Upon confirming to leave, an Ajax call should be sent to PHP confirming the action. Is it possible for PHP to receive the call in time and execute the command? If not, are there any other ways to verify that the Ajax call is sent successfully and the command is executed?
If you need very short-lived data (only relevant while the user is on the page), a database is not the right tool. Databases are designed to store long-lived data.
I suggest you use sessions instead. Here's a quick intro. Basically, sessions allow you to persist data across http requests, but to expire that data after a short while.
Start the session when the user logs in or opens your entry page, and store in $_SESSION any data you want to access while the user is on the page.
entry or login page
<?php
if(session_status()===PHP_SESSION_NONE) session_start();
... work through your script
//store data you'll need later
$_SESSION['username'] = 'Linda';
$_SESSION['age'] = 22;
$_SESSION['expires'] = time()+ 60*15; //expires in 15 minutes
The next time the user makes a request, test whether the session is still active. If so you can get the data from session, and refresh expiration. If the session has expired, you can destroy the data.
protected page
<?php
if(session_status()===PHP_SESSION_NONE) session_start();
if(isset($_SESSION['expires']) && $_SESSION['expires'] > time()){
//session is still active. extend expiration time
$_SESSION['expiration'] = time() + 60*15;
//retrieve data
$user = $_SESSION['username'];
.... run your script
}else{
//either the session doesn't exist or it has expired because the user
//left the page or stopped browsing the site
//destroy the session and redirect the user
session_destroy();
header('Location: /login.php');
}
You should not use unreliable, hacky and annoying methods. The only events that come close to your needs are window.onbeforeunload and window.unload but popups are usually blocked in those events (hence the hacky) and when blocked the remainder code as well.
There is also the issue that closing a tab will fire the events, closing the browser however will skip them and its all dependent if the browser actually supports it.
Perhaps use an ajax call every 5 minutes to detect if the page is still running and update a database with that time.
Now with a server cronjob you should select all rows with a time < now() - 300 and then you should have a list of browsers that recently connected but are not sending any signal anymore.
Or you could save the data in localstorage every 10 seconds so then there is no need to do all this?
Try This:
<script>
window.onbeforeunload = function (event) {
var message = 'Important: Please click on \'Save\' button to leave this page.';
if (typeof event == 'undefined') {
event = window.event;
//ajax call here
}
if (event) {
event.returnValue = message;
}
return message;
};
</script>
I am using Meteor with React and is facing a problem on log out function. When I open more than 2 tabs on the same browser, If I logged out from one tab then the other opening tabs would not be logged out but will be hang if I using it. There are only 2 ways to log out: close the tab or refresh it.
I try the same for log in function and it worked, log in status is synced between all opening tabs.
My current code to call the log out function:
signOut: function(event) {
event.preventDefault();
Meteor.logout();
this.props.history.pushState(null, "/");
},
Thank for the helps.
Update:
I checked the websocket, it's seem that the server did send the logout status but my client code did not call the logout method (or it is hang). Then every data in the hang tab is still existing. But I don't know how to check further more.
I found the cause. It was because I try to avoid sending data on Meteor.publish() if users is not logged in. The problem is I do not return anything on that case.
My solution is return this.ready() when the user is not logged in like this:
Meteor.publish("myCollections", function (){
if (!this.userId) return this.ready();
return MyCollections.find({owner: this.userId});
});
From the meteor documentation, you can use Meteor.logoutOtherClients() before calling Meteor.logout().
Normal (as in non-incognito) browser tabs share the same session resume token. The Meteor server will update them all when the user status changes for the associated session.
It is possible to reactively track the login status using 2 reactive calls:
Meteor.userId() - return the user's id or null if no user is logged in.
Meteor.loggingIn() - returns true if the user is currently in the transient state of logging in and false otherwise.
The status may take a few seconds to update across tabs, but it will happen eventually. It is up to you to detect those changes and act upon them.
You can easily test this by running the following reactive code in the consoles of 2 open tabs connected to the same Meteor server:
Tracker.autorun(function() {
if (Meteor.loggingIn()) {
console.info('logging in');
} else if (Meteor.userId()) {
console.info('logged in');
} else {
console.info('logged out');
}
});
Try to log in and log out from one of the tab and watch the other follow along.
Using this technique, you could track the login state and change your application state and do something accordingly (e.g, redirect/render a different view or layout) when the login state changes.
I am developing an app using angularjs and this is my first hands on using angular. Although, I have started understanding it and have developed some part of the app but I am stuck at one particular point.
I am trying to implement login functionality, so as the page loads, I am authenticating user and redirecting him to login page. On successful login, I am storing some values of user in one of the config provider.
Now I am using an API which has their own method of authentication and they have expose the ajax method which I can use to authenticate a user.
I have provided a snippet below. What I am primarily doing is using the external API, authenticating the user and once authenticated, I am getting roles associated to that user using another ajax method of the API, called "GetUserDetails".
And inside the response of the "GetUserDetails", I am injecting a provider and setting some values, so I can use this across my app.
The problem here is the app.config method is never called/executded. I mean the ajax request is returning response, and the alert is displayed on my page, but app.config is never executed.
But the same app.config if I call inside the done() of GetUser method, the app.config gets executed and stores values in my provider. But I want the GetuserDetails values also to be stored before I do anything in my app as I want to execute certain functionality based on user.
Below is my function in main.js file
function(angular,angularRoute,app,routes,configService){
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.element().ready(function() {
$.c.authentication.getUser()
.done(function(response){
if(response.userName!="anonymous"){
$.c.ajax({
method: "GetUserDetails",
parameters: {
User: response.user
}
})
.done(function(res) {
alert("I have reached the destination").
app.config(['configServiceProvider', function(configServiceProvider){
configServiceProvider.setLoginStatus(true);
configServiceProvider.setUserName(response.userName);
configServiceProvider.setUserObject(response);
configServiceProvider.setUserRoleDetails(res);
}]);
})
.fail(function(res) {
alert("Error while getting user roles ."+res);
});
angular.resumeBootstrap([app['name']]);
}
else
{
app.config(['configServiceProvider', function(configServiceProvider){
configServiceProvider.setLoginStatus(false);
configServiceProvider.setUserName(response.userName);
}]);
//Show Login Screen
var url = window.location.href.split("#")[0];
window.location.href = url + "#/Login";
angular.resumeBootstrap([app['name']]);
}
})
.fail(function(response){
$rootScope.isLoggedIn=false;
});
});
Here is my configServiceProvider
define(['../app'],function(app){
return app.provider('configService', function(){
var options={};
this.setLoginStatus = function(status){
//$rootScope.isLoggedIn = status;
options.isLoggedIn=status;
};
this.setPreLoginInfo=function(info){
options.preLoginInfo=info;
};
this.setUserName=function(name){
options.username=name;
}
this.setUserObject = function(userObject) {
options.userObject = userObject;
}
this.setUserRoleDetails = function(userRoleDetails) {
options.userRoleDetails = userRoleDetails;
}
this.$get=[function(){
if(!options){
}
return options;
}];
});
})
Can anyone please explain me what's going wrong here or what I am missing ?
Also, is there any alternative to achieve the same functionality ?
No luck in figuring out why the above scenario was not working. Since I had already spent lot of time behind this, I have found a workaround to achieve the same with the use of services.
I am creating a Facebook Canvas application, and I am following more or less the demo app.
As in the demo, I can get the user data from the signed_request which is POSTed to my site on the first page load. Moreover, as suggested in the demo, I use the following snippet to reload the page on user changes:
var Config;
function facebookInit(config) {
Config = config;
FB.init({...});
FB.Event.subscribe('auth.sessionChange', handleSessionChange);
...
}
function handleSessionChange(response) {
if ((Config.userIdOnServer && !response.session) ||
Config.userIdOnServer != response.session.uid) {
goHome();
}
}
function goHome() {
top.location = 'http://apps.facebook.com/' + Config.canvasName + '/';
}
Here Config is an object which is populated with info from the server.
The problem appears when the user navigates the application using a link. If I use AJAX, the page is not actually reloaded and everything works fine. But if I use a standard link, the user comes to another page of my application with a standard GET request. In this case, I do not know how to get the info about the user, so Config.userIdOnServer is undefined and a page reload is triggered.
Of course I can avoid this by removing the call to handleSessionChange, or by making a one-page app with only AJAX links, but I feel I am missing something basic about the Facebook flow.
My fault, I had problems in retrieving the cookie with the user identity for subsequent requests.