commit 586f1573c3193f047668082e75da9d823602ae21
Author: Jan Pašek <janpasek97@gmail.com>
Date:   Mon May 3 10:07:49 2021 +0200

    Re #8706 - Downloading PKCS#12 identity

diff --git a/static/certificate.html b/static/certificate.html
index 482c118..85dc3d6 100644
--- a/static/certificate.html
+++ b/static/certificate.html
@@ -226,7 +226,7 @@
                         <table class="table">
                             <thead class="thead-dark">
                                 <tr>
-                                    <th colspan="4" class="text-center">Manage certificate</th>
+                                    <th colspan="5" class="text-center">Manage certificate</th>
                                 </tr>
                             </thead>
                             <tbody>
@@ -237,10 +237,10 @@
                                     <td><button v-on:click="onRootDownload()" class="btn btn-primary btn-sm certificate-control" href="">Root</button></td>
                                 </tr>
                                 <tr class="d-flex">
-                                    <td style="width: 30%" class="font-weight-bold">Key download:</td>
+                                    <td style="width: 30%" class="font-weight-bold">Key/Identity download:</td>
                                     <td><button v-on:click="onPublicKeyDownload()" class="btn btn-success btn-sm certificate-control" href="">Public key</button></td>
                                     <td><button v-on:click="onPrivateKeyDownload()" class="btn btn-success btn-sm certificate-control" href="">Private key</button></td>
-                                    <td> </td>
+                                    <td><button data-toggle="modal" data-target="#identityModal" class="btn btn-success btn-sm certificate-control" href="">PKCS #12</button></td>
                                 </tr>
                                 <tr class="d-flex">
                                     <td style="width: 30%" class="font-weight-bold">Actions:</td>
@@ -283,6 +283,33 @@
                 </div>
             </div>
         </div>
+        <div id="identityModal" class="modal" tabindex="-1" role="dialog">
+            <div class="modal-dialog" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title">Create identity</h5>
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                            <span aria-hidden="true">&times;</span>
+                        </button>
+                    </div>
+                    <div class="modal-body">
+                        <p>Enter identity name and password:</p>
+                        <div class="form-group">
+                            <label for="reasonSelect">Name: </label>
+                            <input v-model="identityName" type="text" class="form-control">
+                        </div>
+                        <div class="form-group">
+                            <label for="reasonSelect">Password: </label>
+                            <input v-model="identityPass" type="password" class="form-control">
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" v-on:click="onIdentityDownload" class="btn btn-primary" data-dismiss="modal">Create</button>
+                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+                    </div>
+                </div>
+            </div>
+        </div>
         <div id="revokeModal" class="modal" tabindex="-1" role="dialog">
             <div class="modal-dialog" role="document">
                 <div class="modal-content">
diff --git a/static/js/certificate.js b/static/js/certificate.js
index 12cb3fe..0b7febd 100644
--- a/static/js/certificate.js
+++ b/static/js/certificate.js
@@ -12,6 +12,8 @@ var certificateDetailsApp = new Vue({
         issuerLoaded: false,
         revocationReason: "unspecified",
         issuedCertificates: [],
+        identityName: "",
+        identityPass: "",
         certificate: {
             subject: {
                 C: "",
@@ -112,6 +114,16 @@ var certificateDetailsApp = new Vue({
         onPrivateKeyDownload: async function () {
             await onPrivateKeyDownload(this.id);
         },
+        onIdentityDownload: async function() {
+            this.errorMessage = "";
+            if (this.identityName === "") {
+                this.errorMessage = "Identity name must not be empty! Please try again.";
+                document.body.scrollTop = 0;
+                document.documentElement.scrollTop = 0;
+                return;
+            }
+            await onIdentityDownload(this.id, this.identityName, this.identityPass);
+        },
         onRevoke: async function () {
             document.body.scrollTop = 0;
             document.documentElement.scrollTop = 0;
diff --git a/static/js/utilities.js b/static/js/utilities.js
index 1c93a31..381a68c 100644
--- a/static/js/utilities.js
+++ b/static/js/utilities.js
@@ -105,4 +105,26 @@ async function onPrivateKeyDownload(id) {
     } catch (error) {
         console.log(error);
     }
+}
+
+/**
+ * Download identity given by certificate id, name and password
+ * @param id identifier of certificate to be used for creating the identity
+ * @param name name of the resulting identity
+ * @param passphrase password protecting the identity
+ */
+async function onIdentityDownload(id, name, passphrase) {
+    try {
+        var identityData = {
+            name: name,
+            password: passphrase
+        }
+        const response = await axios.post(API_URL + "certificates/" + id + "/identity", identityData);
+        if (response.data["success"]) {
+            download(name + ".p12", response.data["data"])
+        } else
+            console.log("Error occurred while downloading the identity") // TODO more action may be required
+    } catch (error) {
+        console.log(error);
+    }
 }
\ No newline at end of file
