[389-ds-base] branch 389-ds-base-1.4.2 updated: Ticket 50741-cont bdb_start - Detected Disorderly Shutdown
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
lkrispen pushed a commit to branch 389-ds-base-1.4.2
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.4.2 by this push:
new 9181282 Ticket 50741-cont bdb_start - Detected Disorderly Shutdown
9181282 is described below
commit 9181282de38995d573e8d161705a3c82ead25ef5
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
AuthorDate: Fri Dec 6 13:54:04 2019 +0100
Ticket 50741-cont bdb_start - Detected Disorderly Shutdown
Bug: Offline import does no longer write guardian file, next
normal start will raise a Disorderly Shutdown
Fix: The bug was introduced with the fix for #50659 when dblayer_close() was
removed from import_moain_offline becasue it was called twice in some
scenarios. But it did miss in ldif2db. Add it there.
Also correct function reference in error messages
Reviewed by: Thierry, thanks
---
ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c | 60 +++++++++++------------
ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c | 3 ++
2 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
index 60b6e13..15574e6 100644
--- a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
+++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
@@ -2274,7 +2274,7 @@ bdb_import_main(void *arg)
producer, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE)) {
PRErrorCode prerr = PR_GetError();
- slapi_log_err(SLAPI_LOG_ERR, "import_main_offline",
+ slapi_log_err(SLAPI_LOG_ERR, "bdb_import_main",
"Unable to spawn upgrade dn producer thread, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
prerr, slapd_pr_strerror(prerr));
goto error;
@@ -2285,19 +2285,19 @@ bdb_import_main(void *arg)
PR_UNJOINABLE_THREAD,
SLAPD_DEFAULT_THREAD_STACKSIZE)) {
PRErrorCode prerr = PR_GetError();
- slapi_log_err(SLAPI_LOG_ERR, "import_main_offline",
+ slapi_log_err(SLAPI_LOG_ERR, "bdb_import_main",
"Unable to spawn index producer thread, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
prerr, slapd_pr_strerror(prerr));
goto error;
}
} else {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Beginning import job...");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Beginning import job...");
if (!CREATE_THREAD(PR_USER_THREAD, (VFP)import_producer, producer,
PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD,
PR_UNJOINABLE_THREAD,
SLAPD_DEFAULT_THREAD_STACKSIZE)) {
PRErrorCode prerr = PR_GetError();
- slapi_log_err(SLAPI_LOG_ERR, "import_main_offline",
+ slapi_log_err(SLAPI_LOG_ERR, "bdb_import_main",
"Unable to spawn import producer thread, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
prerr, slapd_pr_strerror(prerr));
goto error;
@@ -2305,9 +2305,9 @@ bdb_import_main(void *arg)
}
if (0 == job->job_index_buffer_suggestion)
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Index buffering is disabled.");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Index buffering is disabled.");
else
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"Index buffering enabled with bucket size %lu",
(long unsigned int)job->job_index_buffer_suggestion);
@@ -2343,13 +2343,13 @@ bdb_import_main(void *arg)
if (ret == ERR_IMPORT_ABORTED) {
/* at least one of the threads has aborted -- shut down ALL
* of the threads */
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main",
"Aborting all %s threads...", opstr);
/* this abort sets the abort flag on the threads and will block for
* the exit of all threads
*/
import_set_abort_flag_all(job, 1);
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main",
"%s threads aborted.", opstr);
aborted = 1;
goto error;
@@ -2359,7 +2359,7 @@ bdb_import_main(void *arg)
goto error;
} else if (0 != ret) {
/* Some horrible fate has befallen the import */
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main",
"Fatal pass error %d", ret);
goto error;
}
@@ -2405,7 +2405,7 @@ bdb_import_main(void *arg)
job->first_ID = job->ready_ID + 1;
import_free_thread_data(job);
job->worker_list = producer;
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"Beginning pass number %d", job->total_pass + 1);
} else {
/* Bizarro-slapd */
@@ -2416,7 +2416,7 @@ bdb_import_main(void *arg)
/* kill the producer now; we're done */
if (producer) {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Cleaning up producer thread...");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Cleaning up producer thread...");
producer->command = STOP;
/* wait for the lead thread to stop */
while (producer->state != FINISHED) {
@@ -2424,18 +2424,18 @@ bdb_import_main(void *arg)
}
}
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Indexing complete. Post-processing...");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Indexing complete. Post-processing...");
/* Now do the numsubordinates attribute */
/* [610066] reindexed db cannot be used in the following backup/restore */
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"Generating numsubordinates (this may take several minutes to complete)...");
if ((!(job->flags & FLAG_REINDEXING) || (job->flags & FLAG_DN2RDN)) &&
(ret = bdb_update_subordinatecounts(be, job, NULL)) != 0) {
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main",
"Failed to update numsubordinates attributes");
goto error;
}
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"Generating numSubordinates complete.");
if (!entryrdn_get_noancestorid()) {
@@ -2446,12 +2446,12 @@ bdb_import_main(void *arg)
ainfo_get(be, "ancestorid", &ai);
dblayer_erase_index_file(be, ai, PR_TRUE, 0);
if ((ret = bdb_ancestorid_create_index(be, job)) != 0) {
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline", "Failed to create ancestorid index");
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main", "Failed to create ancestorid index");
goto error;
}
}
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Flushing caches...");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Flushing caches...");
/* New way to exit the routine: check the return code.
* If it's non-zero, delete the database files.
@@ -2462,7 +2462,7 @@ bdb_import_main(void *arg)
error:
/* If we fail, the database is now in a mess, so we delete it
except dry run mode */
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "Closing files...");
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "Closing files...");
cache_clear(&job->inst->inst_cache, CACHE_TYPE_ENTRY);
if (entryrdn_get_switch()) {
cache_clear(&job->inst->inst_dncache, CACHE_TYPE_DN);
@@ -2476,14 +2476,14 @@ error:
/* initialize the entry cache */
if (!cache_init(&(inst->inst_cache), DEFAULT_CACHE_SIZE,
DEFAULT_CACHE_ENTRIES, CACHE_TYPE_ENTRY)) {
- slapi_log_err(SLAPI_LOG_ERR, "import_main_offline",
+ slapi_log_err(SLAPI_LOG_ERR, "bdb_import_main",
"cache_init failed. Server should be restarted.\n");
}
/* initialize the dn cache */
if (!cache_init(&(inst->inst_dncache), DEFAULT_DNCACHE_SIZE,
DEFAULT_DNCACHE_MAXCOUNT, CACHE_TYPE_DN)) {
- slapi_log_err(SLAPI_LOG_ERR, "import_main_offline",
+ slapi_log_err(SLAPI_LOG_ERR, "bdb_import_main",
"dn cache_init failed. Server should be restarted.\n");
}
}
@@ -2496,7 +2496,7 @@ error:
}
} else {
if (0 != (ret = dblayer_instance_close(job->inst->inst_be))) {
- import_log_notice(job, SLAPI_LOG_WARNING, "import_main_offline", "Failed to close database");
+ import_log_notice(job, SLAPI_LOG_WARNING, "bdb_import_main", "Failed to close database");
}
}
end = slapi_current_utc_time();
@@ -2508,7 +2508,7 @@ error:
if (job->not_here_skipped) {
if (job->skipped) {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"%s complete. Processed %lu entries "
"(%d bad entries were skipped, "
"%d entries were skipped because they don't "
@@ -2518,7 +2518,7 @@ error:
job->skipped, job->not_here_skipped,
seconds_to_import, entries_per_second);
} else {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"%s complete. Processed %lu entries "
"(%d entries were skipped because they don't "
"belong to this database) "
@@ -2529,7 +2529,7 @@ error:
}
} else {
if (job->skipped) {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"%s complete. Processed %lu entries "
"(%d were skipped) in %d seconds. "
"(%.2f entries/sec)",
@@ -2537,7 +2537,7 @@ error:
job->skipped, seconds_to_import,
entries_per_second);
} else {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main",
"%s complete. Processed %lu entries "
"in %d seconds. (%.2f entries/sec)",
opstr, (long unsigned int)entries_processed,
@@ -2548,7 +2548,7 @@ error:
if (job->flags & (FLAG_DRYRUN | FLAG_UPGRADEDNFORMAT_V1)) {
if (0 == ret) {
- import_log_notice(job, SLAPI_LOG_INFO, "import_main_offline", "%s complete. %s is up-to-date.",
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_import_main", "%s complete. %s is up-to-date.",
opstr, job->inst->inst_name);
ret = 0;
if (job->task) {
@@ -2556,7 +2556,7 @@ error:
}
import_all_done(job, ret);
} else if (NEED_DN_NORM_BT == ret) {
- import_log_notice(job, SLAPI_LOG_NOTICE, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_NOTICE, "bdb_import_main",
"%s complete. %s needs upgradednformat all.",
opstr, job->inst->inst_name);
if (job->task) {
@@ -2565,7 +2565,7 @@ error:
import_all_done(job, ret);
ret = 1;
} else if (NEED_DN_NORM == ret) {
- import_log_notice(job, SLAPI_LOG_NOTICE, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_NOTICE, "bdb_import_main",
"%s complete. %s needs upgradednformat.",
opstr, job->inst->inst_name);
if (job->task) {
@@ -2574,7 +2574,7 @@ error:
import_all_done(job, ret);
ret = 2;
} else if (NEED_DN_NORM_SP == ret) {
- import_log_notice(job, SLAPI_LOG_NOTICE, "import_main_offline",
+ import_log_notice(job, SLAPI_LOG_NOTICE, "bdb_import_main",
"%s complete. %s needs upgradednformat spaces.",
opstr, job->inst->inst_name);
if (job->task) {
@@ -2589,7 +2589,7 @@ error:
}
}
} else if (0 != ret) {
- import_log_notice(job, SLAPI_LOG_ERR, "import_main_offline", "%s failed.", opstr);
+ import_log_notice(job, SLAPI_LOG_ERR, "bdb_import_main", "%s failed.", opstr);
if (job->task != NULL) {
slapi_task_finish(job->task, ret);
}
diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c
index bb411a5..542147c 100644
--- a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c
+++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c
@@ -383,6 +383,9 @@ bdb_ldif2db(Slapi_PBlock *pb)
/* always use "new" import code now */
slapi_pblock_set(pb, SLAPI_BACKEND, inst->inst_be);
ret = bdb_back_ldif2db(pb);
+ if (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) {
+ dblayer_close(li, DBLAYER_IMPORT_MODE);
+ }
if (ret == 0) {
if (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) {
dblayer_import_file_update(inst);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] branch 389-ds-base-1.4.1 updated: Ticket - 50349 - additional fix: filter schema check must handle subtypes
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
tbordaz 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 0adfacd Ticket - 50349 - additional fix: filter schema check must handle subtypes
0adfacd is described below
commit 0adfacd47c6db41cfc2098fe9d2c8a29ac1038f7
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
AuthorDate: Wed Oct 9 16:31:13 2019 +0200
Ticket - 50349 - additional fix: filter schema check must handle subtypes
Bug: if the filter did contain an attribute with a subtype eg givenname;lang-de
then the schema lookup failed.
Fix: The subtype needs to be removed befor asi lookup
Reviewed by: William, Thiery, Mark - thanks
---
ldap/servers/slapd/attrsyntax.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
index 8d218d4..7de006c 100644
--- a/ldap/servers/slapd/attrsyntax.c
+++ b/ldap/servers/slapd/attrsyntax.c
@@ -394,11 +394,33 @@ attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock, PRUi
* The main reason to use this over attr_syntax_get_by_name_locking_optional is to
* avoid the reference count increment/decrement cycle when we only need a boolean
* of existance, rather than retriving the reference to the attribute itself.
+ *
+ * But we do need to strip subtypes
*/
int32_t
attr_syntax_exist_by_name_nolock(char *name) {
struct asyntaxinfo *asi = NULL;
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(name2asi, name);
+ char *check_name = NULL;
+ char *p = NULL;
+ int free_attr = 0;
+
+ /* Ignore any attribute subtypes. */
+ if ((p = strchr(name, ';'))) {
+ int check_len = p - name + 1;
+
+ check_name = (char *)slapi_ch_malloc(check_len);
+ PR_snprintf(check_name, check_len, "%s", name);
+ free_attr = 1;
+ } else {
+ check_name = name;
+ }
+
+ asi = (struct asyntaxinfo *)PL_HashTableLookup_const(name2asi, check_name);
+
+ if (free_attr) {
+ slapi_ch_free_string(&check_name);
+ }
+
if (asi != NULL) {
return 1;
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] 02/02: Issue 50836 - Port Schema UI tab to React
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
spichugi pushed a commit to branch 389-ds-base-1.4.2
in repository 389-ds-base.
commit 45ce51ca1c5711267842e30f8752d005fe9e3a72
Author: Simon Pichugin <spichugi(a)redhat.com>
AuthorDate: Mon Dec 23 00:28:32 2019 +0100
Issue 50836 - Port Schema UI tab to React
Description: Port the schema UI tab to React and preserve all
existing features.
https://pagure.io/389-ds-base/issue/50836
Reviewed by: mreynolds (Thank you!!)
---
src/cockpit/389-console/src/css/ds.css | 5 +
src/cockpit/389-console/src/ds.js | 10 +-
src/cockpit/389-console/src/index.es6 | 7 +
src/cockpit/389-console/src/index.html | 10 +-
.../389-console/src/lib/schema/schemaModals.jsx | 660 +++++++++++++
.../389-console/src/lib/schema/schemaTables.jsx | 558 +++++++++++
src/cockpit/389-console/src/lib/tools.jsx | 54 +-
src/cockpit/389-console/src/schema.html | 377 -------
src/cockpit/389-console/src/schema.js | 925 -----------------
src/cockpit/389-console/src/schema.jsx | 1042 ++++++++++++++++++++
src/cockpit/389-console/webpack.config.js | 2 -
src/lib389/lib389/schema.py | 10 +-
12 files changed, 2323 insertions(+), 1337 deletions(-)
diff --git a/src/cockpit/389-console/src/css/ds.css b/src/cockpit/389-console/src/css/ds.css
index 662d8de..a71f615 100644
--- a/src/cockpit/389-console/src/css/ds.css
+++ b/src/cockpit/389-console/src/css/ds.css
@@ -1021,6 +1021,11 @@ option {
width: 120px;
}
+.ds-schema-dropdown {
+ border-color: #06c !important;
+ color: #06c !important;
+}
+
.treeview .list-group-item {
/* remove focus border */
outline: none;
diff --git a/src/cockpit/389-console/src/ds.js b/src/cockpit/389-console/src/ds.js
index 7b4db77..0bddcef 100644
--- a/src/cockpit/389-console/src/ds.js
+++ b/src/cockpit/389-console/src/ds.js
@@ -12,7 +12,7 @@ var security_page_loaded = 1;
var db_page_loaded = 1;
var repl_page_loaded = 1;
var plugin_page_loaded = 1;
-var schema_page_loaded = 0;
+var schema_page_loaded = 1;
var monitor_page_loaded = 1;
var config_loaded = 0;
@@ -412,10 +412,6 @@ function load_config (refresh){
get_and_set_localpwp();
update_progress();
- // Schema page
- get_and_set_schema_tables();
- update_progress();
-
// Initialize the tabs
$(".ds-tab-list").css( 'color', '#777');
$("#server-tab").css( 'color', '#228bc0');
@@ -472,6 +468,10 @@ $(window.document).ready(function() {
$(".all-pages").hide();
$("#security-content").show();
});
+ $("#schema-tab").on("click", function() {
+ $(".all-pages").hide();
+ $("#schema-content").show();
+ });
$("#replication-tab").on("click", function() {
$(".all-pages").hide();
$("#replication-content").show();
diff --git a/src/cockpit/389-console/src/index.es6 b/src/cockpit/389-console/src/index.es6
index 6797dd5..6f2673f 100644
--- a/src/cockpit/389-console/src/index.es6
+++ b/src/cockpit/389-console/src/index.es6
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
import { Plugins } from "./plugins.jsx";
import { Database } from "./database.jsx";
import { Monitor } from "./monitor.jsx";
+import { Schema } from "./schema.jsx";
import { Security } from "./security.jsx";
import { Replication } from "./replication.jsx";
@@ -49,6 +50,12 @@ function renderReactDOM(clear) {
<Security serverId={serverIdElem} key={tabKey} />,
document.getElementById("security")
);
+
+ // Schema tab
+ ReactDOM.render(
+ <Schema serverId={serverIdElem} key={tabKey} />,
+ document.getElementById("schema")
+ );
}
// We have to create the wrappers because this is no simple way
diff --git a/src/cockpit/389-console/src/index.html b/src/cockpit/389-console/src/index.html
index 6a0479c..c1b9952 100644
--- a/src/cockpit/389-console/src/index.html
+++ b/src/cockpit/389-console/src/index.html
@@ -18,7 +18,6 @@
<script src="static/c3.min.js"></script>
<script src="static/d3.min.js"></script>
<script src="ds.js"></script>
- <script src="schema.js"></script>
<script src="servers.js"></script>
<link href="static/bootstrap.min.css" rel="stylesheet">
<link href="static/jquery.dataTables.min.css" type="text/css" rel="stylesheet">
@@ -109,15 +108,9 @@
<!-- Schema navtab -->
<li class="dropdown ds-nav-tab">
- <a href="#0" class="ds-tab-list" data-toggle="dropdown" id="schema-tab">
+ <a href="#0" class="ds-tab-list ds-tab-standalone" id="schema-tab">
Schema
- <b class="caret"></b>
</a>
- <ul class="dropdown-menu ds-nav-item">
- <li><a href="#0"class="ds-nav-choice" id="objectclass-btn" parent-id="schema-tab">Objectclasses</a></li>
- <li><a href="#0"class="ds-nav-choice" id="attribute-btn" parent-id="schema-tab">Attributes</a></li>
- <li><a href="#0" class="ds-nav-choice" id="schema-mr-btn" parent-id="schema-tab">Matching Rules</a></li>
- </ul>
</li>
<!-- Plugins navtab -->
@@ -514,6 +507,7 @@
</div>
<div id="schema-content" class="all-pages" hidden>
+ <div id="schema"></div>
</div>
<div id="plugin-content" class="all-pages" hidden>
diff --git a/src/cockpit/389-console/src/lib/schema/schemaModals.jsx b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
new file mode 100644
index 0000000..6b6049a
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
@@ -0,0 +1,660 @@
+import React from "react";
+import {
+ Row,
+ Spinner,
+ Modal,
+ Icon,
+ Button,
+ Checkbox,
+ noop,
+ Form,
+ FormControl,
+ FormGroup,
+ ControlLabel,
+ Col
+} from "patternfly-react";
+import { Typeahead } from "react-bootstrap-typeahead";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassModal extends React.Component {
+ render() {
+ const {
+ newOcEntry,
+ ocModalViewOnly,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ objectclasses,
+ attributes,
+ ocName,
+ ocDesc,
+ ocOID,
+ ocParent,
+ ocKind,
+ ocMust,
+ ocMay,
+ objectclassModalShow,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving objectClass...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={objectclassModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close" />
+ </button>
+ <Modal.Title>
+ {ocModalViewOnly ? (
+ `View ObjectClass - ${ocName}`
+ ) : (
+ <div>
+ {newOcEntry ? "Add" : "Edit"} ObjectClass
+ {ocName != "" ? ` - ${ocName}` : ""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="ocName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the objectClass">
+ Objectclass Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="ocName"
+ type="text"
+ value={ocName}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is the objectClass's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocDesc}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocOID">
+ <Col sm={4}>
+ <ControlLabel title="Object identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocOID}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocParent" controlId="ocParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass's parent">
+ Parent Objectclass
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+ handleTypeaheadChange("ocParent", values);
+ }}
+ selected={ocParent}
+ newSelectionPrefix="Add a parent: "
+ options={objectclasses}
+ placeholder="Type a parent objectClass..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocKind" controlId="ocKind" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass kind">
+ Objectclass Kind
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="ocKind"
+ className="btn btn-default dropdown"
+ onChange={handleFieldChange}
+ value={ocKind}
+ disabled={ocModalViewOnly}
+ >
+ <option>STRUCTURAL</option>
+ <option>ABSTRACT</option>
+ <option>AUXILIARY</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMust" controlId="ocMust" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A must attribute name">
+ Required Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMust", values);
+ }}
+ selected={ocMust}
+ newSelectionPrefix="Add a required attribute: "
+ options={attributes}
+ placeholder="Type an attribute name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMay" controlId="ocMay" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A may attribute name">
+ Allowed Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMay", values);
+ }}
+ selected={ocMay}
+ newSelectionPrefix="Add an allowed attribute: "
+ options={attributes}
+ placeholder="Type an attribute name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {ocModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newOcEntry ? addHandler : editHandler}
+ >
+ {newOcEntry ? "Add" : "Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+ObjectClassModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ newOcEntry: PropTypes.bool,
+ ocModalViewOnly: PropTypes.bool,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ objectclasses: PropTypes.array,
+ attributes: PropTypes.array,
+ ocName: PropTypes.string,
+ ocDesc: PropTypes.string,
+ ocOID: PropTypes.string,
+ ocParent: PropTypes.array,
+ ocKind: PropTypes.string,
+ ocMust: PropTypes.array,
+ ocMay: PropTypes.array,
+ objectclassModalShow: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ newOcEntry: true,
+ ocModalViewOnly: false,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ objectclasses: [],
+ attributes: [],
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: false,
+ closeModal: noop,
+ loading: false
+};
+
+class AttributeTypeModal extends React.Component {
+ render() {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr,
+ atModalViewOnly,
+ attributeModalShow,
+ newAtEntry,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ attributes,
+ syntaxes,
+ matchingrules,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving attribute...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={attributeModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close" />
+ </button>
+ <Modal.Title>
+ {atModalViewOnly ? (
+ `View Attribute - ${atName}`
+ ) : (
+ <div>
+ {newAtEntry ? "Add" : "Edit"} Attribute
+ {atName != "" ? ` - ${atName}` : ""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="atName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the attribute">
+ Attribute Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="atName"
+ type="text"
+ value={atName}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is the attribute's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atDesc}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atOID">
+ <Col sm={4}>
+ <ControlLabel title="Object identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atOID}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atParent" controlId="atParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's parent">
+ Parent Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+ handleTypeaheadChange("atParent", values);
+ }}
+ selected={atParent}
+ newSelectionPrefix="Add a parent: "
+ options={attributes}
+ placeholder="Type a parent attribute..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSyntax" controlId="atSyntax" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's syntax">
+ Syntax Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atSyntax", values);
+ }}
+ selected={atSyntax}
+ newSelectionPrefix="Add a syntax: "
+ options={syntaxes}
+ placeholder="Type a syntax name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atUsage" controlId="atUsage" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute usage purpose">
+ Attribute Usage
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="atUsage"
+ className="btn btn-default dropdown"
+ onChange={handleFieldChange}
+ value={atUsage}
+ disabled={atModalViewOnly}
+ >
+ <option>userApplications</option>
+ <option>directoryOperation</option>
+ <option>distributedOperation</option>
+ <option>dSAOperation</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="atMultivalued" controlId="atMultivalued">
+ <Col sm={4}>
+ <ControlLabel title="If attribute can have a multiple values">
+ Multivalued Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atMultivalued"
+ checked={atMultivalued}
+ title="If attribute can have a multiple values"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atNoUserMod" controlId="atNoUserMod">
+ <Col sm={4}>
+ <ControlLabel title="If attribute is not modifiable by a client application">
+ Not Modifiable By A User
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atNoUserMod"
+ checked={atNoUserMod}
+ title="If attribute is not modifiable by a client application"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atAlias" controlId="atAlias" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An alias name for the attribute">
+ Alias Names
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("atAlias", values);
+ }}
+ selected={atAlias}
+ options={[]}
+ newSelectionPrefix="Add an alias: "
+ placeholder="Type an alias name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atEqMr" controlId="atEqMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An equality matching rule">
+ Equality Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atEqMr", values);
+ }}
+ selected={atEqMr}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atOrder" controlId="atOrder" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An order matching rule">
+ Order Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atOrder", values);
+ }}
+ selected={atOrder}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSubMr" controlId="atSubMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A substring matching rule">
+ Substring Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atSubMr", values);
+ }}
+ selected={atSubMr}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {atModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newAtEntry ? addHandler : editHandler}
+ >
+ {newAtEntry ? "Add" : "Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+AttributeTypeModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ attributes: PropTypes.array,
+ matchingrules: PropTypes.array,
+ syntaxes: PropTypes.array,
+ atName: PropTypes.string,
+ atDesc: PropTypes.string,
+ atOID: PropTypes.string,
+ atParent: PropTypes.array,
+ atSyntax: PropTypes.array,
+ atUsage: PropTypes.string,
+ atMultivalued: PropTypes.bool,
+ atNoUserMod: PropTypes.bool,
+ atAlias: PropTypes.array,
+ atEqMr: PropTypes.array,
+ atOrder: PropTypes.array,
+ atSubMr: PropTypes.array,
+ atModalViewOnly: PropTypes.bool,
+ attributeModalShow: PropTypes.bool,
+ newAtEntry: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+AttributeTypeModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ attributes: [],
+ matchingrules: [],
+ syntaxes: [],
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ closeModal: noop,
+ loading: false
+};
+
+export { ObjectClassModal, AttributeTypeModal };
diff --git a/src/cockpit/389-console/src/lib/schema/schemaTables.jsx b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
new file mode 100644
index 0000000..296845c
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
@@ -0,0 +1,558 @@
+import React from "react";
+import {
+ Button,
+ DropdownButton,
+ MenuItem,
+ actionHeaderCellFormatter,
+ sortableHeaderCellFormatter,
+ tableCellFormatter,
+ noop
+} from "patternfly-react";
+import { DSTable } from "../dsTable.jsx";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "ObjectClass Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "must",
+ header: {
+ label: "Required Attributes",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "may",
+ header: {
+ label: "Allowed Attributes",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user defined" ? (
+ <Button
+ onClick={() => {
+ this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Objectclass
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit ObjectClass
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete ObjectClass
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="ObjectClasses"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+ObjectClassesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ loading: false
+};
+
+class AttributesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Attribute Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {
+ this.props.syntaxes.filter(
+ attr => attr.id === value[0]
+ )[0]["label"]
+ }
+ </td>
+ ];
+ }
+ ]
+ }
+ },
+ {
+ property: "multivalued",
+ header: {
+ label: "Multivalued",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value ? "yes" : "no"}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user defined" ? (
+ <Button
+ onClick={() => {
+ this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Attribute
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit Attribute
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete Attribute
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="Attributes"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+AttributesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ syntaxes: PropTypes.array,
+ loading: PropTypes.bool
+};
+
+AttributesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ syntaxes: [],
+ loading: false
+};
+
+class MatchingRulesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Matching Rule Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "desc",
+ header: {
+ label: "Description",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [tableCellFormatter]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="oid"
+ rows={this.props.rows}
+ toolBarSearchField="Matching Rules"
+ toolBarDisableLoadingSpinner
+ />
+ </div>
+ );
+ }
+}
+
+MatchingRulesTable.propTypes = {
+ rows: PropTypes.array
+};
+
+MatchingRulesTable.defaultProps = {
+ rows: []
+};
+
+export { ObjectClassesTable, AttributesTable, MatchingRulesTable };
diff --git a/src/cockpit/389-console/src/lib/tools.jsx b/src/cockpit/389-console/src/lib/tools.jsx
index 631135e..7617a78 100644
--- a/src/cockpit/389-console/src/lib/tools.jsx
+++ b/src/cockpit/389-console/src/lib/tools.jsx
@@ -6,7 +6,9 @@ export function searchFilter(searchFilterValue, columnsToSearch, rows) {
if (columnsToSearch && columnsToSearch.length) {
columnsToSearch.forEach(column => {
if (column in row) {
- rowToSearch.push(row[column]);
+ if (row[column] != null) {
+ rowToSearch.push(row[column]);
+ }
}
});
} else {
@@ -53,22 +55,26 @@ export function log_cmd(js_func, desc, cmd_array) {
cmd_list.push(cmd);
}
}
- console.log(
- "CMD: " + js_func + ": " + desc + " ==> " + cmd_list.join(" ")
- );
+ console.log("CMD: " + js_func + ": " + desc + " ==> " + cmd_list.join(" "));
}
}
// Convert DS timestamp to a friendly string: 20180921142257Z -> 10/21/2018, 2:22:57 PM
-export function get_date_string (timestamp) {
+export function get_date_string(timestamp) {
let year = timestamp.substr(0, 4);
let month = timestamp.substr(4, 2);
let day = timestamp.substr(6, 2);
let hour = timestamp.substr(8, 2);
let minute = timestamp.substr(10, 2);
let sec = timestamp.substr(12, 2);
- let date = new Date(parseInt(year), (parseInt(month) - 1), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let date = new Date(
+ parseInt(year),
+ parseInt(month) - 1,
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
return date.toLocaleString();
}
@@ -81,8 +87,14 @@ export function get_date_diff(start, end) {
let hour = start.substr(8, 2);
let minute = start.substr(10, 2);
let sec = start.substr(12, 2);
- let startDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let startDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Get the servers current date
year = end.substr(0, 4);
@@ -91,17 +103,23 @@ export function get_date_diff(start, end) {
hour = end.substr(8, 2);
minute = end.substr(10, 2);
sec = end.substr(12, 2);
- let currDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let currDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Generate pretty elapsed time string
- let seconds = Math.floor((currDate - (startDate)) / 1000);
+ let seconds = Math.floor((currDate - startDate) / 1000);
let minutes = Math.floor(seconds / 60);
let hours = Math.floor(minutes / 60);
let days = Math.floor(hours / 24);
- hours = hours - (days * 24);
- minutes = minutes - (days * 24 * 60) - (hours * 60);
- seconds = seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
+ hours = hours - days * 24;
+ minutes = minutes - days * 24 * 60 - hours * 60;
+ seconds = seconds - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60;
return `${days} days, ${hours} hours, ${minutes} minutes, and ${seconds} seconds`;
}
@@ -114,7 +132,7 @@ export function bad_file_name(file_name) {
return false;
}
-export function valid_port (val) {
+export function valid_port(val) {
// Validate value is a number and between 1 and 65535
let result = !isNaN(val);
if (result) {
@@ -125,9 +143,9 @@ export function valid_port (val) {
return result;
}
-export function valid_dn (dn) {
+export function valid_dn(dn) {
// Validate value is a valid DN (sanity validation)
- if (dn.endsWith(',')) {
+ if (dn.endsWith(",")) {
return false;
}
let dn_regex = new RegExp("^([A-Za-z]+=.*)");
diff --git a/src/cockpit/389-console/src/schema.html b/src/cockpit/389-console/src/schema.html
deleted file mode 100644
index cb6baf9..0000000
--- a/src/cockpit/389-console/src/schema.html
+++ /dev/null
@@ -1,377 +0,0 @@
-
-<div id="schema-content">
- <div id="objectclass-page" class="all-pages ds-margin-left" hidden>
- <h3 class="ds-config-header">Objectclasses</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="oc-user-defined"><label
- for="oc-user-defined" class="ds-label">Only Non-standard Schema (objectClasses with X-ORIGIN: "user defined")</label>
- </div>
- <table id="oc-table" class="display ds-repl-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Objectclass Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Required Attributes</th>
- <th class="ds-center">Allowed Attributes</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="add-oc-button" name="create-oc" data-toggle="modal" data-target="#add-edit-oc-form" class="btn btn-primary ds-button">Create Objectclass</button>
- </div>
-
- <div id="attribute-page" class="all-pages ds-margin-left" hidden>
- <h3 class="ds-config-header">Attributes</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-user-defined"><label
- for="attr-user-defined" class="ds-label">Only Non-standard Schema (attributes with X-ORIGIN: "user defined")</label>
- </div>
- <table id="attr-table" class="display ds-repl-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Attribute Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Syntax</th>
- <th class="ds-center">Multivalued</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="create-attr-button" data-toggle="modal" data-target="#add-edit-attr-form" class="btn btn-primary ds-button">Create Attribute</button>
- </div>
-
- <div id="schema-mr" class="all-pages ds-margin-left" hidden>
- <div class="">
- <h3 class="ds-config-header">Matching Rules</h3>
- <table id="schema-mr-table" class="display ds-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th>Matching Rule Name</th>
- <th>OID</th>
- <th>Syntax</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody id="standard-body">
- </tbody>
- </table>
- </div>
- </div>
-
-
- <!-- 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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-multivalued-view" disabled="disabled" /><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" disabled="disabled" /><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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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">
- <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" id="add-edit-attr-header">Add Attribute</h4>
- </div>
- <div class="modal-body">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <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
- >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
- >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
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-syntax">
- <option value="">Make a selection</option>
- </select>
- </div>
- <div>
- <label for="attr-usage" class="ds-config-label-lrg" title="The parent attribute"><b>Attribute Usage</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-usage">
- </select>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-multivalued"><label
- for="attr-multivalued" class="ds-label"> Attribute Multi-Valued </label>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-no-user-mod"><label
- for="attr-no-user-mod" class="ds-label"> Read-only (NO-USER-MODIFICATION flag) </label>
- </div>
- <div>
- <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 ds-margin-top">
- <div class="panel-heading"><strong>Matching rules</strong></div>
- <div class="panel-body">
- <div>
- <label for="attr-eq-mr-select" class="ds-config-label-lrg"><b>Equality</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-eq-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-order-mr-select" class="ds-config-label-lrg"><b>Ordering</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-order-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-sub-mr-select" class="ds-config-label-lrg"><b>Substring</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-sub-mr-select">
- <option></option>
- </select>
- </div>
- </div>
- </div>
- </div>
- <div id="save-attr-spinner" class="ds-center" hidden>
- <p></p>
- <p><span class="spinner spinner-xs spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" id="save-attr-button">Save</button>
- </div>
- </div>
- </div>
- </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" disabled />
- </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" disabled/>
- </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" disabled/>
- </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" disabled />
- </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" disabled />
- </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 disabled>
- </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 disabled>
- </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">
- <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" id="add-edit-oc-header">Add Objectclass</h4>
- </div>
- <div class="modal-body">
- <form class="form-horizontal">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <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
- >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>
- </div>
- <hr>
- <div class="ds-container">
- <div name="available-attrs">
- <label for="schema-list" title="The available attributes to choose from."><b>Available Attributes</b></label>
- <select id="schema-list" class="ds-oc-form-list" name="availattrs" multiple>
- </select>
- </div>
-
- <div name="add-remove-buttons">
- <div name="must buttons" class="btn-group ds-oc-must-buttons">
- <input type="button" class="ds-oc-add-del-btn" id="oc-must-add-button" value="Add ► ► ► "/>
- <input type="button" class="ds-oc-add-del-btn" id="oc-must-remove-button" value="◄ ◄ ◄ Remove"/>
- </div>
- <p></p>
- <div name="may buttons" class="btn-group ds-oc-may-buttons">
- <input type="button" class="ds-oc-add-del-btn" id="oc-may-add-button" value="Add ► ► ►"/>
- <input type="button" class="ds-oc-add-del-btn" id="oc-may-remove-button" value="◄ ◄ ◄ Remove"/>
- </div>
- </div>
-
- <div name="may-must-lists">
- <label class="ds-config-label" for="oc-required-list" title=
- "Attributes required by the objectclass"><b>Required Attributes</b></label>
- <select id="oc-required-list" class="ds-may-must-list" name="availattrs" multiple>
- </select>
- <p></p>
- <label class="ds-config-label" for="oc-allowed-list" title=
- "Attributes allowed by the objectclass"><b>Allowed Attributes</b></label>
- <select id="oc-allowed-list" class="ds-may-must-list" name="availattrs" multiple>
- </select>
- </div>
- </div>
- </div>
- </form>
- <div id="save-oc-spinner" class="ds-center" hidden>
- <p></p>
- <p><span class="spinner spinner-xs spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" id="save-oc-button">Save</button>
- </div>
- </div>
- </div>
- </div>
-
-</div>
diff --git a/src/cockpit/389-console/src/schema.js b/src/cockpit/389-console/src/schema.js
deleted file mode 100644
index ea6159b..0000000
--- a/src/cockpit/389-console/src/schema.js
+++ /dev/null
@@ -1,925 +0,0 @@
-var attr_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown" role="menu" id="attr-action-btn" aria-labelledby="attr-action-btn">' +
- '<li role=""><a role="menuitem" tabindex="0" class="attr-edit-btn" href="#schema-tab">Edit Attribute</a></li>' +
- '<li role=""><a role="menuitem" tabindex="1" class="attr-del-btn" href="#schema-tab">Delete Attribute</a></li>' +
- '</ul>' +
- '</div>';
-
-var attr_btn_html_only_view =
- '<button class="btn btn-default attr-view-btn" type="button"' +
- ' href="#schema-tab" title="Only user-defined attributes can be modified"> View Attribute' +
- '</button>';
-
-var oc_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle" type="button"data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown" role="menu">' +
- '<li role=""><a role="menuitem" tabindex="0" class="oc-edit-btn" href="#schema-tab">Edit Objectclass</a></li>' +
- '<li role=""><a role="menuitem" tabindex="1" class="oc-del-btn" href="#schema-tab">Delete Objectclass</a></li>' +
- '</ul>' +
- '</div>';
-
-var oc_btn_html_only_view =
- '<button class="btn btn-default oc-view-btn" type="button"' +
- ' href="#schema-tab" title="Only user-defined objectClasses can be modified"> View Objectclass' +
- '</button>';
-
-var schema_oc_table;
-var schema_at_table;
-var schema_mr_table;
-
-var attr_usage_opts = ['userApplications', 'directoryOperation', 'distributedOperation', 'dSAOperation'];
-var oc_kind_opts = ['STRUCTURAL', 'ABSTRACT', 'AUXILIARY'];
-
-function is_x_origin_user_defined(x_origin) {
- if (typeof x_origin === 'string' && x_origin.toLowerCase() !== 'user defined' || x_origin == null) {
- return false;
- } else {
- return true;
- }
-}
-
-// Leave only user defined attributes if the checkbox is crossed
-$.fn.dataTable.ext.search.push(
- function(settings, searchData, index, rowData, counter) {
- var x_origin;
- if ( settings.sTableId == "attr-table" ) {
- if ( $("#attr-user-defined").is(":checked") ) {
- x_origin = rowData[7];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- } else {
- if ( $("#oc-user-defined").is(":checked") ) {
- x_origin = rowData[5];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- }
- return true;
- }
-);
-
-function clear_oc_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-oc-header").html('Add Objectclass');
- $(".ds-modal-error").hide();
- $("#oc-name").attr('disabled', false);
- $("#oc-name").val("");
- $("#oc-oid").val("");
- $("#oc-kind").prop('selectedIndex',0);
- $("#oc-desc").val("");
- $("#oc-parent").prop('selectedIndex',0);
- $("#schema-list").prop('selectedIndex',-1);
- $('#oc-required-list').find('option').remove();
- $('#oc-allowed-list').find('option').remove();
- $("#save-oc-button").attr('disabled', false);
-}
-
-function clear_attr_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-attr-header").html('Add Attribute');
- $(".ds-modal-error").hide();
- $("#attr-name").attr('disabled', false);
- $("#attr-name").val("");
- $("#attr-syntax").val("");
- $("#attr-desc").val("");
- $("#attr-parent").prop('selectedIndex',0);
- $("#attr-usage").prop('selectedIndex',0);
- $("#attr-oid").val("");
- $("#attr-alias").val("");
- $('#attr-multivalued').prop('checked', false);
- $('#attr-no-user-mod').prop('checked', false);
- $("#attr-eq-mr-select").prop('selectedIndex',0);
- $("#attr-order-mr-select").prop('selectedIndex',0);
- $("#attr-sub-mr-select").prop('selectedIndex',0);
- $("#save-attr-button").attr('disabled', false);
-}
-
-function load_schema_objects_to_select(object, select_id, schema_json_select) {
- var data = [];
- for (var i = 0; i < schema_json_select[object].items.length; i++) {
- item = schema_json_select[object].items[i];
- if (item.name) {
- data.push.apply(data, [item.name]);
- } else {
- data.push.apply(data, [item.oid]);
- }
- }
- // Update html select
- $.each(data, function (i, item) {
- $("#" + select_id).append($('<option>', {
- value: item,
- text : item
- }));
- });
-}
-
-function get_and_set_schema_tables() {
- console.log("Loading schema...");
-
- // Set attribute usage select html in attribute's edit window
- $.each(attr_usage_opts, function (i, item) {
- $("#attr-usage").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- // Set objectClass kind select html in objectClass's edit window
- $.each(oc_kind_opts, function (i, item) {
- $("#oc-kind").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'list'];
- log_cmd('get_and_set_schema_tables', 'Get all schema objects', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(schema_data) {
- var schema_json = JSON.parse(schema_data);
- // Setup the tables: standard, custom, and Matching Rules
- var data = [];
- // If objectClass is user defined them the action button is enabled
- for (var i = 0; i < schema_json.objectclasses.items.length; i++) {
- var oc_btn = oc_btn_html_only_view;
- item = schema_json.objectclasses.items[i];
- if (is_x_origin_user_defined(item.x_origin)) {
- oc_btn = oc_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.must === undefined) {
- item.must = [];
- }
- if (item.may === undefined) {
- item.may = [];
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.kind === undefined) {
- item.kind = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ]]);
- }
- // Update html table
- schema_oc_table = $('#oc-table').DataTable ({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip',
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No objectclasses defined",
- "search": "Search Objectclasses"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
-
- // Get syntaxes and use the data to populate the attribute's table
- cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', "attributetypes", 'get_syntaxes'];
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(syntax_data) {
- var obj = JSON.parse(syntax_data);
- var syntax_list = [];
-
- load_schema_objects_to_select('matchingrules', 'attr-eq-mr-select', schema_json);
- load_schema_objects_to_select('matchingrules', 'attr-order-mr-select', schema_json);
- load_schema_objects_to_select('matchingrules', 'attr-sub-mr-select', schema_json);
- load_schema_objects_to_select('attributetypes', 'schema-list', schema_json);
- load_schema_objects_to_select('objectclasses', 'oc-parent', schema_json);
- load_schema_objects_to_select('attributetypes', 'attr-parent', schema_json);
-
- for (var i = 0; i < obj.items.length; i++) {
- item = obj.items[i];
- syntax_list.push.apply(syntax_list, [item]);
- }
- // Update syntax select html in attribute's edit window
- $.each(syntax_list, function (i, item) {
- $("#attr-syntax").append($('<option>', {
- value: item.id,
- text : item.name + " (" + item.id + ")"
- }));
- });
-
- var data = [];
- var syntax_name = "";
- for (var i = 0; i < schema_json.attributetypes.items.length; i++) {
- var attr_btn = attr_btn_html_only_view;
- item = schema_json.attributetypes.items[i];
- if (item.single_value) {
- multivalued = 'no';
- } else {
- multivalued = 'yes';
- }
- $.each(syntax_list, function (i, syntax) {
- if (syntax.id === item.syntax) {
- syntax_name = '<div title="' + syntax.name + '">' + syntax.name + '</div>';
- }
- });
- // If attribute is user defined them the action button is enabled
- if (is_x_origin_user_defined(item.x_origin)) {
- attr_btn = attr_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.no_user_mod === undefined) {
- item.no_user_mod = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.usage === undefined) {
- item.usage = "";
- }
- if (item.aliases === undefined) {
- item.aliases = "";
- }
- if (item.equality === undefined) {
- item.equality = "";
- }
- if (item.ordering === undefined) {
- item.ordering = "";
- }
- if (item.substr === undefined) {
- item.substr = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- syntax_name,
- multivalued,
- attr_btn,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
- ]]);
- }
- // Update html table
- schema_at_table = $('#attr-table').DataTable({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip', // Moves the search box to the left
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No attributes defined",
- "search": "Search Attributes"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
- update_progress();
- }).fail(function(syntax_data) {
- console.log("Get syntaxes failed: " + syntax_data.message);
- check_inst_alive(1);
- });
-
- var data = [];
- for (var i = 0; i < schema_json.matchingrules.items.length; i++) {
- item = schema_json.matchingrules.items[i];
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.syntax,
- item.desc]]);
- }
- schema_mr_table = $('#schema-mr-table').DataTable({
- "paging": true,
- "data": data,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip',
- "language": {
- "emptyTable": "No matching rules defined",
- "search": "Search Matching Rules"
- },
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- });
-
- 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);
- });
-}
-
-$(document).ready( function() {
- // Set an interval event to wait for all the pages to load, then load the config
- $("#schema-content").load("schema.html", function (){
- // Sort schema list awhile
- sort_list( $("#schema-list") );
-
- $("#objectclass-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#objectclass-page").show();
- });
- $("#attribute-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#attribute-page").show();
- });
- $("#schema-mr-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#schema-mr").show();
- });
-
- $('#attr-user-defined').change(function() {
- schema_at_table.draw();
- });
- $('#oc-user-defined').change(function() {
- schema_oc_table.draw();
- });
-
- //
- // Modals/Forms
- //
-
- /*
- *
- * Add Objectclass Form
- *
- */
- $("#add-oc-button").on("click", function() {
- clear_oc_form();
- document.getElementById("oc-parent").value = 'top';
- });
-
- $("#save-oc-button").on("click", function() {
- var oc_name = $("#oc-name").val();
- var oc_oid = $("#oc-oid").val();
- var oc_parent = $("#oc-parent").val();
- var oc_kind = $("#oc-kind").val();
- var oc_desc = $("#oc-desc").val();
- var oc_x_origin = "user defined";
- var oc_required_list = $('#oc-required-list option').map(function() { return $(this).val(); }).get();
- var oc_allowed_list = $('#oc-allowed-list option').map(function() { return $(this).val(); }).get();
-
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-oc-header").text().indexOf("Edit Objectclass") != -1){
- edit = true;
- action = 'replace';
- }
- if (oc_name == '') {
- report_err($("#oc-name"), 'You must provide an objectClass name');
- return;
- }
- var cmd = [DSCONF, server_inst, 'schema', 'objectclasses', action, oc_name];
- // Process and validate parameters
- if (oc_oid != "") {
- cmd.push.apply(cmd, ["--oid", oc_oid]);
- }
- if (oc_parent != "") {
- cmd.push.apply(cmd, ["--sup", oc_parent]);
- }
- if (oc_kind != "") {
- cmd.push.apply(cmd, ["--kind", oc_kind]);
- }
- if (oc_desc != "") {
- cmd.push.apply(cmd, ["--desc", oc_desc]);
- }
- if (oc_x_origin != "") {
- cmd.push.apply(cmd, ["--x-origin=\"" + oc_x_origin + "\""]);
- }
- if (oc_required_list.length !== 0) {
- cmd.push.apply(cmd, ["--must"]);
- cmd.push.apply(cmd, oc_required_list);
- }
- if (oc_allowed_list.length !== 0) {
- cmd.push.apply(cmd, ["--may"]);
- cmd.push.apply(cmd, oc_allowed_list);
- }
-
- $("#save-oc-spinner").show();
- log_cmd('#save-oc-button (click)', 'Save objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(data) {
- $("#oc-name").attr('disabled', false);
-
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + oc_name + ')');
- schema_oc_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'objectclasses', 'query', oc_name];
- log_cmd('#save-oc-button (click)', 'Search objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(oc_data) {
- var obj = JSON.parse(oc_data);
- var item = obj.oc;
- schema_oc_table.row.add( [
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn_html,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ] ).draw( false );
- }).
- fail(function(oc_data) {
- popup_err("err", oc_data.message);
- console.log("Search objectclasses failed: " + oc_data.message);
- check_inst_alive(1);
- });
- // Replace the option in 'Edit objectClass' window
- if (!edit) {
- var option = $('<option></option>').attr("value", oc_name).text(oc_name);
- $("#oc-parent").append(option);
- }
- $("#save-oc-spinner").hide();
- popup_success("The objectClass was saved in DS");
- $("#add-edit-oc-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-oc-spinner").hide();
- popup_err("Error", "Failed to save the objectClass\n" + data.message);
- $("#add-edit-oc-form").modal('toggle');
- });
- });
-
- // Required Attributes
- $("#oc-must-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-required-list option[value="' + add_attrs[i] + '"]').val() === undefined) {
- $('#oc-required-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-must-remove-button").on("click", function () {
- var add_attrs = $("#oc-required-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text + '"]').val() === undefined) {
- $('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-required-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- // Allowed Attributes
- $("#oc-may-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-allowed-list option[value="' + add_attrs[i] + '"]').val() === undefined) {
- $('#oc-allowed-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-may-remove-button").on("click", function () {
- var add_attrs = $("#oc-allowed-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text + '"]').val() === undefined) {
- $('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-allowed-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- /*
- *
- * Add Attribute Form
- *
- */
- $("#create-attr-button").on("click", function() {
- clear_attr_form();
- });
-
- $("#save-attr-button").on("click", function() {
- var attr_name = $("#attr-name").val();
- var attr_oid = $("#attr-oid").val();
- var attr_syntax = $("#attr-syntax").val();
- var attr_syntax_text = $("#attr-syntax :selected").text();
- var attr_usage = $('#attr-usage').val();
- var attr_desc = $('#attr-desc').val();
- var attr_x_origin = "user defined";
- var attr_parent = $('#attr-parent').val();
- var attr_aliases = $('#attr-alias').val().split(" ");
- var eq_mr= $('#attr-eq-mr-select').val();
- var order_mr = $('#attr-order-mr-select').val();
- var sub_mr = $('#attr-sub-mr-select').val();
- var multiple = 'no';
- if ( $("#attr-multivalued").is(":checked") ) {
- multiple = 'yes';
- }
- var no_user_mod = false;
- if ( $("#attr-no-user-mod").is(":checked") ) {
- no_user_mod = true;
- }
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-attr-header").text().indexOf("Edit Attribute") != -1){
- edit = true;
- action = 'replace';
- }
-
- if (attr_name == '') {
- report_err($("#attr-name"), 'You must provide an attribute name');
- return;
- }
- if (attr_syntax == '') {
- report_err($("#attr-syntax"), 'You must provide an attribute syntax');
- return;
- }
-
- var cmd = [DSCONF, server_inst, 'schema', 'attributetypes', action, attr_name];
- // Process and validate parameters
- if (attr_aliases) {
- cmd.push.apply(cmd, ["--aliases"]);
- cmd.push.apply(cmd, attr_aliases);
- }
- if (attr_syntax) {
- cmd.push.apply(cmd, ["--syntax", attr_syntax]);
- }
- if (multiple == 'no') {
- cmd.push.apply(cmd, ["--single-value"]);
- } else {
- cmd.push.apply(cmd, ["--multi-value"]);
- }
- if (no_user_mod) {
- cmd.push.apply(cmd, ["--no-user-mod"]);
- } else {
- cmd.push.apply(cmd, ["--user-mod"]);
- }
- cmd.push.apply(cmd, ["--oid", attr_oid]);
- cmd.push.apply(cmd, ["--usage", attr_usage]);
- cmd.push.apply(cmd, ["--sup", attr_parent]);
- cmd.push.apply(cmd, ["--desc", attr_desc]);
- cmd.push.apply(cmd, ["--x-origin", attr_x_origin]);
- cmd.push.apply(cmd, ["--equality"]);
- if (eq_mr) {
- cmd.push.apply(cmd, [eq_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--substr"]);
- if (sub_mr) {
- cmd.push.apply(cmd, [sub_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--ordering"]);
- if (order_mr) {
- cmd.push.apply(cmd, [order_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- $("#save-attr-spinner").show();
- log_cmd('#save-attr-button (click)', 'Save attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(data) {
- var attr_syntax_name = '<div title="' + attr_syntax + '">' +
- attr_syntax_text.substr(0, attr_syntax_text.indexOf(" (")) + '</div>';
- $("#attr-name").attr('disabled', false);
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + attr_name + ')');
- schema_at_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'attributetypes', 'query', attr_name];
- log_cmd('#save-oc-button (click)', 'Get attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(at_data) {
- var obj = JSON.parse(at_data);
- var item = obj.at;
- schema_at_table.row.add( [
- item.name,
- item.oid,
- attr_syntax_name,
- multiple,
- attr_btn_html,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
-
- ] ).draw( false );
- $("#attr-name").attr('disabled', false);
- }).
- fail(function(at_data) {
- popup_err("err", at_data.message);
- console.log("Query attributes failed: " + at_data.message);
- check_inst_alive(1);
- });
- if (!edit) {
- var option = $('<option></option>').attr("value", attr_name).text(attr_name);
- $("#schema-list").append(option);
- }
- $("#save-attr-spinner").hide();
- popup_success("The attribute was saved in DS");
- $("#add-edit-attr-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-attr-spinner").hide();
- popup_err("Error", "Failed to save the attribute: " + data.message);
- $("#add-edit-attr-form").modal('toggle');
- });
- });
-
- function load_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];
-
- $("#add-edit-attr-header").html('Edit Attribute: ' + edit_attr_name);
- $("#attr-name").val(edit_attr_name);
- $("#attr-name").attr('disabled', true);
- $("#attr-oid").val(edit_attr_oid);
- $("#attr-usage")[0].value = edit_attr_usage;
- $("#attr-parent")[0].value = edit_attr_parent;
- $("#attr-desc").val(edit_attr_desc);
- if (edit_attr_aliases) {
- $("#attr-alias").val(edit_attr_aliases.join(" "));
- }
- $("#attr-syntax").val(edit_attr_syntax);
- $("#attr-multivalued").prop('checked', false);
- if (edit_attr_multivalued == "yes") {
- $("#attr-multivalued").prop('checked', true);
- }
- $("#attr-no-user-mod").prop('checked', false);
- if (edit_attr_no_user_mod) {
- $("#attr-no-user-mod").prop('checked', true);
- }
- $("#save-attr-spinner").show();
- $("#attr-eq-mr-select")[0].value = edit_attr_eq_mr;
- $("#attr-order-mr-select")[0].value = edit_attr_order_mr;
- $("#attr-sub-mr-select")[0].value = edit_attr_sub_mr;
- $("#save-attr-spinner").hide();
-
- $("#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_view_attr_form($(this));
- });
-
- $(document).on('click', '.attr-edit-btn', function(e) {
- e.preventDefault();
- load_attr_form($(this));
- });
-
- $(document).on('click', '.attr-del-btn', function(e) {
- e.preventDefault();
- var data = schema_at_table.row( $(this).parents('tr') ).data();
- var del_attr_name = data[0];
- var at_row = $(this);
- popup_confirm("Are you sure you want to delete attribute: <b>" + del_attr_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'attributetypes', 'remove', del_attr_name];
- log_cmd('.attr-del-btn (click)', 'Remove attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {
- popup_success("Attribute was successfully removed!");
- schema_at_table.row( at_row.parents('tr') ).remove().draw( false );
- $("#schema-list option[value='" + del_attr_name + "']").remove();
- }).fail(function(data) {
- popup_err("Attribute removal error", del_attr_name + " removal has failed: " + data.message);
- });
- }
- });
- });
-
- 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();
- 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];
-
- $("#save-oc-spinner").show();
- $("#add-edit-oc-header").html('Edit Objectclass: ' + edit_oc_name);
- $("#oc-name").attr('disabled', true);
- $("#oc-name").val(edit_oc_name);
- $("#oc-oid").val(edit_oc_oid);
- $("#oc-kind").val(edit_oc_kind);
- $("#oc-desc").val(edit_oc_desc);
- $("#oc-parent").val(edit_oc_parent);
- $.each(edit_oc_required, function (i, item) {
- if (item) {
- $("#oc-required-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $.each(edit_oc_allowed, function (i, item) {
- if (item) {
- $("#oc-allowed-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $("#save-oc-spinner").hide();
-
- // Update modal html header and fields and show()
- $("#add-edit-oc-form").modal('toggle');
- }
-
- $(document).on('click', '.oc-view-btn', function(e) {
- e.preventDefault();
- load_view_oc_form($(this));
- });
-
- $(document).on('click', '.oc-edit-btn', function(e) {
- e.preventDefault();
- load_oc_form($(this));
- });
-
- $(document).on('click', '.oc-del-btn', function(e) {
- e.preventDefault();
- var data = schema_oc_table.row( $(this).parents('tr') ).data();
- var del_oc_name = data[0];
- var oc_row = $(this);
-
- popup_confirm("Are you sure you want to delete objectclass: <b>" + del_oc_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'objectclasses', 'remove', del_oc_name];
- log_cmd('.oc-del-btn (click)', 'Remove objectclass', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {
- popup_success("ObjectClass was successfully removed!");
- schema_oc_table.row( oc_row.parents('tr') ).remove().draw( false );
- $("#oc-parent option[value='" + del_oc_name + "']").remove();
- }).fail(function(data) {
- popup_err("Error", del_oc_name + " removal has failed: " + data.message);
- });
- }
- });
- });
- // Page is loaded, mark it as so...
- schema_page_loaded = 1;
- });
-});
diff --git a/src/cockpit/389-console/src/schema.jsx b/src/cockpit/389-console/src/schema.jsx
new file mode 100644
index 0000000..7e6ade6
--- /dev/null
+++ b/src/cockpit/389-console/src/schema.jsx
@@ -0,0 +1,1042 @@
+import cockpit from "cockpit";
+import React from "react";
+import { NotificationController } from "./lib/notifications.jsx";
+import { log_cmd, searchFilter } from "./lib/tools.jsx";
+import {
+ ObjectClassesTable,
+ AttributesTable,
+ MatchingRulesTable
+} from "./lib/schema/schemaTables.jsx";
+import { ObjectClassModal, AttributeTypeModal } from "./lib/schema/schemaModals.jsx";
+import {
+ Nav,
+ NavItem,
+ Checkbox,
+ TabContainer,
+ TabContent,
+ TabPane,
+ Spinner,
+ Button
+} from "patternfly-react";
+import PropTypes from "prop-types";
+import "./css/ds.css";
+
+export class Schema extends React.Component {
+ componentWillMount() {
+ this.loadSyntaxesFirst();
+ }
+
+ componentDidUpdate(prevProps) {
+ if (this.props.serverId !== prevProps.serverId) {
+ this.loadSyntaxesFirst();
+ }
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ loading: false,
+ notifications: [],
+ activeKey: 1,
+
+ objectclassRows: [],
+ filteredObjectclassRows: [],
+ attributesRows: [],
+ filteredAttributesRows: [],
+ matchingrulesRows: [],
+ syntaxes: [],
+ attributes: [],
+ objectclasses: [],
+ matchingrules: [],
+
+ ocModalViewOnly: false,
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ ocUserDefined: false,
+ objectclassModalShow: false,
+ newOcEntry: true,
+ ocTableLoading: false,
+ ocModalLoading: false,
+
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atUserDefined: false,
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ atTableLoading: false,
+ atModalLoading: false
+ };
+
+ this.handleFieldChange = this.handleFieldChange.bind(this);
+ this.addNotification = this.addNotification.bind(this);
+ this.removeNotification = this.removeNotification.bind(this);
+ this.handleNavSelect = this.handleNavSelect.bind(this);
+ this.handleTypeaheadChange = this.handleTypeaheadChange.bind(this);
+ this.loadSchemaData = this.loadSchemaData.bind(this);
+ this.loadSyntaxesFirst = this.loadSyntaxesFirst.bind(this);
+ this.toggleLoading = this.toggleLoading.bind(this);
+
+ this.showViewObjectclassModal = this.showViewObjectclassModal.bind(this);
+ this.showEditObjectclassModal = this.showEditObjectclassModal.bind(this);
+ this.showAddObjectclassModal = this.showAddObjectclassModal.bind(this);
+ this.openObjectclassModal = this.openObjectclassModal.bind(this);
+ this.closeObjectclassModal = this.closeObjectclassModal.bind(this);
+ this.deleteObjectclass = this.deleteObjectclass.bind(this);
+ this.addObjectclass = this.addObjectclass.bind(this);
+ this.editObjectclass = this.editObjectclass.bind(this);
+ this.cmdOperationObjectclass = this.cmdOperationObjectclass.bind(this);
+
+ this.showViewAttributeModal = this.showViewAttributeModal.bind(this);
+ this.showEditAttributeModal = this.showEditAttributeModal.bind(this);
+ this.showAddAttributeModal = this.showAddAttributeModal.bind(this);
+ this.openAttributeModal = this.openAttributeModal.bind(this);
+ this.closeAttributeModal = this.closeAttributeModal.bind(this);
+ this.deleteAttribute = this.deleteAttribute.bind(this);
+ this.addAttribute = this.addAttribute.bind(this);
+ this.editAttribute = this.editAttribute.bind(this);
+ this.cmdOperationAttribute = this.cmdOperationAttribute.bind(this);
+ }
+
+ toggleLoading(item) {
+ if (item == "allSchema") {
+ this.setState(prevState => ({
+ loading: !prevState.loading
+ }));
+ } else if (item == "ocTable") {
+ this.setState(prevState => ({
+ ocTableLoading: !prevState.ocTableLoading
+ }));
+ } else if (item == "ocModal") {
+ this.setState(prevState => ({
+ ocModalLoading: !prevState.ocModalLoading
+ }));
+ } else if (item == "atTable") {
+ this.setState(prevState => ({
+ atTableLoading: !prevState.atTableLoading
+ }));
+ } else if (item == "atModal") {
+ this.setState(prevState => ({
+ atModalLoading: !prevState.atModalLoading
+ }));
+ }
+ }
+
+ loadSyntaxesFirst() {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "get_syntaxes"
+ ];
+ log_cmd("loadSyntaxes", "Get syntaxes for attributetypes", cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ this.setState({
+ syntaxes: myObject.items
+ });
+ this.loadSchemaData(true);
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSyntaxes failed: ", errMsg.desc);
+ }
+ });
+ }
+
+ loadSchemaData(initialLoading) {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "list"
+ ];
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ log_cmd("loadSchemaData", "Get schema objects in one batch", cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ let attrs = [];
+ let ocs = [];
+ let mrs = [];
+ for (let content of myObject.attributetypes.items) {
+ attrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.objectclasses.items) {
+ ocs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.matchingrules.items) {
+ mrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ this.setState({
+ objectclassRows: myObject.objectclasses.items,
+ attributesRows: myObject.attributetypes.items,
+ matchingrulesRows: myObject.matchingrules.items,
+ attributes: attrs,
+ matchingrules: mrs,
+ objectclasses: ocs
+ });
+ if (this.state.ocUserDefined) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.objectclasses.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: myObject.objectclasses.items
+ });
+ }
+ if (this.state.atUserDefined) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.attributetypes.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: myObject.attributetypes.items
+ });
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSchemaData failed: ", errMsg.desc);
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ });
+ }
+
+ showViewObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: true
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showEditObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showAddObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal();
+ }
+
+ openObjectclassModal(name) {
+ if (!name) {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("openObjectclassModal", "Fetch ObjectClass data from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.oc;
+ let ocMustList = [];
+ let ocMayList = [];
+ const kindOpts = ["STRUCTURAL", "ABSTRACT", "AUXILIARY"];
+ this.setState({
+ objectclassModalShow: true,
+ newOcEntry: false,
+ ocName: item["name"] === undefined ? "" : item["name"][0],
+ ocDesc: item["desc"] === null ? "" : item["desc"][0],
+ ocOID: item["oid"] === undefined ? "" : item["oid"][0],
+ ocKind: item["kind"] === undefined ? "" : kindOpts[item["kind"]],
+ ocParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ]
+ });
+ if (item["must"] === undefined) {
+ this.setState({ ocMust: [] });
+ } else {
+ for (let value of item["must"]) {
+ ocMustList = [...ocMustList, { id: value, label: value }];
+ }
+ this.setState({
+ ocMust: ocMustList
+ });
+ }
+ if (item["may"] === undefined) {
+ this.setState({ ocMay: [] });
+ } else {
+ for (let value of item["may"]) {
+ ocMayList = [...ocMayList, { id: value, label: value }];
+ }
+ this.setState({
+ ocMay: ocMayList
+ });
+ }
+ this.toggleLoading("ocTable");
+ })
+ .fail(_ => {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ this.toggleLoading("ocTable");
+ });
+ }
+ }
+
+ closeObjectclassModal() {
+ this.setState({ objectclassModalShow: false });
+ }
+
+ deleteObjectclass(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("deleteObjectclass", "Delete ObjectClass from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteObjectclass", "Result", content);
+ this.addNotification("success", `ObjectClass ${name} was successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during ObjectClass removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ });
+ }
+
+ addObjectclass() {
+ this.cmdOperationObjectclass("add");
+ }
+
+ editObjectclass() {
+ this.cmdOperationObjectclass("replace");
+ }
+
+ cmdOperationObjectclass(action) {
+ const { ocName, ocDesc, ocOID, ocParent, ocKind, ocMust, ocMay } = this.state;
+ if (ocName == "") {
+ this.addNotification("warning", "ObjectClass Name is required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ action,
+ ocName
+ ];
+ // Process and validate parameters
+ if (ocOID != "") {
+ cmd = [...cmd, "--oid", ocOID];
+ }
+ if (ocParent.length != 0) {
+ cmd = [...cmd, "--sup", ocParent[0].label];
+ }
+ if (ocKind != "") {
+ cmd = [...cmd, "--kind", ocKind];
+ }
+ if (ocDesc != "") {
+ cmd = [...cmd, "--desc", ocDesc];
+ }
+ if (ocMust.length != 0) {
+ cmd = [...cmd, "--must"];
+ for (let value of ocMust) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (ocMay.length != 0) {
+ cmd = [...cmd, "--may"];
+ for (let value of ocMay) {
+ cmd = [...cmd, value.label];
+ }
+ }
+
+ this.toggleLoading("ocModal");
+ log_cmd("cmdOperationObjectclass", `Do the ${action} operation on ObjectClass`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationObjectclass", "Result", content);
+ this.addNotification(
+ "success",
+ `ObjectClass ${ocName} - ${action} operation was successfull`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the ObjectClass ${action} operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ });
+ }
+ }
+
+ showViewAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: true
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showEditAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showAddAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal();
+ }
+
+ openAttributeModal(name) {
+ if (!name) {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("openAttributeModal", "Fetch Attribute data from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.at;
+ let atAliasList = [];
+ const atUsageOpts = [
+ "userApplications",
+ "directoryOperation",
+ "distributedOperation",
+ "dSAOperation"
+ ];
+ this.setState({
+ attributeModalShow: true,
+ newAtEntry: false,
+ atName: item["name"] === undefined ? "" : item["name"][0],
+ atDesc: item["desc"] === null ? "" : item["desc"][0],
+ atOID: item["oid"] === undefined ? "" : item["oid"][0],
+ atParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ],
+ atSyntax:
+ item["syntax"] === undefined
+ ? []
+ : [
+ {
+ id: item["syntax"][0],
+ label: this.state.syntaxes.filter(
+ attr => attr.id === item["syntax"][0]
+ )[0]["label"]
+ }
+ ],
+ atUsage: item["usage"] === undefined ? "" : atUsageOpts[item["usage"]],
+ atMultivalued: !item["single_value"],
+ atNoUserMod: item["no_user_mod"],
+ atEqMr:
+ item["equality"] === null
+ ? []
+ : [
+ {
+ id: item["equality"][0],
+ label: item["equality"][0]
+ }
+ ],
+ atOrder:
+ item["ordering"] === null
+ ? []
+ : [
+ {
+ id: item["ordering"][0],
+ label: item["ordering"][0]
+ }
+ ],
+ atSubMr:
+ item["substr"] === null
+ ? []
+ : [
+ {
+ id: item["substr"][0],
+ label: item["substr"][0]
+ }
+ ]
+ });
+ if (item["aliases"] === null) {
+ this.setState({ atAlias: [] });
+ } else {
+ for (let value of item["aliases"]) {
+ atAliasList = [...atAliasList, { id: value, label: value }];
+ }
+ this.setState({
+ atAlias: atAliasList
+ });
+ }
+ this.toggleLoading("atTable");
+ })
+ .fail(_ => {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ this.toggleLoading("atTable");
+ });
+ }
+ }
+
+ closeAttributeModal() {
+ this.setState({ attributeModalShow: false });
+ }
+
+ deleteAttribute(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("deleteAttribute", "Delete Attribute from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteAttribute", "Result", content);
+ this.addNotification("success", `Attribute ${name} was successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during Attribute removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ });
+ }
+
+ addAttribute() {
+ this.cmdOperationAttribute("add");
+ }
+
+ editAttribute() {
+ this.cmdOperationAttribute("replace");
+ }
+
+ cmdOperationAttribute(action) {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr
+ } = this.state;
+
+ if (atName == "" || atSyntax.length == 0) {
+ this.addNotification("warning", "Attribute Name and Syntax are required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ action,
+ atName
+ ];
+ cmd = [...cmd, "--syntax", atSyntax[0].id];
+ if (atAlias.length != 0) {
+ cmd = [...cmd, "--aliases"];
+ for (let value of atAlias) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (atMultivalued) {
+ cmd = [...cmd, "--multi-value"];
+ } else {
+ cmd = [...cmd, "--single-value"];
+ }
+ if (atNoUserMod) {
+ cmd = [...cmd, "--no-user-mod"];
+ } else {
+ cmd = [...cmd, "--user-mod"];
+ }
+ cmd = [...cmd, "--oid", atOID];
+ cmd = [...cmd, "--usage", atUsage];
+ cmd = [...cmd, "--desc", atDesc];
+
+ cmd = [...cmd, "--sup"];
+ if (atParent != "") {
+ cmd = [...cmd, atParent[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--equality"];
+ if (atEqMr != "") {
+ cmd = [...cmd, atEqMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--substr"];
+ if (atSubMr != "") {
+ cmd = [...cmd, atSubMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--ordering"];
+ if (atOrder != "") {
+ cmd = [...cmd, atOrder[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ this.toggleLoading("atModal");
+ log_cmd("cmdOperationAttribute", `Do the ${action} operation on Attribute`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationAttribute", "Result", content);
+ this.addNotification(
+ "success",
+ `Attribute ${atName} - ${action} operation was successfull`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the Attribute ${action} operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ });
+ }
+ }
+
+ addNotification(type, message, timerdelay, persistent) {
+ this.setState(prevState => ({
+ notifications: [
+ ...prevState.notifications,
+ {
+ key: prevState.notifications.length + 1,
+ type: type,
+ persistent: persistent,
+ timerdelay: timerdelay,
+ message: message
+ }
+ ]
+ }));
+ }
+
+ removeNotification(notificationToRemove) {
+ this.setState({
+ notifications: this.state.notifications.filter(
+ notification => notificationToRemove.key !== notification.key
+ )
+ });
+ }
+
+ handleNavSelect(key) {
+ this.setState({
+ activeKey: key
+ });
+ }
+
+ handleTypeaheadChange(state, values) {
+ this.setState({
+ [state]: values
+ });
+ }
+
+ handleFieldChange(e) {
+ const value = e.target.type === "checkbox" ? e.target.checked : e.target.value;
+ if (e.target.id == "ocUserDefined" && value) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.objectclassRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: this.state.objectclassRows
+ });
+ }
+ if (e.target.id == "atUserDefined" && value) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.attributesRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: this.state.attributesRows
+ });
+ }
+ this.setState({
+ [e.target.id]: value
+ });
+ }
+
+ render() {
+ let schemaPage = "";
+ if (this.state.loading) {
+ schemaPage = (
+ <div className="ds-loading-spinner ds-center">
+ <p />
+ <h4>Loading schema information ...</h4>
+ <Spinner loading size="md" />
+ </div>
+ );
+ } else {
+ schemaPage = (
+ <div className="container-fluid">
+ <NotificationController
+ notifications={this.state.notifications}
+ removeNotificationAction={this.removeNotification}
+ />
+ <div className="ds-tab-table">
+ <TabContainer
+ id="basic-tabs-pf"
+ onSelect={this.handleNavSelect}
+ activeKey={this.state.activeKey}
+ >
+ <div>
+ <Nav bsClass="nav nav-tabs nav-tabs-pf">
+ <NavItem eventKey={1}>
+ <div
+ dangerouslySetInnerHTML={{ __html: "Objectclasses" }}
+ />
+ </NavItem>
+ <NavItem eventKey={2}>
+ <div dangerouslySetInnerHTML={{ __html: "Attributes" }} />
+ </NavItem>
+ <NavItem eventKey={3}>
+ <div
+ dangerouslySetInnerHTML={{ __html: "Matching Rules" }}
+ />
+ </NavItem>
+ </Nav>
+ <TabContent>
+ <TabPane eventKey={1}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <Checkbox
+ id="ocUserDefined"
+ checked={this.state.ocUserDefined}
+ title="Show only the objectclasses that are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (objectClasses with
+ X-ORIGIN: "user defined")
+ </Checkbox>
+ <hr />
+ <ObjectClassesTable
+ rows={this.state.filteredObjectclassRows}
+ viewModalHandler={this.showViewObjectclassModal}
+ editModalHandler={this.showEditObjectclassModal}
+ deleteHandler={this.deleteObjectclass}
+ loading={this.state.ocTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddObjectclassModal}
+ >
+ Add ObjectClass
+ </Button>
+ <ObjectClassModal
+ addHandler={this.addObjectclass}
+ editHandler={this.editObjectclass}
+ newOcEntry={this.state.newOcEntry}
+ ocModalViewOnly={this.state.ocModalViewOnly}
+ handleTypeaheadChange={this.handleTypeaheadChange}
+ handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ ocName={this.state.ocName}
+ ocDesc={this.state.ocDesc}
+ ocOID={this.state.ocOID}
+ ocParent={this.state.ocParent}
+ ocKind={this.state.ocKind}
+ ocMust={this.state.ocMust}
+ ocMay={this.state.ocMay}
+ objectclassModalShow={
+ this.state.objectclassModalShow
+ }
+ closeModal={this.closeObjectclassModal}
+ loading={this.state.ocModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={2}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <Checkbox
+ id="atUserDefined"
+ checked={this.state.atUserDefined}
+ title="Show only the attributes that are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (attributes with X-ORIGIN:
+ "user defined")
+ </Checkbox>
+ <hr />
+ <AttributesTable
+ rows={this.state.filteredAttributesRows}
+ viewModalHandler={this.showViewAttributeModal}
+ editModalHandler={this.showEditAttributeModal}
+ deleteHandler={this.deleteAttribute}
+ syntaxes={this.state.syntaxes}
+ loading={this.state.atTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddAttributeModal}
+ >
+ Add Attribute
+ </Button>
+ <AttributeTypeModal
+ addHandler={this.addAttribute}
+ editHandler={this.editAttribute}
+ newAtEntry={this.state.newAtEntry}
+ atModalViewOnly={this.state.atModalViewOnly}
+ handleTypeaheadChange={this.handleTypeaheadChange}
+ handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ matchingrules={this.state.matchingrules}
+ syntaxes={this.state.syntaxes}
+ atName={this.state.atName}
+ atDesc={this.state.atDesc}
+ atOID={this.state.atOID}
+ atParent={this.state.atParent}
+ atSyntax={this.state.atSyntax}
+ atUsage={this.state.atUsage}
+ atMultivalued={this.state.atMultivalued}
+ atNoUserMod={this.state.atNoUserMod}
+ atAlias={this.state.atAlias}
+ atEqMr={this.state.atEqMr}
+ atOrder={this.state.atOrder}
+ atSubMr={this.state.atSubMr}
+ attributeModalShow={this.state.attributeModalShow}
+ closeModal={this.closeAttributeModal}
+ loading={this.state.atModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={3}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <MatchingRulesTable
+ rows={this.state.matchingrulesRows}
+ />
+ </div>
+ </TabPane>
+ </TabContent>
+ </div>
+ </TabContainer>
+ </div>
+ </div>
+ );
+ }
+ return <div>{schemaPage}</div>;
+ }
+}
+
+// Props and defaultProps
+
+Schema.propTypes = {
+ serverId: PropTypes.string
+};
+
+Schema.defaultProps = {
+ serverId: ""
+};
+
+export default Schema;
diff --git a/src/cockpit/389-console/webpack.config.js b/src/cockpit/389-console/webpack.config.js
index f32e518..d3d766b 100644
--- a/src/cockpit/389-console/webpack.config.js
+++ b/src/cockpit/389-console/webpack.config.js
@@ -30,8 +30,6 @@ var info = {
"fonts",
"images",
"index.html",
- "schema.html",
- "schema.js",
"servers.html",
"servers.js",
"static",
diff --git a/src/lib389/lib389/schema.py b/src/lib389/lib389/schema.py
index 2a29a01..00443ff 100755
--- a/src/lib389/lib389/schema.py
+++ b/src/lib389/lib389/schema.py
@@ -110,7 +110,7 @@ class Schema(DSLdapObject):
if json:
attr_syntaxes_list = []
for id, name in ATTR_SYNTAXES.items():
- attr_syntaxes_list.append({'name': name, 'id': id})
+ attr_syntaxes_list.append({'label': name, 'id': id})
result = {'type': 'list', 'items': attr_syntaxes_list}
else:
result = ATTR_SYNTAXES
@@ -129,7 +129,7 @@ class Schema(DSLdapObject):
obj_i = vars(object_model(obj))
if len(obj_i["names"]) == 1:
obj_i['name'] = obj_i['names'][0].lower()
- obj_i['aliases'] = ""
+ obj_i['aliases'] = None
elif len(obj_i["names"]) > 1:
obj_i['name'] = obj_i['names'][0].lower()
obj_i['aliases'] = obj_i['names'][1:]
@@ -153,6 +153,12 @@ class Schema(DSLdapObject):
object_insts.append(obj_i)
object_insts = sorted(object_insts, key=itemgetter('name'))
+ # Ensure that the string values are in list so we can use React filter component with it
+ for obj_i in object_insts:
+ for key, value in obj_i.items():
+ if isinstance(value, str):
+ obj_i[key] = (value, )
+
return {'type': 'list', 'items': object_insts}
else:
object_insts = [object_model(obj_i) for obj_i in results]
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] 01/02: Issue 50842 - Decrease 389-console Cockpit component size
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
spichugi pushed a commit to branch 389-ds-base-1.4.2
in repository 389-ds-base.
commit ed29ead894b7599bda54ad07adc2e7eda8c0317c
Author: Simon Pichugin <spichugi(a)redhat.com>
AuthorDate: Wed Jan 22 13:34:49 2020 +0100
Issue 50842 - Decrease 389-console Cockpit component size
Description: Our Web UI source files are too big and
we should make it compact for the production.
Compress and decrease the size of the files that are generated by webpack.
Fix rpm.mk so it delivers RPMs only with production-ready result files
(we can skip js.map because it is used only for development)
Also, fix minor audit-ci issues.
https://pagure.io/389-ds-base/issue/50842
Reviewed by: mreynolds (Thanks!)
---
rpm.mk | 7 +-
src/cockpit/389-console/package-lock.json | 146 +++++++++++++++++++-----------
src/cockpit/389-console/package.json | 4 +-
src/cockpit/389-console/webpack.config.js | 31 ++++---
4 files changed, 119 insertions(+), 69 deletions(-)
diff --git a/rpm.mk b/rpm.mk
index 886f049..05c3533 100644
--- a/rpm.mk
+++ b/rpm.mk
@@ -52,16 +52,19 @@ install-node-modules:
cd src/cockpit/389-console; make -f node_modules.mk install
build-cockpit: install-node-modules
- cd src/cockpit/389-console; make -f node_modules.mk build-cockpit-plugin
+ cd src/cockpit/389-console; \
+ NODE_ENV=production make -f node_modules.mk build-cockpit-plugin
+ cd src/cockpit/389-console; rm -rf cockpit_dist/index.min.js.map
dist-bz2: install-node-modules download-cargo-dependencies
cd src/cockpit/389-console; \
rm -rf cockpit_dist; \
- make -f node_modules.mk build-cockpit-plugin; \
+ NODE_ENV=production make -f node_modules.mk build-cockpit-plugin; \
mv node_modules node_modules.release; \
touch cockpit_dist/*
mkdir -p $(NODE_MODULES_TEST)
touch -r src/cockpit/389-console/package.json $(NODE_MODULES_TEST)
+ cd src/cockpit/389-console; rm -rf cockpit_dist/index.min.js.map
tar cjf $(GIT_TAG).tar.bz2 --transform "s,^,$(GIT_TAG)/," $$(git ls-files) src/cockpit/389-console/cockpit_dist/ src/cockpit/389-console/node_modules
cd src/cockpit/389-console; \
rm -rf node_modules; \
diff --git a/src/cockpit/389-console/package-lock.json b/src/cockpit/389-console/package-lock.json
index a901b0b..52b81fe 100644
--- a/src/cockpit/389-console/package-lock.json
+++ b/src/cockpit/389-console/package-lock.json
@@ -2898,6 +2898,16 @@
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -5184,9 +5194,9 @@
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"events": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
- "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+ "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
"dev": true
},
"evp_bytestokey": {
@@ -5547,6 +5557,13 @@
}
}
},
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -5731,14 +5748,15 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
"dev": true,
"optional": true,
"requires": {
+ "bindings": "^1.5.0",
"nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
+ "node-pre-gyp": "*"
},
"dependencies": {
"abbrev": {
@@ -5786,7 +5804,7 @@
}
},
"chownr": {
- "version": "1.1.1",
+ "version": "1.1.3",
"bundled": true,
"dev": true,
"optional": true
@@ -5816,7 +5834,7 @@
"optional": true
},
"debug": {
- "version": "4.1.1",
+ "version": "3.2.6",
"bundled": true,
"dev": true,
"optional": true,
@@ -5843,12 +5861,12 @@
"optional": true
},
"fs-minipass": {
- "version": "1.2.5",
+ "version": "1.2.7",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.6.0"
}
},
"fs.realpath": {
@@ -5874,7 +5892,7 @@
}
},
"glob": {
- "version": "7.1.3",
+ "version": "7.1.6",
"bundled": true,
"dev": true,
"optional": true,
@@ -5903,7 +5921,7 @@
}
},
"ignore-walk": {
- "version": "3.0.1",
+ "version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true,
@@ -5922,7 +5940,7 @@
}
},
"inherits": {
- "version": "2.0.3",
+ "version": "2.0.4",
"bundled": true,
"dev": true,
"optional": true
@@ -5964,7 +5982,7 @@
"optional": true
},
"minipass": {
- "version": "2.3.5",
+ "version": "2.9.0",
"bundled": true,
"dev": true,
"optional": true,
@@ -5974,12 +5992,12 @@
}
},
"minizlib": {
- "version": "1.2.1",
+ "version": "1.3.3",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.9.0"
}
},
"mkdirp": {
@@ -5992,24 +6010,24 @@
}
},
"ms": {
- "version": "2.1.1",
+ "version": "2.1.2",
"bundled": true,
"dev": true,
"optional": true
},
"needle": {
- "version": "2.3.0",
+ "version": "2.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "debug": "^4.1.0",
+ "debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
}
},
"node-pre-gyp": {
- "version": "0.12.0",
+ "version": "0.14.0",
"bundled": true,
"dev": true,
"optional": true,
@@ -6023,7 +6041,7 @@
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
- "tar": "^4"
+ "tar": "^4.4.2"
}
},
"nopt": {
@@ -6037,13 +6055,22 @@
}
},
"npm-bundled": {
- "version": "1.0.6",
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"npm-packlist": {
- "version": "1.4.1",
+ "version": "1.4.7",
"bundled": true,
"dev": true,
"optional": true,
@@ -6114,7 +6141,7 @@
"optional": true
},
"process-nextick-args": {
- "version": "2.0.0",
+ "version": "2.0.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6155,7 +6182,7 @@
}
},
"rimraf": {
- "version": "2.6.3",
+ "version": "2.7.1",
"bundled": true,
"dev": true,
"optional": true,
@@ -6182,7 +6209,7 @@
"optional": true
},
"semver": {
- "version": "5.7.0",
+ "version": "5.7.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6235,18 +6262,18 @@
"optional": true
},
"tar": {
- "version": "4.4.8",
+ "version": "4.4.13",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
+ "yallist": "^3.0.3"
}
},
"util-deprecate": {
@@ -6271,7 +6298,7 @@
"optional": true
},
"yallist": {
- "version": "3.0.3",
+ "version": "3.1.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6423,9 +6450,9 @@
}
},
"globule": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
- "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.0.tgz",
+ "integrity": "sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg==",
"requires": {
"glob": "~7.1.1",
"lodash": "~4.17.10",
@@ -8088,9 +8115,9 @@
}
},
"node-sass": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
- "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
+ "version": "4.13.1",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz",
+ "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==",
"requires": {
"async-foreach": "^0.1.3",
"chalk": "^1.1.1",
@@ -8099,7 +8126,7 @@
"get-stdin": "^4.0.1",
"glob": "^7.0.3",
"in-publish": "^2.0.0",
- "lodash": "^4.17.11",
+ "lodash": "^4.17.15",
"meow": "^3.7.0",
"mkdirp": "^0.5.1",
"nan": "^2.13.2",
@@ -8109,6 +8136,13 @@
"sass-graph": "^2.2.4",
"stdout-stream": "^1.4.0",
"true-case-path": "^1.0.2"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ }
}
},
"nopt": {
@@ -10369,9 +10403,9 @@
}
},
"terser": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz",
- "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==",
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
+ "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@@ -10513,9 +10547,9 @@
}
},
"p-limit": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
- "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
@@ -11183,9 +11217,9 @@
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
},
"webpack": {
- "version": "4.41.2",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
- "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
+ "version": "4.41.5",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz",
+ "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.8.5",
@@ -11208,7 +11242,7 @@
"node-libs-browser": "^2.2.1",
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
- "terser-webpack-plugin": "^1.4.1",
+ "terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.0",
"webpack-sources": "^1.4.1"
},
@@ -11220,12 +11254,12 @@
"dev": true
},
"ajv": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
- "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
+ "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
"dev": true,
"requires": {
- "fast-deep-equal": "^2.0.1",
+ "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
@@ -11253,6 +11287,12 @@
"estraverse": "^4.1.1"
}
},
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+ "dev": true
+ },
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
diff --git a/src/cockpit/389-console/package.json b/src/cockpit/389-console/package.json
index 4289cf4..cfdab91 100644
--- a/src/cockpit/389-console/package.json
+++ b/src/cockpit/389-console/package.json
@@ -45,7 +45,7 @@
"sizzle": "^2.3.3",
"stdio": "^0.2.7",
"style-loader": "^0.23.1",
- "webpack": "^4.41.2",
+ "webpack": "^4.41.5",
"webpack-cli": "^3.1.0"
},
"dependencies": {
@@ -53,7 +53,7 @@
"bootstrap": "^4.3.1",
"file-loader": "^4.1.0",
"handlebars": "^4.5.3",
- "node-sass": "4.12.0",
+ "node-sass": "^4.13.1",
"patternfly": "^3.59.3",
"patternfly-react": "^2.34.3",
"prop-types": "15.6.2",
diff --git a/src/cockpit/389-console/webpack.config.js b/src/cockpit/389-console/webpack.config.js
index 026eb59..f32e518 100644
--- a/src/cockpit/389-console/webpack.config.js
+++ b/src/cockpit/389-console/webpack.config.js
@@ -90,10 +90,19 @@ if (production) {
output.filename = "[name].min.js";
plugins.unshift(
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: JSON.stringify("production")
+ }
+ })
+ );
+ plugins.unshift(new webpack.optimize.AggressiveMergingPlugin());
+ plugins.unshift(
new CompressionPlugin({
- asset: "[path].gz[query]",
+ filename: "[path].gz[query]",
test: /\.(js|html)$/,
- minRatio: 0.9,
+ threshold: 10240,
+ minRatio: 0.8,
deleteOriginalAssets: true
})
);
@@ -130,15 +139,13 @@ module.exports = {
test: /\.jsx$/,
options: {
presets: [
- '@babel/preset-env',
- '@babel/preset-react',
+ "@babel/preset-env",
+ "@babel/preset-react",
{
- plugins: [
- '@babel/plugin-proposal-class-properties'
- ]
+ plugins: ["@babel/plugin-proposal-class-properties"]
}
]
- },
+ }
},
{
exclude: /node_modules/,
@@ -146,21 +153,21 @@ module.exports = {
test: /\.es6$/
},
{
- // Transform our own .css files with PostCSS and CSS-modules
+ // Transform our own .css files with PostCSS and CSS-modules
test: /\.css$/,
exclude: /node_modules/,
- use: ['style-loader', 'css-loader'],
+ use: ["style-loader", "css-loader"]
},
{
test: /\.css$/,
include: /node_modules/,
- use: ['style-loader', 'css-loader'],
+ use: ["style-loader", "css-loader"]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
- loader: 'url-loader',
+ loader: "url-loader",
options: {
limit: 8192
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] 02/02: Issue 50836 - Port Schema UI tab to React
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
spichugi pushed a commit to branch 389-ds-base-1.4.1
in repository 389-ds-base.
commit 9dc085433c3b3418e205d09f7efbdc5c2a9862a6
Author: Simon Pichugin <spichugi(a)redhat.com>
AuthorDate: Mon Dec 23 00:28:32 2019 +0100
Issue 50836 - Port Schema UI tab to React
Description: Port the schema UI tab to React and preserve all
existing features.
https://pagure.io/389-ds-base/issue/50836
Reviewed by: mreynolds (Thank you!!)
---
src/cockpit/389-console/src/css/ds.css | 5 +
src/cockpit/389-console/src/ds.js | 10 +-
src/cockpit/389-console/src/index.es6 | 7 +
src/cockpit/389-console/src/index.html | 10 +-
.../389-console/src/lib/schema/schemaModals.jsx | 660 +++++++++++++
.../389-console/src/lib/schema/schemaTables.jsx | 558 +++++++++++
src/cockpit/389-console/src/lib/tools.jsx | 54 +-
src/cockpit/389-console/src/schema.html | 377 -------
src/cockpit/389-console/src/schema.js | 925 -----------------
src/cockpit/389-console/src/schema.jsx | 1042 ++++++++++++++++++++
src/cockpit/389-console/webpack.config.js | 2 -
src/lib389/lib389/schema.py | 10 +-
12 files changed, 2323 insertions(+), 1337 deletions(-)
diff --git a/src/cockpit/389-console/src/css/ds.css b/src/cockpit/389-console/src/css/ds.css
index 662d8de..a71f615 100644
--- a/src/cockpit/389-console/src/css/ds.css
+++ b/src/cockpit/389-console/src/css/ds.css
@@ -1021,6 +1021,11 @@ option {
width: 120px;
}
+.ds-schema-dropdown {
+ border-color: #06c !important;
+ color: #06c !important;
+}
+
.treeview .list-group-item {
/* remove focus border */
outline: none;
diff --git a/src/cockpit/389-console/src/ds.js b/src/cockpit/389-console/src/ds.js
index 7b4db77..0bddcef 100644
--- a/src/cockpit/389-console/src/ds.js
+++ b/src/cockpit/389-console/src/ds.js
@@ -12,7 +12,7 @@ var security_page_loaded = 1;
var db_page_loaded = 1;
var repl_page_loaded = 1;
var plugin_page_loaded = 1;
-var schema_page_loaded = 0;
+var schema_page_loaded = 1;
var monitor_page_loaded = 1;
var config_loaded = 0;
@@ -412,10 +412,6 @@ function load_config (refresh){
get_and_set_localpwp();
update_progress();
- // Schema page
- get_and_set_schema_tables();
- update_progress();
-
// Initialize the tabs
$(".ds-tab-list").css( 'color', '#777');
$("#server-tab").css( 'color', '#228bc0');
@@ -472,6 +468,10 @@ $(window.document).ready(function() {
$(".all-pages").hide();
$("#security-content").show();
});
+ $("#schema-tab").on("click", function() {
+ $(".all-pages").hide();
+ $("#schema-content").show();
+ });
$("#replication-tab").on("click", function() {
$(".all-pages").hide();
$("#replication-content").show();
diff --git a/src/cockpit/389-console/src/index.es6 b/src/cockpit/389-console/src/index.es6
index 6797dd5..6f2673f 100644
--- a/src/cockpit/389-console/src/index.es6
+++ b/src/cockpit/389-console/src/index.es6
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
import { Plugins } from "./plugins.jsx";
import { Database } from "./database.jsx";
import { Monitor } from "./monitor.jsx";
+import { Schema } from "./schema.jsx";
import { Security } from "./security.jsx";
import { Replication } from "./replication.jsx";
@@ -49,6 +50,12 @@ function renderReactDOM(clear) {
<Security serverId={serverIdElem} key={tabKey} />,
document.getElementById("security")
);
+
+ // Schema tab
+ ReactDOM.render(
+ <Schema serverId={serverIdElem} key={tabKey} />,
+ document.getElementById("schema")
+ );
}
// We have to create the wrappers because this is no simple way
diff --git a/src/cockpit/389-console/src/index.html b/src/cockpit/389-console/src/index.html
index 6a0479c..c1b9952 100644
--- a/src/cockpit/389-console/src/index.html
+++ b/src/cockpit/389-console/src/index.html
@@ -18,7 +18,6 @@
<script src="static/c3.min.js"></script>
<script src="static/d3.min.js"></script>
<script src="ds.js"></script>
- <script src="schema.js"></script>
<script src="servers.js"></script>
<link href="static/bootstrap.min.css" rel="stylesheet">
<link href="static/jquery.dataTables.min.css" type="text/css" rel="stylesheet">
@@ -109,15 +108,9 @@
<!-- Schema navtab -->
<li class="dropdown ds-nav-tab">
- <a href="#0" class="ds-tab-list" data-toggle="dropdown" id="schema-tab">
+ <a href="#0" class="ds-tab-list ds-tab-standalone" id="schema-tab">
Schema
- <b class="caret"></b>
</a>
- <ul class="dropdown-menu ds-nav-item">
- <li><a href="#0"class="ds-nav-choice" id="objectclass-btn" parent-id="schema-tab">Objectclasses</a></li>
- <li><a href="#0"class="ds-nav-choice" id="attribute-btn" parent-id="schema-tab">Attributes</a></li>
- <li><a href="#0" class="ds-nav-choice" id="schema-mr-btn" parent-id="schema-tab">Matching Rules</a></li>
- </ul>
</li>
<!-- Plugins navtab -->
@@ -514,6 +507,7 @@
</div>
<div id="schema-content" class="all-pages" hidden>
+ <div id="schema"></div>
</div>
<div id="plugin-content" class="all-pages" hidden>
diff --git a/src/cockpit/389-console/src/lib/schema/schemaModals.jsx b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
new file mode 100644
index 0000000..6b6049a
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
@@ -0,0 +1,660 @@
+import React from "react";
+import {
+ Row,
+ Spinner,
+ Modal,
+ Icon,
+ Button,
+ Checkbox,
+ noop,
+ Form,
+ FormControl,
+ FormGroup,
+ ControlLabel,
+ Col
+} from "patternfly-react";
+import { Typeahead } from "react-bootstrap-typeahead";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassModal extends React.Component {
+ render() {
+ const {
+ newOcEntry,
+ ocModalViewOnly,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ objectclasses,
+ attributes,
+ ocName,
+ ocDesc,
+ ocOID,
+ ocParent,
+ ocKind,
+ ocMust,
+ ocMay,
+ objectclassModalShow,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving objectClass...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={objectclassModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close" />
+ </button>
+ <Modal.Title>
+ {ocModalViewOnly ? (
+ `View ObjectClass - ${ocName}`
+ ) : (
+ <div>
+ {newOcEntry ? "Add" : "Edit"} ObjectClass
+ {ocName != "" ? ` - ${ocName}` : ""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="ocName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the objectClass">
+ Objectclass Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="ocName"
+ type="text"
+ value={ocName}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is the objectClass's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocDesc}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocOID">
+ <Col sm={4}>
+ <ControlLabel title="Object identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocOID}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocParent" controlId="ocParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass's parent">
+ Parent Objectclass
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+ handleTypeaheadChange("ocParent", values);
+ }}
+ selected={ocParent}
+ newSelectionPrefix="Add a parent: "
+ options={objectclasses}
+ placeholder="Type a parent objectClass..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocKind" controlId="ocKind" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass kind">
+ Objectclass Kind
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="ocKind"
+ className="btn btn-default dropdown"
+ onChange={handleFieldChange}
+ value={ocKind}
+ disabled={ocModalViewOnly}
+ >
+ <option>STRUCTURAL</option>
+ <option>ABSTRACT</option>
+ <option>AUXILIARY</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMust" controlId="ocMust" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A must attribute name">
+ Required Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMust", values);
+ }}
+ selected={ocMust}
+ newSelectionPrefix="Add a required attribute: "
+ options={attributes}
+ placeholder="Type an attribute name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMay" controlId="ocMay" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A may attribute name">
+ Allowed Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMay", values);
+ }}
+ selected={ocMay}
+ newSelectionPrefix="Add an allowed attribute: "
+ options={attributes}
+ placeholder="Type an attribute name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {ocModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newOcEntry ? addHandler : editHandler}
+ >
+ {newOcEntry ? "Add" : "Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+ObjectClassModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ newOcEntry: PropTypes.bool,
+ ocModalViewOnly: PropTypes.bool,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ objectclasses: PropTypes.array,
+ attributes: PropTypes.array,
+ ocName: PropTypes.string,
+ ocDesc: PropTypes.string,
+ ocOID: PropTypes.string,
+ ocParent: PropTypes.array,
+ ocKind: PropTypes.string,
+ ocMust: PropTypes.array,
+ ocMay: PropTypes.array,
+ objectclassModalShow: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ newOcEntry: true,
+ ocModalViewOnly: false,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ objectclasses: [],
+ attributes: [],
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: false,
+ closeModal: noop,
+ loading: false
+};
+
+class AttributeTypeModal extends React.Component {
+ render() {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr,
+ atModalViewOnly,
+ attributeModalShow,
+ newAtEntry,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ attributes,
+ syntaxes,
+ matchingrules,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving attribute...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={attributeModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close" />
+ </button>
+ <Modal.Title>
+ {atModalViewOnly ? (
+ `View Attribute - ${atName}`
+ ) : (
+ <div>
+ {newAtEntry ? "Add" : "Edit"} Attribute
+ {atName != "" ? ` - ${atName}` : ""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="atName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the attribute">
+ Attribute Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="atName"
+ type="text"
+ value={atName}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is the attribute's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atDesc}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atOID">
+ <Col sm={4}>
+ <ControlLabel title="Object identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atOID}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atParent" controlId="atParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's parent">
+ Parent Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+ handleTypeaheadChange("atParent", values);
+ }}
+ selected={atParent}
+ newSelectionPrefix="Add a parent: "
+ options={attributes}
+ placeholder="Type a parent attribute..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSyntax" controlId="atSyntax" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's syntax">
+ Syntax Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atSyntax", values);
+ }}
+ selected={atSyntax}
+ newSelectionPrefix="Add a syntax: "
+ options={syntaxes}
+ placeholder="Type a syntax name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atUsage" controlId="atUsage" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute usage purpose">
+ Attribute Usage
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="atUsage"
+ className="btn btn-default dropdown"
+ onChange={handleFieldChange}
+ value={atUsage}
+ disabled={atModalViewOnly}
+ >
+ <option>userApplications</option>
+ <option>directoryOperation</option>
+ <option>distributedOperation</option>
+ <option>dSAOperation</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="atMultivalued" controlId="atMultivalued">
+ <Col sm={4}>
+ <ControlLabel title="If attribute can have a multiple values">
+ Multivalued Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atMultivalued"
+ checked={atMultivalued}
+ title="If attribute can have a multiple values"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atNoUserMod" controlId="atNoUserMod">
+ <Col sm={4}>
+ <ControlLabel title="If attribute is not modifiable by a client application">
+ Not Modifiable By A User
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atNoUserMod"
+ checked={atNoUserMod}
+ title="If attribute is not modifiable by a client application"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atAlias" controlId="atAlias" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An alias name for the attribute">
+ Alias Names
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("atAlias", values);
+ }}
+ selected={atAlias}
+ options={[]}
+ newSelectionPrefix="Add an alias: "
+ placeholder="Type an alias name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atEqMr" controlId="atEqMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An equality matching rule">
+ Equality Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atEqMr", values);
+ }}
+ selected={atEqMr}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atOrder" controlId="atOrder" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An order matching rule">
+ Order Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atOrder", values);
+ }}
+ selected={atOrder}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSubMr" controlId="atSubMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A substring matching rule">
+ Substring Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atSubMr", values);
+ }}
+ selected={atSubMr}
+ newSelectionPrefix="Add an matching rule: "
+ options={matchingrules}
+ placeholder="Type an matching rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {atModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newAtEntry ? addHandler : editHandler}
+ >
+ {newAtEntry ? "Add" : "Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+AttributeTypeModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ attributes: PropTypes.array,
+ matchingrules: PropTypes.array,
+ syntaxes: PropTypes.array,
+ atName: PropTypes.string,
+ atDesc: PropTypes.string,
+ atOID: PropTypes.string,
+ atParent: PropTypes.array,
+ atSyntax: PropTypes.array,
+ atUsage: PropTypes.string,
+ atMultivalued: PropTypes.bool,
+ atNoUserMod: PropTypes.bool,
+ atAlias: PropTypes.array,
+ atEqMr: PropTypes.array,
+ atOrder: PropTypes.array,
+ atSubMr: PropTypes.array,
+ atModalViewOnly: PropTypes.bool,
+ attributeModalShow: PropTypes.bool,
+ newAtEntry: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+AttributeTypeModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ attributes: [],
+ matchingrules: [],
+ syntaxes: [],
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ closeModal: noop,
+ loading: false
+};
+
+export { ObjectClassModal, AttributeTypeModal };
diff --git a/src/cockpit/389-console/src/lib/schema/schemaTables.jsx b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
new file mode 100644
index 0000000..296845c
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
@@ -0,0 +1,558 @@
+import React from "react";
+import {
+ Button,
+ DropdownButton,
+ MenuItem,
+ actionHeaderCellFormatter,
+ sortableHeaderCellFormatter,
+ tableCellFormatter,
+ noop
+} from "patternfly-react";
+import { DSTable } from "../dsTable.jsx";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "ObjectClass Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "must",
+ header: {
+ label: "Required Attributes",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "may",
+ header: {
+ label: "Allowed Attributes",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user defined" ? (
+ <Button
+ onClick={() => {
+ this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Objectclass
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit ObjectClass
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete ObjectClass
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="ObjectClasses"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+ObjectClassesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ loading: false
+};
+
+class AttributesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Attribute Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {
+ this.props.syntaxes.filter(
+ attr => attr.id === value[0]
+ )[0]["label"]
+ }
+ </td>
+ ];
+ }
+ ]
+ }
+ },
+ {
+ property: "multivalued",
+ header: {
+ label: "Multivalued",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value ? "yes" : "no"}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user defined" ? (
+ <Button
+ onClick={() => {
+ this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Attribute
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit Attribute
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+ className="ds-schema-dropdown"
+ onClick={() => {
+ this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete Attribute
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="Attributes"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+AttributesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ syntaxes: PropTypes.array,
+ loading: PropTypes.bool
+};
+
+AttributesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ syntaxes: [],
+ loading: false
+};
+
+class MatchingRulesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Matching Rule Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "desc",
+ header: {
+ label: "Description",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [tableCellFormatter]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="oid"
+ rows={this.props.rows}
+ toolBarSearchField="Matching Rules"
+ toolBarDisableLoadingSpinner
+ />
+ </div>
+ );
+ }
+}
+
+MatchingRulesTable.propTypes = {
+ rows: PropTypes.array
+};
+
+MatchingRulesTable.defaultProps = {
+ rows: []
+};
+
+export { ObjectClassesTable, AttributesTable, MatchingRulesTable };
diff --git a/src/cockpit/389-console/src/lib/tools.jsx b/src/cockpit/389-console/src/lib/tools.jsx
index 631135e..7617a78 100644
--- a/src/cockpit/389-console/src/lib/tools.jsx
+++ b/src/cockpit/389-console/src/lib/tools.jsx
@@ -6,7 +6,9 @@ export function searchFilter(searchFilterValue, columnsToSearch, rows) {
if (columnsToSearch && columnsToSearch.length) {
columnsToSearch.forEach(column => {
if (column in row) {
- rowToSearch.push(row[column]);
+ if (row[column] != null) {
+ rowToSearch.push(row[column]);
+ }
}
});
} else {
@@ -53,22 +55,26 @@ export function log_cmd(js_func, desc, cmd_array) {
cmd_list.push(cmd);
}
}
- console.log(
- "CMD: " + js_func + ": " + desc + " ==> " + cmd_list.join(" ")
- );
+ console.log("CMD: " + js_func + ": " + desc + " ==> " + cmd_list.join(" "));
}
}
// Convert DS timestamp to a friendly string: 20180921142257Z -> 10/21/2018, 2:22:57 PM
-export function get_date_string (timestamp) {
+export function get_date_string(timestamp) {
let year = timestamp.substr(0, 4);
let month = timestamp.substr(4, 2);
let day = timestamp.substr(6, 2);
let hour = timestamp.substr(8, 2);
let minute = timestamp.substr(10, 2);
let sec = timestamp.substr(12, 2);
- let date = new Date(parseInt(year), (parseInt(month) - 1), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let date = new Date(
+ parseInt(year),
+ parseInt(month) - 1,
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
return date.toLocaleString();
}
@@ -81,8 +87,14 @@ export function get_date_diff(start, end) {
let hour = start.substr(8, 2);
let minute = start.substr(10, 2);
let sec = start.substr(12, 2);
- let startDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let startDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Get the servers current date
year = end.substr(0, 4);
@@ -91,17 +103,23 @@ export function get_date_diff(start, end) {
hour = end.substr(8, 2);
minute = end.substr(10, 2);
sec = end.substr(12, 2);
- let currDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let currDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Generate pretty elapsed time string
- let seconds = Math.floor((currDate - (startDate)) / 1000);
+ let seconds = Math.floor((currDate - startDate) / 1000);
let minutes = Math.floor(seconds / 60);
let hours = Math.floor(minutes / 60);
let days = Math.floor(hours / 24);
- hours = hours - (days * 24);
- minutes = minutes - (days * 24 * 60) - (hours * 60);
- seconds = seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
+ hours = hours - days * 24;
+ minutes = minutes - days * 24 * 60 - hours * 60;
+ seconds = seconds - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60;
return `${days} days, ${hours} hours, ${minutes} minutes, and ${seconds} seconds`;
}
@@ -114,7 +132,7 @@ export function bad_file_name(file_name) {
return false;
}
-export function valid_port (val) {
+export function valid_port(val) {
// Validate value is a number and between 1 and 65535
let result = !isNaN(val);
if (result) {
@@ -125,9 +143,9 @@ export function valid_port (val) {
return result;
}
-export function valid_dn (dn) {
+export function valid_dn(dn) {
// Validate value is a valid DN (sanity validation)
- if (dn.endsWith(',')) {
+ if (dn.endsWith(",")) {
return false;
}
let dn_regex = new RegExp("^([A-Za-z]+=.*)");
diff --git a/src/cockpit/389-console/src/schema.html b/src/cockpit/389-console/src/schema.html
deleted file mode 100644
index cb6baf9..0000000
--- a/src/cockpit/389-console/src/schema.html
+++ /dev/null
@@ -1,377 +0,0 @@
-
-<div id="schema-content">
- <div id="objectclass-page" class="all-pages ds-margin-left" hidden>
- <h3 class="ds-config-header">Objectclasses</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="oc-user-defined"><label
- for="oc-user-defined" class="ds-label">Only Non-standard Schema (objectClasses with X-ORIGIN: "user defined")</label>
- </div>
- <table id="oc-table" class="display ds-repl-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Objectclass Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Required Attributes</th>
- <th class="ds-center">Allowed Attributes</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="add-oc-button" name="create-oc" data-toggle="modal" data-target="#add-edit-oc-form" class="btn btn-primary ds-button">Create Objectclass</button>
- </div>
-
- <div id="attribute-page" class="all-pages ds-margin-left" hidden>
- <h3 class="ds-config-header">Attributes</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-user-defined"><label
- for="attr-user-defined" class="ds-label">Only Non-standard Schema (attributes with X-ORIGIN: "user defined")</label>
- </div>
- <table id="attr-table" class="display ds-repl-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Attribute Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Syntax</th>
- <th class="ds-center">Multivalued</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="create-attr-button" data-toggle="modal" data-target="#add-edit-attr-form" class="btn btn-primary ds-button">Create Attribute</button>
- </div>
-
- <div id="schema-mr" class="all-pages ds-margin-left" hidden>
- <div class="">
- <h3 class="ds-config-header">Matching Rules</h3>
- <table id="schema-mr-table" class="display ds-table" cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th>Matching Rule Name</th>
- <th>OID</th>
- <th>Syntax</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody id="standard-body">
- </tbody>
- </table>
- </div>
- </div>
-
-
- <!-- 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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-multivalued-view" disabled="disabled" /><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" disabled="disabled" /><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" disabled />
- </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" disabled />
- </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" disabled />
- </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" disabled />
- </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">
- <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" id="add-edit-attr-header">Add Attribute</h4>
- </div>
- <div class="modal-body">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <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
- >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
- >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
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-syntax">
- <option value="">Make a selection</option>
- </select>
- </div>
- <div>
- <label for="attr-usage" class="ds-config-label-lrg" title="The parent attribute"><b>Attribute Usage</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-usage">
- </select>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-multivalued"><label
- for="attr-multivalued" class="ds-label"> Attribute Multi-Valued </label>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox" id="attr-no-user-mod"><label
- for="attr-no-user-mod" class="ds-label"> Read-only (NO-USER-MODIFICATION flag) </label>
- </div>
- <div>
- <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 ds-margin-top">
- <div class="panel-heading"><strong>Matching rules</strong></div>
- <div class="panel-body">
- <div>
- <label for="attr-eq-mr-select" class="ds-config-label-lrg"><b>Equality</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-eq-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-order-mr-select" class="ds-config-label-lrg"><b>Ordering</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-order-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-sub-mr-select" class="ds-config-label-lrg"><b>Substring</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown" id="attr-sub-mr-select">
- <option></option>
- </select>
- </div>
- </div>
- </div>
- </div>
- <div id="save-attr-spinner" class="ds-center" hidden>
- <p></p>
- <p><span class="spinner spinner-xs spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" id="save-attr-button">Save</button>
- </div>
- </div>
- </div>
- </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" disabled />
- </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" disabled/>
- </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" disabled/>
- </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" disabled />
- </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" disabled />
- </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 disabled>
- </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 disabled>
- </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">
- <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" id="add-edit-oc-header">Add Objectclass</h4>
- </div>
- <div class="modal-body">
- <form class="form-horizontal">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <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
- >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>
- </div>
- <hr>
- <div class="ds-container">
- <div name="available-attrs">
- <label for="schema-list" title="The available attributes to choose from."><b>Available Attributes</b></label>
- <select id="schema-list" class="ds-oc-form-list" name="availattrs" multiple>
- </select>
- </div>
-
- <div name="add-remove-buttons">
- <div name="must buttons" class="btn-group ds-oc-must-buttons">
- <input type="button" class="ds-oc-add-del-btn" id="oc-must-add-button" value="Add ► ► ► "/>
- <input type="button" class="ds-oc-add-del-btn" id="oc-must-remove-button" value="◄ ◄ ◄ Remove"/>
- </div>
- <p></p>
- <div name="may buttons" class="btn-group ds-oc-may-buttons">
- <input type="button" class="ds-oc-add-del-btn" id="oc-may-add-button" value="Add ► ► ►"/>
- <input type="button" class="ds-oc-add-del-btn" id="oc-may-remove-button" value="◄ ◄ ◄ Remove"/>
- </div>
- </div>
-
- <div name="may-must-lists">
- <label class="ds-config-label" for="oc-required-list" title=
- "Attributes required by the objectclass"><b>Required Attributes</b></label>
- <select id="oc-required-list" class="ds-may-must-list" name="availattrs" multiple>
- </select>
- <p></p>
- <label class="ds-config-label" for="oc-allowed-list" title=
- "Attributes allowed by the objectclass"><b>Allowed Attributes</b></label>
- <select id="oc-allowed-list" class="ds-may-must-list" name="availattrs" multiple>
- </select>
- </div>
- </div>
- </div>
- </form>
- <div id="save-oc-spinner" class="ds-center" hidden>
- <p></p>
- <p><span class="spinner spinner-xs spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" id="save-oc-button">Save</button>
- </div>
- </div>
- </div>
- </div>
-
-</div>
diff --git a/src/cockpit/389-console/src/schema.js b/src/cockpit/389-console/src/schema.js
deleted file mode 100644
index ea6159b..0000000
--- a/src/cockpit/389-console/src/schema.js
+++ /dev/null
@@ -1,925 +0,0 @@
-var attr_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown" role="menu" id="attr-action-btn" aria-labelledby="attr-action-btn">' +
- '<li role=""><a role="menuitem" tabindex="0" class="attr-edit-btn" href="#schema-tab">Edit Attribute</a></li>' +
- '<li role=""><a role="menuitem" tabindex="1" class="attr-del-btn" href="#schema-tab">Delete Attribute</a></li>' +
- '</ul>' +
- '</div>';
-
-var attr_btn_html_only_view =
- '<button class="btn btn-default attr-view-btn" type="button"' +
- ' href="#schema-tab" title="Only user-defined attributes can be modified"> View Attribute' +
- '</button>';
-
-var oc_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle" type="button"data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown" role="menu">' +
- '<li role=""><a role="menuitem" tabindex="0" class="oc-edit-btn" href="#schema-tab">Edit Objectclass</a></li>' +
- '<li role=""><a role="menuitem" tabindex="1" class="oc-del-btn" href="#schema-tab">Delete Objectclass</a></li>' +
- '</ul>' +
- '</div>';
-
-var oc_btn_html_only_view =
- '<button class="btn btn-default oc-view-btn" type="button"' +
- ' href="#schema-tab" title="Only user-defined objectClasses can be modified"> View Objectclass' +
- '</button>';
-
-var schema_oc_table;
-var schema_at_table;
-var schema_mr_table;
-
-var attr_usage_opts = ['userApplications', 'directoryOperation', 'distributedOperation', 'dSAOperation'];
-var oc_kind_opts = ['STRUCTURAL', 'ABSTRACT', 'AUXILIARY'];
-
-function is_x_origin_user_defined(x_origin) {
- if (typeof x_origin === 'string' && x_origin.toLowerCase() !== 'user defined' || x_origin == null) {
- return false;
- } else {
- return true;
- }
-}
-
-// Leave only user defined attributes if the checkbox is crossed
-$.fn.dataTable.ext.search.push(
- function(settings, searchData, index, rowData, counter) {
- var x_origin;
- if ( settings.sTableId == "attr-table" ) {
- if ( $("#attr-user-defined").is(":checked") ) {
- x_origin = rowData[7];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- } else {
- if ( $("#oc-user-defined").is(":checked") ) {
- x_origin = rowData[5];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- }
- return true;
- }
-);
-
-function clear_oc_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-oc-header").html('Add Objectclass');
- $(".ds-modal-error").hide();
- $("#oc-name").attr('disabled', false);
- $("#oc-name").val("");
- $("#oc-oid").val("");
- $("#oc-kind").prop('selectedIndex',0);
- $("#oc-desc").val("");
- $("#oc-parent").prop('selectedIndex',0);
- $("#schema-list").prop('selectedIndex',-1);
- $('#oc-required-list').find('option').remove();
- $('#oc-allowed-list').find('option').remove();
- $("#save-oc-button").attr('disabled', false);
-}
-
-function clear_attr_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-attr-header").html('Add Attribute');
- $(".ds-modal-error").hide();
- $("#attr-name").attr('disabled', false);
- $("#attr-name").val("");
- $("#attr-syntax").val("");
- $("#attr-desc").val("");
- $("#attr-parent").prop('selectedIndex',0);
- $("#attr-usage").prop('selectedIndex',0);
- $("#attr-oid").val("");
- $("#attr-alias").val("");
- $('#attr-multivalued').prop('checked', false);
- $('#attr-no-user-mod').prop('checked', false);
- $("#attr-eq-mr-select").prop('selectedIndex',0);
- $("#attr-order-mr-select").prop('selectedIndex',0);
- $("#attr-sub-mr-select").prop('selectedIndex',0);
- $("#save-attr-button").attr('disabled', false);
-}
-
-function load_schema_objects_to_select(object, select_id, schema_json_select) {
- var data = [];
- for (var i = 0; i < schema_json_select[object].items.length; i++) {
- item = schema_json_select[object].items[i];
- if (item.name) {
- data.push.apply(data, [item.name]);
- } else {
- data.push.apply(data, [item.oid]);
- }
- }
- // Update html select
- $.each(data, function (i, item) {
- $("#" + select_id).append($('<option>', {
- value: item,
- text : item
- }));
- });
-}
-
-function get_and_set_schema_tables() {
- console.log("Loading schema...");
-
- // Set attribute usage select html in attribute's edit window
- $.each(attr_usage_opts, function (i, item) {
- $("#attr-usage").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- // Set objectClass kind select html in objectClass's edit window
- $.each(oc_kind_opts, function (i, item) {
- $("#oc-kind").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'list'];
- log_cmd('get_and_set_schema_tables', 'Get all schema objects', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(schema_data) {
- var schema_json = JSON.parse(schema_data);
- // Setup the tables: standard, custom, and Matching Rules
- var data = [];
- // If objectClass is user defined them the action button is enabled
- for (var i = 0; i < schema_json.objectclasses.items.length; i++) {
- var oc_btn = oc_btn_html_only_view;
- item = schema_json.objectclasses.items[i];
- if (is_x_origin_user_defined(item.x_origin)) {
- oc_btn = oc_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.must === undefined) {
- item.must = [];
- }
- if (item.may === undefined) {
- item.may = [];
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.kind === undefined) {
- item.kind = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ]]);
- }
- // Update html table
- schema_oc_table = $('#oc-table').DataTable ({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip',
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No objectclasses defined",
- "search": "Search Objectclasses"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
-
- // Get syntaxes and use the data to populate the attribute's table
- cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', "attributetypes", 'get_syntaxes'];
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(syntax_data) {
- var obj = JSON.parse(syntax_data);
- var syntax_list = [];
-
- load_schema_objects_to_select('matchingrules', 'attr-eq-mr-select', schema_json);
- load_schema_objects_to_select('matchingrules', 'attr-order-mr-select', schema_json);
- load_schema_objects_to_select('matchingrules', 'attr-sub-mr-select', schema_json);
- load_schema_objects_to_select('attributetypes', 'schema-list', schema_json);
- load_schema_objects_to_select('objectclasses', 'oc-parent', schema_json);
- load_schema_objects_to_select('attributetypes', 'attr-parent', schema_json);
-
- for (var i = 0; i < obj.items.length; i++) {
- item = obj.items[i];
- syntax_list.push.apply(syntax_list, [item]);
- }
- // Update syntax select html in attribute's edit window
- $.each(syntax_list, function (i, item) {
- $("#attr-syntax").append($('<option>', {
- value: item.id,
- text : item.name + " (" + item.id + ")"
- }));
- });
-
- var data = [];
- var syntax_name = "";
- for (var i = 0; i < schema_json.attributetypes.items.length; i++) {
- var attr_btn = attr_btn_html_only_view;
- item = schema_json.attributetypes.items[i];
- if (item.single_value) {
- multivalued = 'no';
- } else {
- multivalued = 'yes';
- }
- $.each(syntax_list, function (i, syntax) {
- if (syntax.id === item.syntax) {
- syntax_name = '<div title="' + syntax.name + '">' + syntax.name + '</div>';
- }
- });
- // If attribute is user defined them the action button is enabled
- if (is_x_origin_user_defined(item.x_origin)) {
- attr_btn = attr_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.no_user_mod === undefined) {
- item.no_user_mod = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.usage === undefined) {
- item.usage = "";
- }
- if (item.aliases === undefined) {
- item.aliases = "";
- }
- if (item.equality === undefined) {
- item.equality = "";
- }
- if (item.ordering === undefined) {
- item.ordering = "";
- }
- if (item.substr === undefined) {
- item.substr = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- syntax_name,
- multivalued,
- attr_btn,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
- ]]);
- }
- // Update html table
- schema_at_table = $('#attr-table').DataTable({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip', // Moves the search box to the left
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No attributes defined",
- "search": "Search Attributes"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
- update_progress();
- }).fail(function(syntax_data) {
- console.log("Get syntaxes failed: " + syntax_data.message);
- check_inst_alive(1);
- });
-
- var data = [];
- for (var i = 0; i < schema_json.matchingrules.items.length; i++) {
- item = schema_json.matchingrules.items[i];
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.syntax,
- item.desc]]);
- }
- schema_mr_table = $('#schema-mr-table').DataTable({
- "paging": true,
- "data": data,
- "bAutoWidth": false,
- "dom": '<"pull-left"f><"pull-right"l>tip',
- "language": {
- "emptyTable": "No matching rules defined",
- "search": "Search Matching Rules"
- },
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- });
-
- 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);
- });
-}
-
-$(document).ready( function() {
- // Set an interval event to wait for all the pages to load, then load the config
- $("#schema-content").load("schema.html", function (){
- // Sort schema list awhile
- sort_list( $("#schema-list") );
-
- $("#objectclass-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#objectclass-page").show();
- });
- $("#attribute-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#attribute-page").show();
- });
- $("#schema-mr-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#schema-mr").show();
- });
-
- $('#attr-user-defined').change(function() {
- schema_at_table.draw();
- });
- $('#oc-user-defined').change(function() {
- schema_oc_table.draw();
- });
-
- //
- // Modals/Forms
- //
-
- /*
- *
- * Add Objectclass Form
- *
- */
- $("#add-oc-button").on("click", function() {
- clear_oc_form();
- document.getElementById("oc-parent").value = 'top';
- });
-
- $("#save-oc-button").on("click", function() {
- var oc_name = $("#oc-name").val();
- var oc_oid = $("#oc-oid").val();
- var oc_parent = $("#oc-parent").val();
- var oc_kind = $("#oc-kind").val();
- var oc_desc = $("#oc-desc").val();
- var oc_x_origin = "user defined";
- var oc_required_list = $('#oc-required-list option').map(function() { return $(this).val(); }).get();
- var oc_allowed_list = $('#oc-allowed-list option').map(function() { return $(this).val(); }).get();
-
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-oc-header").text().indexOf("Edit Objectclass") != -1){
- edit = true;
- action = 'replace';
- }
- if (oc_name == '') {
- report_err($("#oc-name"), 'You must provide an objectClass name');
- return;
- }
- var cmd = [DSCONF, server_inst, 'schema', 'objectclasses', action, oc_name];
- // Process and validate parameters
- if (oc_oid != "") {
- cmd.push.apply(cmd, ["--oid", oc_oid]);
- }
- if (oc_parent != "") {
- cmd.push.apply(cmd, ["--sup", oc_parent]);
- }
- if (oc_kind != "") {
- cmd.push.apply(cmd, ["--kind", oc_kind]);
- }
- if (oc_desc != "") {
- cmd.push.apply(cmd, ["--desc", oc_desc]);
- }
- if (oc_x_origin != "") {
- cmd.push.apply(cmd, ["--x-origin=\"" + oc_x_origin + "\""]);
- }
- if (oc_required_list.length !== 0) {
- cmd.push.apply(cmd, ["--must"]);
- cmd.push.apply(cmd, oc_required_list);
- }
- if (oc_allowed_list.length !== 0) {
- cmd.push.apply(cmd, ["--may"]);
- cmd.push.apply(cmd, oc_allowed_list);
- }
-
- $("#save-oc-spinner").show();
- log_cmd('#save-oc-button (click)', 'Save objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(data) {
- $("#oc-name").attr('disabled', false);
-
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + oc_name + ')');
- schema_oc_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'objectclasses', 'query', oc_name];
- log_cmd('#save-oc-button (click)', 'Search objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(oc_data) {
- var obj = JSON.parse(oc_data);
- var item = obj.oc;
- schema_oc_table.row.add( [
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn_html,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ] ).draw( false );
- }).
- fail(function(oc_data) {
- popup_err("err", oc_data.message);
- console.log("Search objectclasses failed: " + oc_data.message);
- check_inst_alive(1);
- });
- // Replace the option in 'Edit objectClass' window
- if (!edit) {
- var option = $('<option></option>').attr("value", oc_name).text(oc_name);
- $("#oc-parent").append(option);
- }
- $("#save-oc-spinner").hide();
- popup_success("The objectClass was saved in DS");
- $("#add-edit-oc-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-oc-spinner").hide();
- popup_err("Error", "Failed to save the objectClass\n" + data.message);
- $("#add-edit-oc-form").modal('toggle');
- });
- });
-
- // Required Attributes
- $("#oc-must-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-required-list option[value="' + add_attrs[i] + '"]').val() === undefined) {
- $('#oc-required-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-must-remove-button").on("click", function () {
- var add_attrs = $("#oc-required-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text + '"]').val() === undefined) {
- $('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-required-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- // Allowed Attributes
- $("#oc-may-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-allowed-list option[value="' + add_attrs[i] + '"]').val() === undefined) {
- $('#oc-allowed-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-may-remove-button").on("click", function () {
- var add_attrs = $("#oc-allowed-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length > 0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text + '"]').val() === undefined) {
- $('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-allowed-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- /*
- *
- * Add Attribute Form
- *
- */
- $("#create-attr-button").on("click", function() {
- clear_attr_form();
- });
-
- $("#save-attr-button").on("click", function() {
- var attr_name = $("#attr-name").val();
- var attr_oid = $("#attr-oid").val();
- var attr_syntax = $("#attr-syntax").val();
- var attr_syntax_text = $("#attr-syntax :selected").text();
- var attr_usage = $('#attr-usage').val();
- var attr_desc = $('#attr-desc').val();
- var attr_x_origin = "user defined";
- var attr_parent = $('#attr-parent').val();
- var attr_aliases = $('#attr-alias').val().split(" ");
- var eq_mr= $('#attr-eq-mr-select').val();
- var order_mr = $('#attr-order-mr-select').val();
- var sub_mr = $('#attr-sub-mr-select').val();
- var multiple = 'no';
- if ( $("#attr-multivalued").is(":checked") ) {
- multiple = 'yes';
- }
- var no_user_mod = false;
- if ( $("#attr-no-user-mod").is(":checked") ) {
- no_user_mod = true;
- }
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-attr-header").text().indexOf("Edit Attribute") != -1){
- edit = true;
- action = 'replace';
- }
-
- if (attr_name == '') {
- report_err($("#attr-name"), 'You must provide an attribute name');
- return;
- }
- if (attr_syntax == '') {
- report_err($("#attr-syntax"), 'You must provide an attribute syntax');
- return;
- }
-
- var cmd = [DSCONF, server_inst, 'schema', 'attributetypes', action, attr_name];
- // Process and validate parameters
- if (attr_aliases) {
- cmd.push.apply(cmd, ["--aliases"]);
- cmd.push.apply(cmd, attr_aliases);
- }
- if (attr_syntax) {
- cmd.push.apply(cmd, ["--syntax", attr_syntax]);
- }
- if (multiple == 'no') {
- cmd.push.apply(cmd, ["--single-value"]);
- } else {
- cmd.push.apply(cmd, ["--multi-value"]);
- }
- if (no_user_mod) {
- cmd.push.apply(cmd, ["--no-user-mod"]);
- } else {
- cmd.push.apply(cmd, ["--user-mod"]);
- }
- cmd.push.apply(cmd, ["--oid", attr_oid]);
- cmd.push.apply(cmd, ["--usage", attr_usage]);
- cmd.push.apply(cmd, ["--sup", attr_parent]);
- cmd.push.apply(cmd, ["--desc", attr_desc]);
- cmd.push.apply(cmd, ["--x-origin", attr_x_origin]);
- cmd.push.apply(cmd, ["--equality"]);
- if (eq_mr) {
- cmd.push.apply(cmd, [eq_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--substr"]);
- if (sub_mr) {
- cmd.push.apply(cmd, [sub_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--ordering"]);
- if (order_mr) {
- cmd.push.apply(cmd, [order_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- $("#save-attr-spinner").show();
- log_cmd('#save-attr-button (click)', 'Save attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(data) {
- var attr_syntax_name = '<div title="' + attr_syntax + '">' +
- attr_syntax_text.substr(0, attr_syntax_text.indexOf(" (")) + '</div>';
- $("#attr-name").attr('disabled', false);
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + attr_name + ')');
- schema_at_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'attributetypes', 'query', attr_name];
- log_cmd('#save-oc-button (click)', 'Get attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).
- done(function(at_data) {
- var obj = JSON.parse(at_data);
- var item = obj.at;
- schema_at_table.row.add( [
- item.name,
- item.oid,
- attr_syntax_name,
- multiple,
- attr_btn_html,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
-
- ] ).draw( false );
- $("#attr-name").attr('disabled', false);
- }).
- fail(function(at_data) {
- popup_err("err", at_data.message);
- console.log("Query attributes failed: " + at_data.message);
- check_inst_alive(1);
- });
- if (!edit) {
- var option = $('<option></option>').attr("value", attr_name).text(attr_name);
- $("#schema-list").append(option);
- }
- $("#save-attr-spinner").hide();
- popup_success("The attribute was saved in DS");
- $("#add-edit-attr-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-attr-spinner").hide();
- popup_err("Error", "Failed to save the attribute: " + data.message);
- $("#add-edit-attr-form").modal('toggle');
- });
- });
-
- function load_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];
-
- $("#add-edit-attr-header").html('Edit Attribute: ' + edit_attr_name);
- $("#attr-name").val(edit_attr_name);
- $("#attr-name").attr('disabled', true);
- $("#attr-oid").val(edit_attr_oid);
- $("#attr-usage")[0].value = edit_attr_usage;
- $("#attr-parent")[0].value = edit_attr_parent;
- $("#attr-desc").val(edit_attr_desc);
- if (edit_attr_aliases) {
- $("#attr-alias").val(edit_attr_aliases.join(" "));
- }
- $("#attr-syntax").val(edit_attr_syntax);
- $("#attr-multivalued").prop('checked', false);
- if (edit_attr_multivalued == "yes") {
- $("#attr-multivalued").prop('checked', true);
- }
- $("#attr-no-user-mod").prop('checked', false);
- if (edit_attr_no_user_mod) {
- $("#attr-no-user-mod").prop('checked', true);
- }
- $("#save-attr-spinner").show();
- $("#attr-eq-mr-select")[0].value = edit_attr_eq_mr;
- $("#attr-order-mr-select")[0].value = edit_attr_order_mr;
- $("#attr-sub-mr-select")[0].value = edit_attr_sub_mr;
- $("#save-attr-spinner").hide();
-
- $("#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_view_attr_form($(this));
- });
-
- $(document).on('click', '.attr-edit-btn', function(e) {
- e.preventDefault();
- load_attr_form($(this));
- });
-
- $(document).on('click', '.attr-del-btn', function(e) {
- e.preventDefault();
- var data = schema_at_table.row( $(this).parents('tr') ).data();
- var del_attr_name = data[0];
- var at_row = $(this);
- popup_confirm("Are you sure you want to delete attribute: <b>" + del_attr_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'attributetypes', 'remove', del_attr_name];
- log_cmd('.attr-del-btn (click)', 'Remove attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {
- popup_success("Attribute was successfully removed!");
- schema_at_table.row( at_row.parents('tr') ).remove().draw( false );
- $("#schema-list option[value='" + del_attr_name + "']").remove();
- }).fail(function(data) {
- popup_err("Attribute removal error", del_attr_name + " removal has failed: " + data.message);
- });
- }
- });
- });
-
- 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();
- 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];
-
- $("#save-oc-spinner").show();
- $("#add-edit-oc-header").html('Edit Objectclass: ' + edit_oc_name);
- $("#oc-name").attr('disabled', true);
- $("#oc-name").val(edit_oc_name);
- $("#oc-oid").val(edit_oc_oid);
- $("#oc-kind").val(edit_oc_kind);
- $("#oc-desc").val(edit_oc_desc);
- $("#oc-parent").val(edit_oc_parent);
- $.each(edit_oc_required, function (i, item) {
- if (item) {
- $("#oc-required-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $.each(edit_oc_allowed, function (i, item) {
- if (item) {
- $("#oc-allowed-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $("#save-oc-spinner").hide();
-
- // Update modal html header and fields and show()
- $("#add-edit-oc-form").modal('toggle');
- }
-
- $(document).on('click', '.oc-view-btn', function(e) {
- e.preventDefault();
- load_view_oc_form($(this));
- });
-
- $(document).on('click', '.oc-edit-btn', function(e) {
- e.preventDefault();
- load_oc_form($(this));
- });
-
- $(document).on('click', '.oc-del-btn', function(e) {
- e.preventDefault();
- var data = schema_oc_table.row( $(this).parents('tr') ).data();
- var del_oc_name = data[0];
- var oc_row = $(this);
-
- popup_confirm("Are you sure you want to delete objectclass: <b>" + del_oc_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket', 'schema', 'objectclasses', 'remove', del_oc_name];
- log_cmd('.oc-del-btn (click)', 'Remove objectclass', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {
- popup_success("ObjectClass was successfully removed!");
- schema_oc_table.row( oc_row.parents('tr') ).remove().draw( false );
- $("#oc-parent option[value='" + del_oc_name + "']").remove();
- }).fail(function(data) {
- popup_err("Error", del_oc_name + " removal has failed: " + data.message);
- });
- }
- });
- });
- // Page is loaded, mark it as so...
- schema_page_loaded = 1;
- });
-});
diff --git a/src/cockpit/389-console/src/schema.jsx b/src/cockpit/389-console/src/schema.jsx
new file mode 100644
index 0000000..7e6ade6
--- /dev/null
+++ b/src/cockpit/389-console/src/schema.jsx
@@ -0,0 +1,1042 @@
+import cockpit from "cockpit";
+import React from "react";
+import { NotificationController } from "./lib/notifications.jsx";
+import { log_cmd, searchFilter } from "./lib/tools.jsx";
+import {
+ ObjectClassesTable,
+ AttributesTable,
+ MatchingRulesTable
+} from "./lib/schema/schemaTables.jsx";
+import { ObjectClassModal, AttributeTypeModal } from "./lib/schema/schemaModals.jsx";
+import {
+ Nav,
+ NavItem,
+ Checkbox,
+ TabContainer,
+ TabContent,
+ TabPane,
+ Spinner,
+ Button
+} from "patternfly-react";
+import PropTypes from "prop-types";
+import "./css/ds.css";
+
+export class Schema extends React.Component {
+ componentWillMount() {
+ this.loadSyntaxesFirst();
+ }
+
+ componentDidUpdate(prevProps) {
+ if (this.props.serverId !== prevProps.serverId) {
+ this.loadSyntaxesFirst();
+ }
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ loading: false,
+ notifications: [],
+ activeKey: 1,
+
+ objectclassRows: [],
+ filteredObjectclassRows: [],
+ attributesRows: [],
+ filteredAttributesRows: [],
+ matchingrulesRows: [],
+ syntaxes: [],
+ attributes: [],
+ objectclasses: [],
+ matchingrules: [],
+
+ ocModalViewOnly: false,
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ ocUserDefined: false,
+ objectclassModalShow: false,
+ newOcEntry: true,
+ ocTableLoading: false,
+ ocModalLoading: false,
+
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atUserDefined: false,
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ atTableLoading: false,
+ atModalLoading: false
+ };
+
+ this.handleFieldChange = this.handleFieldChange.bind(this);
+ this.addNotification = this.addNotification.bind(this);
+ this.removeNotification = this.removeNotification.bind(this);
+ this.handleNavSelect = this.handleNavSelect.bind(this);
+ this.handleTypeaheadChange = this.handleTypeaheadChange.bind(this);
+ this.loadSchemaData = this.loadSchemaData.bind(this);
+ this.loadSyntaxesFirst = this.loadSyntaxesFirst.bind(this);
+ this.toggleLoading = this.toggleLoading.bind(this);
+
+ this.showViewObjectclassModal = this.showViewObjectclassModal.bind(this);
+ this.showEditObjectclassModal = this.showEditObjectclassModal.bind(this);
+ this.showAddObjectclassModal = this.showAddObjectclassModal.bind(this);
+ this.openObjectclassModal = this.openObjectclassModal.bind(this);
+ this.closeObjectclassModal = this.closeObjectclassModal.bind(this);
+ this.deleteObjectclass = this.deleteObjectclass.bind(this);
+ this.addObjectclass = this.addObjectclass.bind(this);
+ this.editObjectclass = this.editObjectclass.bind(this);
+ this.cmdOperationObjectclass = this.cmdOperationObjectclass.bind(this);
+
+ this.showViewAttributeModal = this.showViewAttributeModal.bind(this);
+ this.showEditAttributeModal = this.showEditAttributeModal.bind(this);
+ this.showAddAttributeModal = this.showAddAttributeModal.bind(this);
+ this.openAttributeModal = this.openAttributeModal.bind(this);
+ this.closeAttributeModal = this.closeAttributeModal.bind(this);
+ this.deleteAttribute = this.deleteAttribute.bind(this);
+ this.addAttribute = this.addAttribute.bind(this);
+ this.editAttribute = this.editAttribute.bind(this);
+ this.cmdOperationAttribute = this.cmdOperationAttribute.bind(this);
+ }
+
+ toggleLoading(item) {
+ if (item == "allSchema") {
+ this.setState(prevState => ({
+ loading: !prevState.loading
+ }));
+ } else if (item == "ocTable") {
+ this.setState(prevState => ({
+ ocTableLoading: !prevState.ocTableLoading
+ }));
+ } else if (item == "ocModal") {
+ this.setState(prevState => ({
+ ocModalLoading: !prevState.ocModalLoading
+ }));
+ } else if (item == "atTable") {
+ this.setState(prevState => ({
+ atTableLoading: !prevState.atTableLoading
+ }));
+ } else if (item == "atModal") {
+ this.setState(prevState => ({
+ atModalLoading: !prevState.atModalLoading
+ }));
+ }
+ }
+
+ loadSyntaxesFirst() {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "get_syntaxes"
+ ];
+ log_cmd("loadSyntaxes", "Get syntaxes for attributetypes", cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ this.setState({
+ syntaxes: myObject.items
+ });
+ this.loadSchemaData(true);
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSyntaxes failed: ", errMsg.desc);
+ }
+ });
+ }
+
+ loadSchemaData(initialLoading) {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "list"
+ ];
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ log_cmd("loadSchemaData", "Get schema objects in one batch", cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ let attrs = [];
+ let ocs = [];
+ let mrs = [];
+ for (let content of myObject.attributetypes.items) {
+ attrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.objectclasses.items) {
+ ocs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.matchingrules.items) {
+ mrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ this.setState({
+ objectclassRows: myObject.objectclasses.items,
+ attributesRows: myObject.attributetypes.items,
+ matchingrulesRows: myObject.matchingrules.items,
+ attributes: attrs,
+ matchingrules: mrs,
+ objectclasses: ocs
+ });
+ if (this.state.ocUserDefined) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.objectclasses.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: myObject.objectclasses.items
+ });
+ }
+ if (this.state.atUserDefined) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.attributetypes.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: myObject.attributetypes.items
+ });
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSchemaData failed: ", errMsg.desc);
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ });
+ }
+
+ showViewObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: true
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showEditObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showAddObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal();
+ }
+
+ openObjectclassModal(name) {
+ if (!name) {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("openObjectclassModal", "Fetch ObjectClass data from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.oc;
+ let ocMustList = [];
+ let ocMayList = [];
+ const kindOpts = ["STRUCTURAL", "ABSTRACT", "AUXILIARY"];
+ this.setState({
+ objectclassModalShow: true,
+ newOcEntry: false,
+ ocName: item["name"] === undefined ? "" : item["name"][0],
+ ocDesc: item["desc"] === null ? "" : item["desc"][0],
+ ocOID: item["oid"] === undefined ? "" : item["oid"][0],
+ ocKind: item["kind"] === undefined ? "" : kindOpts[item["kind"]],
+ ocParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ]
+ });
+ if (item["must"] === undefined) {
+ this.setState({ ocMust: [] });
+ } else {
+ for (let value of item["must"]) {
+ ocMustList = [...ocMustList, { id: value, label: value }];
+ }
+ this.setState({
+ ocMust: ocMustList
+ });
+ }
+ if (item["may"] === undefined) {
+ this.setState({ ocMay: [] });
+ } else {
+ for (let value of item["may"]) {
+ ocMayList = [...ocMayList, { id: value, label: value }];
+ }
+ this.setState({
+ ocMay: ocMayList
+ });
+ }
+ this.toggleLoading("ocTable");
+ })
+ .fail(_ => {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ this.toggleLoading("ocTable");
+ });
+ }
+ }
+
+ closeObjectclassModal() {
+ this.setState({ objectclassModalShow: false });
+ }
+
+ deleteObjectclass(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("deleteObjectclass", "Delete ObjectClass from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteObjectclass", "Result", content);
+ this.addNotification("success", `ObjectClass ${name} was successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during ObjectClass removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ });
+ }
+
+ addObjectclass() {
+ this.cmdOperationObjectclass("add");
+ }
+
+ editObjectclass() {
+ this.cmdOperationObjectclass("replace");
+ }
+
+ cmdOperationObjectclass(action) {
+ const { ocName, ocDesc, ocOID, ocParent, ocKind, ocMust, ocMay } = this.state;
+ if (ocName == "") {
+ this.addNotification("warning", "ObjectClass Name is required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "objectclasses",
+ action,
+ ocName
+ ];
+ // Process and validate parameters
+ if (ocOID != "") {
+ cmd = [...cmd, "--oid", ocOID];
+ }
+ if (ocParent.length != 0) {
+ cmd = [...cmd, "--sup", ocParent[0].label];
+ }
+ if (ocKind != "") {
+ cmd = [...cmd, "--kind", ocKind];
+ }
+ if (ocDesc != "") {
+ cmd = [...cmd, "--desc", ocDesc];
+ }
+ if (ocMust.length != 0) {
+ cmd = [...cmd, "--must"];
+ for (let value of ocMust) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (ocMay.length != 0) {
+ cmd = [...cmd, "--may"];
+ for (let value of ocMay) {
+ cmd = [...cmd, value.label];
+ }
+ }
+
+ this.toggleLoading("ocModal");
+ log_cmd("cmdOperationObjectclass", `Do the ${action} operation on ObjectClass`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationObjectclass", "Result", content);
+ this.addNotification(
+ "success",
+ `ObjectClass ${ocName} - ${action} operation was successfull`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the ObjectClass ${action} operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ });
+ }
+ }
+
+ showViewAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: true
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showEditAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showAddAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal();
+ }
+
+ openAttributeModal(name) {
+ if (!name) {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("openAttributeModal", "Fetch Attribute data from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.at;
+ let atAliasList = [];
+ const atUsageOpts = [
+ "userApplications",
+ "directoryOperation",
+ "distributedOperation",
+ "dSAOperation"
+ ];
+ this.setState({
+ attributeModalShow: true,
+ newAtEntry: false,
+ atName: item["name"] === undefined ? "" : item["name"][0],
+ atDesc: item["desc"] === null ? "" : item["desc"][0],
+ atOID: item["oid"] === undefined ? "" : item["oid"][0],
+ atParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ],
+ atSyntax:
+ item["syntax"] === undefined
+ ? []
+ : [
+ {
+ id: item["syntax"][0],
+ label: this.state.syntaxes.filter(
+ attr => attr.id === item["syntax"][0]
+ )[0]["label"]
+ }
+ ],
+ atUsage: item["usage"] === undefined ? "" : atUsageOpts[item["usage"]],
+ atMultivalued: !item["single_value"],
+ atNoUserMod: item["no_user_mod"],
+ atEqMr:
+ item["equality"] === null
+ ? []
+ : [
+ {
+ id: item["equality"][0],
+ label: item["equality"][0]
+ }
+ ],
+ atOrder:
+ item["ordering"] === null
+ ? []
+ : [
+ {
+ id: item["ordering"][0],
+ label: item["ordering"][0]
+ }
+ ],
+ atSubMr:
+ item["substr"] === null
+ ? []
+ : [
+ {
+ id: item["substr"][0],
+ label: item["substr"][0]
+ }
+ ]
+ });
+ if (item["aliases"] === null) {
+ this.setState({ atAlias: [] });
+ } else {
+ for (let value of item["aliases"]) {
+ atAliasList = [...atAliasList, { id: value, label: value }];
+ }
+ this.setState({
+ atAlias: atAliasList
+ });
+ }
+ this.toggleLoading("atTable");
+ })
+ .fail(_ => {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ this.toggleLoading("atTable");
+ });
+ }
+ }
+
+ closeAttributeModal() {
+ this.setState({ attributeModalShow: false });
+ }
+
+ deleteAttribute(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("deleteAttribute", "Delete Attribute from schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteAttribute", "Result", content);
+ this.addNotification("success", `Attribute ${name} was successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during Attribute removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ });
+ }
+
+ addAttribute() {
+ this.cmdOperationAttribute("add");
+ }
+
+ editAttribute() {
+ this.cmdOperationAttribute("replace");
+ }
+
+ cmdOperationAttribute(action) {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr
+ } = this.state;
+
+ if (atName == "" || atSyntax.length == 0) {
+ this.addNotification("warning", "Attribute Name and Syntax are required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
+ "schema",
+ "attributetypes",
+ action,
+ atName
+ ];
+ cmd = [...cmd, "--syntax", atSyntax[0].id];
+ if (atAlias.length != 0) {
+ cmd = [...cmd, "--aliases"];
+ for (let value of atAlias) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (atMultivalued) {
+ cmd = [...cmd, "--multi-value"];
+ } else {
+ cmd = [...cmd, "--single-value"];
+ }
+ if (atNoUserMod) {
+ cmd = [...cmd, "--no-user-mod"];
+ } else {
+ cmd = [...cmd, "--user-mod"];
+ }
+ cmd = [...cmd, "--oid", atOID];
+ cmd = [...cmd, "--usage", atUsage];
+ cmd = [...cmd, "--desc", atDesc];
+
+ cmd = [...cmd, "--sup"];
+ if (atParent != "") {
+ cmd = [...cmd, atParent[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--equality"];
+ if (atEqMr != "") {
+ cmd = [...cmd, atEqMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--substr"];
+ if (atSubMr != "") {
+ cmd = [...cmd, atSubMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--ordering"];
+ if (atOrder != "") {
+ cmd = [...cmd, atOrder[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ this.toggleLoading("atModal");
+ log_cmd("cmdOperationAttribute", `Do the ${action} operation on Attribute`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationAttribute", "Result", content);
+ this.addNotification(
+ "success",
+ `Attribute ${atName} - ${action} operation was successfull`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the Attribute ${action} operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ });
+ }
+ }
+
+ addNotification(type, message, timerdelay, persistent) {
+ this.setState(prevState => ({
+ notifications: [
+ ...prevState.notifications,
+ {
+ key: prevState.notifications.length + 1,
+ type: type,
+ persistent: persistent,
+ timerdelay: timerdelay,
+ message: message
+ }
+ ]
+ }));
+ }
+
+ removeNotification(notificationToRemove) {
+ this.setState({
+ notifications: this.state.notifications.filter(
+ notification => notificationToRemove.key !== notification.key
+ )
+ });
+ }
+
+ handleNavSelect(key) {
+ this.setState({
+ activeKey: key
+ });
+ }
+
+ handleTypeaheadChange(state, values) {
+ this.setState({
+ [state]: values
+ });
+ }
+
+ handleFieldChange(e) {
+ const value = e.target.type === "checkbox" ? e.target.checked : e.target.value;
+ if (e.target.id == "ocUserDefined" && value) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.objectclassRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: this.state.objectclassRows
+ });
+ }
+ if (e.target.id == "atUserDefined" && value) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.attributesRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: this.state.attributesRows
+ });
+ }
+ this.setState({
+ [e.target.id]: value
+ });
+ }
+
+ render() {
+ let schemaPage = "";
+ if (this.state.loading) {
+ schemaPage = (
+ <div className="ds-loading-spinner ds-center">
+ <p />
+ <h4>Loading schema information ...</h4>
+ <Spinner loading size="md" />
+ </div>
+ );
+ } else {
+ schemaPage = (
+ <div className="container-fluid">
+ <NotificationController
+ notifications={this.state.notifications}
+ removeNotificationAction={this.removeNotification}
+ />
+ <div className="ds-tab-table">
+ <TabContainer
+ id="basic-tabs-pf"
+ onSelect={this.handleNavSelect}
+ activeKey={this.state.activeKey}
+ >
+ <div>
+ <Nav bsClass="nav nav-tabs nav-tabs-pf">
+ <NavItem eventKey={1}>
+ <div
+ dangerouslySetInnerHTML={{ __html: "Objectclasses" }}
+ />
+ </NavItem>
+ <NavItem eventKey={2}>
+ <div dangerouslySetInnerHTML={{ __html: "Attributes" }} />
+ </NavItem>
+ <NavItem eventKey={3}>
+ <div
+ dangerouslySetInnerHTML={{ __html: "Matching Rules" }}
+ />
+ </NavItem>
+ </Nav>
+ <TabContent>
+ <TabPane eventKey={1}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <Checkbox
+ id="ocUserDefined"
+ checked={this.state.ocUserDefined}
+ title="Show only the objectclasses that are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (objectClasses with
+ X-ORIGIN: "user defined")
+ </Checkbox>
+ <hr />
+ <ObjectClassesTable
+ rows={this.state.filteredObjectclassRows}
+ viewModalHandler={this.showViewObjectclassModal}
+ editModalHandler={this.showEditObjectclassModal}
+ deleteHandler={this.deleteObjectclass}
+ loading={this.state.ocTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddObjectclassModal}
+ >
+ Add ObjectClass
+ </Button>
+ <ObjectClassModal
+ addHandler={this.addObjectclass}
+ editHandler={this.editObjectclass}
+ newOcEntry={this.state.newOcEntry}
+ ocModalViewOnly={this.state.ocModalViewOnly}
+ handleTypeaheadChange={this.handleTypeaheadChange}
+ handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ ocName={this.state.ocName}
+ ocDesc={this.state.ocDesc}
+ ocOID={this.state.ocOID}
+ ocParent={this.state.ocParent}
+ ocKind={this.state.ocKind}
+ ocMust={this.state.ocMust}
+ ocMay={this.state.ocMay}
+ objectclassModalShow={
+ this.state.objectclassModalShow
+ }
+ closeModal={this.closeObjectclassModal}
+ loading={this.state.ocModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={2}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <Checkbox
+ id="atUserDefined"
+ checked={this.state.atUserDefined}
+ title="Show only the attributes that are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (attributes with X-ORIGIN:
+ "user defined")
+ </Checkbox>
+ <hr />
+ <AttributesTable
+ rows={this.state.filteredAttributesRows}
+ viewModalHandler={this.showViewAttributeModal}
+ editModalHandler={this.showEditAttributeModal}
+ deleteHandler={this.deleteAttribute}
+ syntaxes={this.state.syntaxes}
+ loading={this.state.atTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddAttributeModal}
+ >
+ Add Attribute
+ </Button>
+ <AttributeTypeModal
+ addHandler={this.addAttribute}
+ editHandler={this.editAttribute}
+ newAtEntry={this.state.newAtEntry}
+ atModalViewOnly={this.state.atModalViewOnly}
+ handleTypeaheadChange={this.handleTypeaheadChange}
+ handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ matchingrules={this.state.matchingrules}
+ syntaxes={this.state.syntaxes}
+ atName={this.state.atName}
+ atDesc={this.state.atDesc}
+ atOID={this.state.atOID}
+ atParent={this.state.atParent}
+ atSyntax={this.state.atSyntax}
+ atUsage={this.state.atUsage}
+ atMultivalued={this.state.atMultivalued}
+ atNoUserMod={this.state.atNoUserMod}
+ atAlias={this.state.atAlias}
+ atEqMr={this.state.atEqMr}
+ atOrder={this.state.atOrder}
+ atSubMr={this.state.atSubMr}
+ attributeModalShow={this.state.attributeModalShow}
+ closeModal={this.closeAttributeModal}
+ loading={this.state.atModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={3}>
+ <div className="ds-margin-top-xlg ds-indent">
+ <MatchingRulesTable
+ rows={this.state.matchingrulesRows}
+ />
+ </div>
+ </TabPane>
+ </TabContent>
+ </div>
+ </TabContainer>
+ </div>
+ </div>
+ );
+ }
+ return <div>{schemaPage}</div>;
+ }
+}
+
+// Props and defaultProps
+
+Schema.propTypes = {
+ serverId: PropTypes.string
+};
+
+Schema.defaultProps = {
+ serverId: ""
+};
+
+export default Schema;
diff --git a/src/cockpit/389-console/webpack.config.js b/src/cockpit/389-console/webpack.config.js
index f32e518..d3d766b 100644
--- a/src/cockpit/389-console/webpack.config.js
+++ b/src/cockpit/389-console/webpack.config.js
@@ -30,8 +30,6 @@ var info = {
"fonts",
"images",
"index.html",
- "schema.html",
- "schema.js",
"servers.html",
"servers.js",
"static",
diff --git a/src/lib389/lib389/schema.py b/src/lib389/lib389/schema.py
index 929e673..e22418b 100755
--- a/src/lib389/lib389/schema.py
+++ b/src/lib389/lib389/schema.py
@@ -110,7 +110,7 @@ class Schema(DSLdapObject):
if json:
attr_syntaxes_list = []
for id, name in ATTR_SYNTAXES.items():
- attr_syntaxes_list.append({'name': name, 'id': id})
+ attr_syntaxes_list.append({'label': name, 'id': id})
result = {'type': 'list', 'items': attr_syntaxes_list}
else:
result = ATTR_SYNTAXES
@@ -129,7 +129,7 @@ class Schema(DSLdapObject):
obj_i = vars(object_model(obj))
if len(obj_i["names"]) == 1:
obj_i['name'] = obj_i['names'][0].lower()
- obj_i['aliases'] = ""
+ obj_i['aliases'] = None
elif len(obj_i["names"]) > 1:
obj_i['name'] = obj_i['names'][0].lower()
obj_i['aliases'] = obj_i['names'][1:]
@@ -153,6 +153,12 @@ class Schema(DSLdapObject):
object_insts.append(obj_i)
object_insts = sorted(object_insts, key=itemgetter('name'))
+ # Ensure that the string values are in list so we can use React filter component with it
+ for obj_i in object_insts:
+ for key, value in obj_i.items():
+ if isinstance(value, str):
+ obj_i[key] = (value, )
+
return {'type': 'list', 'items': object_insts}
else:
object_insts = [object_model(obj_i) for obj_i in results]
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] 01/02: Issue 50842 - Decrease 389-console Cockpit component size
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
spichugi pushed a commit to branch 389-ds-base-1.4.1
in repository 389-ds-base.
commit 06d55f9ce708712be66913b895f780d9699cf856
Author: Simon Pichugin <spichugi(a)redhat.com>
AuthorDate: Wed Jan 22 13:34:49 2020 +0100
Issue 50842 - Decrease 389-console Cockpit component size
Description: Our Web UI source files are too big and
we should make it compact for the production.
Compress and decrease the size of the files that are generated by webpack.
Fix rpm.mk so it delivers RPMs only with production-ready result files
(we can skip js.map because it is used only for development)
Also, fix minor audit-ci issues.
https://pagure.io/389-ds-base/issue/50842
Reviewed by: mreynolds (Thanks!)
---
rpm.mk | 7 +-
src/cockpit/389-console/package-lock.json | 146 +++++++++++++++++++-----------
src/cockpit/389-console/package.json | 4 +-
src/cockpit/389-console/webpack.config.js | 31 ++++---
4 files changed, 119 insertions(+), 69 deletions(-)
diff --git a/rpm.mk b/rpm.mk
index 28275f1..9ae9164 100644
--- a/rpm.mk
+++ b/rpm.mk
@@ -37,16 +37,19 @@ install-node-modules:
cd src/cockpit/389-console; make -f node_modules.mk install
build-cockpit: install-node-modules
- cd src/cockpit/389-console; make -f node_modules.mk build-cockpit-plugin
+ cd src/cockpit/389-console; \
+ NODE_ENV=production make -f node_modules.mk build-cockpit-plugin
+ cd src/cockpit/389-console; rm -rf cockpit_dist/index.min.js.map
dist-bz2: install-node-modules
cd src/cockpit/389-console; \
rm -rf cockpit_dist; \
- make -f node_modules.mk build-cockpit-plugin; \
+ NODE_ENV=production make -f node_modules.mk build-cockpit-plugin; \
mv node_modules node_modules.release; \
touch cockpit_dist/*
mkdir -p $(NODE_MODULES_TEST)
touch -r src/cockpit/389-console/package.json $(NODE_MODULES_TEST)
+ cd src/cockpit/389-console; rm -rf cockpit_dist/index.min.js.map
tar cjf $(GIT_TAG).tar.bz2 --transform "s,^,$(GIT_TAG)/," $$(git ls-files) src/cockpit/389-console/cockpit_dist/ src/cockpit/389-console/node_modules
cd src/cockpit/389-console; \
rm -rf node_modules; \
diff --git a/src/cockpit/389-console/package-lock.json b/src/cockpit/389-console/package-lock.json
index d6a4125..28eea0c 100644
--- a/src/cockpit/389-console/package-lock.json
+++ b/src/cockpit/389-console/package-lock.json
@@ -2898,6 +2898,16 @@
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
"dev": true
},
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -5184,9 +5194,9 @@
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"events": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
- "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+ "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
"dev": true
},
"evp_bytestokey": {
@@ -5547,6 +5557,13 @@
}
}
},
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -5731,14 +5748,15 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
"dev": true,
"optional": true,
"requires": {
+ "bindings": "^1.5.0",
"nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
+ "node-pre-gyp": "*"
},
"dependencies": {
"abbrev": {
@@ -5786,7 +5804,7 @@
}
},
"chownr": {
- "version": "1.1.1",
+ "version": "1.1.3",
"bundled": true,
"dev": true,
"optional": true
@@ -5816,7 +5834,7 @@
"optional": true
},
"debug": {
- "version": "4.1.1",
+ "version": "3.2.6",
"bundled": true,
"dev": true,
"optional": true,
@@ -5843,12 +5861,12 @@
"optional": true
},
"fs-minipass": {
- "version": "1.2.5",
+ "version": "1.2.7",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.6.0"
}
},
"fs.realpath": {
@@ -5874,7 +5892,7 @@
}
},
"glob": {
- "version": "7.1.3",
+ "version": "7.1.6",
"bundled": true,
"dev": true,
"optional": true,
@@ -5903,7 +5921,7 @@
}
},
"ignore-walk": {
- "version": "3.0.1",
+ "version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true,
@@ -5922,7 +5940,7 @@
}
},
"inherits": {
- "version": "2.0.3",
+ "version": "2.0.4",
"bundled": true,
"dev": true,
"optional": true
@@ -5964,7 +5982,7 @@
"optional": true
},
"minipass": {
- "version": "2.3.5",
+ "version": "2.9.0",
"bundled": true,
"dev": true,
"optional": true,
@@ -5974,12 +5992,12 @@
}
},
"minizlib": {
- "version": "1.2.1",
+ "version": "1.3.3",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "minipass": "^2.2.1"
+ "minipass": "^2.9.0"
}
},
"mkdirp": {
@@ -5992,24 +6010,24 @@
}
},
"ms": {
- "version": "2.1.1",
+ "version": "2.1.2",
"bundled": true,
"dev": true,
"optional": true
},
"needle": {
- "version": "2.3.0",
+ "version": "2.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
- "debug": "^4.1.0",
+ "debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
}
},
"node-pre-gyp": {
- "version": "0.12.0",
+ "version": "0.14.0",
"bundled": true,
"dev": true,
"optional": true,
@@ -6023,7 +6041,7 @@
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
- "tar": "^4"
+ "tar": "^4.4.2"
}
},
"nopt": {
@@ -6037,13 +6055,22 @@
}
},
"npm-bundled": {
- "version": "1.0.6",
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"npm-packlist": {
- "version": "1.4.1",
+ "version": "1.4.7",
"bundled": true,
"dev": true,
"optional": true,
@@ -6114,7 +6141,7 @@
"optional": true
},
"process-nextick-args": {
- "version": "2.0.0",
+ "version": "2.0.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6155,7 +6182,7 @@
}
},
"rimraf": {
- "version": "2.6.3",
+ "version": "2.7.1",
"bundled": true,
"dev": true,
"optional": true,
@@ -6182,7 +6209,7 @@
"optional": true
},
"semver": {
- "version": "5.7.0",
+ "version": "5.7.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6235,18 +6262,18 @@
"optional": true
},
"tar": {
- "version": "4.4.8",
+ "version": "4.4.13",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
+ "yallist": "^3.0.3"
}
},
"util-deprecate": {
@@ -6271,7 +6298,7 @@
"optional": true
},
"yallist": {
- "version": "3.0.3",
+ "version": "3.1.1",
"bundled": true,
"dev": true,
"optional": true
@@ -6423,9 +6450,9 @@
}
},
"globule": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
- "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.0.tgz",
+ "integrity": "sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg==",
"requires": {
"glob": "~7.1.1",
"lodash": "~4.17.10",
@@ -8088,9 +8115,9 @@
}
},
"node-sass": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
- "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
+ "version": "4.13.1",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz",
+ "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==",
"requires": {
"async-foreach": "^0.1.3",
"chalk": "^1.1.1",
@@ -8099,7 +8126,7 @@
"get-stdin": "^4.0.1",
"glob": "^7.0.3",
"in-publish": "^2.0.0",
- "lodash": "^4.17.11",
+ "lodash": "^4.17.15",
"meow": "^3.7.0",
"mkdirp": "^0.5.1",
"nan": "^2.13.2",
@@ -8109,6 +8136,13 @@
"sass-graph": "^2.2.4",
"stdout-stream": "^1.4.0",
"true-case-path": "^1.0.2"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ }
}
},
"nopt": {
@@ -10369,9 +10403,9 @@
}
},
"terser": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz",
- "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==",
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
+ "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@@ -10513,9 +10547,9 @@
}
},
"p-limit": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
- "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
@@ -11183,9 +11217,9 @@
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
},
"webpack": {
- "version": "4.41.2",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
- "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
+ "version": "4.41.5",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz",
+ "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.8.5",
@@ -11208,7 +11242,7 @@
"node-libs-browser": "^2.2.1",
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
- "terser-webpack-plugin": "^1.4.1",
+ "terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.0",
"webpack-sources": "^1.4.1"
},
@@ -11220,12 +11254,12 @@
"dev": true
},
"ajv": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
- "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
+ "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
"dev": true,
"requires": {
- "fast-deep-equal": "^2.0.1",
+ "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
@@ -11253,6 +11287,12 @@
"estraverse": "^4.1.1"
}
},
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+ "dev": true
+ },
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
diff --git a/src/cockpit/389-console/package.json b/src/cockpit/389-console/package.json
index 4289cf4..cfdab91 100644
--- a/src/cockpit/389-console/package.json
+++ b/src/cockpit/389-console/package.json
@@ -45,7 +45,7 @@
"sizzle": "^2.3.3",
"stdio": "^0.2.7",
"style-loader": "^0.23.1",
- "webpack": "^4.41.2",
+ "webpack": "^4.41.5",
"webpack-cli": "^3.1.0"
},
"dependencies": {
@@ -53,7 +53,7 @@
"bootstrap": "^4.3.1",
"file-loader": "^4.1.0",
"handlebars": "^4.5.3",
- "node-sass": "4.12.0",
+ "node-sass": "^4.13.1",
"patternfly": "^3.59.3",
"patternfly-react": "^2.34.3",
"prop-types": "15.6.2",
diff --git a/src/cockpit/389-console/webpack.config.js b/src/cockpit/389-console/webpack.config.js
index 026eb59..f32e518 100644
--- a/src/cockpit/389-console/webpack.config.js
+++ b/src/cockpit/389-console/webpack.config.js
@@ -90,10 +90,19 @@ if (production) {
output.filename = "[name].min.js";
plugins.unshift(
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: JSON.stringify("production")
+ }
+ })
+ );
+ plugins.unshift(new webpack.optimize.AggressiveMergingPlugin());
+ plugins.unshift(
new CompressionPlugin({
- asset: "[path].gz[query]",
+ filename: "[path].gz[query]",
test: /\.(js|html)$/,
- minRatio: 0.9,
+ threshold: 10240,
+ minRatio: 0.8,
deleteOriginalAssets: true
})
);
@@ -130,15 +139,13 @@ module.exports = {
test: /\.jsx$/,
options: {
presets: [
- '@babel/preset-env',
- '@babel/preset-react',
+ "@babel/preset-env",
+ "@babel/preset-react",
{
- plugins: [
- '@babel/plugin-proposal-class-properties'
- ]
+ plugins: ["@babel/plugin-proposal-class-properties"]
}
]
- },
+ }
},
{
exclude: /node_modules/,
@@ -146,21 +153,21 @@ module.exports = {
test: /\.es6$/
},
{
- // Transform our own .css files with PostCSS and CSS-modules
+ // Transform our own .css files with PostCSS and CSS-modules
test: /\.css$/,
exclude: /node_modules/,
- use: ['style-loader', 'css-loader'],
+ use: ["style-loader", "css-loader"]
},
{
test: /\.css$/,
include: /node_modules/,
- use: ['style-loader', 'css-loader'],
+ use: ["style-loader", "css-loader"]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
- loader: 'url-loader',
+ loader: "url-loader",
options: {
limit: 8192
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] branch 389-ds-base-1.4.1 updated: Ticket 50790 - Add result text when filter is invalid
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
firstyear 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 46daeac Ticket 50790 - Add result text when filter is invalid
46daeac is described below
commit 46daeac581fb71ab66df1603b4d1eee619c6576f
Author: William Brown <william(a)blackhats.net.au>
AuthorDate: Fri Jan 10 12:09:00 2020 +1000
Ticket 50790 - Add result text when filter is invalid
Bug Description: As a result of the change in 50727
we need to communicate to users/admins when queries they issue
may be incomplete due to rfc compliance of filter processing.
Fix Description: When we use idl_alloc(0) on attributes, we set
a result text (if none already set) warning that the result set
may be incomplete.
https://pagure.io/389-ds-base/issue/50790
Author: William Brown <william(a)blackhats.net.au>
Review by: tbordaz (Thanks!)
---
ldap/servers/slapd/pblock.c | 9 +++++++++
ldap/servers/slapd/schema.c | 5 ++++-
ldap/servers/slapd/search.c | 2 +-
ldap/servers/slapd/slapi-plugin.h | 2 +-
ldap/servers/slapd/slapi-private.h | 1 +
test/libslapd/schema/filter_validate.c | 8 ++++++--
6 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 348cc6f..cb562e9 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -4369,6 +4369,15 @@ slapi_pblock_set_flag_operation_notes(Slapi_PBlock *pb, uint32_t opflag) {
pb->pb_intop->pb_operation_notes |= opflag;
}
+/* Set result text if it's NULL */
+void
+slapi_pblock_set_result_text_if_empty(Slapi_PBlock *pb, char *text) {
+ _pblock_assert_pb_intop(pb);
+ if (pb->pb_intop->pb_result_text == NULL) {
+ pb->pb_intop->pb_result_text = slapi_ch_strdup(text);
+ }
+}
+
/*
* Clear and then set the bind DN and related credentials for the
* connection `conn'.
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index 6e853fc..a294e67 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -760,7 +760,7 @@ slapi_filter_schema_check_inner(Slapi_Filter *f) {
*
*/
Slapi_Filter_Result
-slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp) {
+slapi_filter_schema_check(Slapi_PBlock *pb, Slapi_Filter *f, Slapi_Filter_Policy fp) {
if (f == NULL) {
return FILTER_SCHEMA_FAILURE;
}
@@ -780,6 +780,9 @@ slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp) {
/* If any warning occured, ensure we fail it. */
if (fp == FILTER_POLICY_STRICT && r != FILTER_SCHEMA_SUCCESS) {
r = FILTER_SCHEMA_FAILURE;
+ } else if (fp == FILTER_POLICY_PROTECT && r == FILTER_SCHEMA_WARNING) {
+ /* Or, make sure we setup text to warn the user submitting the query */
+ slapi_pblock_set_result_text_if_empty(pb, "Invalid attribute in filter - results may not be complete.");
}
return r;
}
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 013bece..afcd2a1 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -203,7 +203,7 @@ do_search(Slapi_PBlock *pb)
* or reject. A question is the location of this and if we should try to work with
* internal searches too ...
*/
- Slapi_Filter_Result r = slapi_filter_schema_check(filter, config_get_verify_filter_schema());
+ Slapi_Filter_Result r = slapi_filter_schema_check(pb, filter, config_get_verify_filter_schema());
if (r == FILTER_SCHEMA_FAILURE) {
char *errtxt = "The filter provided contains invalid attributes not found in schema";
err = LDAP_UNWILLING_TO_PERFORM;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index edf6a9e..56fdfd4 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1592,7 +1592,7 @@ typedef enum {
* WARNING - return SUCCESS, and flag filter elements that are not in schema.
* STRICT - return SUCCESS only if all elements are found - else return FAILURE.
*/
-Slapi_Filter_Result slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp);
+Slapi_Filter_Result slapi_filter_schema_check(Slapi_PBlock *pb, Slapi_Filter *f, Slapi_Filter_Policy fp);
/**
* Determines if the DN violates the Distinguished Name syntax rules.
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 04c0455..4f3b740 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1456,6 +1456,7 @@ void slapi_pblock_set_pw_entry(Slapi_PBlock *pb, struct slapi_entry *entry);
uint32_t slapi_pblock_get_operation_notes(Slapi_PBlock *pb);
void slapi_pblock_set_operation_notes(Slapi_PBlock *pb, uint32_t opnotes);
void slapi_pblock_set_flag_operation_notes(Slapi_PBlock *pb, uint32_t opflag);
+void slapi_pblock_set_result_text_if_empty(Slapi_PBlock *pb, char *text);
#ifdef __cplusplus
}
diff --git a/test/libslapd/schema/filter_validate.c b/test/libslapd/schema/filter_validate.c
index e93bd6b..d42a98f 100644
--- a/test/libslapd/schema/filter_validate.c
+++ b/test/libslapd/schema/filter_validate.c
@@ -52,11 +52,13 @@ validate_filter(char *fstr, Slapi_Filter_Policy policy) {
char fdup[256] = {0};
strcpy(fdup, fstr);
struct slapi_filter *f = slapi_str2filter(fdup);
+ Slapi_PBlock *pb = slapi_pblock_new();
assert_true(f != NULL);
- Slapi_Filter_Result r = slapi_filter_schema_check(f, policy);
+ Slapi_Filter_Result r = slapi_filter_schema_check(pb, f, policy);
// Based on policy, we could assert if flags are set.
+ slapi_pblock_destroy(pb);
slapi_filter_free(f, 1);
return r;
}
@@ -86,7 +88,9 @@ test_libslapd_schema_filter_validate_simple(void **state __attribute__((unused))
/* Did they pass given the policy and expectations? */
/* simple error cases */
- assert_true(slapi_filter_schema_check(NULL, FILTER_POLICY_OFF) == FILTER_SCHEMA_FAILURE);
+ Slapi_PBlock *pb = slapi_pblock_new();
+ assert_true(slapi_filter_schema_check(pb, NULL, FILTER_POLICY_OFF) == FILTER_SCHEMA_FAILURE);
+ slapi_pblock_destroy(pb);
/* policy off, always success no matter what */
assert_true(validate_filter(invalid, FILTER_POLICY_OFF) == FILTER_SCHEMA_SUCCESS);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] branch 389-ds-base-1.4.2 updated: Ticket 50790 - Add result text when filter is invalid
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch 389-ds-base-1.4.2
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.4.2 by this push:
new b8f99b7 Ticket 50790 - Add result text when filter is invalid
b8f99b7 is described below
commit b8f99b73b84989298a099706dbde4ba0bf032b84
Author: William Brown <william(a)blackhats.net.au>
AuthorDate: Fri Jan 10 12:09:00 2020 +1000
Ticket 50790 - Add result text when filter is invalid
Bug Description: As a result of the change in 50727
we need to communicate to users/admins when queries they issue
may be incomplete due to rfc compliance of filter processing.
Fix Description: When we use idl_alloc(0) on attributes, we set
a result text (if none already set) warning that the result set
may be incomplete.
https://pagure.io/389-ds-base/issue/50790
Author: William Brown <william(a)blackhats.net.au>
Review by: tbordaz (Thanks!)
---
ldap/servers/slapd/pblock.c | 9 +++++++++
ldap/servers/slapd/schema.c | 5 ++++-
ldap/servers/slapd/search.c | 2 +-
ldap/servers/slapd/slapi-plugin.h | 2 +-
ldap/servers/slapd/slapi-private.h | 1 +
test/libslapd/schema/filter_validate.c | 8 ++++++--
6 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 348cc6f..cb562e9 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -4369,6 +4369,15 @@ slapi_pblock_set_flag_operation_notes(Slapi_PBlock *pb, uint32_t opflag) {
pb->pb_intop->pb_operation_notes |= opflag;
}
+/* Set result text if it's NULL */
+void
+slapi_pblock_set_result_text_if_empty(Slapi_PBlock *pb, char *text) {
+ _pblock_assert_pb_intop(pb);
+ if (pb->pb_intop->pb_result_text == NULL) {
+ pb->pb_intop->pb_result_text = slapi_ch_strdup(text);
+ }
+}
+
/*
* Clear and then set the bind DN and related credentials for the
* connection `conn'.
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
index d7c3c13..d44b03b 100644
--- a/ldap/servers/slapd/schema.c
+++ b/ldap/servers/slapd/schema.c
@@ -760,7 +760,7 @@ slapi_filter_schema_check_inner(Slapi_Filter *f, slapi_filter_flags flags) {
*
*/
Slapi_Filter_Result
-slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp) {
+slapi_filter_schema_check(Slapi_PBlock *pb, Slapi_Filter *f, Slapi_Filter_Policy fp) {
if (f == NULL) {
return FILTER_SCHEMA_FAILURE;
}
@@ -792,6 +792,9 @@ slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp) {
/* If any warning occured, ensure we fail it. */
if (fp == FILTER_POLICY_STRICT && r != FILTER_SCHEMA_SUCCESS) {
r = FILTER_SCHEMA_FAILURE;
+ } else if (fp == FILTER_POLICY_PROTECT && r == FILTER_SCHEMA_WARNING) {
+ /* Or, make sure we setup text to warn the user submitting the query */
+ slapi_pblock_set_result_text_if_empty(pb, "Invalid attribute in filter - results may not be complete.");
}
return r;
}
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 6cdb276..cd6647f 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -212,7 +212,7 @@ do_search(Slapi_PBlock *pb)
* or reject. A question is the location of this and if we should try to work with
* internal searches too ...
*/
- Slapi_Filter_Result r = slapi_filter_schema_check(filter, config_get_verify_filter_schema());
+ Slapi_Filter_Result r = slapi_filter_schema_check(pb, filter, config_get_verify_filter_schema());
if (r == FILTER_SCHEMA_FAILURE) {
char *errtxt = "The filter provided contains invalid attributes not found in schema";
err = LDAP_UNWILLING_TO_PERFORM;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 40b5c91..00e426a 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1593,7 +1593,7 @@ typedef enum {
* WARNING - return SUCCESS, and flag filter elements that are not in schema.
* STRICT - return SUCCESS only if all elements are found - else return FAILURE.
*/
-Slapi_Filter_Result slapi_filter_schema_check(Slapi_Filter *f, Slapi_Filter_Policy fp);
+Slapi_Filter_Result slapi_filter_schema_check(Slapi_PBlock *pb, Slapi_Filter *f, Slapi_Filter_Policy fp);
/**
* Determines if the DN violates the Distinguished Name syntax rules.
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 1f17eda..0219912 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1457,6 +1457,7 @@ void slapi_pblock_set_pw_entry(Slapi_PBlock *pb, struct slapi_entry *entry);
uint32_t slapi_pblock_get_operation_notes(Slapi_PBlock *pb);
void slapi_pblock_set_operation_notes(Slapi_PBlock *pb, uint32_t opnotes);
void slapi_pblock_set_flag_operation_notes(Slapi_PBlock *pb, uint32_t opflag);
+void slapi_pblock_set_result_text_if_empty(Slapi_PBlock *pb, char *text);
#ifdef __cplusplus
}
diff --git a/test/libslapd/schema/filter_validate.c b/test/libslapd/schema/filter_validate.c
index e93bd6b..d42a98f 100644
--- a/test/libslapd/schema/filter_validate.c
+++ b/test/libslapd/schema/filter_validate.c
@@ -52,11 +52,13 @@ validate_filter(char *fstr, Slapi_Filter_Policy policy) {
char fdup[256] = {0};
strcpy(fdup, fstr);
struct slapi_filter *f = slapi_str2filter(fdup);
+ Slapi_PBlock *pb = slapi_pblock_new();
assert_true(f != NULL);
- Slapi_Filter_Result r = slapi_filter_schema_check(f, policy);
+ Slapi_Filter_Result r = slapi_filter_schema_check(pb, f, policy);
// Based on policy, we could assert if flags are set.
+ slapi_pblock_destroy(pb);
slapi_filter_free(f, 1);
return r;
}
@@ -86,7 +88,9 @@ test_libslapd_schema_filter_validate_simple(void **state __attribute__((unused))
/* Did they pass given the policy and expectations? */
/* simple error cases */
- assert_true(slapi_filter_schema_check(NULL, FILTER_POLICY_OFF) == FILTER_SCHEMA_FAILURE);
+ Slapi_PBlock *pb = slapi_pblock_new();
+ assert_true(slapi_filter_schema_check(pb, NULL, FILTER_POLICY_OFF) == FILTER_SCHEMA_FAILURE);
+ slapi_pblock_destroy(pb);
/* policy off, always success no matter what */
assert_true(validate_filter(invalid, FILTER_POLICY_OFF) == FILTER_SCHEMA_SUCCESS);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] branch 389-ds-base-1.3.10 updated: Ticket 50709: Several memory leaks reported by Valgrind for 389-ds 1.3.9.1-10
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
tbordaz pushed a commit to branch 389-ds-base-1.3.10
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.3.10 by this push:
new f1d48ed Ticket 50709: Several memory leaks reported by Valgrind for 389-ds 1.3.9.1-10
f1d48ed is described below
commit f1d48edbb9a35af4dac2bb6468915e2823dba7ae
Author: Thierry Bordaz <tbordaz(a)redhat.com>
AuthorDate: Fri Nov 8 18:16:06 2019 +0100
Ticket 50709: Several memory leaks reported by Valgrind for 389-ds 1.3.9.1-10
Description of the problem:
When evaluating an ACI with 'ip' subject, it adds a PRNetAddr to the subject
property list. When the list is free (acl__done_aclpb) the property is not freed.
Description of the fix:
Add the property to the pblock (SLAPI_CONN_CLIENTNETADDR_ACLIP) so that it
the property is freed with acl pblock.
https://pagure.io/389-ds-base/issue/50709
Reviewed by: Mark Reynolds, William Brown, Ludwig Krispenz
---
ldap/servers/plugins/acl/acllas.c | 54 ++++++++++++++++++++++++++-------------
ldap/servers/slapd/connection.c | 2 ++
ldap/servers/slapd/pblock.c | 16 ++++++++++++
ldap/servers/slapd/slap.h | 1 +
ldap/servers/slapd/slapi-plugin.h | 1 +
5 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/ldap/servers/plugins/acl/acllas.c b/ldap/servers/plugins/acl/acllas.c
index 3950fd4..a5602e1 100644
--- a/ldap/servers/plugins/acl/acllas.c
+++ b/ldap/servers/plugins/acl/acllas.c
@@ -251,6 +251,7 @@ DS_LASIpGetter(NSErr_t *errp, PList_t subject, PList_t resource, PList_t auth_in
{
struct acl_pblock *aclpb = NULL;
PRNetAddr *client_praddr = NULL;
+ PRNetAddr *pb_client_praddr = NULL;
char ip_str[256];
int rv = LAS_EVAL_TRUE;
@@ -262,25 +263,39 @@ DS_LASIpGetter(NSErr_t *errp, PList_t subject, PList_t resource, PList_t auth_in
return LAS_EVAL_FAIL;
}
- client_praddr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
- if (client_praddr == NULL) {
- slapi_log_err(SLAPI_LOG_ERR, plugin_name, "DS_LASIpGetter - Failed to allocate client_praddr\n");
- return (LAS_EVAL_FAIL);
- }
+ slapi_pblock_get(aclpb->aclpb_pblock, SLAPI_CONN_CLIENTNETADDR_ACLIP, &pb_client_praddr);
+ if (pb_client_praddr == NULL) {
- if (slapi_pblock_get(aclpb->aclpb_pblock, SLAPI_CONN_CLIENTNETADDR, client_praddr) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, plugin_name, "DS_LASIpGetter - Could not get client IP.\n");
- slapi_ch_free((void **)&client_praddr);
- return (LAS_EVAL_FAIL);
- }
+ client_praddr = (PRNetAddr *) slapi_ch_malloc(sizeof (PRNetAddr));
+ if (client_praddr == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "DS_LASIpGetter - Failed to allocate client_praddr\n");
+ return (LAS_EVAL_FAIL);
+ }
- rv = PListInitProp(subject, 0, ACL_ATTR_IP, (void *)client_praddr, NULL);
- if (rv < 0) {
- slapi_log_err(SLAPI_LOG_ACL, plugin_name, "DS_LASIpGetter - "
- "Couldn't set the client addr property(%d)\n",
- rv);
- slapi_ch_free((void **)&client_praddr);
- return LAS_EVAL_FAIL;
+ if (slapi_pblock_get(aclpb->aclpb_pblock, SLAPI_CONN_CLIENTNETADDR, client_praddr) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, plugin_name, "DS_LASIpGetter - Could not get client IP.\n");
+ slapi_ch_free((void **) &client_praddr);
+ return (LAS_EVAL_FAIL);
+ }
+
+ rv = PListInitProp(subject, 0, ACL_ATTR_IP, (void *) client_praddr, NULL);
+ if (rv < 0) {
+ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "DS_LASIpGetter - "
+ "Couldn't set the client addr property(%d)\n",
+ rv);
+ slapi_ch_free((void **) &client_praddr);
+ return LAS_EVAL_FAIL;
+ }
+
+ } else {
+ client_praddr = pb_client_praddr;
+ rv = PListInitProp(subject, 0, ACL_ATTR_IP, (void *) client_praddr, NULL);
+ if (rv < 0) {
+ slapi_log_err(SLAPI_LOG_ACL, plugin_name, "DS_LASIpGetter - "
+ "Couldn't set the client addr property(%d)\n",
+ rv);
+ return LAS_EVAL_FAIL;
+ }
}
if (PR_NetAddrToString(client_praddr, ip_str, sizeof(ip_str)) == PR_SUCCESS) {
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "DS_LASIpGetter - "
@@ -290,7 +305,10 @@ DS_LASIpGetter(NSErr_t *errp, PList_t subject, PList_t resource, PList_t auth_in
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "DS_LASIpGetter - "
"Returning client ip address 'unknown'\n");
}
-
+ if (client_praddr != pb_client_praddr) {
+ /* Set it in pblock only if it is newly allocated */
+ slapi_pblock_set(aclpb->aclpb_pblock, SLAPI_CONN_CLIENTNETADDR_ACLIP, client_praddr);
+ }
return LAS_EVAL_TRUE;
}
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 9abd546..b9b280e 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -205,6 +205,7 @@ connection_cleanup(Connection *conn)
conn->c_isreplication_session = 0;
slapi_ch_free((void **)&conn->cin_addr);
slapi_ch_free((void **)&conn->cin_destaddr);
+ slapi_ch_free((void **)&conn->cin_addr_aclip);
slapi_ch_free_string(&conn->c_ipaddr);
if (conn->c_domain != NULL) {
ber_bvecfree(conn->c_domain);
@@ -397,6 +398,7 @@ connection_reset(Connection *conn, int ns, PRNetAddr *from, int fromLen __attrib
str_destip = str_unknown;
}
}
+ slapi_ch_free((void **)&conn->cin_addr_aclip);
if (!in_referral_mode) {
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index bc18a7b..d2ad614 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -482,6 +482,14 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
}
PR_ExitMonitor(pblock->pb_conn->c_mutex);
break;
+ case SLAPI_CONN_CLIENTNETADDR_ACLIP:
+ if (pblock->pb_conn == NULL) {
+ break;
+ }
+ pthread_mutex_lock(&(pblock->pb_conn->c_mutex));
+ (*(PRNetAddr **) value) = pblock->pb_conn->cin_addr_aclip;
+ pthread_mutex_unlock(&(pblock->pb_conn->c_mutex));
+ break;
case SLAPI_CONN_SERVERNETADDR:
if (pblock->pb_conn == NULL) {
memset(value, 0, sizeof(PRNetAddr));
@@ -2571,6 +2579,14 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
pblock->pb_conn->c_authtype = slapi_ch_strdup((char *)value);
PR_ExitMonitor(pblock->pb_conn->c_mutex);
break;
+ case SLAPI_CONN_CLIENTNETADDR_ACLIP:
+ if (pblock->pb_conn == NULL) {
+ break;
+ }
+ pthread_mutex_lock(&(pblock->pb_conn->c_mutex));
+ slapi_ch_free((void **)&pblock->pb_conn->cin_addr_aclip);
+ pblock->pb_conn->cin_addr_aclip = (PRNetAddr *)value;
+ pthread_mutex_unlock(&(pblock->pb_conn->c_mutex));
case SLAPI_CONN_IS_REPLICATION_SESSION:
if (pblock->pb_conn == NULL) {
slapi_log_err(SLAPI_LOG_ERR,
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index a8908d9..4c53d43 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1617,6 +1617,7 @@ typedef struct conn
char *c_external_dn; /* client DN of this SSL session */
char *c_external_authtype; /* used for c_external_dn */
PRNetAddr *cin_addr; /* address of client on this conn */
+ PRNetAddr *cin_addr_aclip; /* address of client allocated by acl with 'ip' subject */
PRNetAddr *cin_destaddr; /* address client connected to */
struct berval **c_domain; /* DNS names of client */
Operation *c_ops; /* list of pending operations */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 0bc3a6f..679bdbb 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6971,6 +6971,7 @@ slapi_timer_result slapi_timespec_expire_check(struct timespec *expire);
#define SLAPI_CONN_DN 143
#define SLAPI_CONN_CLIENTNETADDR 850
#define SLAPI_CONN_SERVERNETADDR 851
+#define SLAPI_CONN_CLIENTNETADDR_ACLIP 853
#define SLAPI_CONN_IS_REPLICATION_SESSION 149
#define SLAPI_CONN_IS_SSL_SESSION 747
#define SLAPI_CONN_CERT 743
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months
[389-ds-base] branch 389-ds-base-1.3.10 updated: Issue 50834 - Incorrectly setting the NSS default SSL version max
by pagure@pagure.io
This is an automated email from the git hooks/post-receive script.
mreynolds pushed a commit to branch 389-ds-base-1.3.10
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.3.10 by this push:
new bcb1e24 Issue 50834 - Incorrectly setting the NSS default SSL version max
bcb1e24 is described below
commit bcb1e243c8d5226da5af1728c8093b99a856ebcc
Author: Mark Reynolds <mreynolds(a)redhat.com>
AuthorDate: Mon Jan 20 13:16:36 2020 -0500
Issue 50834 - Incorrectly setting the NSS default SSL version max
Description: We've been using the wrong function to get the NSS max
version We were calling SSL_VersionRangeGetSupported()
which gets the versions NSS "can" handle, but
SSL_VersionRangeGetDefault() gets the versions that
are actually "enabled".
relates: https://pagure.io/389-ds-base/issue/50834
Reviewed by: mreynolds(one line commit rule)
---
ldap/servers/slapd/ssl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index ed054db..c71e301 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -1164,7 +1164,7 @@ slapd_nss_init(int init_ssl __attribute__((unused)), int config_available __attr
char *certdir;
char emin[VERSION_STR_LENGTH], emax[VERSION_STR_LENGTH];
/* Get the range of the supported SSL version */
- SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledNSSVersions);
+ SSL_VersionRangeGetDefault(ssl_variant_stream, &enabledNSSVersions);
(void)slapi_getSSLVersion_str(enabledNSSVersions.min, emin, sizeof(emin));
(void)slapi_getSSLVersion_str(enabledNSSVersions.max, emax, sizeof(emax));
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
4 years, 3 months