mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-02 03:54:59 +08:00
bugfix (app): fix server side issues and proper error handling
This commit is contained in:
@ -13,6 +13,8 @@
|
|||||||
--super-light: #f4f4f4;
|
--super-light: #f4f4f4;
|
||||||
--error: #f26d6d;
|
--error: #f26d6d;
|
||||||
--success: #63d9b1;
|
--success: #63d9b1;
|
||||||
|
|
||||||
|
--dark: #313538;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
|||||||
@ -115,9 +115,15 @@ export class PathElementWrapper extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
limitSize(str){
|
limitSize(str, is_highlight = false){
|
||||||
if(str.length > 27){
|
if(is_highlight === true){
|
||||||
return str.substring(0,20)+'...';
|
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;
|
return str;
|
||||||
}
|
}
|
||||||
@ -135,7 +141,7 @@ export class PathElementWrapper extends React.Component {
|
|||||||
<NgIf cond={this.props.path.minify === true}>
|
<NgIf cond={this.props.path.minify === true}>
|
||||||
...
|
...
|
||||||
<span className="title">
|
<span className="title">
|
||||||
{this.limitSize(this.props.path.label)}
|
{this.limitSize(this.props.path.label, true)}
|
||||||
</span>
|
</span>
|
||||||
</NgIf>
|
</NgIf>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -39,10 +39,12 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
.label{color: var(--color);padding: 2px 5px;}
|
.label{color: var(--color);padding: 2px 5px;}
|
||||||
a.label{
|
a.label{
|
||||||
|
position: relative;
|
||||||
color: var(--light);
|
color: var(--light);
|
||||||
span.title{
|
span.title{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: var(--color);
|
left: 0;
|
||||||
|
background: var(--dark);
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@ -50,7 +52,7 @@
|
|||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding: 3px 10px!important;
|
padding: 3px 10px!important;
|
||||||
margin: 5px 0px 5px -5px;
|
margin: 25px 0px 5px 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,6 @@ export function http_get(url, type = 'json'){
|
|||||||
let data = JSON.parse(xhr.responseText);
|
let data = JSON.parse(xhr.responseText);
|
||||||
if(data.status === 'ok'){
|
if(data.status === 'ok'){
|
||||||
done(data);
|
done(data);
|
||||||
}else if(data.status === 'redirect'){
|
|
||||||
if(data.to === 'logout'){location.pathname = "/logout";}
|
|
||||||
}else{
|
}else{
|
||||||
err(data);
|
err(data);
|
||||||
}
|
}
|
||||||
@ -22,11 +20,7 @@ export function http_get(url, type = 'json'){
|
|||||||
done(xhr.responseText);
|
done(xhr.responseText);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(navigator.onLine === false){
|
handle_error_response(xhr, err);
|
||||||
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'});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,8 +46,6 @@ export function http_post(url, data, type = 'json'){
|
|||||||
let data = JSON.parse(xhr.responseText);
|
let data = JSON.parse(xhr.responseText);
|
||||||
if(data.status === 'ok'){
|
if(data.status === 'ok'){
|
||||||
done(data);
|
done(data);
|
||||||
}else if(data.status === 'redirect'){
|
|
||||||
if(data.to === 'logout'){location.pathname = "/logout";}
|
|
||||||
}else{
|
}else{
|
||||||
err(data);
|
err(data);
|
||||||
}
|
}
|
||||||
@ -61,11 +53,7 @@ export function http_post(url, data, type = 'json'){
|
|||||||
err({message: 'oups', trace: error});
|
err({message: 'oups', trace: error});
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(navigator.onLine === false){
|
handle_error_response(xhr, err);
|
||||||
err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'});
|
|
||||||
}else{
|
|
||||||
err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,8 +72,6 @@ export function http_delete(url){
|
|||||||
let data = JSON.parse(xhr.responseText);
|
let data = JSON.parse(xhr.responseText);
|
||||||
if(data.status === 'ok'){
|
if(data.status === 'ok'){
|
||||||
done(data);
|
done(data);
|
||||||
}else if(data.status === 'redirect'){
|
|
||||||
if(data.to === 'logout'){location.pathname = "/logout";}
|
|
||||||
}else{
|
}else{
|
||||||
err(data);
|
err(data);
|
||||||
}
|
}
|
||||||
@ -93,14 +79,38 @@ export function http_delete(url){
|
|||||||
err({message: 'oups', trace: error});
|
err({message: 'oups', trace: error});
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(navigator.onLine === false){
|
handle_error_response(xhr, err);
|
||||||
err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'});
|
|
||||||
}else{
|
|
||||||
err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xhr.send(null);
|
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'});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -3,16 +3,19 @@ import { http_get, http_post, http_delete } from '../helpers/';
|
|||||||
class SessionManager{
|
class SessionManager{
|
||||||
isLogged(){
|
isLogged(){
|
||||||
let url = '/api/session'
|
let url = '/api/session'
|
||||||
return http_get(url);
|
return http_get(url)
|
||||||
|
.then(data => data.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
url(type){
|
url(type){
|
||||||
if(type === 'dropbox'){
|
if(type === 'dropbox'){
|
||||||
let url = '/api/session/auth/dropbox';
|
let url = '/api/session/auth/dropbox';
|
||||||
return http_get(url);
|
return http_get(url)
|
||||||
|
.then(data => data.result);
|
||||||
}else if(type === 'gdrive'){
|
}else if(type === 'gdrive'){
|
||||||
let url = '/api/session/auth/gdrive';
|
let url = '/api/session/auth/gdrive';
|
||||||
return http_get(url);
|
return http_get(url)
|
||||||
|
.then(data => data.result);
|
||||||
}else{
|
}else{
|
||||||
return Promise.error({message: 'not authorization backend for: '+type, code: 'UNKNOWN_PROVIDER'})
|
return Promise.error({message: 'not authorization backend for: '+type, code: 'UNKNOWN_PROVIDER'})
|
||||||
}
|
}
|
||||||
@ -20,12 +23,14 @@ class SessionManager{
|
|||||||
|
|
||||||
authenticate(params){
|
authenticate(params){
|
||||||
let url = '/api/session';
|
let url = '/api/session';
|
||||||
return http_post(url, params);
|
return http_post(url, params)
|
||||||
|
.then(data => data.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(){
|
logout(){
|
||||||
let url = '/api/session';
|
let url = '/api/session';
|
||||||
return http_delete(url);
|
return http_delete(url)
|
||||||
|
.then(data => data.result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export class IDE extends React.Component {
|
|||||||
<MenuBar title={this.props.filename} download={this.props.url} />
|
<MenuBar title={this.props.filename} download={this.props.url} />
|
||||||
<Editor onSave={this.save.bind(this)} filename={this.props.filename} content={this.props.content} onChange={this.onContentUpdate.bind(this)} />
|
<Editor onSave={this.save.bind(this)} filename={this.props.filename} content={this.props.content} onChange={this.onContentUpdate.bind(this)} />
|
||||||
|
|
||||||
<ReactCSSTransitionGroup transitionName="fab" transitionLeave={true} transitionEnter={true} transitionAppear={true} transitionAppearTimeout="300" transitonEnterTimeout="300" transitionLeaveTimeout="200">
|
<ReactCSSTransitionGroup transitionName="fab" transitionLeave={true} transitionEnter={true} transitionAppear={true} transitionAppearTimeout={300} transitionEnterTimeout={300} transitionLeaveTimeout={200}>
|
||||||
<NgIf key={this.state.needSaving} cond={this.state.needSaving}>
|
<NgIf key={this.state.needSaving} cond={this.state.needSaving}>
|
||||||
<NgIf cond={!this.props.isSaving}>
|
<NgIf cond={!this.props.isSaving}>
|
||||||
<Fab onClick={this.save.bind(this)}><Icon name="save" style={{height: '100%', width: '100%'}}/></Fab>
|
<Fab onClick={this.save.bind(this)}><Icon name="save" style={{height: '100%', width: '100%'}}/></Fab>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
.component_menubar{
|
.component_menubar{
|
||||||
background: #313538;
|
background: var(--dark);
|
||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
border-bottom: 1px solid var(--color);
|
border-bottom: 1px solid var(--color);
|
||||||
|
|
||||||
|
|||||||
@ -22,5 +22,5 @@ module.exports = {
|
|||||||
clientID: "dropbox_client_id",
|
clientID: "dropbox_client_id",
|
||||||
redirectURI: "application_url/login"
|
redirectURI: "application_url/login"
|
||||||
},
|
},
|
||||||
secret_key: 'not_so_secret_key'
|
secret_key: process.env.SECRET_KEY || 'not_so_secret_key'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ app.use(function(req, res, next){
|
|||||||
if(req.cookies.auth !== null){
|
if(req.cookies.auth !== null){
|
||||||
return next();
|
return next();
|
||||||
}else{
|
}else{
|
||||||
return res.send({status: 'redirect', to: 'logout'});
|
return res.status(401).send({status: "error", message: "You need to authenticate first"});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ app.post('/', function(req, res){
|
|||||||
};
|
};
|
||||||
const cookie = crypto.encrypt(persist);
|
const cookie = crypto.encrypt(persist);
|
||||||
if(Buffer.byteLength(cookie, 'utf-8') > 4096){
|
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{
|
}else{
|
||||||
res.cookie('auth', crypto.encrypt(persist), { maxAge: 365*24*60*60*1000, httpOnly: true, path: "/api/" });
|
res.cookie('auth', crypto.encrypt(persist), { maxAge: 365*24*60*60*1000, httpOnly: true, path: "/api/" });
|
||||||
res.send({status: 'ok'});
|
res.send({status: 'ok'});
|
||||||
@ -38,7 +38,7 @@ app.post('/', function(req, res){
|
|||||||
}
|
}
|
||||||
return t;
|
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.
|
// 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
|
res.clearCookie("auth"); // the issue was a change in the cookie path which would have make
|
||||||
// impossible for an existing user to logout
|
// impossible for an existing user to logout
|
||||||
res.send({status: 'ok'})
|
res.send({status: 'ok'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/auth/:id', function(req, res){
|
app.get('/auth/:id', function(req, res){
|
||||||
Session.auth({type: req.params.id})
|
Session.auth({type: req.params.id})
|
||||||
.then((url) => {
|
.then((url) => {
|
||||||
res.send({status: 'ok', result: url})
|
res.send({status: 'ok', result: url});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.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});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const crypto = require('crypto'),
|
const crypto = require('crypto'),
|
||||||
algorithm = 'aes-256-cbc',
|
algorithm = 'aes-256-cbc',
|
||||||
password = require('../../config_server')['secret_key'];
|
password = require('../../config_server')['secret_key'];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
encrypt: function(obj){
|
encrypt: function(obj){
|
||||||
|
|||||||
Reference in New Issue
Block a user