From 310505e82c4097294a26a0492b1ca61cb4dda13d Mon Sep 17 00:00:00 2001
From: Frank Sauerburger <frank@sauerburger.com>
Date: Sat, 20 Feb 2021 16:06:26 +0100
Subject: [PATCH] Add ssh key add view

---
 ssh/forms.py                               | 31 ++++++++++++++++++
 ssh/templates/ssh/sshpublickey_create.html | 11 +++++++
 ssh/templates/ssh/sshpublickey_list.html   |  5 +++
 ssh/urls.py                                |  2 +-
 ssh/views.py                               | 37 +++++++++++++++++++---
 5 files changed, 81 insertions(+), 5 deletions(-)
 create mode 100644 ssh/forms.py
 create mode 100644 ssh/templates/ssh/sshpublickey_create.html

diff --git a/ssh/forms.py b/ssh/forms.py
new file mode 100644
index 0000000..962146d
--- /dev/null
+++ b/ssh/forms.py
@@ -0,0 +1,31 @@
+
+import re
+from django import forms
+from django.core.exceptions import ValidationError
+
+class KeyStringField(forms.CharField):
+    def __init__(self, *args, **kwds):
+        kwds["widget"] = forms.Textarea
+        super().__init__(*args, **kwds)
+
+    def to_python(self, value):
+        """Split keystring on whitespace"""
+        if not value:
+            return []
+
+        return re.split("\s+", value)
+
+    def validate(self, value):
+        """Check if there are at least two tokens"""
+        super().validate(value)
+        if len(value) < 2:
+            raise ValidationError("KeyString needs type and key part")
+
+    
+
+class PublicKeyCreateForm(forms.Form):
+    keystring = KeyStringField()
+    hostname = forms.CharField(max_length=128)
+    port = forms.IntegerField(required=False)
+    client_cert = forms.BooleanField(required=False)
+    public = forms.BooleanField(required=False)
diff --git a/ssh/templates/ssh/sshpublickey_create.html b/ssh/templates/ssh/sshpublickey_create.html
new file mode 100644
index 0000000..7334027
--- /dev/null
+++ b/ssh/templates/ssh/sshpublickey_create.html
@@ -0,0 +1,11 @@
+{% extends 'keys/base.html' %}
+
+{% block content %}
+<h2>Add public key</h2>
+<form action="" method="post">
+  {% csrf_token %}
+  {{ form.as_p }}
+  <button type="submit">Add</button>
+</form>
+
+{% endblock %}
diff --git a/ssh/templates/ssh/sshpublickey_list.html b/ssh/templates/ssh/sshpublickey_list.html
index 478fd57..0f6195d 100644
--- a/ssh/templates/ssh/sshpublickey_list.html
+++ b/ssh/templates/ssh/sshpublickey_list.html
@@ -1,6 +1,11 @@
 {% extends 'keys/base.html' %}
 
 {% block content %}
+
+{% if perms.ssh.add_sshpublickey %}
+<a href="{% url 'ssh-create' %}">Add public key</a>
+{% endif %}
+
 {% if sshpublickey_list %}
 <ul>
 {% for publickey in sshpublickey_list %}
diff --git a/ssh/urls.py b/ssh/urls.py
index 409a872..8e1257d 100644
--- a/ssh/urls.py
+++ b/ssh/urls.py
@@ -5,5 +5,5 @@ from . import views
 
 urlpatterns = [
     path("", views.PublicKeyListView.as_view(), name="ssh-list"),
-    path("<int:pk>", views.PublicKeyDetailView.as_view(), name="ssh-detail"),
+    path("new", views.publickey_create, name="ssh-create"),
 ]
diff --git a/ssh/views.py b/ssh/views.py
index 9725af4..3a8cd2b 100644
--- a/ssh/views.py
+++ b/ssh/views.py
@@ -1,14 +1,43 @@
-from django.shortcuts import render
+from django.shortcuts import render, reverse
 from django.views.generic import DetailView, ListView, CreateView
+from django.http import HttpResponseRedirect
 from guardian.mixins import PermissionRequiredMixin, PermissionListMixin
+from guardian.decorators import permission_required
+from guardian.shortcuts import assign_perm
+from guardian.utils import get_anonymous_user
 from . import models
+from . import forms
 
 
 class PublicKeyListView(PermissionListMixin, ListView):
     model = models.SSHPublicKey
     permission_required = ['view_sshpublickey']
 
-class PublicKeyDetailView(PermissionRequiredMixin, DetailView):
-    model = models.SSHPublicKey
-    permission_required = ['view_sshpublickey']
+@permission_required('ssh.add_sshpublickey')
+def publickey_create(request):
+    if request.method == 'POST':
+        form = forms.PublicKeyCreateForm(request.POST)
+        if form.is_valid():
+            pk = models.SSHPublicKey()
+            pk.hostname = form.cleaned_data['hostname']
+            pk.port = form.cleaned_data['port']
+            pk.client_cert = form.cleaned_data['client_cert']
+            pk.keytype, pk.key = form.cleaned_data['keystring'][:2]
+            pk.save()
+
+            assign_perm('view_sshpublickey', request.user, pk)
+            assign_perm('change_sshpublickey', request.user, pk)
+
+            if form.cleaned_data['public']:
+                assign_perm('view_sshpublickey',
+                            get_anonymous_user(),
+                            pk)
+            return HttpResponseRedirect(reverse('ssh-list'))
+
+    # if a GET (or any other method) we'll create a blank form
+    else:
+        form = forms.PublicKeyCreateForm()
 
+    return render(request,
+                  'ssh/sshpublickey_create.html',
+                  {'form': form})
-- 
GitLab