== [PATCH] 898 webui: cert-request improvements ==
Certificate request action and dialog now supports 'profile_id',
'add' and 'principal' options. 'add' and 'principal' are disaplayed
only if certificate is added from certificate search facet.

Certificate search facet allows to add a certificate.

User details facet allows to add a certificate.

part of
https://fedorahosted.org/freeipa/ticket/5046

== [PATCH] 899 webui: show multiple cert ==
New certificate widget which replaced certificate status widget.

It can display multiple certs. Drawback is that it cannot display
if the certificate was revoked. Web UI does not have the information.

part of: https://fedorahosted.org/freeipa/ticket/5045

== [PATCH] 900 webui: remove cert manipulation actions from host and service ==
Remove
* cert_view
* cert_get
* cert_revoke
* cert_restore

These actions require serial number which is not provided to Web UI if
multiple certificates are present.

As an alternative to patch 900 we could also provide the original interface if there is only one cert and hide the actions if there are multiple certs.

note: {user|host|service}-{add|remove}_cert command support is still missing.
--
Petr Vobornik
From ddae79eafc144e338bab0504647a9295a928025c Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 9 Jul 2015 00:18:54 +0200
Subject: [PATCH] webui: remove cert manipulation actions from host and service

Remove
* cert_view
* cert_get
* cert_revoke
* cert_restore

These actions require serial number which is not provided to Web UI if
multiple certificates are present.
---
 install/ui/src/freeipa/host.js    |  8 ++------
 install/ui/src/freeipa/service.js | 12 ++----------
 2 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js
index e033279b2c374c00887fc51589c435b833ea0ad7..764e551b40a00d3a35ea4e8ec99de9164bc97be3 100644
--- a/install/ui/src/freeipa/host.js
+++ b/install/ui/src/freeipa/host.js
@@ -264,14 +264,10 @@ return {
                     enable_cond: ['userpassword_w'],
                     show_cond: ['has_password']
                 },
-                'cert_view',
-                'cert_get',
-                'cert_request',
-                'cert_revoke',
-                'cert_restore'
+                'cert_request'
             ],
             header_actions: ['automember_rebuild', 'unprovision', 'set_otp', 'reset_otp',
-                'request_cert', 'view_cert', 'get_cert', 'revoke_cert', 'restore_cert'],
+                'request_cert'],
             state: {
                 evaluators: [
                     IPA.host.has_password_evaluator,
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 28a01f635288b3fb164853a3c819dc3f4f58e3b7..f1f8d951e415e9768aab433e28da852a732bc8ba 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -226,19 +226,11 @@ return {
             ],
             actions: [
                 'service_unprovision',
-                'cert_view',
-                'cert_get',
-                'cert_request',
-                'cert_revoke',
-                'cert_restore'
+                'cert_request'
             ],
             header_actions: [
                 'unprovision',
-                'request_cert',
-                'view_cert',
-                'get_cert',
-                'revoke_cert',
-                'restore_cert'
+                'request_cert'
             ],
             state: {
                 evaluators: [
-- 
2.4.3

From 6aaa77b6f71b07af3264d470255b6d46fce23cdc Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 9 Jul 2015 00:12:00 +0200
Subject: [PATCH] webui: show multiple cert

New certificate widget which replaced certificate status widget.

It can display multiple certs. Drawback is that it cannot display
if the certificate was revoked. Web UI does not have the information.

part of: https://fedorahosted.org/freeipa/ticket/5045
---
 install/ui/less/widgets.less          | 12 +++++
 install/ui/src/freeipa/certificate.js | 90 +++++++++++++++++++++++++++++++++++
 install/ui/src/freeipa/host.js        |  5 +-
 install/ui/src/freeipa/service.js     |  5 +-
 install/ui/src/freeipa/user.js        |  4 ++
 install/ui/test/data/ipa_init.json    |  3 ++
 ipalib/plugins/internal.py            |  3 ++
 7 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/install/ui/less/widgets.less b/install/ui/less/widgets.less
index 7778f6bf46b3bbebf99fff4a7799fe4b0b090385..99b22068d7b721d93e7b6901e262ad11781ffae7 100644
--- a/install/ui/less/widgets.less
+++ b/install/ui/less/widgets.less
@@ -131,5 +131,17 @@
     }
 }
 
+// Certificate Widget
+
+.certificate-widget {
+    label {
+        padding-right: 10px;
+    }
+    .certificate {
+        word-wrap: break-word;
+        padding-bottom: 10px;
+    }
+}
+
 // workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=409254
 tbody:empty { display: none; }
\ No newline at end of file
diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js
index 71f0dfbf54540318e7ae84cea549a7a00253b3e2..93f3cfc68a95bfb8014aaf96d1b571568ac605dc 100755
--- a/install/ui/src/freeipa/certificate.js
+++ b/install/ui/src/freeipa/certificate.js
@@ -1000,6 +1000,95 @@ IPA.cert.status_field = function(spec) {
     return that;
 };
 
+IPA.cert.cert_widget = function(spec) {
+
+    spec = spec || {};
+    spec.css_class = spec.css_class || 'certificate-widget';
+
+    var that = IPA.input_widget(spec);
+    that.certs_visible = false;
+
+    that.create = function(container) {
+
+        that.widget_create(container);
+        that.content_el = $('<div>').appendTo(container);
+    };
+
+    that.create_status = function(name, text, icon) {
+
+        var status = $('<label/>', {
+            'class': 'certificate-status'
+        });
+
+        $('<i/>', {
+            'class': icon
+        }).appendTo(status);
+
+        status.append(" " + text);
+
+        return status;
+    };
+
+    that.create_certs = function() {
+
+        that.content_el.empty();
+        var l = that.certificates.length;
+
+        if (l && that.certs_visible) {
+            for (var i=0; i<l; i++) {
+                $('<div/>', {
+                    'class': 'certificate',
+                    text: that.certificates[i]
+                }).appendTo(that.content_el);
+            }
+            $('<div/>').append(
+                IPA.button({
+                    name: 'hide',
+                    label: '@i18n:buttons.hide',
+                    click: function() {
+                        that.certs_visible = false;
+                        that.create_certs();
+                    }
+                })).
+            appendTo(that.content_el);
+        }
+
+        if (!l) {
+            that.content_el.append(that.create_status(
+                'missing',
+                text.get('@i18n:objects.cert.missing'),
+                'fa fa-warning'));
+        }
+
+        if (l && !that.certs_visible) {
+
+            var msg = text.get('@i18n:objects.cert.present');
+            msg = msg.replace('${count}', l);
+            that.content_el.append(
+                that.create_status('present', msg, 'fa fa-check'));
+
+            IPA.button({
+                name: 'show',
+                label: '@i18n:buttons.show',
+                click: function() {
+                    that.certs_visible = true;
+                    that.create_certs();
+                }
+            }).appendTo(that.content_el);
+        }
+    };
+
+    that.update = function(values) {
+        that.certificates = values;
+        that.create_certs();
+    };
+
+    that.clear = function() {
+        that.content_el.empty();
+    };
+
+    return that;
+};
 
 exp.create_cert_metadata = function() {
 
@@ -1409,6 +1498,7 @@ exp.register = function() {
     var f = reg.field;
     var a = reg.action;
 
+    w.register('certificate', IPA.cert.cert_widget);
     w.register('certificate_status', IPA.cert.status_widget);
     f.register('certificate_status', IPA.cert.status_field);
 
diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js
index 17fe423e51394859216bb280298514717bd120f5..e033279b2c374c00887fc51589c435b833ea0ad7 100644
--- a/install/ui/src/freeipa/host.js
+++ b/install/ui/src/freeipa/host.js
@@ -140,9 +140,8 @@ return {
                     name: 'certificate',
                     fields: [
                         {
-                            $type: 'certificate_status',
-                            name: 'certificate_status',
-                            label: '@i18n:objects.host.status'
+                            $type: 'certificate',
+                            name: 'usercertificate'
                         }
                     ]
                 },
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 5b469b5e1091e63ecc8c5c9b570541c57c54ceaa..28a01f635288b3fb164853a3c819dc3f4f58e3b7 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -134,9 +134,8 @@ return {
                     name: 'certificate',
                     fields: [
                         {
-                            $type: 'certificate_status',
-                            name: 'certificate_status',
-                            label: '@i18n:objects.service.status'
+                            $type: 'certificate',
+                            name: 'usercertificate'
                         }
                     ]
                 },
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index 33bc6ec10a8c7e286341693c01852304362610f4..e30311bbf0763d9efbc38fdb19e80e114e7636c9 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -175,6 +175,10 @@ return {
                             label: '@i18n:objects.sshkeystore.keys'
                         },
                         {
+                            $type: 'certificate',
+                            name: 'usercertificate'
+                        },
+                        {
                             $type: 'checkboxes',
                             name: 'ipauserauthtype',
                             flags: ['w_if_no_aci'],
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 21b12f14411d4f4d2f79a325d0b7c6071e12e193..ef172950527512e71c28916274153036f17212fe 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -73,6 +73,7 @@
                         "filter": "Filter",
                         "find": "Find",
                         "get": "Get",
+                        "hide": "Hide",
                         "issue": "Issue",
                         "ok": "OK",
                         "refresh": "Refresh",
@@ -85,6 +86,7 @@
                         "revoke": "Revoke",
                         "save": "Save",
                         "set": "Set",
+                        "show": "Show",
                         "unapply": "Un-apply",
                         "update": "Update",
                         "view": "View"
@@ -253,6 +255,7 @@
                             "note": "Note",
                             "organization": "Organization",
                             "organizational_unit": "Organizational Unit",
+                            "present": "${count} certificate(s) present",
                             "privilege_withdrawn": "Privilege Withdrawn",
                             "reason": "Reason for Revocation",
                             "remove_from_crl": "Remove from CRL",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index ae019e7ef8fc7cca0d36338730fe7818ab8d4021..f97885ceae8f3c0913a16c281c2faa8a918541e7 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -216,6 +216,7 @@ class i18n_messages(Command):
             "filter": _("Filter"),
             "find": _("Find"),
             "get": _("Get"),
+            "hide": _("Hide"),
             "issue": _("Issue"),
             "ok": _("OK"),
             "refresh": _("Refresh"),
@@ -228,6 +229,7 @@ class i18n_messages(Command):
             "revoke": _("Revoke"),
             "save": _("Save"),
             "set": _("Set"),
+            "show": _("Show"),
             "unapply": ("Un-apply"),
             "update": _("Update"),
             "view": _("View"),
@@ -397,6 +399,7 @@ class i18n_messages(Command):
                 "note": _("Note"),
                 "organization": _("Organization"),
                 "organizational_unit": _("Organizational Unit"),
+                "present": _("${count} certificate(s) present"),
                 "privilege_withdrawn": _("Privilege Withdrawn"),
                 "reason": _("Reason for Revocation"),
                 "remove_from_crl": _("Remove from CRL"),
-- 
2.4.3

From aa0a0aa8a11c9c770ecd30c9b3414dfa85281263 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Wed, 8 Jul 2015 22:04:45 +0200
Subject: [PATCH] webui: cert-request improvements

Certificate request action and dialog now supports 'profile_id',
'add' and 'principal' options. 'add' and 'principal' are disaplayed
only if certificate is added from certificate search facet.

Certificate search facet allows to add a certificate.

User details facet allows to add a certificate.

part of
https://fedorahosted.org/freeipa/ticket/5046
---
 install/ui/src/freeipa/certificate.js | 137 +++++++++++++++++++++++++++-------
 install/ui/src/freeipa/host.js        |   6 +-
 install/ui/src/freeipa/service.js     |   6 +-
 install/ui/src/freeipa/user.js        |  45 +++++++++--
 install/ui/test/data/ipa_init.json    |   4 +-
 ipalib/plugins/internal.py            |   4 +-
 6 files changed, 168 insertions(+), 34 deletions(-)

diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js
index 28d0407db319a4b72f0021c7d10a30418c2e498f..71f0dfbf54540318e7ae84cea549a7a00253b3e2 100755
--- a/install/ui/src/freeipa/certificate.js
+++ b/install/ui/src/freeipa/certificate.js
@@ -21,6 +21,7 @@
 
 define([
     'dojo/_base/lang',
+    './builder',
     './metadata',
     './ipa',
     './jquery',
@@ -30,7 +31,9 @@ define([
     './rpc',
     './text',
     './dialog'],
-        function(lang, metadata_provider, IPA, $, menu, phases, reg, rpc, text) {
+    function(
+        lang, builder, metadata_provider, IPA, $, menu,
+        phases, reg, rpc, text) {
 
 var exp = IPA.cert = {};
 
@@ -395,11 +398,42 @@ IPA.cert.request_dialog = function(spec) {
 
     spec = spec || {};
 
+    spec.sections = spec.sections || [];
+    var section = { fields: [] };
+    spec.sections.push(section);
+
+    if (spec.show_principal) {
+        section.fields.push(
+            {
+                $type: 'text',
+                name: 'principal',
+                label: '@mc-opt:cert_request:principal:label',
+                required: true
+            },
+            {
+                $type: 'checkbox',
+                name: 'add',
+                label: '@i18n:objects.cert.add_principal',
+                tooltip: '@mc-opt:cert_request:add:doc'
+            }
+        );
+    }
+    section.fields.push(
+        {
+            $type: 'entity_select',
+            name: 'profile_id',
+            other_entity: 'certprofile',
+            other_field: 'cn',
+            label: '@mc-opt:cert_request:profile_id:label'
+        }
+    );
+
     var that = IPA.dialog(spec);
 
     that.width = spec.width || 600;
     that.height = spec.height || 480;
     that.message = text.get(spec.message);
+    that.show_principal = spec.show_principal;
 
     that.request = spec.request;
 
@@ -408,8 +442,10 @@ IPA.cert.request_dialog = function(spec) {
         label: '@i18n:buttons.issue',
         click: function() {
             var values = {};
+            that.save(values);
             var request = $.trim(that.textarea.val());
             values.request = IPA.cert.pem_csr_format(request);
+
             if (that.request) {
                 that.request(values);
             }
@@ -426,11 +462,16 @@ IPA.cert.request_dialog = function(spec) {
     });
 
     that.create_content = function() {
-        that.container.append(that.message);
-
+        that.dialog_create_content();
+        var node = $("<div/>", {
+            'class': 'col-sm-12'
+        });
+        node.append(that.message);
         that.textarea = $('<textarea/>', {
             'class': 'certificate'
-        }).appendTo(that.container);
+        }).appendTo(node);
+        that.body_node.append(node);
+        return that.body_node;
     };
 
     return that;
@@ -444,10 +485,13 @@ IPA.cert.loader = function(spec) {
     that.get_pkey = spec.get_pkey;
     that.get_name = spec.get_name;
     that.get_principal = spec.get_principal;
-    that.get_hostname = spec.get_hostname;
+    that.get_cn = spec.get_cn;
+    that.get_cn_name = spec.get_cn_name;
+    that.adapter = builder.build('adapter', spec.adapter || 'adapter', {});
 
-    that.load = function (result) {
+    that.load = function (data) {
 
+        var result = that.adapter.get_record(data);
         var certificate = {
             issuer: result.issuer,
             certificate: result.certificate,
@@ -474,7 +518,8 @@ IPA.cert.loader = function(spec) {
         if (that.get_pkey) info.pkey = that.get_pkey(result);
         if (that.get_name) info.name = that.get_name(result);
         if (that.get_principal) info.principal = that.get_principal(result);
-        if (that.get_hostname) info.hostname = that.get_hostname(result);
+        if (that.get_cn_name) info.cn_name = that.get_cn_name(result);
+        if (that.get_cn) info.cn = that.get_cn(result);
 
         certificate.entity_info = info;
 
@@ -492,7 +537,9 @@ IPA.cert.load_policy = function(spec) {
         get_pkey: spec.get_pkey,
         get_name: spec.get_name,
         get_principal: spec.get_principal,
-        get_hostname: spec.get_hostname
+        get_cn: spec.get_cn,
+        get_cn_name: spec.get_cn_name,
+        adapter: spec.adapter
     };
 
     var that = IPA.facet_policy();
@@ -502,7 +549,7 @@ IPA.cert.load_policy = function(spec) {
     that.post_load = function(data) {
 
         // update cert info in facet (show at least something)
-        var certificate = that.loader.load(data.result.result);
+        var certificate = that.loader.load(data);
 
         //store cert directly to facet. FIXME: introduce concept of models
         that.container.certificate = certificate;
@@ -518,6 +565,8 @@ IPA.cert.load_policy = function(spec) {
     };
 
     that.load_revocation_reason = function(serial_number) {
+        if (serial_number === null || serial_number === undefined) return;
+
         rpc.command({
             entity: 'cert',
             method: 'show',
@@ -622,41 +671,59 @@ IPA.cert.request_action = function(spec) {
 
     var that = IPA.action(spec);
     that.entity_label = spec.entity_label;
+    that.generic = spec.generic !== undefined ? spec.generic : false;
 
     that.execute_action = function(facet) {
 
-        var certificate = facet.certificate;
-        if (!certificate) facet.refresh();
+        var entity_principal = null;
+        var cn_name = 'common name';
+        var cn = '&ltcommon name&gt';
+        var title = text.get('@i18n:objects.cert.issue_certificate_generic');
+        if (!that.generic) {
+            var certificate = facet.certificate;
+            if (!certificate) facet.refresh();
 
-        var entity_principal = certificate.entity_info.principal;
-        var entity_label = that.entity_label || facet.entity.metadata.label_singular;
-        var entity_name = certificate.entity_info.name;
-        var hostname = certificate.entity_info.hostname;
+            var entity_label = that.entity_label || facet.entity.metadata.label_singular;
 
-        var title = text.get('@i18n:objects.cert.issue_certificate');
-        title = title.replace('${entity}', entity_label);
-        title = title.replace('${primary_key}', entity_name);
+            entity_principal = certificate.entity_info.principal;
+            var entity_name = certificate.entity_info.name;
+            cn = certificate.entity_info.cn || cn;
+            cn_name = certificate.entity_info.cn_name || cn_name;
+
+            title = text.get('@i18n:objects.cert.issue_certificate');
+            title = title.replace('${entity}', entity_label);
+            title = title.replace('${primary_key}', entity_name);
+        }
 
         var request_message = text.get('@i18n:objects.cert.request_message');
-        request_message = request_message.replace(/\$\{hostname\}/g, hostname);
+        request_message = request_message.replace(/\$\{cn_name\}/g, cn_name);
+        request_message = request_message.replace(/\$\{cn\}/g, cn);
         request_message = request_message.replace(/\$\{realm\}/g, IPA.env.realm);
 
         var dialog = IPA.cert.request_dialog({
             title: title,
             message: request_message,
+            show_principal: !entity_principal,
             request: function(values) {
 
+                var options = {
+                    'principal': entity_principal
+                };
+                if (values.profile_id) options.profile_id = values.profile_id[0];
+                if (values.principal) options.principal = values.principal[0];
+                if (values.add) options.add = values.add[0];
+
                 rpc.command({
                     entity: 'cert',
                     method: 'request',
                     args: [values.request],
-                    options: {
-                        'principal': entity_principal
-                    },
+                    options: options,
                     on_success: function(data, text_status, xhr) {
                         facet.refresh();
                         IPA.notify_success('@i18n:objects.cert.requested');
-                        facet.certificate_updated.notify([], that.facet);
+                        if (facet.certificate_updated) {
+                            facet.certificate_updated.notify([], that.facet);
+                        }
                     }
                 }).execute();
             }
@@ -1052,6 +1119,12 @@ return {
             source_facet: 'details',
             dest_entity: 'service',
             dest_facet: 'details'
+        },
+        {
+            $factory: IPA.cert.cert_update_policy,
+            source_facet: 'details',
+            dest_entity: 'user',
+            dest_facet: 'details'
         }
     ],
     enable_test: function() {
@@ -1080,6 +1153,20 @@ return {
                     width: '120px'
                 }
             ],
+            control_buttons: [
+                 {
+                    name: 'request_cert',
+                    label: '@i18n:buttons.issue',
+                    icon: 'fa-plus'
+                }
+            ],
+            actions: [
+                {
+                    $type: 'cert_request',
+                    enable_cond: [],
+                    generic: true
+                }
+            ],
             search_options:  [
                 {
                     value: 'subject',
@@ -1322,8 +1409,6 @@ exp.register = function() {
     var f = reg.field;
     var a = reg.action;
 
-    e.register({type: 'cert', spec: exp.entity_spec});
-
     w.register('certificate_status', IPA.cert.status_widget);
     f.register('certificate_status', IPA.cert.status_field);
 
@@ -1335,6 +1420,8 @@ exp.register = function() {
     a.register('cert_request', IPA.cert.request_action);
     a.register('cert_revoke', IPA.cert.revoke_action);
     a.register('cert_restore', IPA.cert.restore_action);
+
+    e.register({type: 'cert', spec: exp.entity_spec});
 };
 
 phases.on('registration', exp.register);
diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js
index 1120c82e708f20081ee9ec5f5c1b4c349d101b15..17fe423e51394859216bb280298514717bd120f5 100644
--- a/install/ui/src/freeipa/host.js
+++ b/install/ui/src/freeipa/host.js
@@ -912,7 +912,11 @@ IPA.host.certificate_policy = function(spec) {
         return values ? values[0] : null;
     };
 
-    spec.get_hostname = spec.get_hostname || spec.get_name;
+    spec.get_cn = spec.get_cn || spec.get_name;
+
+    spec.get_cn_name = spec.get_cn_name || function(result) {
+        return "hostname";
+    };
 
     var that = IPA.cert.load_policy(spec);
     return that;
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index 5c28e939dedf0986d969afeeb6cff00f856bea8e..5b469b5e1091e63ecc8c5c9b570541c57c54ceaa 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -554,7 +554,7 @@ IPA.service.certificate_policy = function(spec) {
 
     spec.get_principal = spec.get_principal || get_pkey;
 
-    spec.get_hostname = spec.get_hostname || function(result) {
+    spec.get_cn = spec.get_cn || function(result) {
         var value = get_pkey(result);
         if (value) {
             value = value.replace(/@.*$/, '').replace(/^.*\//, '');
@@ -562,6 +562,10 @@ IPA.service.certificate_policy = function(spec) {
         return value;
     };
 
+    spec.get_cn_name = spec.get_cn_name || function(result) {
+        return "hostname";
+    };
+
     var that = IPA.cert.load_policy(spec);
     return that;
 };
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index bf84ba3ac194e7ff7e172f70475a726ca6607a9c..33bc6ec10a8c7e286341693c01852304362610f4 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -340,9 +340,16 @@ return {
                     name: 'automember_rebuild',
                     hide_cond: ['preserved-user'],
                     label: '@i18n:actions.automember_rebuild'
+                },
+                {
+                    $type: 'cert_request',
+                    hide_cond: ['preserved-user']
                 }
             ],
-            header_actions: ['reset_password', 'enable', 'disable', 'delete', 'unlock', 'add_otptoken', 'automember_rebuild'],
+            header_actions: [
+                'reset_password', 'enable', 'disable', 'delete',
+                'unlock', 'add_otptoken', 'automember_rebuild', 'request_cert'
+            ],
             state: {
                 evaluators: [
                     {
@@ -358,7 +365,8 @@ return {
                         attribute: 'userpassword'
                     },
                     IPA.user.self_service_other_user_evaluator,
-                    IPA.user.preserved_user_evaluator
+                    IPA.user.preserved_user_evaluator,
+                    IPA.cert.certificate_evaluator
                 ],
                 summary_conditions: [
                     {
@@ -372,7 +380,8 @@ return {
                 ]
             },
             policies: [
-                IPA.user.preserved_user_policy
+                IPA.user.preserved_user_policy,
+                IPA.user.certificate_policy
             ]
         },
         {
@@ -451,11 +460,13 @@ return {
     }
 };};
 
-IPA.user.details_facet = function(spec) {
+IPA.user.details_facet = function(spec, no_init) {
 
     spec = spec || {};
 
-    var that = IPA.details_facet(spec);
+    var that = IPA.details_facet(spec, true);
+    that.certificate_loaded = IPA.observer();
+    that.certificate_updated = IPA.observer();
 
     that.create_refresh_command = function() {
 
@@ -513,6 +524,8 @@ IPA.user.details_facet = function(spec) {
         return batch;
     };
 
+    if (!no_init) that.init_details_facet();
+
     return that;
 };
 
@@ -703,6 +716,28 @@ IPA.user.add_otptoken_action = function(spec) {
     return that;
 };
 
+IPA.user.certificate_policy = function(spec) {
+
+    spec = spec || {};
+
+    function get_pkey(result) {
+        var values = result.uid;
+        return values ? values[0] : null;
+    }
+
+    spec.adapter = { result_index: 0 };
+    spec.get_pkey = spec.get_pkey || get_pkey;
+    spec.get_name = spec.get_name || get_pkey;
+    spec.get_principal = spec.get_principal || get_pkey;
+    spec.get_cn = spec.get_cn || get_pkey;
+    spec.get_cn_name = spec.get_cn_name || function(result) {
+        return "uid";
+    };
+
+    var that = IPA.cert.load_policy(spec);
+    return that;
+};
+
 IPA.user.self_service_other_user_evaluator = function(spec) {
 
     spec = spec || {};
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index f253c57fe80dc0846b25cfea8402ad7353e8da28..21b12f14411d4f4d2f79a325d0b7c6071e12e193 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -218,6 +218,7 @@
                         },
                         "cert": {
                             "aa_compromise": "AA Compromise",
+                            "add_principal": "Add principal",
                             "affiliation_changed": "Affiliation Changed",
                             "ca_compromise": "CA Compromise",
                             "certificate": "Certificate",
@@ -240,6 +241,7 @@
                             "find_validnotbefore_from": "Valid not before from",
                             "find_validnotbefore_to": "Valid not before to",
                             "get_certificate": "Get Certificate",
+                            "issue_certificate_generic": "Issue New Certificate",
                             "issue_certificate": "Issue New Certificate for ${entity} ${primary_key}",
                             "issued_by": "Issued By",
                             "issued_on": "Issued On",
@@ -254,7 +256,7 @@
                             "privilege_withdrawn": "Privilege Withdrawn",
                             "reason": "Reason for Revocation",
                             "remove_from_crl": "Remove from CRL",
-                            "request_message": "<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;hostname&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${hostname},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>",
+                            "request_message": "<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;${cn_name}&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${cn},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>",
                             "requested": "Certificate requested",
                             "restore_certificate": "Restore Certificate for ${entity} ${primary_key}",
                             "restore_certificate_simple": "Restore Certificate",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 653d866da509dd2cfb4d013850f797f8ef1d4fb4..ae019e7ef8fc7cca0d36338730fe7818ab8d4021 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -362,6 +362,7 @@ class i18n_messages(Command):
             },
             "cert": {
                 "aa_compromise": _("AA Compromise"),
+                "add_principal": _("Add principal"),
                 "affiliation_changed": _("Affiliation Changed"),
                 "ca_compromise": _("CA Compromise"),
                 "certificate": _("Certificate"),
@@ -385,6 +386,7 @@ class i18n_messages(Command):
                 "fingerprints": _("Fingerprints"),
                 "get_certificate": _("Get Certificate"),
                 "issue_certificate": _("Issue New Certificate for ${entity} ${primary_key}"),
+                "issue_certificate_generic": _("Issue New Certificate"),
                 "issued_by": _("Issued By"),
                 "issued_on": _("Issued On"),
                 "issued_to": _("Issued To"),
@@ -398,7 +400,7 @@ class i18n_messages(Command):
                 "privilege_withdrawn": _("Privilege Withdrawn"),
                 "reason": _("Reason for Revocation"),
                 "remove_from_crl": _("Remove from CRL"),
-                "request_message": _("<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;hostname&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${hostname},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>"),
+                "request_message": _("<ol> <li>Create a certificate database or use an existing one. To create a new database:<br/> <code># certutil -N -d &lt;database path&gt;</code> </li> <li>Create a CSR with subject <em>CN=&lt;${cn_name}&gt;,O=&lt;realm&gt;</em>, for example:<br/> <code># certutil -R -d &lt;database path&gt; -a -g &lt;key size&gt; -s 'CN=${cn},O=${realm}'</code> </li> <li> Copy and paste the CSR (from <em>-----BEGIN NEW CERTIFICATE REQUEST-----</em> to <em>-----END NEW CERTIFICATE REQUEST-----</em>) into the text area below: </li> </ol>"),
                 "requested": _("Certificate requested"),
                 "restore_certificate": _("Restore Certificate for ${entity} ${primary_key}"),
                 "restore_certificate_simple": _("Restore Certificate"),
-- 
2.4.3

-- 
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