@luminati-io/luminati-proxy
Version:
A configurable local proxy for brightdata.com
391 lines (382 loc) • 14.2 kB
JavaScript
// LICENSE_CODE ZON ISC
; /*jslint react:true, es6:true*/
import React from 'react';
import _ from 'lodash4';
import {
Modal,
Tooltip,
Button,
} from 'uikit';
import Pure_component from '/www/util/pub/pure_component.js';
import etask from '../../../util/etask.js';
import date from '../../../util/date.js';
import {
Labeled_section,
Warning,
} from '../common.js';
import {get_form_toggle_transform} from '../util.js';
import {main as Api} from '../api.js';
import {Input} from './controls.js';
import {T} from './i18n.js';
import Tab_group from './tab_group.js';
const {assign} = Object;
const remote_field = 'logs_settings';
const S3_DEF_TARGET = 'logs/pm/';
const {Popup} = Modal;
const Test_btn = ({on_test, tip='Test aggregator', t})=>
<Tooltip tooltip={t(tip)}>
<Button
onFocus={e=>e.stopPropagation()}
onClick={on_test}
size="xs"
text={t('Test')}
/>
</Tooltip>;
const Webhook_tab = ({set, settings, test, t})=>{
const {url, username, password, use_ssl} = settings;
const ssl_disabled = !username || !password;
if (ssl_disabled && use_ssl)
set('use_ssl')(false);
return <React.Fragment>
<div className="inputs_container">
<div className="aggr_url">
<Input val={url} type="string"
placeholder={t('Logs aggregator url')}
on_change_wrapper={set('url')}
/>
</div>
<Test_btn tip="Test aggregator url" t={t} on_test={test}/>
</div>
<div className="inputs_container">
<div className="cred_first">
<Input val={username} placeholder={t('Username')}
on_change_wrapper={set('username')} type="string" />
</div>
<div className="cred_second">
<Input val={password} placeholder={t('Password')}
type="password" on_change_wrapper={set('password')} />
</div>
</div>
<div className="use_limit">
<Labeled_section
small
label_variant="base"
label={t('Use SSL')}
tooltip={t('Use SSL to save logs')}
type="toggle"
on_change_wrapper={set('use_ssl')}
val={use_ssl}
/>
</div>
</React.Fragment>;
};
const Datadog_tab = ({set, settings, test, t})=>{
const {port, token, host, tags, source} = settings;
return <React.Fragment>
<div className="inputs_container">
<div className="aggr_url">
<Input val={token} placeholder={t(`Datadog API key or token`)}
on_change_wrapper={set('token')} type="string" />
</div>
<Test_btn t={t} on_test={test}/>
</div>
<div className="inputs_container">
<div className="input_main_sub">
<Input val={host} type="string"
placeholder={t('Host (optional)')}
on_change_wrapper={set('host')} />
</div>
<div className="input_second">
<Input placeholder={t('Port (optional)')} val={port}
on_change_wrapper={set('Port')} type="string" />
</div>
</div>
<div className="inputs_container">
<div className="input_main_sub">
<Input val={tags} placeholder={t('Tags')}
on_change_wrapper={set('tags')} type="string" />
</div>
<div className="input_second">
<Input placeholder={t('Integration name')} val={source}
on_change_wrapper={set('source')} type="string" />
</div>
</div>
</React.Fragment>;
};
const Logzio_tab = ({set, settings, test, t})=>
<React.Fragment>
<div className="inputs_container">
<div className="aggr_url">
<Input placeholder={t('Host, default listener.logz.io')}
on_change_wrapper={set('host')} type="string"
val={settings.host} />
</div>
<Test_btn t={t} on_test={test}/>
</div>
<div className="inputs_container">
<div className="input_main">
<Input val={settings.token} placeholder={t('Token')}
on_change_wrapper={set('token')} type="string" />
</div>
<div className="input_second">
<Input val={settings.port} on_change_wrapper={set('port')}
placeholder={t('Port, default 8071')} type="number" />
</div>
</div>
<div className="inputs_container">
<div className="input_main_sub">
<Input placeholder={t('Log type for parsing')}
val={settings.source} on_change_wrapper={set('source')}
type="string" />
</div>
</div>
</React.Fragment>;
const build_s3_file_path = (target, compress, group_by_day)=>{
const ext = compress ? '.gz' : '';
const tgt = target || S3_DEF_TARGET;
const slash = !tgt.endsWith('/') ? '/' : '';
const file = group_by_day ? '%H:%M' : '%Y-%m-%d_%H:%M';
const group = group_by_day ? '%Y-%m-%d/' : '';
return date.strftime(`${tgt}${slash}${group}brd_test_${file}`
+`.log${ext}`, date());
};
const S3_tab = ({set, settings, test, t})=>{
const {bucket, access_key, secret_key, target, tag_type,
tag_project, compress, encryption, group_by_day,
rotation_hour} = settings;
const test_msg = `Pleace check your bucket ${bucket} for file`
+` ${build_s3_file_path(target, compress, group_by_day)}`;
const target_tt = t('Target path in which the log is uploaded')
+', default '+S3_DEF_TARGET;
return <React.Fragment>
<div className="inputs_container">
<div className="aggr_url">
<Input val={bucket} placeholder={t('AWS S3 Bucket name')}
on_change_wrapper={set('bucket')} type="string" />
</div>
<Test_btn t={t} on_test={()=>test(test_msg)}/>
</div>
<div className="inputs_container">
<div className="input_half">
<Input val={access_key} placeholder={t('AWS access key')}
on_change_wrapper={set('access_key')} type="string" />
</div>
<div className="input_half_sub">
<Input val={secret_key} placeholder={t('AWS secret key')}
on_change_wrapper={set('secret_key')} type="string" />
</div>
</div>
<div className="inputs_container">
<div className="input_full">
<Input val={target} type="string"
placeholder={target_tt}
on_change_wrapper={set('target')} />
</div>
</div>
<div className="inputs_container">
<div className="input_half">
<Input val={tag_type} placeholder={t('Tag type')}
on_change_wrapper={set('tag_type')} type="string" />
</div>
<div className="input_half_sub">
<Input val={tag_project} placeholder={t('Tag project')}
on_change_wrapper={set('tag_project')} type="string" />
</div>
</div>
<div className="use_limit">
<Labeled_section
w20
label_variant="base"
label={t('Group by day')}
tooltip={t('Group objects by day')}
type="toggle"
on_change_wrapper={set('group_by_day')}
val={group_by_day}
/>
</div>
<div className="use_limit">
<Labeled_section
w20
label_variant="base"
label={t('Rotate every hour')}
tooltip={t(`Rotate objects every hour (default 10 min)`)}
type="toggle"
on_change_wrapper={set('rotation_hour')}
val={rotation_hour}
/>
</div>
<div className="use_limit">
<Labeled_section
w20
label_variant="base"
label={t('Use compression')}
tooltip={t(`Files will be gzipped before uploading`)}
type="toggle"
on_change_wrapper={set('compress')}
val={compress}
/>
</div>
<div className="use_limit">
<Labeled_section
w20
label_variant="base"
label={t('Use encryption')}
tooltip={t(`The server side encryption AES256 algorithm
used when storing objects`)}
type="toggle"
on_change_wrapper={set('encryption')}
val={encryption}
/>
</div>
</React.Fragment>;
};
const all_tabs = [
{
id: 'custom',
text: 'Webhook',
element: Webhook_tab,
},
{
id: 'datadog',
text: 'Datadog',
element: Datadog_tab,
},
{
id: 'logzio',
text: 'Logz.io',
element: Logzio_tab,
},
{
id: 's3',
text: 'AWS S3',
element: S3_tab,
},
];
export default class Logs_settings_modal extends Pure_component {
constructor(props){
super(props);
this.state = {
is_submit_disabled: false,
use_limit: false,
cur_tab: 'custom',
logs_num: 0,
error: '',
remote: {},
saved_type: '',
};
this.tabs = all_tabs
.map(t=>({onClick: ()=>this.set_const('cur_tab', t.id), ...t}));
}
componentDidUpdate(prev_props){
if (prev_props.show!=this.props.show)
this.reset_state();
}
test_remote(msg){
let _this = this, {cur_tab, remote} = this.state;
return etask(function*(){
const test_res = yield Api.json.post('test_logs_remote',
assign({}, remote, {type: cur_tab}));
if (!test_res?.success)
return _this.setState({error: test_res.error});
_this.setState({is_submit_disabled: false, info: msg||false});
});
}
reset_state = ()=>{
const {remote_enabled, logs_disabled_num, logs_enabled_num,
settings} = this.props;
const logs_settings = settings||{};
this.setState({
saved_type: logs_settings.type,
logs_num: remote_enabled ? logs_disabled_num : logs_enabled_num,
use_limit: remote_enabled,
is_submit_disabled: remote_enabled,
remote: logs_settings,
cur_tab: logs_settings.type || 'custom',
});
};
get set_def_state(){
return {
is_submit_disabled: this.state.use_limit,
error: '',
info: '',
};
}
set_const = (field, val)=>this.set(field)(val);
set = field=>val=>this.setState({[field]: val, ...this.set_def_state});
set_remote = type=>field=>val=>this.setState({is_submit_disabled: true,
remote: assign({}, this.state.remote, {[field]: val, type}),
error: '', info: ''});
ch_use_limit = val=>this.setState({use_limit: val,
is_submit_disabled: val, error: '', info: '', logs_num: val ?
this.props.logs_disabled_num : this.props.logs_enabled_num});
save = ()=>{
const s = this.state;
let settings = [
{field: 'logs', value: s.logs_num, opt: {number: 1}},
{field: remote_field, value: {}},
];
let sid = settings.findIndex(st=>st.field==remote_field);
if (s.use_limit)
settings[sid].value = assign({}, s.remote, {type: s.cur_tab});
else if (this.props.settings?.type)
settings[sid].value = assign({}, {disable: true});
this.props.on_save(settings);
};
get_tab = _.memoize(cur_tab=>
this.tabs.find(t=>t.id==cur_tab)||this.tabs[0]);
get content(){
const {logs_data} = this.props;
const {use_limit, logs_num, cur_tab, error, remote, info} = this.state;
return <T>{t=><>
<div className="use_limit">
<Labeled_section
short
label_variant="base"
label={t('Use remote logs aggregator')}
tooltip={t(`Save logs locally or use remote aggregator`)}
type="toggle"
on_change_wrapper={this.ch_use_limit}
val={use_limit}
/>
</div>
{use_limit && <div className='logs_settings_modal_tabs'>
<Tab_group tabs={this.tabs} selected={cur_tab}
variant='contain' wide />
{React.createElement(this.get_tab(cur_tab).element, {
set: this.set_remote(cur_tab),
settings: remote,
test: this.test_remote.bind(this),
t
})}
</div>}
{!use_limit && <div className="inputs_container">
<Labeled_section
short
label_variant="base"
label={t('Save request logs')}
tooltip={this.props.tooltip}
type="toggle"
toggle_transform={get_form_toggle_transform(logs_data)}
on_change_wrapper={this.set('logs_num')}
val={logs_num}
/>
</div>}
{info && <Warning text={info} />}
{error && <Warning text={error} />}
</>}</T>;
}
render(){
return <Popup
show={this.props.show}
onOk={this.save}
okLabel="Save"
cancelLabel="Dismiss"
okDisabled={this.state.is_submit_disabled}
onCancel={this.props.on_hide}
title="Logs settings"
content={this.content}
shadow="sm"
size="lg"
/>;
}
}