From 0c7bb79109f94877b00d97e8eb4ab34a2b5efff5 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Sun, 1 Feb 2015 00:44:31 +0100 Subject: [PATCH] add view osusers.views.AddSshPublicKey - implement new form osusers.forms.AddSshPublicKeyForm - move message texts from osusers.admin to osusers.forms - add new view osusers.views.AddSshPublicKey - add new URL patter 'add_ssh_key' to osusers.urls - add new template osusers/sshpublickey_create.html - link from hosting package detail template to 'add_ssh_key' - add changelog entry for new feature --- docs/changelog.rst | 1 + gnuviechadmin/osusers/admin.py | 8 +-- gnuviechadmin/osusers/forms.py | 69 ++++++++++++++++++- gnuviechadmin/osusers/urls.py | 7 +- gnuviechadmin/osusers/views.py | 52 +++++++++++++- .../customerhostingpackage_detail.html | 1 + .../osusers/sshpublickey_create.html | 30 ++++++++ 7 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 gnuviechadmin/templates/osusers/sshpublickey_create.html diff --git a/docs/changelog.rst b/docs/changelog.rst index 9c7e187..55cbdb4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,7 @@ Changelog ========= +* :feature:`-` add ability to add SSH public keys for operating system users * :support:`-` make tests in osusers.tests work again * :support:`-` minor HTML improvements * :support:`-` add API for gvafile task set_file_ssh_authorized_keys (requires diff --git a/gnuviechadmin/osusers/admin.py b/gnuviechadmin/osusers/admin.py index 95fe0a1..91df5a8 100644 --- a/gnuviechadmin/osusers/admin.py +++ b/gnuviechadmin/osusers/admin.py @@ -12,6 +12,10 @@ from gvawebcore.forms import ( ) from taskresults.models import TaskResult +from .forms import ( + INVALID_SSH_PUBLIC_KEY, + DUPLICATE_SSH_PUBLIC_KEY_FOR_USER, +) from .models import ( AdditionalGroup, Group, @@ -20,10 +24,6 @@ from .models import ( User, ) -INVALID_SSH_PUBLIC_KEY = _('Invalid SSH public key data format.') -DUPLICATE_SSH_PUBLIC_KEY_FOR_USER = _( - 'This SSH public key is already assigned to this user.') - class AdditionalGroupInline(admin.TabularInline): """ diff --git a/gnuviechadmin/osusers/forms.py b/gnuviechadmin/osusers/forms.py index 73faa02..89fb10c 100644 --- a/gnuviechadmin/osusers/forms.py +++ b/gnuviechadmin/osusers/forms.py @@ -13,7 +13,14 @@ from crispy_forms.layout import Submit from gvawebcore.forms import PasswordModelFormMixin -from .models import User +from .models import ( + SshPublicKey, + User, +) + +INVALID_SSH_PUBLIC_KEY = _('Invalid SSH public key data format.') +DUPLICATE_SSH_PUBLIC_KEY_FOR_USER = _( + 'This SSH public key is already assigned to this user.') class ChangeOsUserPasswordForm(PasswordModelFormMixin, forms.ModelForm): @@ -43,3 +50,63 @@ class ChangeOsUserPasswordForm(PasswordModelFormMixin, forms.ModelForm): """ self.instance.set_password(self.cleaned_data['password1']) return super(ChangeOsUserPasswordForm, self).save(commit=commit) + + +class AddSshPublicKeyForm(forms.ModelForm): + """ + A form for creating :py:class:`SSH public keys + `. + + """ + publickeytext = forms.CharField( + label=_('Key text'), widget=forms.Textarea, + help_text=_('A SSH public key in either OpenSSH or RFC 4716 format')) + + class Meta: + model = SshPublicKey + fields = [] + + def __init__(self, *args, **kwargs): + hosting_package = kwargs.pop('hostingpackage') + self.osuser = hosting_package.osuser + super(AddSshPublicKeyForm, self).__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.form_action = reverse( + 'add_ssh_key', kwargs={'package': hosting_package.id}) + self.helper.add_input(Submit('submit', _('Add SSH public key'))) + + def clean_publickeytext(self): + keytext = self.cleaned_data.get('publickeytext') + try: + SshPublicKey.objects.parse_keytext(keytext) + except: + raise forms.ValidationError(INVALID_SSH_PUBLIC_KEY) + return keytext + + def clean(self): + keytext = self.cleaned_data.get('publickeytext') + alg, data, comment = SshPublicKey.objects.parse_keytext(keytext) + if SshPublicKey.objects.filter( + user=self.osuser, algorithm=alg, data=data + ).exists(): + self.add_error( + 'publickeytext', + forms.ValidationError(DUPLICATE_SSH_PUBLIC_KEY_FOR_USER) + ) + + def save(self, commit=True): + """ + Save the provided ssh public key in properly split format. + + :param boolean commit: whether to save the created public key + :return: ssh public key instance + :rtype: :py:class:`osusers.models.SshPublicKey` + + """ + algorithm, keydata, comment = SshPublicKey.objects.parse_keytext( + self.cleaned_data.get('publickeytext')) + self.instance.user = self.osuser + self.instance.algorithm = algorithm + self.instance.data = keydata + self.instance.comment = comment + return super(AddSshPublicKeyForm, self).save(commit) diff --git a/gnuviechadmin/osusers/urls.py b/gnuviechadmin/osusers/urls.py index 7b62056..c2cacf6 100644 --- a/gnuviechadmin/osusers/urls.py +++ b/gnuviechadmin/osusers/urls.py @@ -6,11 +6,16 @@ from __future__ import absolute_import, unicode_literals from django.conf.urls import patterns, url -from .views import SetOsUserPassword +from .views import ( + AddSshPublicKey, + SetOsUserPassword, +) urlpatterns = patterns( '', url(r'^(?P[\w0-9@.+-_]+)/setpassword$', SetOsUserPassword.as_view(), name='set_osuser_password'), + url(r'^(?P\d+)/add-ssh-key$', AddSshPublicKey.as_view(), + name='add_ssh_key'), ) diff --git a/gnuviechadmin/osusers/views.py b/gnuviechadmin/osusers/views.py index a78067a..8d1098a 100644 --- a/gnuviechadmin/osusers/views.py +++ b/gnuviechadmin/osusers/views.py @@ -5,14 +5,24 @@ This module defines the views for gnuviechadmin operating system user handling. from __future__ import unicode_literals, absolute_import from django.shortcuts import redirect -from django.views.generic import UpdateView +from django.views.generic import ( + UpdateView, + CreateView, +) from django.utils.translation import ugettext as _ from django.contrib import messages from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin +from gvawebcore.views import HostingPackageAndCustomerMixin -from .forms import ChangeOsUserPasswordForm -from .models import User +from .forms import ( + AddSshPublicKeyForm, + ChangeOsUserPasswordForm, +) +from .models import ( + SshPublicKey, + User, +) class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView): @@ -43,3 +53,39 @@ class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView): username=osuser.username )) return redirect(osuser.customerhostingpackage) + + +class AddSshPublicKey( + HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, CreateView +): + """ + This view is used to add an SSH key for an existing hosting account's + operating system user. + + """ + model = SshPublicKey + context_object_name = 'key' + template_name_suffix = '_create' + form_class = AddSshPublicKeyForm + + def get_form_kwargs(self): + kwargs = super(AddSshPublicKey, self).get_form_kwargs() + kwargs['hostingpackage'] = self.get_hosting_package() + return kwargs + + def get_context_data(self, **kwargs): + context = super(AddSshPublicKey, self).get_context_data(**kwargs) + context.update({ + 'customer': self.get_customer_object(), + 'osuser': self.get_hosting_package().osuser.username, + }) + return context + + def form_valid(self, form): + key = form.save() + messages.success( + self.request, + _('Successfully added new {algorithm} SSH public key').format( + algorithm=key.algorithm) + ) + return redirect(self.get_hosting_package()) diff --git a/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html b/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html index e66ae9b..2f88bed 100644 --- a/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html +++ b/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html @@ -68,6 +68,7 @@ diff --git a/gnuviechadmin/templates/osusers/sshpublickey_create.html b/gnuviechadmin/templates/osusers/sshpublickey_create.html new file mode 100644 index 0000000..06911ed --- /dev/null +++ b/gnuviechadmin/templates/osusers/sshpublickey_create.html @@ -0,0 +1,30 @@ +{% extends "osusers/base.html" %} +{% load i18n crispy_forms_tags %} + +{% block title %}{{ block.super }} - {% spaceless %} +{% if user == customer %} +{% blocktrans %}Add new SSH Public Key{% endblocktrans %} +{% else %} +{% blocktrans with full_name=customer.get_full_name %}Add a new SSH Public Key for Operating System User {{ osuser }} of Customer {{ full_name }}{% endblocktrans %} +{% endif %} +{% endspaceless %}{% endblock title %} + +{% block page_title %}{% spaceless %} +{% if user == customer %} +{% blocktrans %}Add new SSH Public Key{% endblocktrans %} +{% else %} +{% blocktrans with full_name=customer.get_full_name %}Add a new SSH Public Key for Operating System User {{ osuser }} of Customer {{ full_name }}{% endblocktrans %} +{% endif %} +{% endspaceless %}{% endblock page_title %} + +{% block content %} +{% crispy form %} +{% endblock content %} + +{% block extra_js %} + +{% endblock extra_js %}