Commit 5d69fbf8 authored by Stavros Sachtouris's avatar Stavros Sachtouris Committed by Giorgos Korfiatis
Browse files

Manage remote authentication failure

The helper will catch all remote client errors and inform the UI
instead of terminating.

At the GUI side, on 401 UNAUTHORIZED errors, the settings window
will open, prompting users to check their settings. This behavior
will be repeated whenever there is an authentication error (e.g.,
when the token expires).
parent bd9fd1b4
......@@ -97,6 +97,8 @@ var settings_menu = new gui.MenuItem({
icon: 'static/images/settings.png',
enabled: false,
click: function () {
globals.settings_are_open = true;
globals.open_settings = false;
export_settings(globals.settings);
if (windows['settings']) windows['settings'].close();
var old_settings = {};
......@@ -107,6 +109,7 @@ var settings_menu = new gui.MenuItem({
});
windows['settings'].on('closed', function() {
log_debug('Settings windows is closed');
globals.settings_are_open = false;
var new_settings = import_settings();
$.each(new_settings, function(key, setting) {
log_debug('Compare ' + old_settings[key] + ' with ' + setting);
......@@ -144,12 +147,33 @@ menu.append(new gui.MenuItem({
}));
function deactivate_menu() {
if (
pause_item.enabled ||
local_folder_menu.enabled ||
pithos_page_menu.enabled) {
progress_item.label = 'Settings window is open';
pause_item.enabled = false;
local_folder_menu.enabled = false;
pithos_page_menu.enabled = false;
tray.menu = menu;
}
}
// Update progress
var client_ready = false;
window.setInterval(function() {
if (globals.settings_are_open) {
deactivate_menu();
return;
}
if (globals.open_settings) {
globals.open_settings = false;
settings_menu.click();
deactivate_menu();
return;
}
var menu_modified = false;
......@@ -159,6 +183,7 @@ window.setInterval(function() {
}
if (client_ready) {
pause_item.enabled = (pause_item.label !== 'inactive');
if (!settings_menu.enabled) {
if (globals.settings.url) refresh_endpoints(globals.settings.url);
settings_menu.enabled = true;
......@@ -182,7 +207,7 @@ window.setInterval(function() {
var new_progress = progress_item.label;
var new_pause = pause_item.label;
if (!status.can_sync) {
new_progress = 'Incomplete settings'
new_progress = 'Not able to sync'
new_pause = 'inactive'
pause_item.enabled = false;
} else {
......
......@@ -38,7 +38,8 @@ var globals = {
status: {synced: 0, unsynced: 0, paused: null, can_sync: false},
authenticated: false,
just_opened: false,
open_settings: false
open_settings: false,
settings_are_open: false
}
// Protocol: requests ::: responses
......@@ -89,6 +90,12 @@ socket.onopen = function() {
socket.onmessage = function(e) {
var r = JSON.parse(e.data)
log_debug('RECV: ' + r['action'])
if (globals.authenticated && r['UNAUTHORIZED'] === 401) {
log_debug('Authentication error (wrong token?)');
globals.open_settings = true;
return
}
switch(r['action']) {
case 'post ui_id':
if (r['ACCEPTED'] === 202) {
......
......@@ -117,6 +117,10 @@ class WebSocketProtocol(WebSocket):
HELPER: {"ACCEPTED": 202, "action": "post ui_id"}" or
"{"REJECTED": 401, "action": "post ui_id"}
-- ERRORS WITH SIGNIFICANCE --
If the token doesn't work:
HELPER: {"action": <action that caused the error>, "UNAUTHORIZED": 401}
-- SHUT DOWN --
GUI: {"method": "post", "path": "shutdown"}
......@@ -325,19 +329,23 @@ class WebSocketProtocol(WebSocket):
except KeyError:
pass
syncer_settings = setup.SyncerSettings(
self.settings['url'], self.settings['token'],
self.settings['container'], self.settings['directory'],
**kwargs)
master = pithos_client.PithosFileClient(syncer_settings)
slave = localfs_client.LocalfsFileClient(syncer_settings)
self.syncer = syncer.FileSyncer(syncer_settings, master, slave)
self.syncer_settings = syncer_settings
self.syncer.initiate_probe()
try:
syncer_settings = setup.SyncerSettings(
self.settings['url'], self.settings['token'],
self.settings['container'], self.settings['directory'],
**kwargs)
master = pithos_client.PithosFileClient(syncer_settings)
slave = localfs_client.LocalfsFileClient(syncer_settings)
self.syncer = syncer.FileSyncer(syncer_settings, master, slave)
self.syncer_settings = syncer_settings
self.syncer.initiate_probe()
except setup.ClientError:
self.syncer = None
raise
# Syncer-related methods
def get_status(self):
if self.can_sync():
if getattr(self, 'syncer', None) and self.can_sync():
self._update_statistics()
self.status['paused'] = self.syncer.paused
self.status['can_sync'] = self.can_sync()
......@@ -352,7 +360,7 @@ class WebSocketProtocol(WebSocket):
def set_settings(self, new_settings):
"""Set the settings and dump them to permanent storage if needed"""
# Prepare setting save
could_sync = self.can_sync()
could_sync = getattr(self, 'syncer', None) and self.can_sync()
was_active = False
if could_sync and not self.syncer.paused:
was_active = True
......@@ -367,7 +375,7 @@ class WebSocketProtocol(WebSocket):
if self.can_sync():
if must_reset_syncing or not could_sync:
self.init_sync()
elif was_active:
if was_active:
self.start_sync()
def pause_sync(self):
......@@ -421,9 +429,9 @@ class WebSocketProtocol(WebSocket):
}[action]()
self.send_json({'OK': 200, 'action': 'post %s' % action})
elif r['ui_id'] == self.ui_id:
self._load_settings()
self.accepted = True
self.send_json({'ACCEPTED': 202, 'action': 'post ui_id'})
self._load_settings()
if self.can_sync():
self.init_sync()
self.start_sync()
......@@ -442,14 +450,16 @@ class WebSocketProtocol(WebSocket):
self.send_json(r)
else:
action = r['path']
self.send_json({'UNAUTHORIZED': 401, 'action': 'put %s' % action})
self.send_json({
'UNAUTHORIZED UI': 401, 'action': 'put %s' % action})
self.terminate()
def _get(self, r):
"""Handle GET requests"""
action = r.pop('path')
if not self.accepted:
self.send_json({'UNAUTHORIZED': 401, 'action': 'get %s' % action})
self.send_json({
'UNAUTHORIZED UI': 401, 'action': 'get %s' % action})
self.terminate()
else:
data = {
......@@ -478,7 +488,14 @@ class WebSocketProtocol(WebSocket):
except KeyError as ke:
self.send_json({'BAD REQUEST': 400})
LOG.error('KEY ERROR: %s' % ke)
except setup.ClientError as ce:
action = '%s %s' % (
method, r.get('path', 'ui_id' if 'ui_id' in r else ''))
self.send_json({'%s' % ce: ce.status, 'action': action})
return
except Exception as e:
from traceback import print_stack
print_stack(e)
self.send_json({'INTERNAL ERROR': 500})
LOG.error('EXCEPTION: %s' % e)
self.terminate()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment