Config page refactoring
This commit is contained in:
parent
460b044720
commit
f69b9c1887
4 changed files with 458 additions and 443 deletions
|
|
@ -30,34 +30,8 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div id="view"></div>
|
||||||
<div class="container-fluid">
|
<script type="text/javascript" src="config.js"></script>
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
<li><a href="/cockpit/@localhost/session-recording/index.html">Session Recording</a></li>
|
|
||||||
<li class="active">Configuration</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading"><span>General Configuration</span></div>
|
|
||||||
<div class="panel-body" id="sr_config"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading"><span>SSSD Configuration</span></div>
|
|
||||||
<div class="panel-body" id="sssd_config"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript" src="config.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
861
src/config.jsx
861
src/config.jsx
|
|
@ -16,442 +16,313 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
let cockpit = require("cockpit");
|
||||||
"use strict";
|
let React = require("react");
|
||||||
|
let ReactDOM = require("react-dom");
|
||||||
|
let json = require('comment-json');
|
||||||
|
let ini = require('ini');
|
||||||
|
|
||||||
let cockpit = require("cockpit");
|
class Config extends React.Component {
|
||||||
let React = require("react");
|
constructor(props) {
|
||||||
let ReactDOM = require("react-dom");
|
super(props);
|
||||||
let json = require('comment-json');
|
this.handleInputChange = this.handleInputChange.bind(this);
|
||||||
let ini = require('ini');
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
this.setConfig = this.setConfig.bind(this);
|
||||||
class Config extends React.Component {
|
this.fileReadFailed = this.fileReadFailed.bind(this);
|
||||||
constructor(props) {
|
this.readConfig = this.readConfig.bind(this);
|
||||||
super(props);
|
this.file = null;
|
||||||
this.handleInputChange = this.handleInputChange.bind(this);
|
this.config = null;
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.state = {
|
||||||
this.setConfig = this.setConfig.bind(this);
|
config_loaded: false,
|
||||||
this.fileReadFailed = this.fileReadFailed.bind(this);
|
file_error: false,
|
||||||
this.readConfig = this.readConfig.bind(this);
|
submitting: "none",
|
||||||
this.file = null;
|
shell: "",
|
||||||
this.config = null;
|
notice: "",
|
||||||
this.state = {
|
latency: "",
|
||||||
config_loaded: false,
|
payload: "",
|
||||||
file_error: false,
|
log_input: false,
|
||||||
submitting: "none",
|
log_output: true,
|
||||||
shell: "",
|
log_window: true,
|
||||||
notice: "",
|
limit_rate: "",
|
||||||
latency: "",
|
limit_burst: "",
|
||||||
payload: "",
|
limit_action: "",
|
||||||
log_input: false,
|
file_path: "",
|
||||||
log_output: true,
|
syslog_facility: "",
|
||||||
log_window: true,
|
syslog_priority: "",
|
||||||
limit_rate: "",
|
journal_augment: "",
|
||||||
limit_burst: "",
|
journal_priority: "",
|
||||||
limit_action: "",
|
writer: "",
|
||||||
file_path: "",
|
};
|
||||||
syslog_facility: "",
|
|
||||||
syslog_priority: "",
|
|
||||||
journal_augment: "",
|
|
||||||
journal_priority: "",
|
|
||||||
writer: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputChange(e) {
|
|
||||||
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
|
||||||
const name = e.target.name;
|
|
||||||
const state = {};
|
|
||||||
state[name] = value;
|
|
||||||
this.setState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit(event) {
|
|
||||||
this.setState({submitting:"block"});
|
|
||||||
let config = {
|
|
||||||
shell: this.state.shell,
|
|
||||||
notice: this.state.notice,
|
|
||||||
latency: parseInt(this.state.latency),
|
|
||||||
payload: parseInt(this.state.payload),
|
|
||||||
log: {
|
|
||||||
input: this.state.log_input,
|
|
||||||
output: this.state.log_output,
|
|
||||||
window: this.state.log_window,
|
|
||||||
},
|
|
||||||
limit: {
|
|
||||||
rate: parseInt(this.state.limit_rate),
|
|
||||||
burst: parseInt(this.state.limit_burst),
|
|
||||||
action: this.state.limit_action,
|
|
||||||
},
|
|
||||||
file: {
|
|
||||||
path: this.state.file_path,
|
|
||||||
},
|
|
||||||
syslog: {
|
|
||||||
facility: this.state.syslog_facility,
|
|
||||||
priority: this.state.syslog_priority,
|
|
||||||
},
|
|
||||||
journal: {
|
|
||||||
priority: this.state.journal_priority,
|
|
||||||
augment: this.state.journal_augment
|
|
||||||
},
|
|
||||||
writer: this.state.writer
|
|
||||||
};
|
|
||||||
this.file.replace(config).done(() => {
|
|
||||||
this.setState({submitting:"none"});
|
|
||||||
})
|
|
||||||
.fail((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfig(data) {
|
|
||||||
delete data.configuration;
|
|
||||||
delete data.args;
|
|
||||||
var flattenObject = function(ob) {
|
|
||||||
var toReturn = {};
|
|
||||||
|
|
||||||
for (var i in ob) {
|
|
||||||
if (!ob.hasOwnProperty(i)) continue;
|
|
||||||
|
|
||||||
if ((typeof ob[i]) == 'object') {
|
|
||||||
var flatObject = flattenObject(ob[i]);
|
|
||||||
for (var x in flatObject) {
|
|
||||||
if (!flatObject.hasOwnProperty(x)) continue;
|
|
||||||
|
|
||||||
toReturn[i + '_' + x] = flatObject[x];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toReturn[i] = ob[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
};
|
|
||||||
let state = flattenObject(data);
|
|
||||||
state.config_loaded = true;
|
|
||||||
this.setState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfig() {
|
|
||||||
let proc = cockpit.spawn(["tlog-rec-session", "--configuration"]);
|
|
||||||
|
|
||||||
proc.stream((data) => {
|
|
||||||
this.setConfig(json.parse(data, null, true));
|
|
||||||
proc.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.fail((fail) => {
|
|
||||||
console.log(fail);
|
|
||||||
this.readConfig();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
readConfig() {
|
|
||||||
let parseFunc = function(data) {
|
|
||||||
return json.parse(data, null, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
let stringifyFunc = function(data) {
|
|
||||||
return json.stringify(data, null, true);
|
|
||||||
};
|
|
||||||
// needed for cockpit.file usage
|
|
||||||
let syntax_object = {
|
|
||||||
parse: parseFunc,
|
|
||||||
stringify: stringifyFunc,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.file = cockpit.file("/etc/tlog/tlog-rec-session.conf", {
|
|
||||||
syntax: syntax_object,
|
|
||||||
superuser: true,
|
|
||||||
});
|
|
||||||
/*
|
|
||||||
let promise = this.file.read();
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
if (data === null) {
|
|
||||||
this.fileReadFailed();
|
|
||||||
}
|
|
||||||
}).fail((data) => {
|
|
||||||
this.fileReadFailed(data);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
fileReadFailed(reason) {
|
|
||||||
console.log(reason);
|
|
||||||
this.setState({file_error: reason});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
this.getConfig();
|
|
||||||
this.readConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.config_loaded === false && this.state.file_error === false) {
|
|
||||||
return (
|
|
||||||
<div>Loading</div>
|
|
||||||
);
|
|
||||||
} else if (this.state.config_loaded === true && this.state.file_error === false) {
|
|
||||||
return (
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
|
||||||
<table className="form-table-ct col-sm-3">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="shell" className="control-label">Shell</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" id="shell" name="shell" value={this.state.shell}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="notice" className="control-label">Notice</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" id="notice" name="notice" value={this.state.notice}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="latency" className="control-label">Latency</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="number" step="1" id="latency" name="latency" value={this.state.latency}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="latency" className="control-label">Payload Size, bytes</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="number" step="1" id="payload" name="payload" value={this.state.payload}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="log_input" className="control-label">Log User's Input</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox" id="log_input" name="log_input" defaultChecked={this.state.log_input} onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="log_output" className="control-label">Log User's Output</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox" id="log_output" name="log_output" defaultChecked={this.state.log_output} onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="log_window" className="control-label">Log Window Resize</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox" id="log_window" name="log_window" defaultChecked={this.state.log_window} onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="limit_rate" className="control-label">Limit Rate, bytes/sec</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="number" step="1" id="limit_rate" name="limit_rate" value={this.state.limit_rate}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="limit_burst" className="control-label">Burst, bytes</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="number" step="1" id="limit_burst" name="limit_burst" value={this.state.limit_burst}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="limit_action" className="control-label">Logging Limit Action</label></td>
|
|
||||||
<td>
|
|
||||||
<select name="limit_action" id="limit_action" onChange={this.handleInputChange} value={this.state.limit_action} className="form-control">
|
|
||||||
<option value="" />
|
|
||||||
<option value="pass">Pass</option>
|
|
||||||
<option value="delay">Delay</option>
|
|
||||||
<option value="drop">Drop</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="file_path" className="control-label">File Path</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" id="file_path" name="file_path" defaultChecked={this.state.file_path}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="syslog_facility" className="control-label">Syslog Facility</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" id="syslog_facility" name="syslog_facility" value={this.state.syslog_facility}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="syslog_priority" className="control-label">Syslog Priority</label></td>
|
|
||||||
<td>
|
|
||||||
<select name="syslog_priority" id="syslog_priority" onChange={this.handleInputChange} value={this.state.syslog_priority} className="form-control">
|
|
||||||
<option value="" />
|
|
||||||
<option value="info">Info</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="journal_priority" className="control-label">Journal Priority</label></td>
|
|
||||||
<td>
|
|
||||||
<select name="journal_priority" id="journal_priority" onChange={this.handleInputChange} value={this.state.journal_priority} className="form-control">
|
|
||||||
<option value="" />
|
|
||||||
<option value="info">Info</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="journal_augment" className="control-label">Journal Augment</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox" id="journal_augment" name="journal_augment" defaultChecked={this.state.journal_augment} onChange={this.handleInputChange} />
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top"><label htmlFor="writer" className="control-label">Writer</label></td>
|
|
||||||
<td>
|
|
||||||
<select name="writer" id="writer" onChange={this.handleInputChange} value={this.state.writer} className="form-control">
|
|
||||||
<option value="" />
|
|
||||||
<option value="journal">Journal</option>
|
|
||||||
<option value="syslog">Syslog</option>
|
|
||||||
<option value="file">File</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td className="top">
|
|
||||||
<button className="btn btn-default" type="submit">Save</button>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span style={{display: this.state.submitting}}>Saving...</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div className="alert alert-danger">
|
|
||||||
<span className="pficon pficon-error-circle-o" />
|
|
||||||
<p><strong>There is no configuration file of tlog present in your system.</strong></p>
|
|
||||||
<p>Please, check the /etc/tlog/tlog-rec-session.conf or if tlog is installed.</p>
|
|
||||||
<p><strong>{this.state.file_error}</strong></p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SssdConfig extends React.Component {
|
handleInputChange(e) {
|
||||||
constructor(props) {
|
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
||||||
super(props);
|
const name = e.target.name;
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
const state = {};
|
||||||
this.handleInputChange = this.handleInputChange.bind(this);
|
state[name] = value;
|
||||||
this.setConfig = this.setConfig.bind(this);
|
this.setState(state);
|
||||||
this.file = null;
|
}
|
||||||
this.state = {
|
|
||||||
scope: "",
|
|
||||||
users: "",
|
|
||||||
groups: "",
|
|
||||||
submitting: "none",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputChange(e) {
|
handleSubmit(event) {
|
||||||
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
this.setState({submitting:"block"});
|
||||||
const name = e.target.name;
|
let config = {
|
||||||
const state = {};
|
shell: this.state.shell,
|
||||||
state[name] = value;
|
notice: this.state.notice,
|
||||||
this.setState(state);
|
latency: parseInt(this.state.latency),
|
||||||
}
|
payload: parseInt(this.state.payload),
|
||||||
|
log: {
|
||||||
|
input: this.state.log_input,
|
||||||
|
output: this.state.log_output,
|
||||||
|
window: this.state.log_window,
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
rate: parseInt(this.state.limit_rate),
|
||||||
|
burst: parseInt(this.state.limit_burst),
|
||||||
|
action: this.state.limit_action,
|
||||||
|
},
|
||||||
|
file: {
|
||||||
|
path: this.state.file_path,
|
||||||
|
},
|
||||||
|
syslog: {
|
||||||
|
facility: this.state.syslog_facility,
|
||||||
|
priority: this.state.syslog_priority,
|
||||||
|
},
|
||||||
|
journal: {
|
||||||
|
priority: this.state.journal_priority,
|
||||||
|
augment: this.state.journal_augment
|
||||||
|
},
|
||||||
|
writer: this.state.writer
|
||||||
|
};
|
||||||
|
this.file.replace(config).done(() => {
|
||||||
|
this.setState({submitting:"none"});
|
||||||
|
})
|
||||||
|
.fail((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
setConfig(data) {
|
setConfig(data) {
|
||||||
console.log(data);
|
delete data.configuration;
|
||||||
const config = {...data['session_recording']};
|
delete data.args;
|
||||||
this.setState(config);
|
var flattenObject = function(ob) {
|
||||||
}
|
var toReturn = {};
|
||||||
|
|
||||||
componentWillMount() {
|
for (var i in ob) {
|
||||||
let syntax_object = {
|
if (!ob.hasOwnProperty(i)) continue;
|
||||||
parse: ini.parse,
|
|
||||||
stringify: ini.stringify
|
|
||||||
};
|
|
||||||
|
|
||||||
this.file = cockpit.file("/etc/sssd/conf.d/sssd-session-recording.conf", {
|
if ((typeof ob[i]) == 'object') {
|
||||||
syntax: syntax_object,
|
var flatObject = flattenObject(ob[i]);
|
||||||
superuser: true,
|
for (var x in flatObject) {
|
||||||
});
|
if (!flatObject.hasOwnProperty(x)) continue;
|
||||||
|
|
||||||
let promise = this.file.read();
|
toReturn[i + '_' + x] = flatObject[x];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toReturn[i] = ob[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
};
|
||||||
|
let state = flattenObject(data);
|
||||||
|
state.config_loaded = true;
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
promise.done(this.setConfig);
|
getConfig() {
|
||||||
|
let proc = cockpit.spawn(["tlog-rec-session", "--configuration"]);
|
||||||
|
|
||||||
promise.fail(function(error) {
|
proc.stream((data) => {
|
||||||
console.log(error);
|
this.setConfig(json.parse(data, null, true));
|
||||||
});
|
proc.close();
|
||||||
}
|
});
|
||||||
|
|
||||||
handleSubmit(e) {
|
proc.fail((fail) => {
|
||||||
this.setState({submitting:"block"});
|
console.log(fail);
|
||||||
const obj = {};
|
this.readConfig();
|
||||||
obj.session_recording = {};
|
});
|
||||||
obj.session_recording.scope = this.state.scope;
|
}
|
||||||
obj.session_recording.users = this.state.users;
|
|
||||||
obj.session_recording.groups = this.state.groups;
|
|
||||||
|
|
||||||
let _this = this;
|
readConfig() {
|
||||||
this.file.replace(obj).done(function() {
|
let parseFunc = function(data) {
|
||||||
_this.setState({submitting:"none"});
|
return json.parse(data, null, true);
|
||||||
})
|
};
|
||||||
.fail(function(error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
let stringifyFunc = function(data) {
|
||||||
|
return json.stringify(data, null, true);
|
||||||
|
};
|
||||||
|
// needed for cockpit.file usage
|
||||||
|
let syntax_object = {
|
||||||
|
parse: parseFunc,
|
||||||
|
stringify: stringifyFunc,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.file = cockpit.file("/etc/tlog/tlog-rec-session.conf", {
|
||||||
|
syntax: syntax_object,
|
||||||
|
superuser: true,
|
||||||
|
});
|
||||||
|
/*
|
||||||
|
let promise = this.file.read();
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
if (data === null) {
|
||||||
|
this.fileReadFailed();
|
||||||
|
}
|
||||||
|
}).fail((data) => {
|
||||||
|
this.fileReadFailed(data);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fileReadFailed(reason) {
|
||||||
|
console.log(reason);
|
||||||
|
this.setState({file_error: reason});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.getConfig();
|
||||||
|
this.readConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.config_loaded === false && this.state.file_error === false) {
|
||||||
|
return (
|
||||||
|
<div>Loading</div>
|
||||||
|
);
|
||||||
|
} else if (this.state.config_loaded === true && this.state.file_error === false) {
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<table className="info-table-ct col-md-12">
|
<table className="form-table-ct col-sm-3">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label htmlFor="scope">Scope</label></td>
|
<td className="top"><label htmlFor="shell" className="control-label">Shell</label></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="scope" id="scope" className="form-control"
|
<input type="text" id="shell" name="shell" value={this.state.shell}
|
||||||
value={this.state.scope}
|
|
||||||
onChange={this.handleInputChange} >
|
|
||||||
<option value="none">None</option>
|
|
||||||
<option value="some">Some</option>
|
|
||||||
<option value="all">All</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{this.state.scope === "some" &&
|
|
||||||
<tr>
|
|
||||||
<td><label htmlFor="users">Users</label></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" id="users" name="users"
|
|
||||||
value={this.state.users}
|
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
|
||||||
{this.state.scope === "some" &&
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><label htmlFor="groups">Groups</label></td>
|
<td className="top"><label htmlFor="notice" className="control-label">Notice</label></td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" id="groups" name="groups"
|
<input type="text" id="notice" name="notice" value={this.state.notice}
|
||||||
value={this.state.groups}
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
className="form-control" onChange={this.handleInputChange} />
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><button className="btn btn-default" type="submit">Save</button></td>
|
<td className="top"><label htmlFor="latency" className="control-label">Latency</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="number" step="1" id="latency" name="latency" value={this.state.latency}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="latency" className="control-label">Payload Size, bytes</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="number" step="1" id="payload" name="payload" value={this.state.payload}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="log_input" className="control-label">Log User's Input</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" id="log_input" name="log_input" defaultChecked={this.state.log_input} onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="log_output" className="control-label">Log User's Output</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" id="log_output" name="log_output" defaultChecked={this.state.log_output} onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="log_window" className="control-label">Log Window Resize</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" id="log_window" name="log_window" defaultChecked={this.state.log_window} onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="limit_rate" className="control-label">Limit Rate, bytes/sec</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="number" step="1" id="limit_rate" name="limit_rate" value={this.state.limit_rate}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="limit_burst" className="control-label">Burst, bytes</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="number" step="1" id="limit_burst" name="limit_burst" value={this.state.limit_burst}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="limit_action" className="control-label">Logging Limit Action</label></td>
|
||||||
|
<td>
|
||||||
|
<select name="limit_action" id="limit_action" onChange={this.handleInputChange} value={this.state.limit_action} className="form-control">
|
||||||
|
<option value="" />
|
||||||
|
<option value="pass">Pass</option>
|
||||||
|
<option value="delay">Delay</option>
|
||||||
|
<option value="drop">Drop</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="file_path" className="control-label">File Path</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="file_path" name="file_path" defaultChecked={this.state.file_path}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="syslog_facility" className="control-label">Syslog Facility</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="syslog_facility" name="syslog_facility" value={this.state.syslog_facility}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="syslog_priority" className="control-label">Syslog Priority</label></td>
|
||||||
|
<td>
|
||||||
|
<select name="syslog_priority" id="syslog_priority" onChange={this.handleInputChange} value={this.state.syslog_priority} className="form-control">
|
||||||
|
<option value="" />
|
||||||
|
<option value="info">Info</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="journal_priority" className="control-label">Journal Priority</label></td>
|
||||||
|
<td>
|
||||||
|
<select name="journal_priority" id="journal_priority" onChange={this.handleInputChange} value={this.state.journal_priority} className="form-control">
|
||||||
|
<option value="" />
|
||||||
|
<option value="info">Info</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="journal_augment" className="control-label">Journal Augment</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" id="journal_augment" name="journal_augment" defaultChecked={this.state.journal_augment} onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top"><label htmlFor="writer" className="control-label">Writer</label></td>
|
||||||
|
<td>
|
||||||
|
<select name="writer" id="writer" onChange={this.handleInputChange} value={this.state.writer} className="form-control">
|
||||||
|
<option value="" />
|
||||||
|
<option value="journal">Journal</option>
|
||||||
|
<option value="syslog">Syslog</option>
|
||||||
|
<option value="file">File</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="top">
|
||||||
|
<button className="btn btn-default" type="submit">Save</button>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span style={{display: this.state.submitting}}>Saving...</span>
|
<span style={{display: this.state.submitting}}>Saving...</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -460,9 +331,175 @@
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className="alert alert-danger">
|
||||||
|
<span className="pficon pficon-error-circle-o" />
|
||||||
|
<p><strong>There is no configuration file of tlog present in your system.</strong></p>
|
||||||
|
<p>Please, check the /etc/tlog/tlog-rec-session.conf or if tlog is installed.</p>
|
||||||
|
<p><strong>{this.state.file_error}</strong></p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.render(<Config />, document.getElementById('sr_config'));
|
class SssdConfig extends React.Component {
|
||||||
ReactDOM.render(<SssdConfig />, document.getElementById('sssd_config'));
|
constructor(props) {
|
||||||
}());
|
super(props);
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
this.handleInputChange = this.handleInputChange.bind(this);
|
||||||
|
this.setConfig = this.setConfig.bind(this);
|
||||||
|
this.file = null;
|
||||||
|
this.state = {
|
||||||
|
scope: "",
|
||||||
|
users: "",
|
||||||
|
groups: "",
|
||||||
|
submitting: "none",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputChange(e) {
|
||||||
|
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
||||||
|
const name = e.target.name;
|
||||||
|
const state = {};
|
||||||
|
state[name] = value;
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(data) {
|
||||||
|
const config = {...data['session_recording']};
|
||||||
|
this.setState(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
let syntax_object = {
|
||||||
|
parse: ini.parse,
|
||||||
|
stringify: ini.stringify
|
||||||
|
};
|
||||||
|
|
||||||
|
this.file = cockpit.file("/etc/sssd/conf.d/sssd-session-recording.conf", {
|
||||||
|
syntax: syntax_object,
|
||||||
|
superuser: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let promise = this.file.read();
|
||||||
|
|
||||||
|
promise.done(this.setConfig);
|
||||||
|
|
||||||
|
promise.fail(function(error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(e) {
|
||||||
|
this.setState({submitting:"block"});
|
||||||
|
const obj = {};
|
||||||
|
obj.session_recording = {};
|
||||||
|
obj.session_recording.scope = this.state.scope;
|
||||||
|
obj.session_recording.users = this.state.users;
|
||||||
|
obj.session_recording.groups = this.state.groups;
|
||||||
|
|
||||||
|
let _this = this;
|
||||||
|
this.file.replace(obj).done(function() {
|
||||||
|
_this.setState({submitting:"none"});
|
||||||
|
})
|
||||||
|
.fail(function(error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
<table className="info-table-ct col-md-12">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><label htmlFor="scope">Scope</label></td>
|
||||||
|
<td>
|
||||||
|
<select name="scope" id="scope" className="form-control"
|
||||||
|
value={this.state.scope}
|
||||||
|
onChange={this.handleInputChange} >
|
||||||
|
<option value="none">None</option>
|
||||||
|
<option value="some">Some</option>
|
||||||
|
<option value="all">All</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{this.state.scope === "some" &&
|
||||||
|
<tr>
|
||||||
|
<td><label htmlFor="users">Users</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="users" name="users"
|
||||||
|
value={this.state.users}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
{this.state.scope === "some" &&
|
||||||
|
<tr>
|
||||||
|
<td><label htmlFor="groups">Groups</label></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" id="groups" name="groups"
|
||||||
|
value={this.state.groups}
|
||||||
|
className="form-control" onChange={this.handleInputChange} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
<tr>
|
||||||
|
<td><button className="btn btn-default" type="submit">Save</button></td>
|
||||||
|
<td>
|
||||||
|
<span style={{display: this.state.submitting}}>Saving...</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigView extends React.Component {
|
||||||
|
render() {
|
||||||
|
const goBack = () => {
|
||||||
|
cockpit.jump(['session-recording']);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<ol className="breadcrumb">
|
||||||
|
<li><a onClick={goBack}>Session
|
||||||
|
Recording</a></li>
|
||||||
|
<li className="active">Configuration</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<div className="panel panel-default">
|
||||||
|
<div className="panel-heading"><span>General Configuration</span></div>
|
||||||
|
<div className="panel-body" id="sr_config">
|
||||||
|
<Config />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<div className="panel panel-default">
|
||||||
|
<div className="panel-heading"><span>SSSD Configuration</span></div>
|
||||||
|
<div className="panel-body" id="sssd_config">
|
||||||
|
<SssdConfig />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<ConfigView />, document.getElementById('view'));
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="view"/>
|
<div id="view"></div>
|
||||||
<script type="text/javascript" src="recordings.js"></script>
|
<script type="text/javascript" src="recordings.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,7 @@ class View extends React.Component {
|
||||||
this.handleTsChange = this.handleTsChange.bind(this);
|
this.handleTsChange = this.handleTsChange.bind(this);
|
||||||
this.handleLogTsChange = this.handleLogTsChange.bind(this);
|
this.handleLogTsChange = this.handleLogTsChange.bind(this);
|
||||||
this.handleDateSinceChange = this.handleDateSinceChange.bind(this);
|
this.handleDateSinceChange = this.handleDateSinceChange.bind(this);
|
||||||
|
this.openConfig = this.openConfig.bind(this);
|
||||||
/* Journalctl instance */
|
/* Journalctl instance */
|
||||||
this.journalctl = null;
|
this.journalctl = null;
|
||||||
/* Recording ID journalctl instance is invoked with */
|
/* Recording ID journalctl instance is invoked with */
|
||||||
|
|
@ -831,6 +832,10 @@ class View extends React.Component {
|
||||||
this.setState({logsTs: ts});
|
this.setState({logsTs: ts});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openConfig() {
|
||||||
|
cockpit.jump(['session-recording/config']);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let proc = cockpit.spawn(["getent", "passwd", "tlog"]);
|
let proc = cockpit.spawn(["getent", "passwd", "tlog"]);
|
||||||
|
|
||||||
|
|
@ -929,8 +934,7 @@ class View extends React.Component {
|
||||||
<label className="control-label" htmlFor="config">Configuration</label>
|
<label className="control-label" htmlFor="config">Configuration</label>
|
||||||
</td>
|
</td>
|
||||||
<td className="top">
|
<td className="top">
|
||||||
<a href="/cockpit/@localhost/session-recording/config.html" className="btn btn-default" data-toggle="modal">
|
<button className="btn btn-default" onClick={this.openConfig}><i className="fa fa-cog" aria-hidden="true" /></button>
|
||||||
<i className="fa fa-cog" aria-hidden="true" /></a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue