From 538178b53dcb6ecb7a2f1892d648a86202afb7ce Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Jun 04 2015 11:20:44 +0000 Subject: webui: topology plugin https://fedorahosted.org/freeipa/ticket/4997 Reviewed-By: Martin Babinsky --- diff --git a/install/ui/doc/categories.json b/install/ui/doc/categories.json index 555367a..83c24c5 100644 --- a/install/ui/doc/categories.json +++ b/install/ui/doc/categories.json @@ -252,6 +252,7 @@ "otptoken", "radiusproxy", "stageuser", + "topology", "user", "plugins.load", "plugins.login", diff --git a/install/ui/src/freeipa/app.js b/install/ui/src/freeipa/app.js index 140fe93..9b290ab 100644 --- a/install/ui/src/freeipa/app.js +++ b/install/ui/src/freeipa/app.js @@ -47,6 +47,7 @@ define([ './service', './sudo', './trust', + './topology', './user', './stageuser', 'dojo/domReady!' diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js index f26033c..fdf925e 100644 --- a/install/ui/src/freeipa/field.js +++ b/install/ui/src/freeipa/field.js @@ -821,7 +821,7 @@ field.Adapter = declare(null, { var dr = data.result; var record = null; if (dr) { - if (dr.result) record = dr.result; + if (IPA.defined(dr.result)) record = dr.result; else if (dr.results) { var result = dr.results[this.result_index]; if (result) record = result.result; diff --git a/install/ui/src/freeipa/navigation/menu_spec.js b/install/ui/src/freeipa/navigation/menu_spec.js index 13f533d..c35445f 100644 --- a/install/ui/src/freeipa/navigation/menu_spec.js +++ b/install/ui/src/freeipa/navigation/menu_spec.js @@ -184,6 +184,28 @@ var nav = {}; { entity: 'trustconfig' } ] }, + { + entity: 'topologysuffix', + label: '@i18n:tabs.topology', + facet: 'search', + children: [ + { + entity: 'topologysuffix', + facet: 'search', + hidden: true + }, + { + entity: 'server', + facet: 'search', + hidden: true + }, + { + entity: 'domainlevel', + facet: 'details', + hidden: true + } + ] + }, { entity: 'config' } ] } diff --git a/install/ui/src/freeipa/topology.js b/install/ui/src/freeipa/topology.js new file mode 100644 index 0000000..51714d9 --- /dev/null +++ b/install/ui/src/freeipa/topology.js @@ -0,0 +1,393 @@ +// +// Copyright (C) 2015 FreeIPA Contributors see COPYING for license +// + +define([ + 'dojo/_base/lang', + 'dojo/_base/declare', + 'dojo/on', + './builder', + './ipa', + './jquery', + './menu', + './metadata', + './phases', + './reg', + './rpc', + './text', + './details', + './facet', + './field', + './search', + './entity'], + function(lang, declare, on, builder, IPA, $, menu, metadata_provider, + phases, reg, rpc, text, mod_details, mod_facet, mod_field) { +/** + * Topology module + * @class + * @singleton + */ +var topology = IPA.topology = { + + search_facet_group: { + name: 'search', + label: '@i18n:tabs.topology', + facets: { + suffix_search: 'topologysuffix_search', + server_search: 'server_search', + domainlevel: 'domainlevel_details' + } + } +}; + +var make_suffix_spec = function() { +return { + name: 'topologysuffix', + enable_test: function() { + return true; + }, + facet_groups: [ 'segments', 'settings' ], + facets: [ + { + $type: 'search', + disable_facet_tabs: false, + tabs_in_sidebar: true, + tab_label: '@mo:topologysuffix.label', + facet_groups: [topology.search_facet_group], + facet_group: 'search', + columns: [ + 'cn', + 'iparepltopoconfroot' + ] + }, + { + $type: 'nested_search', + facet_group: 'segments', + nested_entity: 'topologysegment', + search_all_entries: true, + label: '@mo:topologysegment.label', + tab_label: '@mo:topologysegment.label', + name: 'topologysegment', + columns: [ + 'cn', + 'iparepltoposegmentleftnode', + 'iparepltoposegmentrightnode', + 'iparepltoposegmentdirection' + ] + }, + { + $type: 'details', + sections: [ + { + name: 'details', + fields: [ + 'cn', + 'iparepltopoconfroot' + ] + } + ] + } + ], + adder_dialog: { + fields: [ + 'cn', + 'iparepltopoconfroot' + ] + } +};}; + + +var make_segment_spec = function() { +return { + name: 'topologysegment', + containing_entity: 'topologysuffix', + enable_test: function() { + return true; + }, + facets: [ + { + $type: 'details', + disable_breadcrumb: false, + sections: [ + { + name: 'details', + label: '@i18n:objects.topology.segment_details', + fields: [ + 'cn', + { + $type: 'entity_select', + name: 'iparepltoposegmentleftnode', + other_entity: 'server', + other_field: 'cn', + z_index: 2 + }, + { + $type: 'entity_select', + name: 'iparepltoposegmentrightnode', + other_entity: 'server', + other_field: 'cn', + z_index: 1 + }, + { + $type: 'radio', + name: 'iparepltoposegmentdirection', + options: IPA.create_options([ + 'both', 'left-right', 'right-left', 'none' + ]), + default_value: 'both' + } + ] + }, + { + name: 'replication_config', + label: '@i18n:objects.topology.replication_config', + fields: [ + { + $type: 'radio', + name: 'nsds5replicaenabled', + options: ['on', 'off'], + default_value: 'on' + }, + 'nsds5replicatimeout', + 'nsds5replicastripattrs', + 'nsds5replicatedattributelist', + 'nsds5replicatedattributelisttotal' + ] + } + ] + } + ], + adder_dialog: { + fields: [ + { + name: 'cn', + required: false + }, + { + $type: 'entity_select', + name: 'iparepltoposegmentleftnode', + other_entity: 'server', + other_field: 'cn', + z_index: 2 + }, + { + $type: 'entity_select', + name: 'iparepltoposegmentrightnode', + other_entity: 'server', + other_field: 'cn', + z_index: 1 + }, + { + $type: 'radio', + name: 'iparepltoposegmentdirection', + options: IPA.create_options([ + 'both', 'left-right', 'right-left', 'none' + ]), + default_value: 'both' + } + ] + } +};}; + +var make_server_spec = function() { +return { + name: 'server', + facets: [ + { + $type: 'search', + no_update: true, + disable_facet_tabs: false, + tabs_in_sidebar: true, + tab_label: '@mo:server.label', + facet_groups: [topology.search_facet_group], + facet_group: 'search', + columns: [ + 'cn', + 'ipamindomainlevel', + 'ipamaxdomainlevel', + 'iparepltopomanagedsuffix' + ] + }, + { + $type: 'details', + no_update: true, + disable_facet_tabs: true, + sections: [ + { + name: 'details', + fields: [ + { name: 'cn', read_only: true }, + { name: 'ipamindomainlevel', read_only: true }, + { name: 'ipamaxdomainlevel', read_only: true }, + { name: 'iparepltopomanagedsuffix', read_only: true } + ] + } + ] + } + ] +};}; + +var make_domainlevel_spec = function() { +return { + name: 'domainlevel', + facets: [ + { + $type: 'details', + get_all_attrs: false, + check_rights: false, + no_update: true, + refresh_command_name: 'get', + disable_facet_tabs: false, + tabs_in_sidebar: true, + tab_label: '@mo:domainlevel.label', + facet_groups: [topology.search_facet_group], + facet_group: 'search', + sections: [ + { + name: 'details', + fields: [ + { + name: 'ipadomainlevel', + read_only: true, + adapter: topology.domainlevel_adapter + } + ] + } + ], + actions: ['domainlevel_set'], + control_buttons: [{ + label: '@i18n:objects.domainlevel.set', + name: 'domainlevel_set' + }] + } + ] +};}; + +topology.domainlevel_adapter = declare([mod_field.Adapter], { + load: function(data) { + return [this.get_record(data)]; + } +}); + + +topology.domainlevel_metadata = function(spec, context) { + var metadata = metadata_provider.source; + metadata.objects.domainlevel = { + name: 'domainlevel', + label: text.get('@i18n:objects.domainlevel.label'), + label_singular: text.get('@i18n:objects.domainlevel.label_singular'), + takes_params: [ + { + 'class': "Int", + doc: "", + flags: [], + label: text.get("@i18n:objects.domainlevel.ipadomainlevel"), + maxvalue: 2147483647, + minvalue: 0, + name: "ipadomainlevel", + type: "int" + } + ] + }; + return spec; +}; + +/** + * Set Domain Level Action + * + * @class topology.domainlevel_set_action + * @extends {IPA.action} + */ +topology.domainlevel_set_action = function(spec) { + + spec = spec || {}; + spec.name = spec.name || 'domainlevel_set'; + spec.label = spec.label || '@i18n:objects.domainlevel.set'; + var that = IPA.action(spec); + + /** + * Dialog spec + * @property {Object} + */ + that.dialog = spec.dialog || { + $type: 'command', + entity: 'domainlevel', + method: 'set', + title: '@i18n:objects.domainlevel.set', + confirm_button_label: '@i18n:buttons.set', + fields: [ + { + name: 'ipadomainlevel', + primary_key: true + } + ] + }; + + /** + * Refresh facet after successful action + * @property {boolean} refresh=true + */ + that.refresh = spec.refresh !== undefined ? spec.refresh : true; + + /** + * @inheritDoc + */ + that.execute_action = function(facet) { + + var dialog = builder.build('dialog', that.dialog); + dialog.succeeded.attach(function() { + if (that.refresh) facet.refresh(); + }); + dialog.open(); + }; + return that; +}; + + + +/** + * Topology suffix entity specification object + * @member topology + */ +topology.suffix_spec = make_suffix_spec(); + +/** + * Topology segment entity specification object + * @member topology + */ +topology.segment_spec = make_segment_spec(); + +/** + * IPA server entity specification object + * @member topology + */ +topology.server_spec = make_server_spec(); + +/** + * Domain Level entity specification object + * @member topology + */ +topology.domainlevel_spec = make_domainlevel_spec(); + + +/** + * Register entity + * @member topology + */ +topology.register = function() { + var e = reg.entity; + var a = reg.action; + + e.register({type: 'topologysuffix', spec: topology.suffix_spec}); + e.register({type: 'topologysegment', spec: topology.segment_spec}); + e.register({type: 'server', spec: topology.server_spec}); + e.register({type: 'domainlevel', spec: topology.domainlevel_spec}); + + a.register('domainlevel_set', topology.domainlevel_set_action); +}; + +phases.on('registration', topology.register); +phases.on('post-metadata', topology.domainlevel_metadata); + +return topology; +}); diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json index cbaf69e..e5d306c 100644 --- a/install/ui/test/data/ipa_init.json +++ b/install/ui/test/data/ipa_init.json @@ -307,6 +307,12 @@ "soamname_change_message": "Do you want to check if new authoritative nameserver address is in DNS", "soamname_change_title": "Authoritative nameserver change" }, + "domainlevel": { + "label": "Domain Level", + "label_singular": "Domain Level", + "ipadomainlevel": "Level", + "set": "Set Domain Level" + }, "group": { "details": "Group Settings", "external": "External", @@ -545,6 +551,10 @@ "specified_users": "Specified Users and Groups", "user": "Who" }, + "topology": { + "segment_details": "Segment details", + "replication_config": "Replication configuration", + }, "trust": { "account": "Account", "admin_account": "Administrative account", @@ -641,6 +651,7 @@ "policy": "Policy", "role": "Role Based Access Control", "sudo": "Sudo", + "topology": "Topology", "trust": "Trusts" }, "true": "True", diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py index bb05a74..ff09661 100644 --- a/ipalib/plugins/internal.py +++ b/ipalib/plugins/internal.py @@ -452,6 +452,12 @@ class i18n_messages(Command): "soamname_change_message": _("Do you want to check if new authoritative nameserver address is in DNS"), "soamname_change_title": _("Authoritative nameserver change"), }, + "domainlevel": { + "label": _("Domain Level"), + "label_singular": _("Domain Level"), + "ipadomainlevel": _("Level"), + "set": _("Set Domain Level"), + }, "group": { "details": _("Group Settings"), "external": _("External"), @@ -691,6 +697,10 @@ class i18n_messages(Command): "specified_users": _("Specified Users and Groups"), "user": _("Who"), }, + "topology": { + "segment_details": _("Segment details"), + "replication_config": _("Replication configuration"), + }, "trust": { "account": _("Account"), "admin_account": _("Administrative account"), @@ -787,6 +797,7 @@ class i18n_messages(Command): "policy": _("Policy"), "role": _("Role Based Access Control"), "sudo": _("Sudo"), + "topology": _("Topology"), "trust": _("Trusts"), }, "true": _("True"),