[enhance] handle session expired in a graceful manner (#3022)

This commit is contained in:
Rushabh Mehta 2017-04-10 12:44:39 +05:30 committed by GitHub
parent a304beb664
commit 83045eb36c
6 changed files with 78 additions and 13 deletions

View file

@ -134,6 +134,12 @@ def handle_exception(e):
# code 409 represents conflict
http_status_code = 508
if http_status_code==401:
frappe.respond_as_web_page(_("Session Expired"),
_("Your session has expired, please login again to continue."),
http_status_code=http_status_code, indicator_color='red')
return_as_message = True
if http_status_code==403:
frappe.respond_as_web_page(_("Not Permitted"),
_("You do not have enough permissions to complete the action"),

View file

@ -14,6 +14,9 @@ class ValidationError(Exception):
class AuthenticationError(Exception):
http_status_code = 401
class SessionExpired(Exception):
http_status_code = 401
class PermissionError(Exception):
http_status_code = 403

View file

@ -311,13 +311,61 @@ frappe.Application = Class.extend({
method:'logout',
callback: function(r) {
if(r.exc) {
console.log(r.exc);
return;
}
me.redirect_to_login();
}
})
},
handle_session_expired: function() {
if(!frappe.app.session_expired_dialog) {
var dialog = new frappe.ui.Dialog({
title: __('Session Expired'),
fields: [
{ fieldtype:'Password', fieldname:'password',
label: __('Please Enter Your Password to Continue') },
],
onhide: () => {
if (!dialog.logged_in) {
frappe.app.redirect_to_login();
}
}
});
dialog.set_primary_action(__('Login'), () => {
frappe.call({
method: 'login',
args: {
usr: frappe.session.user,
pwd: dialog.get_values().password
},
callback: (r) => {
if (r.message==='Logged In') {
dialog.logged_in = true;
// revert backdrop
$('.modal-backdrop').css({
'opacity': '',
'background-color': '#334143'
});
}
dialog.hide();
},
statusCode: () => {
dialog.hide();
}
});
});
frappe.app.session_expired_dialog = dialog;
}
if(!frappe.app.session_expired_dialog.display) {
frappe.app.session_expired_dialog.show();
// add backdrop
$('.modal-backdrop').css({
'opacity': 1,
'background-color': '#EBEFF2'
});
}
},
redirect_to_login: function() {
window.location.href = '/';
},

View file

@ -67,15 +67,22 @@ frappe.request.call = function(opts) {
opts.success_callback && opts.success_callback(data, xhr.responseText);
},
401: function(xhr) {
msgprint({message:__("You have been logged out"), indicator: 'red'});
frappe.app.logout();
if(frappe.app.session_expired_dialog && frappe.app.session_expired_dialog.display) {
frappe.app.redirect_to_login();
} else {
frappe.app.handle_session_expired();
};
},
404: function(xhr) {
msgprint({title:__("Not found"), indicator:'red',
message: __('The resource you are looking for is not available')});
},
403: function(xhr) {
if (xhr.responseJSON && xhr.responseJSON._server_messages) {
if (frappe.get_cookie('sid')==='Guest') {
// session expired
frappe.app.handle_session_expired();
}
else if (xhr.responseJSON && xhr.responseJSON._server_messages) {
var _server_messages = JSON.parse(xhr.responseJSON._server_messages);
// avoid double messages
@ -83,10 +90,13 @@ frappe.request.call = function(opts) {
return;
}
}
else {
frappe.msgprint({
title:__("Not permitted"), indicator:'red',
message: __('You do not have enough permissions to access this resource. Please contact your manager to get access.')});
}
frappe.utils.play_sound("error");
msgprint({title:__("Not permitted"), indicator:'red',
message: __('You do not have enough permissions to access this resource. Please contact your manager to get access.')});
},
508: function(xhr) {
frappe.utils.play_sound("error");
@ -233,11 +243,7 @@ frappe.request.cleanup = function(opts, r) {
// session expired? - Guest has no business here!
if(r.session_expired || frappe.get_cookie("sid")==="Guest") {
if(!frappe.app.logged_out) {
localStorage.setItem("session_last_route", location.hash);
msgprint(__('Session Expired. Logging you out'));
frappe.app.logout();
}
frappe.app.handle_session_expired();
return;
}

View file

@ -47,7 +47,8 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({
cur_dialog = null;
}
}
me.onhide && me.onhide.apply(me);
me.onhide && me.onhide();
me.on_hide && me.on_hide();
})
.on("shown.bs.modal", function() {
// focus on first input

View file

@ -286,6 +286,7 @@ class Session:
"""get session record, or return the standard Guest Record"""
from frappe.auth import clear_cookies
r = self.get_session_data()
if not r:
frappe.response["session_expired"] = 1
clear_cookies()