From 51851c1a007b82eb73987f6ce476455e63a3b7f5 Mon Sep 17 00:00:00 2001
From: Frank Sauerburger <frank@sauerburger.com>
Date: Tue, 23 Feb 2021 16:24:11 +0100
Subject: [PATCH] Redesign with SSH detail view

---
 keys/settings.py                           |  2 +-
 keys_home/static/keys_home/css/main.css    |  2 +-
 ssh/templates/ssh/sshpublickey_detail.html | 82 ++++++++++++++++++++++
 ssh/templates/ssh/sshpublickey_list.html   | 63 ++++++-----------
 ssh/urls.py                                |  5 +-
 ssh/views.py                               |  5 ++
 6 files changed, 113 insertions(+), 46 deletions(-)
 create mode 100644 ssh/templates/ssh/sshpublickey_detail.html

diff --git a/keys/settings.py b/keys/settings.py
index 9585f93..a73c2a3 100644
--- a/keys/settings.py
+++ b/keys/settings.py
@@ -24,7 +24,7 @@ SECRET_KEY = 'mye*a(w-z-x_5+f$%5gvr$6&$pp_u=jkd3ad2--kaxg_bb(e$e'
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
 
-ALLOWED_HOSTS = []
+ALLOWED_HOSTS = ["*"]
 
 
 # Application definition
diff --git a/keys_home/static/keys_home/css/main.css b/keys_home/static/keys_home/css/main.css
index 5eb36bf..de54f73 100644
--- a/keys_home/static/keys_home/css/main.css
+++ b/keys_home/static/keys_home/css/main.css
@@ -36,7 +36,7 @@ body {
     margin-top: 3rem !important;
     margin-bottom: 3rem !important;
 }
-.mainlist a:hover {
+a:hover {
     text-decoration: none;
 }
 
diff --git a/ssh/templates/ssh/sshpublickey_detail.html b/ssh/templates/ssh/sshpublickey_detail.html
new file mode 100644
index 0000000..ae9299b
--- /dev/null
+++ b/ssh/templates/ssh/sshpublickey_detail.html
@@ -0,0 +1,82 @@
+{% extends 'keys_home/base.html' %}
+
+{% block content %}
+
+  <nav class="d-md-block d-none" aria-label="breadcrumb">
+    <ol class="breadcrumb">
+      <li class="breadcrumb-item"><a href="{% url 'home' %}">Home</a></li>
+      <li class="breadcrumb-item"><a href="{% url 'ssh-list' %}">SSH Keys</a></li>
+      <li class="breadcrumb-item active" aria-current="page">
+        <a href="{% url 'ssh-detail' publickey.pk %}">{{ publickey.server }}</a>
+      </li>
+    </ol>
+  </nav>
+
+    <div class="border my-3 rounded">
+      <h3 class="bg-dark mb-0 text-light p-2 rounded-top d-flex justify-content-between">
+        <div>
+        {% if publickey.client_cert %}
+          <i class="fas fa-user mx-2" title="Client key"></i>
+        {% else %}
+          <i class="fas fa-server mx-2" title="Host key"></i>
+        {% endif %}
+        {{ publickey.server }}
+        </div>
+        <div class="text-muted d-none d-md-block"><small>
+          {{ publickey.key_algo }}{% if publickey.key_length %}, {{ publickey.key_length}} bits {% endif %}
+        </small></div>
+      </h3>
+      <div class="px-4 py-2 border-bottom bg-light">
+        <div class="text-muted mb-1">
+          <i class="fas fa-fingerprint mr-1"></i> Fingerprint
+          {% if not publickey.client_cert %}<small>compare on first connect</small>{% endif %}
+        </div>
+
+        <div class="input-group mb-2">
+          <input style="background-color: inherit" title="SHA256 fingerprint" type="text" class="form-control" readonly value="{{publickey.fingerprint_sha256 }}" />
+          <div class="input-group-append">
+            <div class="input-group-text">Base64 â—¦ SHA256</div>
+          </div>
+        </div>
+        <div class="input-group mb-2">
+          <input style="background-color: inherit" title="MD5 fingerprint" type="text" class="form-control" readonly value="{{publickey.fingerprint_md5 }}" />
+          <div class="input-group-append">
+            <div class="input-group-text">Hex â—¦ MD5</div>
+          </div>
+        </div>
+      </div>
+      <div class="px-4 py-2 border-bottom">
+        <div class="d-lg-flex mb-1 justify-content-between">
+          <div class="text-muted">
+            <i class="fas fa-key mr-1"></i> Public key (OpenSSH)
+            {% if publickey.client_cert %}<small>use in <code>.ssh/authorized_keys</code></small>{% endif %}
+          </div>
+          <div>
+            <a href="{% url 'ssh-download-openssh' publickey.pk %}">
+              <i class="fas fa-download mr-1"></i>
+              {{ request.scheme }}://{{ request.get_host}}{% url 'ssh-download-openssh' publickey.pk %}
+            </a>
+          </div>
+        </div>
+        <pre style="white-space: normal; word-break: break-all;">
+            {{ publickey.key_openssh }}
+        </pre>
+      </div>
+      <div class="px-4 py-2">
+        <div class="d-lg-flex mb-1 justify-content-between">
+          <div class="text-muted">
+            <i class="fas fa-key mr-1"></i> Public key (RFC4716)
+            {% if publickey.client_cert %}<small>use in <code>.sftp/authorized_keys</code></small>{% endif %}
+          </div>
+
+          <div>
+            <a href="{% url 'ssh-download-rfc4716' publickey.pk %}">
+              <i class="fas fa-download mr-1"></i>
+              {{ request.scheme }}://{{ request.get_host}}{% url 'ssh-download-rfc4716' publickey.pk %}
+            </a>
+          </div>
+        </div>
+        <pre>{{ publickey.key_rfc4716 }}</pre>
+      </div>
+  </div>
+{% endblock %}
diff --git a/ssh/templates/ssh/sshpublickey_list.html b/ssh/templates/ssh/sshpublickey_list.html
index 1a8824e..1629208 100644
--- a/ssh/templates/ssh/sshpublickey_list.html
+++ b/ssh/templates/ssh/sshpublickey_list.html
@@ -2,6 +2,15 @@
 
 {% block content %}
 
+  <nav class="d-md-block d-none" aria-label="breadcrumb">
+    <ol class="breadcrumb">
+      <li class="breadcrumb-item"><a href="{% url 'home' %}">Home</a></li>
+      <li class="breadcrumb-item active" aria-current="page">
+        <a href="{% url 'ssh-list' %}">SSH Keys</a>
+      </li>
+    </ol>
+  </nav>
+
 <h2 class="d-flex justify-content-between">
   <div>SSH Public Keys</div>
   {% if perms.ssh.add_sshpublickey %}
@@ -15,20 +24,23 @@
 {% if sshpublickey_list %}
 <ul class="list-unstyled">
 {% for publickey in sshpublickey_list %}
-    <li class="border my-4 rounded">
-      <h3 class="bg-dark text-light p-2 rounded-top d-lg-flex justify-content-between">
+    <li class="border my-3 rounded position-relative">
+      <h3 class="bg-dark mb-0 text-light p-2 rounded-top d-flex justify-content-between">
         <div>
-        {% if publickey.client_cert %}
-          <i class="fas fa-user mx-2" title="Client key"></i> {{ publickey.server }}
-        {% else %}
-          <i class="fas fa-server mx-2" title="Host key"></i> {{ publickey.server }}
-        {% endif %}
+          <a class="text-light stretched-link" href="{% url 'ssh-detail' publickey.pk %}">
+            {% if publickey.client_cert %}
+              <i class="fas fa-user mx-2" title="Client key"></i>
+            {% else %}
+              <i class="fas fa-server mx-2" title="Host key"></i>
+            {% endif %}
+            {{ publickey.server }}
+          </a>
         </div>
-        <div style="text-muted"><small>
+        <div class="text-muted d-none d-md-block"><small>
           {{ publickey.key_algo }}{% if publickey.key_length %}, {{ publickey.key_length}} bits {% endif %}
         </small></div>
       </h3>
-      <div class="px-4 py-2 border-bottom bg-light">
+      <div class="px-4 py-2 bg-light rounded">
         <div class="text-muted mb-1">
           <i class="fas fa-fingerprint mr-1"></i> Fingerprint
           {% if not publickey.client_cert %}<small>compare on first connect</small>{% endif %}
@@ -47,39 +59,6 @@
           </div>
         </div>
       </div>
-      <div class="px-4 py-2 border-bottom">
-        <div class="d-lg-flex mb-1 justify-content-between">
-          <div class="text-muted">
-            <i class="fas fa-key mr-1"></i> Public key (OpenSSH)
-            {% if publickey.client_cert %}<small>use in <code>.ssh/authorized_keys</code></small>{% endif %}
-          </div>
-          <div>
-            <a href="{% url 'ssh-download-openssh' publickey.pk %}">
-              <i class="fas fa-download mr-1"></i>
-              {{ request.scheme }}://{{ request.get_host}}{% url 'ssh-download-openssh' publickey.pk %}
-            </a>
-          </div>
-        </div>
-        <pre style="white-space: normal; word-break: break-all;">
-            {{ publickey.key_openssh }}
-        </pre>
-      </div>
-      <div class="px-4 py-2">
-        <div class="d-lg-flex mb-1 justify-content-between">
-          <div class="text-muted">
-            <i class="fas fa-key mr-1"></i> Public key (RFC4716)
-            {% if publickey.client_cert %}<small>use in <code>.sftp/authorized_keys</code></small>{% endif %}
-          </div>
-
-          <div>
-            <a href="{% url 'ssh-download-rfc4716' publickey.pk %}">
-              <i class="fas fa-download mr-1"></i>
-              {{ request.scheme }}://{{ request.get_host}}{% url 'ssh-download-rfc4716' publickey.pk %}
-            </a>
-          </div>
-        </div>
-        <pre>{{ publickey.key_rfc4716 }}</pre>
-      </div>
   </li>
 {% endfor %}
 </ul>
diff --git a/ssh/urls.py b/ssh/urls.py
index ce0fde0..57dd3d0 100644
--- a/ssh/urls.py
+++ b/ssh/urls.py
@@ -6,8 +6,9 @@ from . import views
 urlpatterns = [
     path("", views.PublicKeyListView.as_view(), name="ssh-list"),
     path("new", views.publickey_create, name="ssh-create"),
-    path("openssh/<int:pk>", views.PublicKeyDownloadOpenSshView.as_view(),
+    path("<int:pk>/", views.PublicKeyDetailView.as_view(), name="ssh-detail"),
+    path("<int:pk>/openssh", views.PublicKeyDownloadOpenSshView.as_view(),
          name="ssh-download-openssh"),
-    path("rfc4716/<int:pk>", views.PublicKeyDownloadRfc4716View.as_view(),
+    path("<int:pk>/rfc4716", views.PublicKeyDownloadRfc4716View.as_view(),
          name="ssh-download-rfc4716"),
 ]
diff --git a/ssh/views.py b/ssh/views.py
index 72224f6..f2434b9 100644
--- a/ssh/views.py
+++ b/ssh/views.py
@@ -42,6 +42,11 @@ def publickey_create(request):
                   'ssh/sshpublickey_create.html',
                   {'form': form})
 
+class PublicKeyDetailView(PermissionRequiredMixin, DetailView):
+    model = models.SSHPublicKey
+    context_object_name = "publickey"
+    permission_required = ['view_sshpublickey']
+
 class PublicKeyDownloadOpenSshView(PermissionRequiredMixin, DetailView):
     model = models.SSHPublicKey
     template_name = "ssh/sshpublickey_download_openssh.html"
-- 
GitLab