This is an automated email from the git hooks/post-receive script.
mreynolds pushed a commit to branch 389-ds-base-1.4.1
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.4.1 by this push:
new 9b9c7a4 Issue 50546 - Fix various issues in UI
9b9c7a4 is described below
commit 9b9c7a40b81c063a9f095e4e854045319801d1f2
Author: Mark Reynolds <mreynolds(a)redhat.com>
AuthorDate: Fri Sep 6 16:37:26 2019 -0400
Issue 50546 - Fix various issues in UI
Description: This patch addresses several issues:
- #50546 - Exports from Cockpit can be stored outside of
/var/lib/dirsrv/slapd-instance_name/ldif/
- #50418 - dsctl remove does not cleanup /etc/tmpfiles.d
- #50554 - Cockpit incorrectly shows that a server is in read-only mode
- #49856 - Changing port should adjust selinux labels
- This also enforces a minimum password length for root DN
- Added confirmation modal is you disable LDAPI(and UI)
- Added port verification
- Created new "view" modals for schema instead oi reusing edit forms
- Improved instance creation form validation
- Added a progress bar for doing the initial load of configuration
relates:
https://pagure.io/389-ds-base/issue/50546
Reviewed by: spichugi(Thanks!)
---
src/cockpit/389-console/src/css/ds.css | 16 +-
src/cockpit/389-console/src/ds.js | 49 +++++-
src/cockpit/389-console/src/index.html | 25 +++-
.../389-console/src/lib/database/backups.jsx | 34 ++++-
.../389-console/src/lib/database/suffix.jsx | 19 ++-
.../389-console/src/lib/monitor/serverMonitor.jsx | 28 ++--
src/cockpit/389-console/src/lib/tools.jsx | 8 +
src/cockpit/389-console/src/replication.html | 42 +++---
src/cockpit/389-console/src/replication.js | 6 +-
src/cockpit/389-console/src/schema.html | 165 +++++++++++++++++++--
src/cockpit/389-console/src/schema.js | 99 +++++++++++--
src/cockpit/389-console/src/security.jsx | 14 +-
src/cockpit/389-console/src/servers.html | 12 +-
src/cockpit/389-console/src/servers.js | 91 ++++++++++--
src/lib389/lib389/config.py | 2 +-
src/lib389/lib389/instance/options.py | 5 +-
src/lib389/lib389/instance/remove.py | 5 +-
src/lib389/lib389/instance/setup.py | 15 +-
18 files changed, 511 insertions(+), 124 deletions(-)
diff --git a/src/cockpit/389-console/src/css/ds.css
b/src/cockpit/389-console/src/css/ds.css
index 3481db8..6da4b9d 100644
--- a/src/cockpit/389-console/src/css/ds.css
+++ b/src/cockpit/389-console/src/css/ds.css
@@ -317,6 +317,7 @@ td {
width: 875px !important;
min-width: 875px !important;
vertical-align: middle;
+ margin-left: -100px !important;
}
.ds-button-right {
@@ -686,6 +687,10 @@ option {
text-align: center;
}
+.modal {
+ overflow-y:auto;
+}
+
/* wizard accordions are narrower */
.ds-wiz-accordion {
margin-top: 20px;
@@ -826,6 +831,13 @@ option {
transform: translate(-25%, -50%);
}
+.ds-loading {
+ position: fixed;
+ top: 25%;
+ left: 35%;
+ transform: translate(-25%, -35%);
+}
+
.ds-popup {
min-width: 350px !important;
}
@@ -885,10 +897,6 @@ option {
}
}
-.control-label {
- text-align: left !important;
-}
-
.rbt-token {
background-color: #ededed;
color: #363636;
diff --git a/src/cockpit/389-console/src/ds.js b/src/cockpit/389-console/src/ds.js
index 47247e6..efe337c 100644
--- a/src/cockpit/389-console/src/ds.js
+++ b/src/cockpit/389-console/src/ds.js
@@ -76,8 +76,14 @@ function valid_dn (dn){
}
function valid_num (val){
- // Validate value is a number
- return !isNaN(val);
+ // Validate value is a number and between 1 and 65535
+ let result = !isNaN(val);
+ if (result) {
+ if (val < 1 || val > 65535) {
+ result = false;
+ }
+ }
+ return result;
}
function tableize (val) {
@@ -340,7 +346,27 @@ function popup_success(msg) {
// This is called when any Save button is clicked on the main page. We call
// all the save functions for all the pages here. This is not used for modal forms
function save_all () {
- save_config(); // Server Config Page
+ if ("nsslapd-ldapilisten" in config_values ||
"nsslapd-ldapiautobind" in config_values) {
+ if ( (!$("#nsslapd-ldapilisten").is(":checked") &&
config_values["nsslapd-ldapilisten"] == "on") ||
+ (!$("#nsslapd-ldapiautobind").is(":checked") &&
config_values["nsslapd-ldapiautobind"] == "on") )
+ {
+ // Okay we are disabling some form of LDAPI that will break the UI, warn the
user
+ popup_confirm("Disabling LDAPI or LDAPI Autobind will make the UI
unusable. Are you sure you want to proceed",
+ "Confirmation", function (yes)
+ {
+ if (yes) {
+ save_config();
+ } else {
+ // No, reset config
+ get_and_set_config();
+ }
+ });
+ } else {
+ save_config();
+ }
+ } else {
+ save_config();
+ }
}
function load_repl_suffix_dropdowns() {
@@ -374,6 +400,18 @@ function load_repl_suffix_dropdowns() {
});
}
+var progress = 10;
+
+function update_progress () {
+ progress += 10;
+ if (progress > 100) {
+ progress = 100;
+ }
+ $("#ds-progress-label").text(progress + "%");
+ $("#ds-progress-bar").attr("aria-valuenow", progress);
+ $("#ds-progress-bar").css("width", progress + "%");
+}
+
var loading_cfg = 0;
function load_config (refresh){
@@ -382,6 +420,8 @@ function load_config (refresh){
return;
}
loading_cfg = 1;
+ progress = 10;
+ update_progress();
// Load the configuration for all the pages.
var dropdowns = ['local-pwp-suffix', 'select-repl-cfg-suffix'];
@@ -415,15 +455,18 @@ function load_config (refresh){
get_and_set_config();
get_and_set_sasl();
get_and_set_localpwp();
+ update_progress();
// Schema page
get_and_set_schema_tables();
+ update_progress();
// Replication page
get_and_set_repl_config();
get_and_set_repl_agmts();
get_and_set_repl_winsync_agmts();
get_and_set_cleanallruv();
+ update_progress();
// Initialize the tabs
$(".ds-tab-list").css( 'color', '#777');
diff --git a/src/cockpit/389-console/src/index.html
b/src/cockpit/389-console/src/index.html
index eb7ea4a..1a42c97 100644
--- a/src/cockpit/389-console/src/index.html
+++ b/src/cockpit/389-console/src/index.html
@@ -33,9 +33,20 @@
<body>
<div id="reload-page" hidden></div>
- <div id="loading-page" class="ds-center ds-loading-spinner"
hidden>
+ <div id="loading-page" class="ds-center ds-loading" hidden>
<h4 id="loading-msg">Loading Directory Server
Configuration...</h4>
<p><span class="spinner spinner-lg
spinner-inline"></span></p>
+
+ <div class="progress">
+ <div class="progress-bar" role="progressbar"
id="ds-progress-bar"
+ aria-valuenow="20" aria-valuemin="0"
+ aria-valuemax="100" style="width: 20%;"
+ >
+ <span id="ds-progress-label">20%</span>
+ </div>
+ </div>
+
+
</div>
<div id="everything" hidden>
<div class="ds-nav-bar">
@@ -375,7 +386,7 @@
<p class="ds-modal-error"></p>
<div class="ds-inline">
<div>
- <label for="create-inst-serverid"
class="ds-config-label" title="The instance name, this is what gets
appended to \"slapi-\"">
+ <label for="create-inst-serverid"
class="ds-config-label" title="The instance name, this is what gets
appended to 'slapi-'. The instance name can only contain letters, numbers, and:
# % : - _">
Instance Name</label><input class="ds-input
ds-inst-input" size="40" type="text"
id="create-inst-serverid" placeholder="Your_Instance_Name" required
/>
</div>
<div>
@@ -400,12 +411,12 @@
</div>
<hr>
<div>
- <label for="backend-name"
class="ds-config-label" title="The backend name, like
'userroot'">Backend Name (optional)</label><input
- class="ds-input ds-inst-input" size="40"
type="text" id="backend-name">
+ <label for="backend-name"
class="ds-config-label" title="The name for the backend database, like
'userroot'">Backend Name (optional)</label><input
+ class="ds-input ds-inst-input" placeholder="e.g.
userRoot" size="40" type="text" id="backend-name">
</div>
<div>
<label for="backend-suffix"
class="ds-config-label" title="Database suffix, like
'dc=example,dc=com'">Backend Suffix (optional)</label><input
- class="ds-input ds-inst-input" size="40"
type="text" id="backend-suffix">
+ class="ds-input ds-inst-input" size="40"
placeholder="e.g. dc=example,dc=com" type="text"
id="backend-suffix">
</div>
<div>
<label for="create-sample-entries"
class="ds-config-label" title="Create sample entries in the
suffix">Create Sample Entries </label><input
@@ -445,8 +456,8 @@
</div>
<div class="modal-body">
<form class="form-horizontal">
- <label for="backup-name" title="Enter a directory name
for the backup">
- Backup Name:</label><input class="ds-input-auto"
type="text" id="backup-name"/>
+ <label for="backup-name" title="Enter a name for the
backup subdirectory located under the server's backup directory
(nsslapd-bakdir)">
+ Name For The Backup</label><input
class="ds-input-auto" type="text" id="backup-name"/>
</form>
<div id="backup-spinner" class="ds-center" hidden>
<p></p>
diff --git a/src/cockpit/389-console/src/lib/database/backups.jsx
b/src/cockpit/389-console/src/lib/database/backups.jsx
index 9a9f6bb..96d6e97 100644
--- a/src/cockpit/389-console/src/lib/database/backups.jsx
+++ b/src/cockpit/389-console/src/lib/database/backups.jsx
@@ -19,7 +19,7 @@ import {
Row,
noop
} from "patternfly-react";
-import { log_cmd } from "../tools.jsx";
+import { log_cmd, bad_file_name } from "../tools.jsx";
import PropTypes from "prop-types";
import "../../css/ds.css";
@@ -289,19 +289,26 @@ export class Backups extends React.Component {
}
doBackup () {
- this.setState({
- backupSpinning: true
- });
-
let cmd = [
"dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-"
+ this.props.serverId + ".socket",
"backup", "create"
];
if (this.state.backupName != "") {
+ if (bad_file_name(this.state.backupName)) {
+ this.props.addNotification(
+ "warning",
+ `Backup name should not be a path. All backups are stored in the
server's backup directory`
+ );
+ return;
+ }
cmd.push(this.state.backupName);
}
+ this.setState({
+ backupSpinning: true
+ });
+
log_cmd("doBackup", "Add backup task", cmd);
cockpit
.spawn(cmd, { superuser: true, err: "message" })
@@ -399,12 +406,25 @@ export class Backups extends React.Component {
}
doExport() {
- let missingArgs = {ldifLocation: false};
- if (this.state.ldifLocation == "") {
+ let missingArgs = {ldifName: false};
+ if (this.state.ldifName == "") {
this.props.addNotification(
"warning",
`LDIF name is empty`
);
+ missingArgs.ldifName = true;
+ this.setState({
+ errObj: missingArgs
+ });
+ return;
+ }
+
+ // Must not be a path
+ if (bad_file_name(this.state.ldifName)) {
+ this.props.addNotification(
+ "warning",
+ `LDIF name should not be a path. All export files are stored in the
server's LDIF directory`
+ );
missingArgs.ldifLocation = true;
this.setState({
errObj: missingArgs
diff --git a/src/cockpit/389-console/src/lib/database/suffix.jsx
b/src/cockpit/389-console/src/lib/database/suffix.jsx
index 8d58da9..4366c19 100644
--- a/src/cockpit/389-console/src/lib/database/suffix.jsx
+++ b/src/cockpit/389-console/src/lib/database/suffix.jsx
@@ -6,7 +6,7 @@ import { SuffixConfig } from "./suffixConfig.jsx";
import { SuffixReferrals } from "./referrals.jsx";
import { SuffixIndexes } from "./indexes.jsx";
import { VLVIndexes } from "./vlvIndexes.jsx";
-import { log_cmd } from "../tools.jsx";
+import { log_cmd, bad_file_name } from "../tools.jsx";
import {
ImportModal,
ExportModal,
@@ -260,7 +260,20 @@ export class Suffix extends React.Component {
return;
}
- // Do import
+ // Must not be a path
+ if (bad_file_name(this.state.ldifLocation)) {
+ this.props.addNotification(
+ "warning",
+ `LDIF name should not be a path. All export files are stored in the
server's LDIF directory`
+ );
+ missingArgs.ldifLocation = true;
+ this.setState({
+ errObj: missingArgs
+ });
+ return;
+ }
+
+ // Do Export
let export_cmd = [
"dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-"
+ this.props.serverId + ".socket",
"backend", "export", this.props.suffix,
"--ldif=" + this.state.ldifLocation
@@ -289,7 +302,7 @@ export class Suffix extends React.Component {
})
.fail(err => {
let errMsg = JSON.parse(err);
- this.loadLDIFs();
+ this.props.reloadLDIFs();
this.props.addNotification(
"error",
`Error exporting database - ${errMsg.desc}`
diff --git a/src/cockpit/389-console/src/lib/monitor/serverMonitor.jsx
b/src/cockpit/389-console/src/lib/monitor/serverMonitor.jsx
index 0169f39..93c2aef 100644
--- a/src/cockpit/389-console/src/lib/monitor/serverMonitor.jsx
+++ b/src/cockpit/389-console/src/lib/monitor/serverMonitor.jsx
@@ -67,7 +67,7 @@ export class ServerMonitor extends React.Component {
<TabPane eventKey={1}>
<div className="ds-margin-top-lg">
<Row>
- <Col componentClass={ControlLabel} sm={3}>
+ <Col componentClass={ControlLabel} sm={4}>
Server Instance
</Col>
<Col sm={8}>
@@ -75,7 +75,7 @@ export class ServerMonitor extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top">
- <Col componentClass={ControlLabel} sm={3}>
+ <Col componentClass={ControlLabel} sm={4}>
Version
</Col>
<Col sm={8}>
@@ -83,7 +83,7 @@ export class ServerMonitor extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top">
- <Col componentClass={ControlLabel} sm={3}>
+ <Col componentClass={ControlLabel} sm={4}>
Server Started
</Col>
<Col sm={8}>
@@ -91,7 +91,7 @@ export class ServerMonitor extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top">
- <Col componentClass={ControlLabel} sm={3}>
+ <Col componentClass={ControlLabel} sm={4}>
Server Uptime
</Col>
<Col sm={8}>
@@ -105,7 +105,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Worker Threads
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-threads"
value={this.props.data.threads} readOnly />
</Col>
</Row>
@@ -113,7 +113,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Threads Waiting To Read
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-readwaiters"
value={this.props.data.readwaiters} readOnly />
</Col>
</Row>
@@ -121,7 +121,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Conns At Max Threads
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto"
id="monitor-server-currentconnectionsatmaxthreads"
value={this.props.data.currentconnectionsatmaxthreads} readOnly />
</Col>
</Row>
@@ -129,7 +129,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Conns Exceeded Max Threads
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-maxthreadsperconnhits"
value={this.props.data.maxthreadsperconnhits} readOnly />
</Col>
</Row>
@@ -137,7 +137,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Total Connections
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-totalconnections"
value={this.props.data.totalconnections} readOnly />
</Col>
</Row>
@@ -145,7 +145,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Current Conections
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-currentconnections"
value={this.props.data.currentconnections} readOnly />
</Col>
</Row>
@@ -153,7 +153,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Operations Started
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-opsinitiated"
value={this.props.data.opsinitiated} readOnly />
</Col>
</Row>
@@ -161,7 +161,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Operations Completed
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-opscompleted"
value={this.props.data.opscompleted} readOnly />
</Col>
</Row>
@@ -169,7 +169,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Entries Returned To Clients
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-entriessent"
value={this.props.data.entriessent} readOnly />
</Col>
</Row>
@@ -177,7 +177,7 @@ export class ServerMonitor extends React.Component {
<Col componentClass={ControlLabel} sm={4}>
Bytes Sent to Clients
</Col>
- <Col sm={7}>
+ <Col sm={8}>
<input type="text"
className="ds-input-auto" id="monitor-server-bytessent"
value={this.props.data.bytessent} readOnly />
</Col>
</Row>
diff --git a/src/cockpit/389-console/src/lib/tools.jsx
b/src/cockpit/389-console/src/lib/tools.jsx
index b3e7573..eb0a67c 100644
--- a/src/cockpit/389-console/src/lib/tools.jsx
+++ b/src/cockpit/389-console/src/lib/tools.jsx
@@ -103,3 +103,11 @@ export function get_date_diff(start, end) {
return `${days} days, ${hours} hours, ${minutes} minutes, and ${seconds} seconds`;
}
+
+export function bad_file_name(file_name) {
+ // file_name must be a string, and not a location/directory
+ if (file_name.includes("/")) {
+ return true;
+ }
+ return false;
+}
diff --git a/src/cockpit/389-console/src/replication.html
b/src/cockpit/389-console/src/replication.html
index 9d65107..af9fca4 100644
--- a/src/cockpit/389-console/src/replication.html
+++ b/src/cockpit/389-console/src/replication.html
@@ -257,27 +257,27 @@ CleanAllRUV Tasks
<div class="ds-inline">
<div>
<label for="agmt-cn" class="ds-config-label"
title="Agreement name (cn).">Agreement Name</label><input
- class="ds-input agmt-form-input" type="text"
placeholder="Agreement name" id="agmt-cn" name="name"
size="35" required>
+ class="ds-input agmt-form-input" type="text"
placeholder="Agreement name" id="agmt-cn" name="name"
size="40" required>
</div>
<div>
<label for="nsds5replicahost"
class="ds-config-label" title="Agreement name
(nsDS5ReplicaHost).">Consumer Host</label><input
- class="ds-input agmt-form-input" type="text"
placeholder="Consumer hostname" id="nsds5replicahost"
name="port" size="35" required>
+ class="ds-input agmt-form-input" type="text"
placeholder="Consumer hostname" id="nsds5replicahost"
name="port" size="40" required>
</div>
<div>
<label for="nsds5replicaport"
class="ds-config-label" title="Agreement name
(nsDS5ReplicaPort).">Consumer Port</label><input
- class="ds-input agmt-form-input" type="text"
placeholder="Consumer port number" id="nsds5replicaport"
name="name" size="35" required>
+ class="ds-input agmt-form-input" type="text"
placeholder="Consumer port number" id="nsds5replicaport"
name="name" size="40" required>
</div>
<div>
<label for="nsds5replicabinddn"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaBindDN).">Replication Bind DN</label><input
- class="ds-input agmt-form-input" type="text"
autocomplete="username" placeholder="Bind DN"
id="nsds5replicabinddn" name="name" size="35" required>
+ class="ds-input agmt-form-input" type="text"
autocomplete="username" placeholder="Bind DN"
id="nsds5replicabinddn" name="name" size="40" required>
</div>
<div>
- <label for="nsds5replicacredentials"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaCredentials).">Replication Bind DN
Credentials</label><input
- class="ds-input agmt-form-input" type="password"
autocomplete="new-password" placeholder="Enter password"
id="nsds5replicacredentials" name="name" size="35"
required>
+ <label for="nsds5replicacredentials"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaCredentials).">Bind DN Password</label><input
+ class="ds-input agmt-form-input" type="password"
autocomplete="new-password" placeholder="Enter password"
id="nsds5replicacredentials" name="name" size="40"
required>
</div>
<div>
<label for="nsds5replicacredentials-confirm"
class="ds-config-label" title="Confirm password">Confirm
Password</label><input
- class="ds-input agmt-form-input" type="password"
autocomplete="new-password" placeholder="Confirm password"
id="nsds5replicacredentials-confirm" name="name" size="35"
required>
+ class="ds-input agmt-form-input" type="password"
autocomplete="new-password" placeholder="Confirm password"
id="nsds5replicacredentials-confirm" name="name" size="40"
required>
</div>
<div>
<label for="nsds5replicatransportinfo"
class="ds-config-label" title="The protocol used to connect to the replica
(nsDS5ReplicaTransportInfo).">Connection Protocol</label><select
@@ -448,7 +448,7 @@ CleanAllRUV Tasks
<!-- Winsync Agreement Wizard -->
<div class="modal fade" id="winsync-agmt-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="winsync-agmt-wizard-title" aria-hidden="true">
- <div class="modal-dialog ds-modal-wide">
+ <div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
@@ -462,27 +462,27 @@ CleanAllRUV Tasks
<div class="ds-inline">
<div>
<label for="winsync-agmt-cn"
class="ds-config-label" title="Agreement name (cn).">Agreement
Name</label><input
- class="ds-input" type="text"
placeholder="Agreement name" id="winsync-agmt-cn"
name="name" required>
+ class="ds-input" type="text"
placeholder="Agreement name" id="winsync-agmt-cn"
name="name" size="40" required>
</div>
<div>
<label for="winsync-nsds7windowsdomain"
class="ds-config-label" title="Agreement name
(nsds7WindowsDomain).">Windows Domain Name</label><input
- class="ds-input" type="text"
placeholder="Windows Domain Name, example: mydomain.com"
id="winsync-nsds7windowsdomain" name="name" required>
+ class="ds-input" type="text"
placeholder="Windows Domain Name, example: mydomain.com"
id="winsync-nsds7windowsdomain" size="40" name="name"
required>
</div>
<div>
<label for="winsync-nsds5replicahost"
class="ds-config-label" title="Agreement name
(nsDS5ReplicaHost).">Windows Host</label><input
- class="ds-input" type="text"
placeholder="Windows hostname" id="winsync-nsds5replicahost"
name="port" required>
+ class="ds-input" type="text"
placeholder="Windows hostname" id="winsync-nsds5replicahost"
name="port" size="40" required>
</div>
<div>
<label for="winsync-nsds5replicaport"
class="ds-config-label" title="Agreement name
(nsDS5ReplicaPort).">Windows Port</label><input
- class="ds-input" type="text"
placeholder="Windows server port number" id="winsync-nsds5replicaport"
name="name" required>
+ class="ds-input" type="text"
placeholder="Windows server port number" id="winsync-nsds5replicaport"
name="name" size="40" required>
</div>
<div>
<label for="winsync-nsds7windowsreplicasubtree"
class="ds-config-label" title="Agreement name
(nsds7WindowsReplicaSubtree).">Windows Subtree</label><input
- class="ds-input" type="text"
placeholder="Active Directory subtree"
id="winsync-nsds7windowsreplicasubtree" name="name" required>
+ class="ds-input" type="text"
placeholder="Active Directory subtree"
id="winsync-nsds7windowsreplicasubtree" name="name"
size="40" required>
</div>
<div>
<label for="winsync-nsds7directoryreplicasubtree"
class="ds-config-label" title="Agreement name
(nsds7DirectoryReplicaSubtree).">Directory Server Subtree</label><input
- class="ds-input" type="text"
placeholder="The local Directory Server subtree"
id="winsync-nsds7directoryreplicasubtree" name="name" required>
+ class="ds-input" type="text"
placeholder="The local Directory Server subtree"
id="winsync-nsds7directoryreplicasubtree" name="name"
size="40" required>
</div>
<div>
<input type="checkbox"
class="ds-config-checkbox"
id="winsync-nsds7newwinusersyncenabled-checkbox" checked><label
@@ -502,15 +502,15 @@ CleanAllRUV Tasks
<div>
<hr class="ds-hr">
<label for="winsync-nsds5replicabinddn"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaBindDN).">Replication Bind DN</label><input
- class="ds-input" type="text"
autocomplete="username" placeholder="Bind DN"
id="winsync-nsds5replicabinddn" name="name" required>
+ class="ds-input" type="text"
autocomplete="username" placeholder="Bind DN"
id="winsync-nsds5replicabinddn" name="name" size="40"
required>
</div>
<div>
- <label for="winsync-nsds5replicacredentials"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaCredentials).">Replication Bind DN
Credentials</label><input
- class="ds-input" type="password"
autocomplete="new-password" placeholder="Enter password"
id="winsync-nsds5replicacredentials" name="name" required>
+ <label for="winsync-nsds5replicacredentials"
class="ds-config-label" title="Replication Bind DN
(nsDS5ReplicaCredentials).">Bind DN Password</label><input
+ class="ds-input" type="password"
autocomplete="new-password" placeholder="Enter password"
id="winsync-nsds5replicacredentials" name="name" size="40"
required>
</div>
<div>
<label for="winsync-nsds5replicacredentials-confirm"
class="ds-config-label" title="Confirm password">Confirm
Password</label><input
- class="ds-input"
type="password"autocomplete="new-password" placeholder="Confirm
password" id="winsync-nsds5replicacredentials-confirm"
name="name" required>
+ class="ds-input"
type="password"autocomplete="new-password" placeholder="Confirm
password" id="winsync-nsds5replicacredentials-confirm"
name="name" size="40" required>
</div>
<div>
<label for="winsync-nsds5replicatransportinfo"
class="ds-config-label" title="The protocol used to connect to the replica
(nsDS5ReplicaTransportInfo).">Connection Protocol</label><select
@@ -581,7 +581,7 @@ CleanAllRUV Tasks
<!-- Add replication manager Form -->
<div class="modal fade" id="add-repl-mgr-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="repl-mgr-label" aria-hidden="true">
- <div class="modal-dialog ds-modal-wide">
+ <div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
@@ -594,7 +594,7 @@ CleanAllRUV Tasks
<div class="ds-inline">
<div>
<label for="add-repl-mgr-dn" class="" title=
- "The DN of the replication manager. The entry should use
'cn' for RDN, and the entry should be under 'cn=config'.
(nsds5replicabinddn)">
+ "The DN of the replication manager. The entry should use
'cn' for the RDN, and the entry should be under 'cn=config'.
(nsds5replicabinddn)">
Replication Manager DN</label>
</div>
<div>
@@ -689,7 +689,7 @@ CleanAllRUV Tasks
<label for="enable-repl-mgr-dn"
class="ds-label-sm" title=
"The DN of the replication manager. The DN should use
'cn' for the RDN, 'cn=replication manager,cn=config'
(nsds5replicabinddn)">Replication Manager DN</label><input
type="text" title="The DN of the replication
manager entry. It must use the RDN attribute 'cn', and it must be located under
'cn=config'. For example: cn=replication manager,cn=config"
- id="enable-repl-mgr-dn" size="40"
class="ds-left-margin" />
+ id="enable-repl-mgr-dn" value="cn=replication
manager,cn=config" size="40" class="ds-left-margin" />
<p></p>
</div>
<div>
diff --git a/src/cockpit/389-console/src/replication.js
b/src/cockpit/389-console/src/replication.js
index 58f9b4b..e28d175 100644
--- a/src/cockpit/389-console/src/replication.js
+++ b/src/cockpit/389-console/src/replication.js
@@ -109,7 +109,7 @@ function clear_enable_repl_form () {
$("#select-enable-repl-role").prop("selectedIndex", 0);
$("#enable-repl-pw").val("");
$("#enable-repl-pw-confirm").val("");
- $("#enable-repl-mgr-dn").val("");
+ $("#enable-repl-mgr-dn").val("cn=replication manager,cn=config");
$("#enable-repl-mgr-checkbox").prop('checked', false);
$("#enable-repl-mgr-passwd").hide();
}
@@ -203,6 +203,7 @@ function get_and_set_repl_winsync_agmts() {
log_cmd('get_and_set_repl_winsync_agmts', 'Get the winsync agmts',
cmd);
cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
var obj = JSON.parse(data);
+ update_progress();
for (var idx in obj['items']) {
var state = "Enabled";
var con_host = "";
@@ -278,6 +279,7 @@ function get_and_set_repl_agmts () {
cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
repl_agmt_table.clear().draw();
var obj = JSON.parse(data);
+ update_progress();
for (var idx in obj['items']) {
agmt_attrs = obj['items'][idx]['attrs'];
var agmt_name = agmt_attrs['cn'][0];
@@ -351,6 +353,7 @@ function get_and_set_cleanallruv() {
log_cmd('get_and_set_cleanallruv', 'Get the cleanAllRUV tasks', cmd);
cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
var tasks = JSON.parse(data);
+ update_progress();
repl_clean_table.clear().draw();
for (var idx in tasks['items']) {
task_attrs = tasks['items'][idx]['attrs'];
@@ -394,6 +397,7 @@ function get_and_set_repl_config () {
$('#repl-mgr-table').find("tr:gt(0)").remove();
$(".ds-cfg").val("");
$("#nsds5replicaprecisetombstonepurging").prop('checked',
false);
+ update_progress();
// Set configuration and the repl manager table
for (var attr in repl['attrs']) {
diff --git a/src/cockpit/389-console/src/schema.html
b/src/cockpit/389-console/src/schema.html
index 10bdabe..872abab 100644
--- a/src/cockpit/389-console/src/schema.html
+++ b/src/cockpit/389-console/src/schema.html
@@ -65,6 +65,80 @@
<!-- Modals/Popups/Wizards -->
+ <!-- View Attribute modal -->
+ <div class="modal fade" id="view-attr-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="view-attr-header" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">View Attribute</h4>
+ </div>
+ <div class="modal-body">
+ <div class="ds-inline">
+ <div>
+ <label for="attr-name-view"
class="ds-config-label-lrg" title="The attribute name"><b
+ >Attribute Name</b></label><input
class="ds-input" type="text" id="attr-name-view"
size="40" readonly />
+ </div>
+ <div>
+ <label for="attr-desc-view"
class="ds-config-label-lrg" title="The attribute
description"><b
+ >Description</b></label><input
class="ds-input" type="text" id="attr-desc-view"
size="40" readonly />
+ </div>
+ <div>
+ <label for="attr-oid-view"
class="ds-config-label-lrg" title="The attribute name"><b
+ >OID</b></label><input
class="ds-input" type="text" id="attr-oid-view"
size="40" readonly />
+ </div>
+ <div>
+ <label for="attr-parent-view"
class="ds-config-label-lrg" title="The parent
attribute"><b>Parent Attribute</b></label><input
+ class="ds-input" type="text"
id="attr-parent-view" size="40" readonly />
+ </div>
+ <div>
+ <label for="attr-syntax-view"
class="ds-config-label-lrg" title="The attribute
syntax"><b>Attribute Syntax</b></label><input
+ class="ds-input" type="text"
id="attr-syntax-view" size="40" readonly />
+ </div>
+ <div>
+ <label for="attr-usage-view"
class="ds-config-label-lrg" title="The parent
attribute"><b>Attribute Usage</b></label><input
+ class="ds-input" type="text"
id="attr-usage-view" size="40" readonly />
+ </div>
+ <div>
+ <input type="checkbox"
class="ds-config-checkbox" id="attr-multivalued-view" readonly
/><label
+ for="attr-multivalued-view"
class="ds-label"> Attribute Multi-Valued </label>
+ </div>
+ <div>
+ <input type="checkbox"
class="ds-config-checkbox" id="attr-no-user-mod-view" readonly
/><label
+ for="attr-no-user-mod-view"
class="ds-label"> Read-only (NO-USER-MODIFICATION flag) </label>
+ </div>
+ <div>
+ <label for="attr-alias-view"
class="ds-config-label-lrg" title="The attribute alias list separated by
space"><b
+ >Attribute Aliases</b></label><input
class="ds-input" type="text" id="attr-alias-view"
size="40" readonly />
+ </div>
+ <div class="panel panel-default ds-margin-top">
+ <div
class="panel-heading"><strong>Matching
rules</strong></div>
+ <div class="panel-body">
+ <div>
+ <label for="attr-eq-mr-select-view"
class="ds-config-label-lrg"><b>Equality</b></label><input
+ class="ds-input"
type="text" id="attr-eq-mr-select-view" size="35" readonly
/>
+ </div>
+ <div>
+ <label for="attr-order-mr-select-view"
class="ds-config-label-lrg"><b>Ordering</b></label><input
+ class="ds-input" type="text"
id="attr-order-mr-select-view" size="35" readonly />
+ </div>
+ <div>
+ <label for="attr-sub-mr-select-view"
class="ds-config-label-lrg"><b>Substring</b></label><input
+ class="ds-input" type="text"
id="attr-sub-mr-select-view" size="35" readonly />
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn
btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
<!-- Add/edit Attribute modal -->
<div class="modal fade" id="add-edit-attr-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="add-edit-attr-header" aria-hidden="true">
<div class="modal-dialog">
@@ -79,22 +153,22 @@
<div class="ds-inline">
<p class="ds-modal-error"></p>
<div>
- <label for="attr-parent" class="ds-config-label-lrg"
title="The parent attribute"><b>Parent
Attribute</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-parent">
- <option value=""></option>
- </select>
- </div>
- <div>
<label for="attr-name" class="ds-config-label-lrg"
title="The attribute name"><b
Attribute Name</b></label><input
class="ds-input" type="text" id="attr-name"
size="40"/>
</div>
<div>
<label for="attr-desc" class="ds-config-label-lrg"
title="The attribute description"><b
- >Attribute Description</b></label><input
class="ds-input" type="text" id="attr-desc"
size="40"/>
+ >Description</b></label><input class="ds-input"
type="text" id="attr-desc" size="40"/>
</div>
<div>
<label for="attr-oid" class="ds-config-label-lrg"
title="The attribute name"><b
- >Attribute OID</b></label><input
class="ds-input" type="text" id="attr-oid"
size="40"/>
+ >OID</b></label><input class="ds-input"
type="text" id="attr-oid" size="40"/>
+ </div>
+ <div>
+ <label for="attr-parent" class="ds-config-label-lrg"
title="The parent attribute"><b>Parent
Attribute</b></label><select
+ class="btn btn-default dropdown ds-oc-dropdown"
id="attr-parent">
+ <option value=""></option>
+ </select>
</div>
<div>
<label for="attr-syntax" class="ds-config-label-lrg"
title="The attribute syntax"><b>Attribute
Syntax</b></label><select
@@ -119,7 +193,7 @@
<label for="attr-alias" class="ds-config-label-lrg"
title="The attribute alias list separated by space"><b
Attribute Aliases</b></label><input
class="ds-input" type="text" id="attr-alias"
size="40"/>
</div>
- <div class="panel panel-default">
+ <div class="panel panel-default ds-margin-top">
<div class="panel-heading"><strong>Matching
rules</strong></div>
<div class="panel-body">
<div>
@@ -157,6 +231,65 @@
</div>
+ <!-- View Objectclass -->
+ <div class="modal fade" id="view-objectclass-form"
aria-labelledby="view-objectclass-form" data-backdrop="static"
tabindex="-1" role="dialog" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">View Objectclass</h4>
+ </div>
+ <div class="modal-body">
+ <form class="form-horizontal">
+ <div class="ds-inline">
+ <div>
+ <label for="oc-name-view"
class="ds-config-label-lrg" title="The objectclass name"><b
+ >Objectclass Name</b></label><input
class="ds-input" type="text" id="oc-name-view"
size="40" readonly />
+ </div>
+ <div>
+ <label for="oc-desc-view"
class="ds-config-label-lrg" title="The objectClass
description"><b
+ >Description</b></label><input
class="ds-input" type="text" id="oc-desc-view"
size="40" readonly/>
+ </div>
+ <div>
+ <label for="oc-oid-view"
class="ds-config-label-lrg" title="Objectclass OID
(optional)"><b
+ >OID (optional)</b></label><input
class="ds-input" value="" type="text"
id="oc-oid-view" size="40" readonly/>
+ </div>
+ <div>
+ <label for="oc-parent-view"
class="ds-config-label-lrg" title="The parent
objectclass"><b>Parent Objectclass</b></label><input
+ class="ds-input" value=""
type="text" id="oc-parent-view" size="40" readonly />
+ </div>
+ <div>
+ <label for="oc-kind-view"
class="ds-config-label-lrg" title="The parent
objectclass"><b>Objectclass Kind</b></label><input
+ class="ds-input" value=""
type="text" id="oc-kind-view" size="40" readonly />
+ </div>
+ <hr>
+ <div class="ds-container">
+ <div>
+ <label class="ds-config-label"
for="oc-required-list-view" title=
+ "Attributes allowed by the
objectclass"><b>Required Attributes</b></label>
+ <select id="oc-required-list-view"
class="ds-may-must-list" multiple>
+ </select>
+ </div>
+ <div class="ds-divider"></div>
+ <div>
+ <label class="ds-config-label"
for="oc-allowed-list-view" title=
+ "Attributes allowed by the
objectclass"><b>Allowed Attributes</b></label>
+ <select id="oc-allowed-list-view"
class="ds-may-must-list" multiple>
+ </select>
+ </div>
+ </div>
+ </div>
+ </form>
+ <div class="modal-footer">
+ <button type="button" class="btn
btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
<!-- Add/Edit Objectclass -->
<div class="modal fade" id="add-edit-oc-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="add-edit-oc-header" aria-hidden="true">
<div class="modal-dialog">
@@ -172,27 +305,27 @@
<div class="ds-inline">
<p class="ds-modal-error"></p>
<div>
- <label for="oc-parent" class="ds-config-label-lrg"
title="The parent objectclass"><b>Parent
Objectclass</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="oc-parent">
- </select>
- </div>
- <div>
<label for="oc-name" class="ds-config-label-lrg"
title="The objectclass name"><b
Objectclass Name</b></label><input
class="ds-input" type="text" id="oc-name"
size="40" required />
</div>
<div>
<label for="oc-desc" class="ds-config-label-lrg"
title="The objectClass description"><b
- >ObjectClass Description</b></label><input
class="ds-input" type="text" id="oc-desc"
size="40"/>
+ >Description</b></label><input
class="ds-input" type="text" id="oc-desc"
size="40"/>
</div>
<div>
<label for="oc-oid" class="ds-config-label-lrg"
title="Objectclass OID (optional)"><b
OID (optional)</b></label><input
class="ds-input" value="" type="text" id="oc-oid"
size="40"/>
</div>
<div>
+ <label for="oc-parent" class="ds-config-label-lrg"
title="The parent objectclass"><b>Parent
Objectclass</b></label><select
+ class="btn btn-default dropdown ds-oc-dropdown"
id="oc-parent">
+ </select>
+ </div>
+ <div>
<label for="oc-kind" class="ds-config-label-lrg"
title="The parent objectclass"><b>Objectclass
Kind</b></label><select
class="btn btn-default dropdown ds-oc-dropdown"
id="oc-kind">
<option value=""></option>
- </select>
+ </select>
</div>
<hr>
<div class="ds-container">
diff --git a/src/cockpit/389-console/src/schema.js
b/src/cockpit/389-console/src/schema.js
index a31e74a..618c555 100644
--- a/src/cockpit/389-console/src/schema.js
+++ b/src/cockpit/389-console/src/schema.js
@@ -251,7 +251,7 @@ function get_and_set_schema_tables() {
}
$.each(syntax_list, function (i, syntax) {
if (syntax.id === item.syntax) {
- syntax_name = '<div title="' + syntax.id +
'">' + syntax.name + '</div>';
+ syntax_name = '<div title="' + syntax.name +
'">' + syntax.name + '</div>';
}
});
// If attribute is user defined them the action button is enabled
@@ -326,6 +326,7 @@ function get_and_set_schema_tables() {
"visible": false
}]
});
+ update_progress();
}).fail(function(syntax_data) {
console.log("Get syntaxes failed: " + syntax_data.message);
check_inst_alive(1);
@@ -353,6 +354,7 @@ function get_and_set_schema_tables() {
});
console.log("Finished loading schema.");
+ update_progress();
}).fail(function(oc_data) {
console.log("Get all schema objects failed: " + oc_data.message);
check_inst_alive(1);
@@ -738,13 +740,50 @@ $(document).ready( function() {
$("#add-edit-attr-form").modal('toggle');
}
+ function load_view_attr_form(element) {
+ clear_attr_form();
+ var data = schema_at_table.row(element.parents('tr') ).data();
+ var edit_attr_name = data[0];
+ var edit_attr_oid = data[1];
+ var edit_attr_syntax = $.parseHTML(data[2])[0].title;
+ var edit_attr_multivalued = data[3];
+ var edit_attr_desc = data[5];
+ var edit_attr_aliases = data[6];
+ var edit_attr_x_origin = data[7];
+ var edit_attr_usage = data[8];
+ var edit_attr_no_user_mod = data[9];
+ var edit_attr_parent = data[10];
+ var edit_attr_eq_mr = data[11];
+ var edit_attr_order_mr = data[12];
+ var edit_attr_sub_mr = data[13];
+
+ $("#attr-name-view").val(edit_attr_name);
+ $("#attr-oid-view").val(edit_attr_oid);
+ $("#attr-usage-view")[0].value = edit_attr_usage;
+ $("#attr-parent-view")[0].value = edit_attr_parent;
+ $("#attr-desc-view").val(edit_attr_desc);
+ if (edit_attr_aliases) {
+ $("#attr-alias-view").val(edit_attr_aliases.join(" "));
+ }
+ $("#attr-syntax-view").val(edit_attr_syntax);
+ $("#attr-multivalued-view").prop('checked', false);
+ if (edit_attr_multivalued == "yes") {
+ $("#attr-multivalued-view").prop('checked', true);
+ }
+ $("#attr-no-user-mod-view").prop('checked', false);
+ if (edit_attr_no_user_mod) {
+ $("#attr-no-user-mod-view").prop('checked', true);
+ }
+ $("#attr-eq-mr-select-view").val(edit_attr_eq_mr);
+ $("#attr-order-mr-select-view").val(edit_attr_order_mr);
+ $("#attr-sub-mr-select-view").val(edit_attr_sub_mr);
+
+ $("#view-attr-form").modal('toggle');
+ }
+
$(document).on('click', '.attr-view-btn', function(e) {
e.preventDefault();
- load_attr_form($(this));
- var edit_attr_name = schema_at_table.row($(this).parents('tr')
).data()[0];
- $("#add-edit-attr-header").html('View Attribute: ' +
edit_attr_name);
- $("#save-attr-button").attr('title', 'Only user-defined
attributes can be modified');
- $("#save-attr-button").attr('disabled', true);
+ load_view_attr_form($(this));
});
$(document).on('click', '.attr-edit-btn', function(e) {
@@ -772,6 +811,44 @@ $(document).ready( function() {
});
});
+ function load_view_oc_form(element) {
+ clear_oc_form();
+ var data = schema_oc_table.row(element.parents('tr') ).data();
+ var edit_oc_name = data[0];
+ var edit_oc_oid = data[1];
+ var edit_oc_required = data[2].split(" ");
+ var edit_oc_allowed = data[3].split(" ");
+ var edit_oc_x_origin = data[5];
+ var edit_oc_kind = data[6];
+ var edit_oc_desc = data[7];
+ var edit_oc_parent = data[8];
+
+ $("#oc-name-view").val(edit_oc_name);
+ $("#oc-oid-view").val(edit_oc_oid);
+ $("#oc-kind-view")[0].value = edit_oc_kind;
+ $("#oc-desc-view").val(edit_oc_desc);
+ $("#oc-parent-view")[0].value = edit_oc_parent;
+ $.each(edit_oc_required, function (i, item) {
+ if (item) {
+ $("#oc-required-list-view").append($('<option>', {
+ value: item,
+ text : item
+ }));
+ }
+ });
+ $.each(edit_oc_allowed, function (i, item) {
+ if (item) {
+ $("#oc-allowed-list-view").append($('<option>', {
+ value: item,
+ text : item
+ }));
+ }
+ });
+
+ // Update modal html header and fields and show()
+ $("#view-objectclass-form").modal('toggle');
+ }
+
function load_oc_form(element) {
clear_oc_form();
var data = schema_oc_table.row(element.parents('tr') ).data();
@@ -789,9 +866,9 @@ $(document).ready( function() {
$("#oc-name").attr('disabled', true);
$("#oc-name").val(edit_oc_name);
$("#oc-oid").val(edit_oc_oid);
- $("#oc-kind")[0].value = edit_oc_kind;
+ $("#oc-kind").val(edit_oc_kind);
$("#oc-desc").val(edit_oc_desc);
- $("#oc-parent")[0].value = edit_oc_parent;
+ $("#oc-parent").val(edit_oc_parent);
$.each(edit_oc_required, function (i, item) {
if (item) {
$("#oc-required-list").append($('<option>', {
@@ -816,11 +893,7 @@ $(document).ready( function() {
$(document).on('click', '.oc-view-btn', function(e) {
e.preventDefault();
- load_oc_form($(this));
- var edit_oc_name = schema_oc_table.row($(this).parents('tr') ).data()[0];
- $("#add-edit-oc-header").html('View Objectclass: ' +
edit_oc_name);
- $("#save-oc-button").attr('title', 'Only user-defined
objectClasses can be modified');
- $("#save-oc-button").attr('disabled', true);
+ load_view_oc_form($(this));
});
$(document).on('click', '.oc-edit-btn', function(e) {
diff --git a/src/cockpit/389-console/src/security.jsx
b/src/cockpit/389-console/src/security.jsx
index 43edf49..77b25f9 100644
--- a/src/cockpit/389-console/src/security.jsx
+++ b/src/cockpit/389-console/src/security.jsx
@@ -599,7 +599,7 @@ export class Security extends React.Component {
configPage =
<div>
<Row className="ds-margin-top" title="The
server's secure port number (nsslapd-secureport).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Server Secure Port
</Col>
<Col sm={4}>
@@ -607,7 +607,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="This
parameter can be used to restrict the Directory Server instance to a single IP interface
(hostname, or IP address). This parameter specifically sets what interface to use for TLS
traffic. Requires restart. (nsslapd-securelistenhost).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Secure Listen Host
</Col>
<Col sm={4}>
@@ -615,7 +615,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="The name,
or nickname, of the server certificate inthe NSS datgabase the server should use
(nsSSLPersonalitySSL).">
- <Col className="ds-no-padding" sm={2}>
+ <Col className="ds-no-padding" sm={3}>
<ControlLabel>Server Certificate
Name</ControlLabel>
</Col>
<Col sm={4}>
@@ -631,7 +631,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="The
minimum SSL/TLS version the server will accept (sslversionmin).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Minimum TLS Version
</Col>
<Col sm={4}>
@@ -646,7 +646,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="The
maximum SSL/TLS version the server will accept (sslversionmax).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Maximum TLS Version
</Col>
<Col sm={4}>
@@ -661,7 +661,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="Sets how
the Directory Server enforces TLS client authentication (nsSSLClientAuth).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Client Authentication
</Col>
<Col sm={4}>
@@ -673,7 +673,7 @@ export class Security extends React.Component {
</Col>
</Row>
<Row className="ds-margin-top" title="Validate
server's certificate expiration date (nsslapd-validate-cert).">
- <Col componentClass={ControlLabel} sm={2}>
+ <Col componentClass={ControlLabel} sm={3}>
Validate Certificate
</Col>
<Col sm={4}>
diff --git a/src/cockpit/389-console/src/servers.html
b/src/cockpit/389-console/src/servers.html
index e8171c0..02e39ab 100644
--- a/src/cockpit/389-console/src/servers.html
+++ b/src/cockpit/389-console/src/servers.html
@@ -95,24 +95,24 @@
<div class="ds-divider"></div>
<div class="ds-inline">
<div>
- <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-attribute-name-exceptions" checked><label
+ <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-attribute-name-exceptions"><label
for="nsslapd-attribute-name-exceptions" class="ds-label"
title="Allows non-standard characters in attribute names to be used for backwards
compatibility with older servers"> Allow Attribute Naming Exceptions
</label>
</div>
<div>
- <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-dn-validate-strict" checked><label
+ <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-dn-validate-strict"><label
for="nsslapd-dn-validate-strict" class="ds-label"
title="Enables strict syntax validation for DNs, according to section 3 in RFC 4514
(nsslapd-dn-validate-strict)."> Enable Strict DN Syntax Validation</label>
</div>
<div>
- <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-entryusn-global" checked><label
+ <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-entryusn-global"><label
for="nsslapd-entryusn-global" class="ds-label"
title="For USN plugin - maintain unique USNs across all back end databases
(nsslapd-entryusn-global)."> Enable Unique USNs Across All Backends</label>
</div>
<div>
- <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-ignore-time-skew" checked><label
+ <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-ignore-time-skew"><label
for="nsslapd-ignore-time-skew" class="ds-label"
title="Ignore time skew when generating CSNs"> Ignore CSN Time
Skew</label>
</div>
<div>
- <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-readonly-server" checked><label
- for="nsslapd-readonly-server" class="ds-label"
title="Make entire server read-only (nsslapd-readonly)"> Server
Read-Only</label>
+ <input type="checkbox" class="ds-config-checkbox"
id="nsslapd-readonly"><label
+ for="nsslapd-readonly" class="ds-label" title="Make
entire server read-only (nsslapd-readonly)"> Server Read-Only</label>
</div>
</div>
diff --git a/src/cockpit/389-console/src/servers.js
b/src/cockpit/389-console/src/servers.js
index d3e285d..3d1c4fa 100644
--- a/src/cockpit/389-console/src/servers.js
+++ b/src/cockpit/389-console/src/servers.js
@@ -165,6 +165,7 @@ function get_and_set_config () {
$(".ds-accesslog-table").prop('checked', false);
$(".ds-errorlog-table").prop('checked', false);
config_values = {};
+ update_progress();
for (var attr in obj['attrs']) {
var val = obj['attrs'][attr][0];
@@ -189,6 +190,7 @@ function get_and_set_config () {
// Do the log level tables
if (attr == "nsslapd-accesslog-level") {
+ config_values[attr] = val;
var level_val = parseInt(val);
for ( var level in accesslog_levels ) {
if (level_val & accesslog_levels[level]) {
@@ -196,6 +198,7 @@ function get_and_set_config () {
}
}
} else if (attr == "nsslapd-errorlog-level") {
+ config_values[attr] = val;
var level_val = parseInt(val);
for ( var level in errorlog_levels ) {
if (level_val & errorlog_levels[level]) {
@@ -232,6 +235,7 @@ function update_suffix_dropdowns () {
$("#" + dropdowns[list]).append('<option value="' +
obj['items'][idx] + '" selected="selected">' +
obj['items'][idx] +'</option>');
}
}
+ update_progress();
}).fail(function(data) {
if (quiet === undefined) {
popup_err("Error", "Failed to get backend suffix list\n" +
data.message);
@@ -251,6 +255,7 @@ function get_and_set_localpwp (quiet) {
log_cmd('get_and_set_localpwp', 'Get local password policies', cmd);
cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
var obj = JSON.parse(data);
+ update_progress();
// Empty table
pwp_table.clear().draw();
@@ -276,13 +281,13 @@ function get_and_set_sasl () {
log_cmd('get_and_set_sasl', 'Get SASL mappings', cmd);
cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
var obj = JSON.parse(data);
+ update_progress();
sasl_table.clear().draw();
for (var idx in obj['items']) {
var map_cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id
+ '.socket','sasl', 'get', obj['items'][idx] ];
log_cmd('get_and_set_sasl', 'Get SASL mapping', map_cmd);
cockpit.spawn(map_cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
var map_obj = JSON.parse(data);
-
// Update html table
var sasl_priority = '100';
if ( map_obj['attrs'].hasOwnProperty('nssaslmappriority') ){
@@ -357,14 +362,29 @@ function save_config() {
var val = $("#" + attr).val();
// But first check for rootdn-pw changes and check confirm input matches
- if (attr == "nsslapd-rootpw" && (val != config_values[attr] ||
val != $("#nsslapd-rootpw-confirm").val())) {
- // Password change, make sure passwords match
- if (val != $("#nsslapd-rootpw-confirm").val()){
- popup_msg("Passwords do not match!", "The Directory Manager
passwords do not match, please correct before saving again.");
- return;
+ if (attr == "nsslapd-rootpw") {
+ if (val != config_values[attr] || val !=
$("#nsslapd-rootpw-confirm").val()) {
+ // Password change, make sure passwords match
+ if (val != $("#nsslapd-rootpw-confirm").val()){
+ popup_msg("Passwords do not match!", "The Directory Manager
passwords do not match, please correct before saving again.");
+ return;
+ }
+ }
+ if (val.length < 8) {
+ popup_msg("Password is too short!", "The Directory Manager
password must be at least 8 characters long.");
+ $("#nsslapd-rootpw").val(config_values[attr]);
+ $("#nsslapd-rootpw-confirm").val(config_values[attr]);
+ return;
}
}
+ if (attr == "nsslapd-port") {
+ if (!valid_num(config_values[attr])) {
+ popup_msg("Port number is not valid");
+ $("#nsslapd-port").val(config_values[attr]);
+ }
+ }
+
if ( val && val != config_values[attr]) {
mod['attr'] = attr;
mod['val'] = val;
@@ -382,10 +402,15 @@ function save_config() {
access_log_level += val;
}
});
- mod = {}
- mod['attr'] = "nsslapd-accesslog-level";
- mod['val'] = access_log_level;
- mod_list.push(mod);
+ if (config_values["nsslapd-accesslog-level"] === undefined) {
+ config_values["nsslapd-accesslog-level"] = "256";
+ }
+ if (config_values["nsslapd-accesslog-level"] != access_log_level) {
+ mod = {}
+ mod['attr'] = "nsslapd-accesslog-level";
+ mod['val'] = access_log_level;
+ mod_list.push(mod);
+ }
// Save error log levels
var error_log_level = 0;
@@ -396,10 +421,17 @@ function save_config() {
error_log_level += val;
}
});
- mod = {}
- mod['attr'] = "nsslapd-errorlog-level";
- mod['val'] = error_log_level;
- mod_list.push(mod);
+ if (config_values["nsslapd-errorlog-level"] === undefined ||
+ config_values["nsslapd-errorlog-level"] == "16384")
+ {
+ config_values["nsslapd-errorlog-level"] = "0";
+ }
+ if (config_values["nsslapd-errorlog-level"] != error_log_level) {
+ mod = {}
+ mod['attr'] = "nsslapd-errorlog-level";
+ mod['val'] = error_log_level;
+ mod_list.push(mod);
+ }
// Build dsconf commands to apply all the mods
if (mod_list.length) {
@@ -1007,6 +1039,10 @@ $(document).ready( function() {
* Get all the current values from the form.
*/
var policy_name = $("#local-entry-dn").val();
+ if (policy_name == "" || !valid_dn(policy_name)) {
+ popup_msg("Error", "You must enter a valid DN for the local
password policy");
+ return;
+ }
var pwp_track = "off";
if ( $("#local-passwordtrackupdatetime").is(":checked") ) {
pwp_track = "on";
@@ -1479,19 +1515,33 @@ $(document).ready( function() {
var new_server_id = $("#create-inst-serverid").val();
if (new_server_id == ""){
report_err($("#create-inst-serverid"), 'You must provide an
Instance name');
+ $("#create-inst-serverid").css("border-color",
"red");
return;
} else {
new_server_id = new_server_id.replace(/^slapd-/i, ""); // strip
"slapd-"
- setup_inf = setup_inf.replace('INST_NAME', new_server_id);
+ if (new_server_id.length > 128) {
+ report_err($("#create-inst-serverid"), 'Instance name is too
long, it must not exceed 128 characters');
+ $("#create-inst-serverid").css("border-color",
"red");
+ return;
+ }
+ if (new_server_id.match(/^[#%:-A-Za-z0-9_]+$/g)) {
+ setup_inf = setup_inf.replace('INST_NAME', new_server_id);
+ } else {
+ report_err($("#create-inst-serverid"), 'Instance name can only
contain letters, numbers, and: # % : - _');
+ $("#create-inst-serverid").css("border-color",
"red");
+ return;
+ }
}
// Port
var server_port = $("#create-inst-port").val();
if (server_port == ""){
report_err($("#create-inst-port"), 'You must provide a port
number');
+ $("#create-inst-port").css("border-color", "red");
return;
} else if (!valid_num(server_port)) {
- report_err($("#create-inst-port"), 'Port must be a number!');
+ report_err($("#create-inst-port"), 'Port must be a number between 1
and 65534!');
+ $("#create-inst-port").css("border-color", "red");
return;
} else {
setup_inf = setup_inf.replace('PORT', server_port);
@@ -1501,9 +1551,11 @@ $(document).ready( function() {
var secure_port = $("#create-inst-secureport").val();
if (secure_port == ""){
report_err($("#create-inst-secureport"), 'You must provide a secure
port number');
+ $("#create-inst-secureport").css("border-color",
"red");
return;
} else if (!valid_num(secure_port)) {
report_err($("#create-inst-secureport"), 'Secure port must be a
number!');
+ $("#create-inst-secureport").css("border-color",
"red");
return;
} else {
setup_inf = setup_inf.replace('SECURE_PORT', secure_port);
@@ -1513,6 +1565,7 @@ $(document).ready( function() {
var server_rootdn = $("#create-inst-rootdn").val();
if (server_rootdn == ""){
report_err($("#create-inst-rootdn"), 'You must provide a Directory
Manager DN');
+ $("#create-inst-rootdn").css("border-color",
"red");
return;
} else {
setup_inf = setup_inf.replace('ROOTDN', server_rootdn);
@@ -1536,6 +1589,10 @@ $(document).ready( function() {
report_err($("#rootdn-pw"), 'Directory Manager password can not be
empty!');
$("#rootdn-pw-confirm").css("border-color",
"red");
return;
+ } else if (root_pw.length < 8) {
+ report_err($("#rootdn-pw"), 'Directory Manager password must have
at least 8 characters');
+ $("#rootdn-pw-confirm").css("border-color",
"red");
+ return;
} else {
setup_inf = setup_inf.replace('ROOTPW', root_pw);
}
@@ -1546,9 +1603,11 @@ $(document).ready( function() {
if ( (backend_name != "" && backend_suffix == "") ||
(backend_name == "" && backend_suffix != "") ) {
if (backend_name == ""){
report_err($("#backend-name"), 'If you specify a backend suffix,
you must also specify a backend name');
+ $("#backend-name").css("border-color", "red");
return;
} else {
report_err($("#backend-suffix"), 'If you specify a backend name,
you must also specify a backend suffix');
+ $("#backend-suffix").css("border-color", "red");
return;
}
}
diff --git a/src/lib389/lib389/config.py b/src/lib389/lib389/config.py
index 23ab9f2..53f1b16 100644
--- a/src/lib389/lib389/config.py
+++ b/src/lib389/lib389/config.py
@@ -64,7 +64,7 @@ class Config(DSLdapObject):
return DN_CONFIG
def replace(self, key, value):
- if key.lower() == 'nsslapd-secureport' and selinux_present():
+ if selinux_present() and (key.lower() == 'nsslapd-secureport' or
key.lower() == 'nsslapd-port'):
# Get old port and remove label
old_port = self.get_attr_val_utf8(key)
self.log.debug("Removing old port's selinux label...")
diff --git a/src/lib389/lib389/instance/options.py
b/src/lib389/lib389/instance/options.py
index 702b60a..dcc7f63 100644
--- a/src/lib389/lib389/instance/options.py
+++ b/src/lib389/lib389/instance/options.py
@@ -166,8 +166,9 @@ class Slapd2Base(Options2):
self._helptext['root_password'] = ("Sets the password of the account
specified in the \"root_dn\" parameter. " +
"You can either set this parameter to a
plain text password dscreate hashes " +
"during the installation or to a
\"{algorithm}hash\" string generated by the " +
- "pwdhash utility. Note that setting a
plain text password can be a security " +
- "risk if unprivileged users can read this
INF file!")
+ "pwdhash utility. The password must be at
least 8 characters long. Note " +
+ "that setting a plain text password can
be a security risk if unprivileged " +
+ "users can read this INF file!")
self._options['prefix'] = ds_paths.prefix
self._type['prefix'] = str
diff --git a/src/lib389/lib389/instance/remove.py b/src/lib389/lib389/instance/remove.py
index 1f15b46..c9a872e 100644
--- a/src/lib389/lib389/instance/remove.py
+++ b/src/lib389/lib389/instance/remove.py
@@ -105,7 +105,10 @@ def remove_ds_instance(dirsrv, force=False):
_log.debug(f"CMD: {' '.join(result.args)} ; STDOUT: {result.stdout}
; STDERR: {result.stderr}")
_log.debug("Removing %s" % tmpfiles_d_path)
- shutil.rmtree(tmpfiles_d_path, ignore_errors=True)
+ try:
+ os.remove(tmpfiles_d_path)
+ except OSError as e:
+ _log.debug("Failed to remove tmpfile: " + str(e))
# Nor can we assume we have selinux. Try docker sometime ;)
if dirsrv.ds_paths.with_selinux:
diff --git a/src/lib389/lib389/instance/setup.py b/src/lib389/lib389/instance/setup.py
index 58012b3..bb0ff32 100644
--- a/src/lib389/lib389/instance/setup.py
+++ b/src/lib389/lib389/instance/setup.py
@@ -243,8 +243,11 @@ class SetupDs(object):
print('===========================================')
# Set the defaults
- general = {'config_version': 2, 'full_machine_name':
socket.getfqdn(),
- 'strict_host_checking': False, 'selinux': True,
'systemd': ds_paths.with_systemd,
+ general = {'config_version': 2,
+ 'full_machine_name': socket.getfqdn(),
+ 'strict_host_checking': False,
+ 'selinux': True,
+ 'systemd': ds_paths.with_systemd,
'defaults': '999999999', 'start': True}
slapd = {'self_sign_cert_valid_months': 24,
@@ -394,6 +397,11 @@ class SetupDs(object):
print('Password can not be empty')
continue
+ if len(rootpw1) < 8:
+ print('Password must be at least 8 characters long')
+ continue
+
+
rootpw2 = getpass.getpass('Confirm the Directory Manager Password:
').rstrip()
if rootpw1 != rootpw2:
print('Passwords do not match')
@@ -568,6 +576,9 @@ class SetupDs(object):
assert_c(is_a_dn(slapd['root_dn']), "root_dn in section [slapd] is
not a well formed LDAP DN")
assert_c(slapd['root_password'] is not None and
slapd['root_password'] != '',
"Configuration attribute 'root_password' in section [slapd]
not found")
+ if len(slapd['root_password']) < 8:
+ raise ValueError("root_password must be at least 8 characters
long")
+
# Check if pre-hashed or not.
# !!!!!!!!!!!!!!
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.