From d67c200af7774c91d28786ef5b45924fe2c328f8 Mon Sep 17 00:00:00 2001 From: Mickael KERJEAN Date: Wed, 11 Apr 2018 23:55:39 +1000 Subject: [PATCH] bugfix (app): fix server side issues and proper error handling --- client/assets/css/reset.scss | 2 ++ client/components/breadcrumb.js | 14 +++++--- client/components/breadcrumb.scss | 6 ++-- client/helpers/ajax.js | 52 +++++++++++++++++----------- client/model/session.js | 15 +++++--- client/pages/viewerpage/ide.js | 2 +- client/pages/viewerpage/menubar.scss | 2 +- config_server.js | 2 +- server/ctrl/files.js | 2 +- server/ctrl/session.js | 10 +++--- server/utils/crypto.js | 4 +-- 11 files changed, 68 insertions(+), 43 deletions(-) diff --git a/client/assets/css/reset.scss b/client/assets/css/reset.scss index 2b9a27ae..9bb0e78c 100644 --- a/client/assets/css/reset.scss +++ b/client/assets/css/reset.scss @@ -13,6 +13,8 @@ --super-light: #f4f4f4; --error: #f26d6d; --success: #63d9b1; + + --dark: #313538; } html { diff --git a/client/components/breadcrumb.js b/client/components/breadcrumb.js index c8249f17..55565edb 100644 --- a/client/components/breadcrumb.js +++ b/client/components/breadcrumb.js @@ -115,9 +115,15 @@ export class PathElementWrapper extends React.Component { super(props); } - limitSize(str){ - if(str.length > 27){ - return str.substring(0,20)+'...'; + limitSize(str, is_highlight = false){ + if(is_highlight === true){ + if(str.length > 30){ + return str.substring(0,12).trim()+'...'+str.substring(str.length - 10, str.length).trim(); + } + }else{ + if(str.length > 27){ + return str.substring(0,20).trim()+'...'; + } } return str; } @@ -135,7 +141,7 @@ export class PathElementWrapper extends React.Component { ... - {this.limitSize(this.props.path.label)} + {this.limitSize(this.props.path.label, true)} diff --git a/client/components/breadcrumb.scss b/client/components/breadcrumb.scss index 1a6560ad..a52dca2a 100644 --- a/client/components/breadcrumb.scss +++ b/client/components/breadcrumb.scss @@ -39,10 +39,12 @@ display: inline-block; .label{color: var(--color);padding: 2px 5px;} a.label{ + position: relative; color: var(--light); span.title{ position: absolute; - background: var(--color); + left: 0; + background: var(--dark); color: white; font-size: 0.8em; opacity: 0; @@ -50,7 +52,7 @@ border-radius: 2px; white-space: nowrap; padding: 3px 10px!important; - margin: 5px 0px 5px -5px; + margin: 25px 0px 5px 0px; } } diff --git a/client/helpers/ajax.js b/client/helpers/ajax.js index 033b3381..c0b59ca5 100644 --- a/client/helpers/ajax.js +++ b/client/helpers/ajax.js @@ -10,8 +10,6 @@ export function http_get(url, type = 'json'){ let data = JSON.parse(xhr.responseText); if(data.status === 'ok'){ done(data); - }else if(data.status === 'redirect'){ - if(data.to === 'logout'){location.pathname = "/logout";} }else{ err(data); } @@ -22,11 +20,7 @@ export function http_get(url, type = 'json'){ done(xhr.responseText); } }else{ - if(navigator.onLine === false){ - err({status: xhr.status, code: "CONNECTION_LOST", message: 'Ooups! Looks like your internet has gone away'}); - }else{ - err({status: xhr.status, message: xhr.responseText || 'Oups! Something went wrong'}); - } + handle_error_response(xhr, err); } } } @@ -52,8 +46,6 @@ export function http_post(url, data, type = 'json'){ let data = JSON.parse(xhr.responseText); if(data.status === 'ok'){ done(data); - }else if(data.status === 'redirect'){ - if(data.to === 'logout'){location.pathname = "/logout";} }else{ err(data); } @@ -61,11 +53,7 @@ export function http_post(url, data, type = 'json'){ err({message: 'oups', trace: error}); } }else{ - if(navigator.onLine === false){ - err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'}); - }else{ - err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'}); - } + handle_error_response(xhr, err); } } } @@ -84,8 +72,6 @@ export function http_delete(url){ let data = JSON.parse(xhr.responseText); if(data.status === 'ok'){ done(data); - }else if(data.status === 'redirect'){ - if(data.to === 'logout'){location.pathname = "/logout";} }else{ err(data); } @@ -93,14 +79,38 @@ export function http_delete(url){ err({message: 'oups', trace: error}); } }else{ - if(navigator.onLine === false){ - err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'}); - }else{ - err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'}); - } + handle_error_response(xhr, err); } } } xhr.send(null); }); } + + + +function handle_error_response(xhr, err){ + let message = (function(content){ + let message = content; + try{ + message = JSON.parse(content)['message']; + }catch(err){} + return message; + })(xhr.responseText); + + if(xhr.status === 500){ + err({message: message || "Oups something went wrong with our servers"}) + }else if(xhr.status === 401){ + if(location.pathname !== '/login'){ location.pathname = "/login"; } + err({message: message || "Authentication error"}); + }else if(xhr.status === 403){ + err({message: message || "You can\'t do that"}); + }else if(xhr.status === 413){ + err({message: message || "Payload too large"}); + }else if(navigator.onLine === false){ + err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'}); + }else{ + err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'}); + } + +} diff --git a/client/model/session.js b/client/model/session.js index a7ed29a6..d8130bfd 100644 --- a/client/model/session.js +++ b/client/model/session.js @@ -3,16 +3,19 @@ import { http_get, http_post, http_delete } from '../helpers/'; class SessionManager{ isLogged(){ let url = '/api/session' - return http_get(url); + return http_get(url) + .then(data => data.result); } url(type){ if(type === 'dropbox'){ let url = '/api/session/auth/dropbox'; - return http_get(url); + return http_get(url) + .then(data => data.result); }else if(type === 'gdrive'){ let url = '/api/session/auth/gdrive'; - return http_get(url); + return http_get(url) + .then(data => data.result); }else{ return Promise.error({message: 'not authorization backend for: '+type, code: 'UNKNOWN_PROVIDER'}) } @@ -20,12 +23,14 @@ class SessionManager{ authenticate(params){ let url = '/api/session'; - return http_post(url, params); + return http_post(url, params) + .then(data => data.result); } logout(){ let url = '/api/session'; - return http_delete(url); + return http_delete(url) + .then(data => data.result); } } diff --git a/client/pages/viewerpage/ide.js b/client/pages/viewerpage/ide.js index ff8c104f..f81f12b9 100644 --- a/client/pages/viewerpage/ide.js +++ b/client/pages/viewerpage/ide.js @@ -40,7 +40,7 @@ export class IDE extends React.Component { - + diff --git a/client/pages/viewerpage/menubar.scss b/client/pages/viewerpage/menubar.scss index 0b1b7b59..620370d4 100644 --- a/client/pages/viewerpage/menubar.scss +++ b/client/pages/viewerpage/menubar.scss @@ -1,5 +1,5 @@ .component_menubar{ - background: #313538; + background: var(--dark); color: #f1f1f1; border-bottom: 1px solid var(--color); diff --git a/config_server.js b/config_server.js index ad1a14a9..b0874bbb 100644 --- a/config_server.js +++ b/config_server.js @@ -22,5 +22,5 @@ module.exports = { clientID: "dropbox_client_id", redirectURI: "application_url/login" }, - secret_key: 'not_so_secret_key' + secret_key: process.env.SECRET_KEY || 'not_so_secret_key' } diff --git a/server/ctrl/files.js b/server/ctrl/files.js index 73a87921..0286e6d4 100644 --- a/server/ctrl/files.js +++ b/server/ctrl/files.js @@ -11,7 +11,7 @@ app.use(function(req, res, next){ if(req.cookies.auth !== null){ return next(); }else{ - return res.send({status: 'redirect', to: 'logout'}); + return res.status(401).send({status: "error", message: "You need to authenticate first"}); } }); diff --git a/server/ctrl/session.js b/server/ctrl/session.js index 01da8952..966293d2 100644 --- a/server/ctrl/session.js +++ b/server/ctrl/session.js @@ -24,7 +24,7 @@ app.post('/', function(req, res){ }; const cookie = crypto.encrypt(persist); if(Buffer.byteLength(cookie, 'utf-8') > 4096){ - res.send({status: 'error', message: 'we can\'t authenticate you', }) + res.status(413).send({status: 'error', message: 'we can\'t authenticate you', }) }else{ res.cookie('auth', crypto.encrypt(persist), { maxAge: 365*24*60*60*1000, httpOnly: true, path: "/api/" }); res.send({status: 'ok'}); @@ -38,7 +38,7 @@ app.post('/', function(req, res){ } return t; } - res.send({status: 'error', message: message(err), code: err.code}); + res.status(401).send({status: 'error', message: message(err), code: err.code}); }); }); @@ -48,16 +48,16 @@ app.delete('/', function(req, res){ // TODO in May 2019: remove the line below which was inserted to mitigate a cookie migration issue. res.clearCookie("auth"); // the issue was a change in the cookie path which would have make // impossible for an existing user to logout - res.send({status: 'ok'}) + res.send({status: 'ok'}); }); app.get('/auth/:id', function(req, res){ Session.auth({type: req.params.id}) .then((url) => { - res.send({status: 'ok', result: url}) + res.send({status: 'ok', result: url}); }) .catch((err) => { - res.send({status: 'error', message: 'can\'t get authorization url', trace: err}) + res.status(404).send({status: 'error', message: 'can\'t get authorization url', trace: err}); }); }); diff --git a/server/utils/crypto.js b/server/utils/crypto.js index 4a74cb2b..e2837f8c 100644 --- a/server/utils/crypto.js +++ b/server/utils/crypto.js @@ -1,6 +1,6 @@ const crypto = require('crypto'), - algorithm = 'aes-256-cbc', - password = require('../../config_server')['secret_key']; + algorithm = 'aes-256-cbc', + password = require('../../config_server')['secret_key']; module.exports = { encrypt: function(obj){