@luminati-io/luminati-proxy
Version:
A configurable local proxy for luminati.io
269 lines (260 loc) • 9.93 kB
JavaScript
// LICENSE_CODE ZON ISC
; /*jslint browser:true, react:true, es6:true*/
import Pure_component from '/www/util/pub/pure_component.js';
import React from 'react';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
import {withRouter, Switch, BrowserRouter, Route} from 'react-router-dom';
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import 'flag-icon-css/css/flag-icon.css';
import 'es6-shim';
import setdb from '../../util/setdb.js';
import ajax from '../../util/ajax.js';
import etask from '../../util/etask.js';
import zurl from '../../util/url.js';
import './css/app.less';
import Proxy_edit from './proxy_edit/index.js';
import Howto from './howto.js';
import Nav from './nav.js';
import Login from './login.js';
import Overview from './overview.js';
import Config from './config.js';
import Settings from './settings.js';
import Proxy_add from './proxy_add.js';
import Whitelist_ips from './whitelist_ips.js';
import {Logs, Dock_logs} from './logs.js';
import Enable_ssl_modal from './common/ssl_modal.js';
import Api_url_modal from './common/api_url_modal.js';
import Error_boundry from './common/error_boundry.js';
import {Modal} from './common/modals.js';
import {report_exception} from './util.js';
window.setdb = setdb;
setdb.setMaxListeners(50);
const App = withRouter(class App extends Pure_component {
componentDidMount(){
setdb.set('head.save_settings', this.save_settings);
const _this = this;
this.etask(function*(){
const version = yield ajax.json({url: '/api/version'});
setdb.set('head.version', version.version);
setdb.set('head.is_upgraded', version.is_upgraded);
setdb.set('head.backup_exist', version.backup_exist);
setdb.set('head.argv', version.argv);
});
this.etask(function*(){
this.on('uncaught', e=>_this.etask(function*(){
yield report_exception(e, 'app.App.componentDidMount');
}));
const url_o = zurl.parse(document.location.href);
const qs_o = zurl.qs_parse((url_o.search||'').substr(1));
if (qs_o.lpm_token)
{
yield window.fetch('/api/cloud_auth', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({lpm_token: qs_o.lpm_token}),
});
}
const mode = yield window.fetch('/api/mode');
let block_ip;
if (block_ip = mode.headers.get('x-lpm-block-ip'))
{
setdb.set('head.blocked_ip', block_ip);
return _this.props.history.replace('/whitelist_ips');
}
_this.load_data();
if (mode.headers.get('x-lpm-local-login'))
return _this.props.history.replace('/login');
const data = yield mode.json();
if (data.logged_in)
{
if (!['/login', '/whitelist_ips'].includes(
_this.props.location.pathname))
{
return;
}
return _this.props.history.replace('/overview');
}
if (_this.props.location.pathname=='/login')
return;
return _this.props.history.replace({
pathname: '/login',
search: _this.props.location.search,
});
});
}
load_data = ()=>this.etask(function*(){
const errors = [];
const err_handler = msg=>etask.fn(function*(e){
errors.push(`${msg}: ${e.message}`);
yield report_exception(e, 'app.App.componentDidMount.load_data');
});
this.spawn(etask(function*(){
this.on('uncaught', err_handler('Error fetching locations'));
const locations = yield ajax.json({url: '/api/all_locations'});
setdb.set('head.locations', locations);
}));
this.spawn(etask(function*(){
this.on('uncaught', err_handler('Error fetching carriers'));
const carriers = yield ajax.json({url: '/api/all_carriers'});
setdb.set('head.carriers', carriers);
}));
etask(function*(){
const settings = yield ajax.json({url: '/api/settings'});
setdb.set('head.settings', settings);
});
etask(function*(){
const conn = yield ajax.json({url: '/api/conn'});
setdb.set('head.conn', conn);
});
etask(function*(){
const version = yield ajax.json({url: '/api/last_version'});
setdb.set('head.ver_last', version);
});
etask(function*(){
const defaults = yield ajax.json({url: '/api/defaults'});
setdb.set('head.defaults', defaults);
});
etask(function*(){
const node = yield ajax.json({url: '/api/node_version'});
setdb.set('head.ver_node', node);
});
etask(function*(){
const proxies = yield ajax.json({url: '/api/proxies_running'});
setdb.set('head.proxies_running', proxies);
});
etask(function*(){
const consts = yield ajax.json({url: '/api/consts'});
setdb.set('head.consts', consts);
});
etask(function*(){
const zones = yield ajax.json({url: '/api/zones'});
setdb.set('ws.zones', zones);
});
etask(function*(){
const w = yield ajax.json({url: '/api/tls_warning'});
setdb.set('ws.tls_warning', w);
});
yield this.wait_child('all');
if (errors.length)
setdb.set('head.app_errors', errors);
});
save_settings = settings=>{
return this.etask(function*(){
const raw = yield window.fetch('/api/settings', {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(settings),
});
if (raw.status!=200)
return {err: yield raw.text()};
const new_settings = yield raw.json();
setdb.set('head.settings', new_settings);
return new_settings;
});
};
render(){
return <div className="page_wrapper">
<Enable_ssl_modal/>
<Api_url_modal/>
<Old_modals/>
<Switch>
<Route path="/login" exact component={Login}/>
<Route path="/whitelist_ips" exact component={Whitelist_ips}/>
<Route path="/dock_logs" exact component={Dock_logs}/>
<Route path="/" component={Page}/>
</Switch>
</div>;
}
});
const general_modals_info = [
{
id: 'restarting',
title: 'Restarting...',
body: 'Please wait. The page will be reloaded automatically once the '
+'application has restarted.',
},
{
id: 'missing_root_perm',
title: 'LPM process is not running with root permissions',
body: "You can't upgrade LPM from the UI because it's not running "
+'with root permission. You have to close the process in the '
+'terminal and run <code>sudo luminati --upgrade</code>',
},
{
id: 'upgrading',
title: 'Luminati Proxy Manager is upgrading',
body: 'Please wait...',
},
{
id: 'downgrading',
title: 'Luminati Proxy Manager is downgrading',
body: 'Please wait...',
},
{
id: 'shutdown',
title: 'Shutdown',
body: 'The application has been shut down. To restart, please run it '
+'manually and reload this page.',
},
];
const General_old_modals = ()=>
general_modals_info.map(({id, title, body: __html})=>
<div key={id} id={id} className="modal fade" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">{title}</h4>
</div>
<div className="modal-body" dangerouslySetInnerHTML={{__html}}/>
<div className="modal-footer"/>
</div>
</div>
</div>);
const Old_modals = ()=>
<div className="old_modals">
<General_old_modals/>
<Modal id="fetching_chrome_modal"
title="Downloading Chromium. Please wait..." no_cancel_btn>
</Modal>
<Modal id="applying_config"
title="Synchronizing LPM configuration. Please wait..." no_cancel_btn>
</Modal>
</div>;
class Page extends Pure_component {
state = {settings: {}};
componentDidMount(){
this.setdb_on('head.settings', settings=>
settings && this.setState({settings}));
}
render(){
const {settings} = this.state;
const {zagent} = settings;
return <div>
<Nav/>
<Proxy_add settings={settings}/>
<div className={classnames('page_body vbox', {zagent})}>
<Error_boundry>
<Switch>
<Route path="/overview" exact component={Overview}/>
<Route path="/proxy/:port" component={Proxy_edit}/>
<Route path="/howto/:option?/:suboption?" exact
component={Howto}/>
<Route path="/logs" exact component={Logs}/>
<Route path="/config" exact component={Config}/>
<Route path="/settings" exact component={Settings}/>
<Route path="/" component={Overview}/>
</Switch>
</Error_boundry>
</div>
</div>;
}
}
const Root = ()=>
<BrowserRouter>
<Switch>
<Route path="/" component={App}/>
</Switch>
</BrowserRouter>;
ReactDOM.render(<Root/>, document.getElementById('react_root'));