On 05/19/2015 05:34 PM, thierry bordaz wrote:
On 05/15/2015 05:38 PM, David Kupka wrote:
On 05/15/2015 12:34 PM, Petr Vobornik wrote:
On 05/15/2015 10:59 AM, Petr Vobornik wrote:
Stage User Web UI is actually just the last four patches(847-850).

I expect that patch 848 - deleter dialog needs some adjustments (was
discussed offline).

The rest are prerequisites, namely:
- update of patternfly
- update navigation code to support multiple entities under one entity
tree (it broke a "memory feature/bug" of the navigation)
- support for "facet tabs" in sidebar




Attaching new version of 847-1. The old version did not apply because I
had also a new version of topology plugin UI (will be send later today)
in my git tree.
Hi!
thanks for patches. Please note that I tested only functionality
because I'm not familiar with WebUI internals.

I tried your patch set together with Thierry's ULC patches and found
following issues:

1) Missing all but 'Delete' actions in single stage user view.
'Enable', 'Disable', 'Unlock', 'Add OTP Token' and 'Rebuild auto
membership ' actions are not relevant here.

Fixed in patch 850-1.


2) Missing 'Restore' action in single preserve user view.

Will be added later.


3) When deleting preserved user there are options to preserve or
permanently delete user. This doesn't make sense and don't work.
Preserved user is always permanently removed.

Fixed in patch  new patch 853


4) Action 'Delete' in single user view deletes the user without asking
whether to 'preserve' or 'delete permanently'.

Will be fixed later.


*) I would prefer if the choice between 'preserve' and 'permanently
delete' in delete dialog was done by directly clicking button not
switching 'mode' radio button and then clicking 'delete'.

Otherwise everything seems to work well.
Hello,

Petr this is looking very nice and easy to use. I am not an expert of
the console, so I run the demo use case and was able to complete all the
steps (being a stage adminitrator).
The only remark I have is that when activating a stage user, the message
mentions 'users' be the CLI actually supports only one user.
Are you sure you want to activate selected users

You can select multiple users and activate them in UI. It will call stageuser_activate for each user.


Except that this is perfect for me.

Thanks a lot
thierry

In this new patch set there are also new icons.

Instead of http://fontawesome.io/icon/plus/
- restore action has http://fontawesome.io/icon/heart/
- activate action has http://fontawesome.io/icon/check/

There are also new icons which indicates user state(in page header) in stage user details page.
- stage users have http://fontawesome.io/icon/wrench/
- preserved users have http://fontawesome.io/icon/trash-o/

--
Petr Vobornik
From 76ca6c223b842aecb87c41ee87164cc6eb3b0fb9 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Tue, 19 May 2015 18:48:06 +0200
Subject: [PATCH] webui: prefer search facet's deleter dialog

Deleter dialog in search facet is now chosen in order as follows:
- facet's, defined as spec, e.g.:
  deleter_dialog: { $factory: IPA.user.deleter_dialog }
- entity's, the same but it entity spec
- default, which is IPA.search_deleter_dialog

Previous didn't allow to override entity dialog with facet one and
also definition by spec was not allowed.
---
 install/ui/src/freeipa/search.js | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/install/ui/src/freeipa/search.js b/install/ui/src/freeipa/search.js
index 87523b673e9595ec02af2f5ed8fed5838cf8f958..941597561b50e17230a7f56affc9bd853b44b738 100644
--- a/install/ui/src/freeipa/search.js
+++ b/install/ui/src/freeipa/search.js
@@ -22,6 +22,7 @@
  */
 
 define([
+        './builder',
         './ipa',
         './jquery',
         './phases',
@@ -30,7 +31,7 @@ define([
         './spec_util',
         './text',
         './facet'],
-    function(IPA, $, phases, reg, rpc, su, text, mod_facet) {
+    function(builder, IPA, $, phases, reg, rpc, su, text, mod_facet) {
 
 var exp = {};
 
@@ -111,7 +112,7 @@ IPA.search_facet = function(spec, no_init) {
      */
     that.command_options = spec.command_options || {};
 
-    that.deleter_dialog = spec.deleter_dialog || IPA.search_deleter_dialog;
+    that.deleter_dialog = spec.deleter_dialog;
 
     that.create_header = function(container) {
 
@@ -191,10 +192,12 @@ IPA.search_facet = function(spec, no_init) {
             return null;
         }
 
-        var dialog = that.managed_entity.get_dialog('remove');
-
+        var dialog = builder.build('', that.deleter_dialog);
         if (!dialog) {
-            dialog = that.deleter_dialog();
+            dialog = that.managed_entity.get_dialog('remove');
+        }
+        if (!dialog) {
+            dialog = IPA.search_deleter_dialog();
         }
 
         dialog.entity_name = that.managed_entity.name;
-- 
2.1.0

From 043dd3c66b94fa88a129428d6a261a33128a5e8b Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 14 May 2015 13:30:49 +0200
Subject: [PATCH] webui: stageusers, display page elements based on user state

---
 install/ui/doc/categories.json      |   6 +-
 install/ui/ipa.css                  |  10 +++
 install/ui/src/freeipa/details.js   |  11 ++--
 install/ui/src/freeipa/facet.js     |  70 ++++++++++++++++++++-
 install/ui/src/freeipa/field.js     |   4 +-
 install/ui/src/freeipa/stageuser.js |  28 ++++-----
 install/ui/src/freeipa/user.js      | 122 ++++++++++++++++++++++++++++++++++--
 7 files changed, 222 insertions(+), 29 deletions(-)

diff --git a/install/ui/doc/categories.json b/install/ui/doc/categories.json
index 9de673593765fc828cca07b4ad133ea16a5ccd76..8741d82e11f11c7fb75fdf187937c83af08697b3 100644
--- a/install/ui/doc/categories.json
+++ b/install/ui/doc/categories.json
@@ -144,6 +144,8 @@
                 "classes": [
                     "*facet_policy",
                     "IPA.hide_empty_row_policy",
+                    "IPA.user.preserved_user_policy",
+                    "IPA.user.stageuser_sidebar_policy",
                     "aci.permission_target_policy",
                     "aci.permission_managed_policy"
                 ]
@@ -158,8 +160,8 @@
                 "name": "Evaluators & Summaries",
                 "classes": [
                     "*_evaluator",
-                    "details.enabled_summary_cond",
-                    "details.disabled_summary_cond"
+                    "facet.summary_cond",
+                    "*_summary_cond"
                 ]
             },
 
diff --git a/install/ui/ipa.css b/install/ui/ipa.css
index 770b98391ed58107ba9992b2ab6da32ca829b019..f419eb224252aa03eaf4b25bb03435f4c9a6de9b 100644
--- a/install/ui/ipa.css
+++ b/install/ui/ipa.css
@@ -504,6 +504,16 @@ table.scrollable tbody {
     margin-right: 5px;
 }
 
+.facet-title.preserved .header-icon:before {
+    content: "\f014";
+    margin-right: 5px;
+}
+
+.facet-title.staging .header-icon:before {
+    content: "\f0ad";
+    margin-right: 5px;
+}
+
 .facet-title.disabled h1,
 .facet-title.disabled h1 .facet-pkey{
     color: gray;
diff --git a/install/ui/src/freeipa/details.js b/install/ui/src/freeipa/details.js
index cce19616f09b4123eeee2b0f6dba0826cf1ccec5..01fcfc56508449ea1f5d6ec685a38119f94621a3 100644
--- a/install/ui/src/freeipa/details.js
+++ b/install/ui/src/freeipa/details.js
@@ -34,7 +34,8 @@ define([
         './widget',
         './facet',
         './add'],
-    function(lang, builder, IPA, $, phases, reg, rpc, su, text, widget_mod) {
+    function(lang, builder, IPA, $, phases, reg, rpc, su, text, widget_mod,
+             facet_mod) {
 
 /**
  * Details module
@@ -1957,11 +1958,11 @@ exp.delete_action = IPA.delete_action = function(spec) {
  *
  * @class details.enabled_summary_cond
  * @alternateClassName IPA.enabled_summary_cond
+ * @extends facet.summary_cond
  */
 exp.enabled_summary_cond = IPA.enabled_summary_cond = function() {
 
-    var that = IPA.object();
-    lang.mixin(that, {
+    var that = facet_mod.summary_cond ({
         pos: ['enabled'],
         neg: [],
         description: text.get('@i18n:status.enabled'),
@@ -1975,10 +1976,10 @@ exp.enabled_summary_cond = IPA.enabled_summary_cond = function() {
  *
  * @class details.disabled_summary_cond
  * @alternateClassName IPA.disabled_summary_cond
+ * @extends facet.summary_cond
  */
 exp.disabled_summary_cond = IPA.disabled_summary_cond = function() {
-    var that = IPA.object();
-    lang.mixin(that, {
+    var that = facet_mod.summary_cond({
         pos: [],
         neg: ['enabled'],
         description: text.get('@i18n:status.disabled'),
diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js
index 2bb2c4837b3f2fb39d36b3d14fc711ba5cecffa0..e29be75512095c0deb4a9fcdbdb62f8e5f56670d 100644
--- a/install/ui/src/freeipa/facet.js
+++ b/install/ui/src/freeipa/facet.js
@@ -2716,7 +2716,8 @@ exp.state = IPA.state = function(spec) {
      * Summary conditions
      * @property {Array.<Object>}
      */
-    that.summary_conditions = builder.build('', spec.summary_conditions) || [];
+    that.summary_conditions = builder.build('', spec.summary_conditions, {},
+                                    { $factory: exp.summary_cond }) || [];
 
     /**
      * Initializes evaluators
@@ -2795,6 +2796,42 @@ exp.state = IPA.state = function(spec) {
 };
 
 /**
+ * Summary condition base class
+ *
+ * @class facet.summary_cond
+ */
+exp.summary_cond = function(spec) {
+
+    var that = IPA.object();
+
+    /**
+     * State which must be present in order to be positively evaluated
+     * @property {string[]}
+     */
+    that.pos = spec.pos || [];
+
+    /**
+     * State which must not be present in order to be positively evaluated
+     * @property {string[]}
+     */
+    that.neg = spec.neg || [];
+
+    /**
+     * States which will be set in positive evaluation
+     * @property {string[]}
+     */
+    that.state = spec.state || [];
+
+    /**
+     * Description which will be set in positive evaluation
+     * @property {string}
+     */
+    that.description = spec.description || '';
+
+    return that;
+};
+
+/**
  * Summary evaluator for {@link facet.state}
  * @class facet.summary_evaluator
  * @alternateClassName IPA.summary_evaluator
@@ -2927,6 +2964,37 @@ exp.state_evaluator = IPA.state_evaluator = function(spec) {
 };
 
 /**
+ * Noop evaluator always sets the state on post_load on the first time
+ * @class facet.noop_state_evaluator
+ * @extends facet.state_evaluator
+ * @alternateClassName IPA.noop_state_evaluator
+ */
+exp.noop_state_evaluator = IPA.noop_state_evaluator = function(spec) {
+
+    spec = spec || {};
+    spec.event = spec.event || 'post_load';
+
+    var that = IPA.state_evaluator(spec);
+    that.name = spec.name || 'noop_state_evaluator';
+
+    /**
+     * States to be set
+     * @property {string[]}
+     */
+    that.state = spec.state || [];
+
+    /**
+     * @inheritDoc
+     */
+    that.on_event = function() {
+        that.notify_on_change(that.state);
+    };
+
+    return that;
+};
+
+
+/**
  * Sets 'dirty' state when facet is dirty
  * @class facet.dirty_state_evaluator
  * @extends facet.state_evaluator
diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js
index 7768114306abe44759a80554e6ef488d02b6b5b0..d8e249b2c5dc447d626eda88d06c828674692c6f 100644
--- a/install/ui/src/freeipa/field.js
+++ b/install/ui/src/freeipa/field.js
@@ -1494,7 +1494,9 @@ reg.set('validator', field.validator_builder.registry);
 field.adapter_builder = builder.get('adapter');
 field.adapter_builder.ctor = field.Adapter;
 field.adapter_builder.post_ops.push(function(obj, spec, context) {
-        obj.context = context.context;
+        if (context.context) {
+            obj.context = context.context;
+        }
         return obj;
     }
 );
diff --git a/install/ui/src/freeipa/stageuser.js b/install/ui/src/freeipa/stageuser.js
index 62a059ce453e53370f27dba9afe0845dc83906e6..ca4e30025a14853a287e4a29478f80a843ab1c27 100644
--- a/install/ui/src/freeipa/stageuser.js
+++ b/install/ui/src/freeipa/stageuser.js
@@ -78,6 +78,9 @@ return {
                     label: '@i18n:buttons.activate',
                     icon: 'fa-check'
                 }
+            ],
+            policies: [
+                mod_user.stageuser_sidebar_policy
             ]
         },
         {
@@ -209,22 +212,16 @@ return {
             state: {
                 evaluators: [
                     {
-                        $factory: IPA.enable_state_evaluator,
-                        field: 'nsaccountlock',
-                        adapter: { $type: 'batch', result_index: 0 },
-                        invert_value: true
-                    },
-                    {
-                        $factory: IPA.acl_state_evaluator,
-                        name: 'reset_password_acl_evaluator',
-                        adapter: { $type: 'batch', result_index: 0 },
-                        attribute: 'userpassword'
-                    },
-                    IPA.user.self_service_other_user_evaluator
+                        $factory: mod_facet.noop_state_evaluator,
+                        state: ['staging']
+                    }
                 ],
                 summary_conditions: [
-                    IPA.enabled_summary_cond,
-                    IPA.disabled_summary_cond
+                    {
+                        pos: ['staging'],
+                        state: ['staging'],
+                        description: 'Staging user'
+                    }
                 ]
             }
         }
@@ -302,6 +299,9 @@ stageuser.search_preserved_facet_spec = {
             label: '@i18n:buttons.restore',
             icon: 'fa-heart'
         }
+    ],
+    policies: [
+        mod_user.stageuser_sidebar_policy
     ]
 };
 
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index 73124f203104b6bf8c97c3c3a905aee0306e88b3..85c9faa814bb5657e4f840773f3fbb623b689e7f 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -117,6 +117,9 @@ return {
                     icon: 'fa-check'
                 }
             ],
+            policies: [
+                IPA.user.stageuser_sidebar_policy
+            ],
             deleter_dialog: {
                 $factory: IPA.user.deleter_dialog
             }
@@ -302,22 +305,40 @@ return {
                 }
             ],
             actions: [
-                'add_otptoken',
-                'enable',
-                'disable',
+                {
+                    $type: 'add_otptoken',
+                    hide_cond: ['preserved-user']
+                },
+                {
+                    $type: 'enable',
+                    hide_cond: ['preserved-user']
+                },
+                {
+                    $type: 'disable',
+                    hide_cond: ['preserved-user']
+                },
+                {
+                    $type: 'enable',
+                    hide_cond: ['preserved-user']
+                },
                 'delete',
-                'reset_password',
+                {
+                    $type: 'reset_password',
+                    hide_cond: ['preserved-user']
+                },
                 {
                     $factory: IPA.object_action,
                     name: 'unlock',
                     method: 'unlock',
                     label: '@i18n:objects.user.unlock',
                     needs_confirm: true,
+                    hide_cond: ['preserved-user'],
                     confirm_msg: '@i18n:objects.user.unlock_confirm'
                 },
                 {
                     $type: 'automember_rebuild',
                     name: 'automember_rebuild',
+                    hide_cond: ['preserved-user'],
                     label: '@i18n:actions.automember_rebuild'
                 }
             ],
@@ -336,13 +357,23 @@ return {
                         adapter: { $type: 'batch', result_index: 0 },
                         attribute: 'userpassword'
                     },
-                    IPA.user.self_service_other_user_evaluator
+                    IPA.user.self_service_other_user_evaluator,
+                    IPA.user.preserved_user_evaluator
                 ],
                 summary_conditions: [
+                    {
+                        pos: ['preserved-user'],
+                        neg: [],
+                        state: ['preserved'],
+                        description: 'Preserved user'
+                    },
                     IPA.enabled_summary_cond,
                     IPA.disabled_summary_cond
                 ]
-            }
+            },
+            policies: [
+                IPA.user.preserved_user_policy
+            ]
         },
         {
             $type: 'association',
@@ -695,6 +726,85 @@ IPA.user.self_service_other_user_evaluator = function(spec) {
     return that;
 };
 
+/**
+ * Evaluates if user is "preserved" user
+ * @class IPA.user.preserved_user_evaluator
+ */
+IPA.user.preserved_user_evaluator = function(spec) {
+
+    spec = spec || {};
+    spec.event = spec.event || 'post_load';
+
+    var that = IPA.state_evaluator(spec);
+    that.name = spec.name || 'preserved_user_evaluator';
+    that.param = spec.param || 'dn';
+    that.adapter = builder.build('adapter', { $type: 'adapter'}, { context: that });
+
+    /**
+     * Evaluates if user is preserved, i.e. is in provisioning tree
+     */
+    that.on_event = function(data) {
+
+        var old_state = that.state;
+        that.state = [];
+
+        var dn = that.adapter.load(data)[0];
+        if (dn.indexOf('cn=provisioning') > 0) {
+            that.state.push('preserved-user');
+        }
+
+        that.notify_on_change(old_state);
+    };
+
+    return that;
+};
+
+/**
+ * Change breadcrumb navigation and therefore also target facet on first
+ * navigation item based on user state (active/preserved)
+ * @class
+ */
+IPA.user.preserved_user_policy = function(spec) {
+
+    var that = IPA.facet_policy(spec);
+    that.post_load = function(data) {
+        var adapter = builder.build('adapter', {
+            $type: 'adapter',
+            result_index: 0,
+            context: { param: 'dn' }
+        });
+        var dn = adapter.load(data)[0];
+        var preserved_user = dn.indexOf('cn=provisioning') > 0;
+        var details_facet = that.container;
+        details_facet.set_tabs_visible(!preserved_user);
+        details_facet.redirect_info = { entity: 'user', facet: 'search' };
+        if (preserved_user) {
+            details_facet.redirect_info.facet = 'search_preserved';
+        }
+        details_facet.header.update_breadcrumb();
+    };
+
+    return that;
+};
+
+
+/**
+ * Display sidebar (facet tabs) only if user can view stage and preserved user.
+ * Atm. the sidebar is hidden only in self-service. Should be extended by a
+ * check if user can actually read it.
+ * @class
+ */
+IPA.user.stageuser_sidebar_policy = function(spec) {
+
+    var that = IPA.facet_policy(spec);
+
+    that.post_create = function(data) {
+        that.container.set_tabs_visible(!IPA.is_selfservice);
+    };
+
+    return that;
+};
+
 IPA.user.deleter_dialog = function(spec) {
 
     spec = spec || {};
-- 
2.1.0

From 9147f8dc03029b4fa5c320867e0e0d7af5f677bc Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 7 May 2015 18:01:53 +0200
Subject: [PATCH] webui: update stageuser/user pages based on action in
 diffrent user search page

---
 install/ui/src/freeipa/stageuser.js | 33 +++++++++++++++++++++++++++++++++
 install/ui/src/freeipa/user.js      |  4 ++++
 2 files changed, 37 insertions(+)

diff --git a/install/ui/src/freeipa/stageuser.js b/install/ui/src/freeipa/stageuser.js
index cfec12bcce4ba5fa5fcb5371a526e86e36a3539d..62a059ce453e53370f27dba9afe0845dc83906e6 100644
--- a/install/ui/src/freeipa/stageuser.js
+++ b/install/ui/src/freeipa/stageuser.js
@@ -40,6 +40,16 @@ var make_stageuser_spec = function() {
 return {
     name: 'stageuser',
     facet_groups: ['settings'],
+    policies: [
+        IPA.search_facet_update_policy,
+        IPA.details_facet_update_policy,
+        {
+            $factory: IPA.facet_update_policy,
+            source_facet: 'search',
+            dest_entity: 'user',
+            dest_facet: 'search'
+        }
+    ],
     facets: [
         {
             $type: 'search',
@@ -295,6 +305,29 @@ stageuser.search_preserved_facet_spec = {
     ]
 };
 
+mod_user.entity_spec.policies = mod_user.entity_spec.policies || {};
+mod_user.entity_spec.policies.push(
+    {
+        $factory: IPA.facet_update_policy,
+        source_facet: 'search',
+        dest_entity: 'stageuser',
+        dest_facet: 'search'
+    },
+    {
+        $factory: IPA.facet_update_policy,
+        source_facet: 'search_preserved',
+        dest_entity: 'user',
+        dest_facet: 'search'
+    },
+    {
+        $factory: IPA.facet_update_policy,
+        source_facet: 'search',
+        dest_entity: 'user',
+        dest_facet: 'search_preserved'
+    }
+);
+
+
 stageuser.batch_activate_action = function(spec) {
 
     spec = spec || {};
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index 1ee5a28c2e5703fb22b01356d2b068202e630162..73124f203104b6bf8c97c3c3a905aee0306e88b3 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -58,6 +58,10 @@ var exp = IPA.user = {
 var make_spec = function() {
 return {
     name: 'user',
+    policies: [
+        IPA.search_facet_update_policy,
+        IPA.details_facet_update_policy
+    ],
     facets: [
         {
             $type: 'search',
-- 
2.1.0

From 1754a960937c8969209db01ebe11b10048ab9988 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 14 May 2015 16:54:02 +0200
Subject: [PATCH] webui: extend user deleter dialog with --permanent and
 --preserve options

---
 install/ui/src/freeipa/user.js | 58 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index 787e95f8ffde7a9266adfe197579b9de12ab6164..1ee5a28c2e5703fb22b01356d2b068202e630162 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -112,7 +112,10 @@ return {
                     label: '@i18n:buttons.enable',
                     icon: 'fa-check'
                 }
-            ]
+            ],
+            deleter_dialog: {
+                $factory: IPA.user.deleter_dialog
+            }
         },
         {
             $type: 'details',
@@ -688,6 +691,59 @@ IPA.user.self_service_other_user_evaluator = function(spec) {
     return that;
 };
 
+IPA.user.deleter_dialog = function(spec) {
+
+    spec = spec || {};
+
+    var that = IPA.search_deleter_dialog(spec);
+
+    /**
+     * Adds options to user-del command
+     * @type {IPA.radio_widget}
+     */
+    that.option_radio = null;
+
+    that.create_content = function() {
+
+        that.deleter_dialog_create_content();
+
+        that.option_layout = IPA.fluid_layout({
+            label_cls: 'col-sm-3',
+            widget_cls: 'col-sm-9'
+        });
+
+        that.option_radio = IPA.radio_widget({
+            name: 'deletemode',
+            label: 'Delete mode',
+            options: [
+                { label: 'default', value: '' },
+                { label: 'delete permanently', value: 'permanently' },
+                { label: 'preserve', value: 'preserve' }
+            ]
+        });
+
+        var html = that.option_layout.create([that.option_radio]);
+        that.container.append(html);
+        that.option_radio.set_value(['']);
+    };
+
+    that.create_command = function() {
+        var batch = that.search_deleter_dialog_create_command();
+        var option = that.option_radio.get_value()[0];
+
+        if (option) {
+            for (var i=0; i<batch.commands.length; i++) {
+                var command = batch.commands[i];
+                command.set_option(option, true);
+            }
+        }
+
+        return batch;
+    };
+
+    return that;
+};
+
 exp.entity_spec = make_spec();
 exp.register = function() {
     var e = reg.entity;
-- 
2.1.0

From 92ff6b4fe842cbfbf028907aaafb94c126376db9 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Wed, 22 Apr 2015 14:57:26 +0200
Subject: [PATCH] webui: stageuser plugin

---
 install/ui/doc/categories.json                 |   1 +
 install/ui/src/freeipa/app.js                  |   1 +
 install/ui/src/freeipa/navigation/menu_spec.js |  17 +-
 install/ui/src/freeipa/stageuser.js            | 351 +++++++++++++++++++++++++
 install/ui/src/freeipa/user.js                 |  17 +-
 install/ui/test/data/ipa_init.json             |  10 +
 ipalib/plugins/internal.py                     |  11 +
 7 files changed, 406 insertions(+), 2 deletions(-)
 create mode 100644 install/ui/src/freeipa/stageuser.js

diff --git a/install/ui/doc/categories.json b/install/ui/doc/categories.json
index c84077682eafa42981e8a1c1a2f93c712e6421fd..9de673593765fc828cca07b4ad133ea16a5ccd76 100644
--- a/install/ui/doc/categories.json
+++ b/install/ui/doc/categories.json
@@ -250,6 +250,7 @@
                     "idviews",
                     "otptoken",
                     "radiusproxy",
+                    "stageuser",
                     "user",
                     "plugins.load",
                     "plugins.login",
diff --git a/install/ui/src/freeipa/app.js b/install/ui/src/freeipa/app.js
index 46752fa09e47be9e14e5fa37ce1bd1cbd0b0afdf..140fe938f68975310175fb9fadf0ec36db048b72 100644
--- a/install/ui/src/freeipa/app.js
+++ b/install/ui/src/freeipa/app.js
@@ -48,6 +48,7 @@ define([
     './sudo',
     './trust',
     './user',
+    './stageuser',
     'dojo/domReady!'
 ],function(app_container) {
     return app_container;
diff --git a/install/ui/src/freeipa/navigation/menu_spec.js b/install/ui/src/freeipa/navigation/menu_spec.js
index ca1a290f479fd0cc6a399e6bc93bd3e8ed1fca40..13f533d1a6fbb21c73e1f0e5fe1df2836c99f832 100644
--- a/install/ui/src/freeipa/navigation/menu_spec.js
+++ b/install/ui/src/freeipa/navigation/menu_spec.js
@@ -36,7 +36,22 @@ var nav = {};
             name: 'identity',
             label: '@i18n:tabs.identity',
             children: [
-                { entity: 'user' },
+                {
+                    entity: 'user',
+                    facet: 'search',
+                    children: [
+                        {
+                            entity: 'stageuser',
+                            facet: 'search',
+                            hidden: true
+                        },
+                        {
+                            entity: 'user',
+                            facet: 'search_preserved',
+                            hidden: true
+                        }
+                    ]
+                },
                 { entity: 'group' },
                 { entity: 'host' },
                 { entity: 'hostgroup' },
diff --git a/install/ui/src/freeipa/stageuser.js b/install/ui/src/freeipa/stageuser.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfec12bcce4ba5fa5fcb5371a526e86e36a3539d
--- /dev/null
+++ b/install/ui/src/freeipa/stageuser.js
@@ -0,0 +1,351 @@
+//
+// Copyright (C) 2015  FreeIPA Contributors see COPYING for license
+//
+
+define([
+        'dojo/on',
+        './ipa',
+        './jquery',
+        './menu',
+        './phases',
+        './reg',
+        './rpc',
+        './text',
+        './details',
+        './facet',
+        './user',
+        './search',
+        './entity'],
+            function(
+    on, IPA, $, menu, phases, reg, rpc, text, mod_details, mod_facet, mod_user) {
+/**
+ * Stage user module
+ * @class
+ * @singleton
+ */
+var stageuser = IPA.stageuser = {
+
+    search_facet_group: {
+        name: 'search',
+        label: '@i18n:objects.stageuser.user_categories',
+        facets: {
+            search_normal: 'user_search',
+            search: 'stageuser_search',
+            search_preserved: 'user_search_preserved'
+        }
+    }
+};
+
+var make_stageuser_spec = function() {
+return {
+    name: 'stageuser',
+    facet_groups: ['settings'],
+    facets: [
+        {
+            $type: 'search',
+            disable_facet_tabs: false,
+            tabs_in_sidebar: true,
+            tab_label: '@i18n:objects.stageuser.label',
+            facet_groups: [stageuser.search_facet_group],
+            facet_group: 'search',
+            columns: [
+                'uid',
+                'givenname',
+                'sn',
+                'uidnumber',
+                'mail',
+                'telephonenumber',
+                'title'
+            ],
+            actions: [
+                {
+                    $type: 'batch_activate'
+                }
+            ],
+            control_buttons: [
+                {
+                    name: 'activate',
+                    label: '@i18n:buttons.activate',
+                    icon: 'fa-check'
+                }
+            ]
+        },
+        {
+            $type: 'details',
+            disable_facet_tabs: true,
+            sections: [
+                {
+                    name: 'identity',
+                    label: '@i18n:details.identity',
+                    fields: [
+                        'title',
+                        'givenname',
+                        'sn',
+                        'cn',
+                        'displayname',
+                        'initials',
+                        'gecos',
+                        {
+                            name: 'userclass',
+                            flags: ['w_if_no_aci']
+                        }
+                    ]
+                },
+                {
+                    name: 'account',
+                    label: '@i18n:objects.user.account',
+                    fields: [
+                        'uid',
+                        {
+                            $factory: mod_user.password_widget,
+                            name: 'has_password',
+                            metadata: '@mo-param:user:userpassword'
+                        },
+                        {
+                            $type: 'datetime',
+                            name: 'krbpasswordexpiration',
+                            label: '@i18n:objects.user.krbpasswordexpiration',
+                            read_only: true
+                        },
+                        {
+                            name: 'uidnumber',
+                            minvalue: -1
+                        },
+                        {
+                            name: 'gidnumber',
+                            minvalue: -1
+                        },
+                        'krbprincipalname',
+                        {
+                            $type: 'datetime',
+                            name: 'krbprincipalexpiration'
+                        },
+                        'loginshell',
+                        'homedirectory',
+                        {
+                            $type: 'sshkeys',
+                            name: 'ipasshpubkey',
+                            label: '@i18n:objects.sshkeystore.keys'
+                        },
+                        {
+                            $type: 'checkboxes',
+                            name: 'ipauserauthtype',
+                            flags: ['w_if_no_aci'],
+                            options: [
+                                { label: '@i18n:authtype.type_password', value: 'password' },
+                                { label: '@i18n:authtype.type_radius', value: 'radius' },
+                                { label: '@i18n:authtype.type_otp', value: 'otp' }
+                            ],
+                            tooltip: '@i18n:authtype.user_tooltip'
+                        },
+                        {
+                            $type: 'entity_select',
+                            name: 'ipatokenradiusconfiglink',
+                            flags: ['w_if_no_aci'],
+                            other_entity: 'radiusproxy',
+                            other_field: 'cn'
+                        },
+                        {
+                            name: 'ipatokenradiususername',
+                            flags: ['w_if_no_aci']
+                        }
+                    ]
+                },
+                {
+                    name: 'contact',
+                    label: '@i18n:objects.user.contact',
+                    fields: [
+                        { $type: 'multivalued', name: 'mail' },
+                        { $type: 'multivalued', name: 'telephonenumber' },
+                        { $type: 'multivalued', name: 'pager' },
+                        { $type: 'multivalued', name: 'mobile' },
+                        { $type: 'multivalued', name: 'facsimiletelephonenumber' }
+                    ]
+                },
+                {
+                    name: 'mailing',
+                    label: '@i18n:objects.user.mailing',
+                    fields: ['street', 'l', 'st', 'postalcode']
+                },
+                {
+                    name: 'employee',
+                    label: '@i18n:objects.user.employee',
+                    fields: [
+                        'ou',
+                        {
+                            $type: 'entity_select',
+                            name: 'manager',
+                            other_entity: 'user',
+                            other_field: 'uid'
+                        },
+                        { $type: 'multivalued', name: 'departmentnumber' },
+                        'employeenumber',
+                        'employeetype',
+                        'preferredlanguage'
+                    ]
+                },
+                {
+                    name: 'misc',
+                    label: '@i18n:objects.user.misc',
+                    fields: [
+                        { $type: 'multivalued', name: 'carlicense' }
+                    ]
+                }
+            ],
+            actions: [
+                'delete'
+            ],
+            header_actions: ['delete'],
+            state: {
+                evaluators: [
+                    {
+                        $factory: IPA.enable_state_evaluator,
+                        field: 'nsaccountlock',
+                        adapter: { $type: 'batch', result_index: 0 },
+                        invert_value: true
+                    },
+                    {
+                        $factory: IPA.acl_state_evaluator,
+                        name: 'reset_password_acl_evaluator',
+                        adapter: { $type: 'batch', result_index: 0 },
+                        attribute: 'userpassword'
+                    },
+                    IPA.user.self_service_other_user_evaluator
+                ],
+                summary_conditions: [
+                    IPA.enabled_summary_cond,
+                    IPA.disabled_summary_cond
+                ]
+            }
+        }
+    ],
+    adder_dialog: {
+        sections: [
+            {
+                fields: [
+                    {
+                        name: 'uid',
+                        required: false
+                    },
+                    'givenname',
+                    'sn',
+                    'userclass'
+                ]
+            },
+            {
+                fields: [
+                    {
+                        name: 'userpassword',
+                        label: '@i18n:password.new_password',
+                        $type: 'password'
+                    },
+                    {
+                        name: 'userpassword2',
+                        label: '@i18n:password.verify_password',
+                        $type: 'password',
+                        flags: ['no_command'],
+                        validators: [{
+                            $type: 'same_password',
+                            other_field: 'userpassword'
+                        }]
+                    }
+                ]
+            }
+        ]
+    }
+};};
+
+stageuser.search_preserved_facet_spec = {
+    $type: 'search',
+    $pre_ops: [
+        { $del: [[ 'control_buttons', [{ name: 'add'}, { name: 'delete'}] ]] }
+    ],
+    disable_facet_tabs: false,
+    tabs_in_sidebar: true,
+    entity: 'user',
+    managed_entity: 'user',
+    name: 'search_preserved',
+    label: '@i18n:objects.stageuser.preserved_label',
+    tab_label: '@i18n:objects.stageuser.preserved_label',
+    facet_groups: [stageuser.search_facet_group],
+    facet_group: 'search',
+    command_options: {
+        'preserved': true
+    },
+    columns: [
+        'uid',
+        'givenname',
+        'sn',
+        'uidnumber',
+        'mail',
+        'telephonenumber',
+        'title'
+    ],
+    actions: [
+        {
+            $type: 'batch_undel'
+        }
+    ],
+    control_buttons: [
+        {
+            name: 'undel',
+            label: '@i18n:buttons.restore',
+            icon: 'fa-heart'
+        }
+    ]
+};
+
+stageuser.batch_activate_action = function(spec) {
+
+    spec = spec || {};
+
+    spec.name = spec.name || 'activate';
+    spec.method = spec.method || 'activate';
+    spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
+    spec.enabled = spec.enabled === undefined ? false : spec.enabled;
+    spec.enable_cond = spec.enable_cond || ['item-selected'];
+    spec.success_msg = spec.success_msg || '@i18n:objects.stageuser.activate_success';
+    spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.activate_confirm';
+
+    return IPA.batch_items_action(spec);
+};
+
+stageuser.batch_undel_action = function(spec) {
+
+    spec = spec || {};
+
+    spec.name = spec.name || 'undel';
+    spec.method = spec.method || 'undel';
+    spec.needs_confirm = spec.needs_confirm === undefined ? true : spec.needs_confirm;
+    spec.enabled = spec.enabled === undefined ? false : spec.enabled;
+    spec.enable_cond = spec.enable_cond || ['item-selected'];
+    spec.success_msg = spec.success_msg || '@i18n:objects.stageuser.undel_success';
+    spec.confirm_msg = spec.confirm_msg || '@i18n:objects.stageuser.undel_confirm';
+
+    return IPA.batch_items_action(spec);
+};
+
+/**
+ * Stage user entity specification object
+ * @member stageuser
+ */
+stageuser.stageuser_spec = make_stageuser_spec();
+
+/**
+ * Register entity
+ * @member stageuser
+ */
+stageuser.register = function() {
+    var a = reg.action;
+    var e = reg.entity;
+    var f = reg.facet;
+    a.register('batch_activate', stageuser.batch_activate_action);
+    a.register('batch_undel', stageuser.batch_undel_action);
+    e.register({type: 'stageuser', spec: stageuser.stageuser_spec});
+    f.register_from_spec('user_search_preserved', stageuser.search_preserved_facet_spec);
+};
+
+phases.on('registration', stageuser.register);
+
+return stageuser;
+});
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index 72d295020ce812d30abda359a2dbdf6ef88dd833..787e95f8ffde7a9266adfe197579b9de12ab6164 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -43,7 +43,17 @@ define([
  * @alternateClassName IPA.user
  * @singleton
  */
-var exp = IPA.user = {};
+var exp = IPA.user = {
+    search_facet_group: {
+        name: 'search',
+        label: '@i18n:objects.stageuser.user_categories',
+        facets: {
+            search_normal: 'user_search',
+            search: 'stageuser_search',
+            search_preserved: 'user_search_preserved'
+        }
+    }
+};
 
 var make_spec = function() {
 return {
@@ -51,6 +61,11 @@ return {
     facets: [
         {
             $type: 'search',
+            label: '@i18n:objects.user.activeuser_label',
+            tab_label: '@i18n:objects.user.activeuser_label',
+            disable_facet_tabs: false,
+            tabs_in_sidebar: true,
+            facet_groups: [exp.search_facet_group],
             row_disabled_attribute: 'nsaccountlock',
             columns: [
                 'uid',
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index f969a874f84da5e9bff36d6b33678b5e908df852..b17bf777fb665a77b31505f79149902ba7fd3ede 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -508,6 +508,15 @@
                             "status_new_ns": "New: key not set",
                             "status_new_s": "New: key set"
                         },
+                        "stageuser": {
+                            "activate_confirm": "Are you sure you want to activate selected users?",
+                            "activate_success": "${count} user(s) activated",
+                            "label": "Stage users",
+                            "preserved_label": "Preserved users",
+                            "undel_confirm": "Are you sure you want to restore selected users?",
+                            "undel_success": "${count} user(s) restored",
+                            "user_categories": "User categories",
+                        },
                         "sudocmd": {
                             "groups": "Groups"
                         },
@@ -556,6 +565,7 @@
                         "user": {
                             "account": "Account Settings",
                             "account_status": "Account Status",
+                            "activeuser_label": "Active users",
                             "contact": "Contact Settings",
                             "employee": "Employee Information",
                             "error_changing_status": "Error changing account status",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index a76a3180dde01211d291e55922da57b7f8b4f7ba..56d271b4a7a9f3abe9167f7a273b48df7979c552 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -200,6 +200,7 @@ class i18n_messages(Command):
         },
         "buttons": {
             "about": _("About"),
+            "activate": _("Activate"),
             "add": _("Add"),
             "add_and_add_another": _("Add and Add Another"),
             "add_and_close": _("Add and Close"),
@@ -653,6 +654,15 @@ class i18n_messages(Command):
                 "status_new_ns": _("New: key not set"),
                 "status_new_s": _("New: key set"),
             },
+            "stageuser": {
+                "activate_confirm": _("Are you sure you want to activate selected users?"),
+                "activate_success": _("${count} user(s) activated"),
+                "label": _("Stage users"),
+                "preserved_label": _("Preserved users"),
+                "undel_confirm": _("Are you sure you want to restore selected users?"),
+                "undel_success": _("${count} user(s) restored"),
+                "user_categories": _("User categories"),
+            },
             "sudocmd": {
                 "groups": _("Groups"),
             },
@@ -701,6 +711,7 @@ class i18n_messages(Command):
             "user": {
                 "account": _("Account Settings"),
                 "account_status": _("Account Status"),
+                "activeuser_label": _("Active users"),
                 "contact": _("Contact Settings"),
                 "employee": _("Employee Information"),
                 "error_changing_status": _("Error changing account status"),
-- 
2.1.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to