add list, delete and edit comment of SSH public keys

- add sshkeys to hostingpackage detail view context
- implement new osusers.forms.EditSshPublicKeyCommentForm
- implement new views ListSshPublicKeys, DeleteSshPublicKey and
  EditSshPublicKeyComment
- add new URL patterns 'list_ssh_keys', 'edit_ssh_key_comment' and
  'delete_ssh_key'
- link from hosting package detail view to 'list_ssh_keys' when there are
  SSH keys assigned to the shown hosting package
- add new templates osusers/sshpublickey_list.html,
  osusers/sshpublickey_confirm_delete.html and
  osusers/sshpublickey_edit_comment
- add operating system user output to template
  osusers/sshpublickey_create.html
- add changelog entry
This commit is contained in:
Jan Dittberner 2015-02-01 01:55:09 +01:00
parent 0c7bb79109
commit 832a611602
10 changed files with 222 additions and 5 deletions

View file

@ -1,6 +1,8 @@
Changelog Changelog
========= =========
* :feature:`-` add ability to add, list and delete SSH public keys assigned to
a hosting package's operating system user and change their comments
* :feature:`-` add ability to add SSH public keys for operating system users * :feature:`-` add ability to add SSH public keys for operating system users
* :support:`-` make tests in osusers.tests work again * :support:`-` make tests in osusers.tests work again
* :support:`-` minor HTML improvements * :support:`-` minor HTML improvements

View file

@ -121,6 +121,7 @@ class CustomerHostingPackageDetails(StaffOrSelfLoginRequiredMixin, DetailView):
'domains': context['hostingpackage'].domains.all(), 'domains': context['hostingpackage'].domains.all(),
'mailboxes': context['hostingpackage'].mailboxes, 'mailboxes': context['hostingpackage'].mailboxes,
}) })
context['sshkeys'] = context['osuser'].sshpublickey_set.all()
return context return context

View file

@ -110,3 +110,25 @@ class AddSshPublicKeyForm(forms.ModelForm):
self.instance.data = keydata self.instance.data = keydata
self.instance.comment = comment self.instance.comment = comment
return super(AddSshPublicKeyForm, self).save(commit) return super(AddSshPublicKeyForm, self).save(commit)
class EditSshPublicKeyCommentForm(forms.ModelForm):
"""
A form for editing :py:class:`SSH public key
<osusers.models.SshPublicKey>` comment fields.
"""
class Meta:
model = SshPublicKey
fields = ['comment']
def __init__(self, *args, **kwargs):
hosting_package = kwargs.pop('hostingpackage')
self.osuser = hosting_package.osuser
super(EditSshPublicKeyCommentForm, self).__init__(*args, **kwargs)
self.fields['comment'].widget = forms.TextInput()
self.helper = FormHelper()
self.helper.form_action = reverse(
'edit_ssh_key_comment',
kwargs={'package': hosting_package.id, 'pk': self.instance.id})
self.helper.add_input(Submit('submit', _('Change Comment')))

View file

@ -8,6 +8,9 @@ from django.conf.urls import patterns, url
from .views import ( from .views import (
AddSshPublicKey, AddSshPublicKey,
DeleteSshPublicKey,
EditSshPublicKeyComment,
ListSshPublicKeys,
SetOsUserPassword, SetOsUserPassword,
) )
@ -16,6 +19,12 @@ urlpatterns = patterns(
'', '',
url(r'^(?P<slug>[\w0-9@.+-_]+)/setpassword$', SetOsUserPassword.as_view(), url(r'^(?P<slug>[\w0-9@.+-_]+)/setpassword$', SetOsUserPassword.as_view(),
name='set_osuser_password'), name='set_osuser_password'),
url(r'^(?P<package>\d+)/add-ssh-key$', AddSshPublicKey.as_view(), url(r'^(?P<package>\d+)/ssh-keys/$', ListSshPublicKeys.as_view(),
name='list_ssh_keys'),
url(r'^(?P<package>\d+)/ssh-keys/add$', AddSshPublicKey.as_view(),
name='add_ssh_key'), name='add_ssh_key'),
url(r'^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/edit-comment$',
EditSshPublicKeyComment.as_view(), name='edit_ssh_key_comment'),
url(r'^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/delete$',
DeleteSshPublicKey.as_view(), name='delete_ssh_key'),
) )

View file

@ -4,10 +4,13 @@ This module defines the views for gnuviechadmin operating system user handling.
""" """
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from django.core.urlresolvers import reverse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.views.generic import ( from django.views.generic import (
UpdateView,
CreateView, CreateView,
DeleteView,
ListView,
UpdateView,
) )
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib import messages from django.contrib import messages
@ -18,6 +21,7 @@ from gvawebcore.views import HostingPackageAndCustomerMixin
from .forms import ( from .forms import (
AddSshPublicKeyForm, AddSshPublicKeyForm,
ChangeOsUserPasswordForm, ChangeOsUserPasswordForm,
EditSshPublicKeyCommentForm,
) )
from .models import ( from .models import (
SshPublicKey, SshPublicKey,
@ -89,3 +93,70 @@ class AddSshPublicKey(
algorithm=key.algorithm) algorithm=key.algorithm)
) )
return redirect(self.get_hosting_package()) return redirect(self.get_hosting_package())
class ListSshPublicKeys(
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, ListView
):
model = SshPublicKey
context_object_name = 'keys'
def get_context_data(self, **kwargs):
context = super(ListSshPublicKeys, self).get_context_data(**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
return context
class DeleteSshPublicKey(
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, DeleteView
):
model = SshPublicKey
context_object_name = 'key'
def get_context_data(self, **kwargs):
context = super(DeleteSshPublicKey, self).get_context_data(**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
return context
def get_success_url(self):
return reverse(
'list_ssh_keys', kwargs={'package': self.get_hosting_package().id}
)
class EditSshPublicKeyComment(
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, UpdateView
):
model = SshPublicKey
context_object_name = 'key'
fields = ['comment']
template_name_suffix = '_edit_comment'
form_class = EditSshPublicKeyCommentForm
def get_form_kwargs(self):
kwargs = super(EditSshPublicKeyComment, self).get_form_kwargs()
kwargs['hostingpackage'] = self.get_hosting_package()
return kwargs
def get_context_data(self, **kwargs):
context = super(EditSshPublicKeyComment, self).get_context_data(
**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
return context
def get_success_url(self):
return reverse(
'list_ssh_keys', kwargs={'package': self.get_hosting_package().id}
)

View file

@ -39,7 +39,7 @@
<dd>{% blocktrans with num=hostingpackage.used_mailbox_count total=hostingpackage.mailbox_count %}{{ num }} of {{ total }} in use{% endblocktrans %} <span class="glyphicon <dd>{% blocktrans with num=hostingpackage.used_mailbox_count total=hostingpackage.mailbox_count %}{{ num }} of {{ total }} in use{% endblocktrans %} <span class="glyphicon
glyphicon-info-sign" title="{% blocktrans with mailboxcount=hostingpackage.mailboxcount %}The package provides {{ mailboxcount }} mailboxes the difference comes from mailbox options.{% endblocktrans %}"></span></dd> glyphicon-info-sign" title="{% blocktrans with mailboxcount=hostingpackage.mailboxcount %}The package provides {{ mailboxcount }} mailboxes the difference comes from mailbox options.{% endblocktrans %}"></span></dd>
<dt>{% if osuser.is_sftp_user %}{% trans "SFTP username" %}{% else %}{% trans "SSH/SFTP username" %}{% endif %}</dt> <dt>{% if osuser.is_sftp_user %}{% trans "SFTP username" %}{% else %}{% trans "SSH/SFTP username" %}{% endif %}</dt>
<dd>{{ osuser.username }}</dd> <dd>{{ osuser.username }}{% if sshkeys %} <a href="{% url 'list_ssh_keys' package=hostingpackage.id %}" class="badge" title="{% blocktrans count counter=sshkeys|length %}There is an SSH public key set for this user.{% plural %}There are {{ counter }} SSH public keys set for this user.{% endblocktrans %}"><i class="fa fa-key"></i> {{ sshkeys|length }}</a>{% endif %}</dd>
<dt>{% trans "Upload server" %}</dt> <dt>{% trans "Upload server" %}</dt>
<dd>{{ uploadserver }}</dd> <dd>{{ uploadserver }}</dd>
</dl> </dl>

View file

@ -0,0 +1,35 @@
{% extends "osusers/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %}
{% blocktrans %}Delete SSH Public Key for Operating System User {{ osuser }}{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}Delete 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 %}Delete SSH Public Key <small>for Operating System User {{ osuser }}</small>{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}Delete SSH Public Key <small>for Operating System User {{ osuser }} of Customer {{ full_name }}</small>{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock page_title %}
{% block content %}
<div class="panel panel-warning">
<div class="panel-heading">
{% blocktrans with algorithm=key.algorithm %}Do you really want to delete the {{ algorithm }} SSH public key?{% endblocktrans %}
</div>
<div class="panel-body form">
<p >{% blocktrans %}When you confirm the deletion of this key you will no longer be able to use the corresponding private key for authentication.{% endblocktrans %}</p>
<pre>{{ key }}</pre>
<form action="{% url 'delete_ssh_key' package=hostingpackage.id pk=key.id %}" method="post">
{% csrf_token %}
<input class="btn btn-warning" type="submit" value="{% trans "Yes, do it!" %}" />
<a class="btn btn-default" href="{% url 'list_ssh_keys' package=hostingpackage.id %}" title="{% trans "Cancel and go back to the SSH key list" %}">{% trans "Cancel" %}</a>
</form>
</div>
</div>
{% endblock content %}

View file

@ -3,7 +3,7 @@
{% block title %}{{ block.super }} - {% spaceless %} {% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %} {% if user == customer %}
{% blocktrans %}Add new SSH Public Key{% endblocktrans %} {% blocktrans %}Add new SSH Public Key for Operating System User {{ osuser }}{% endblocktrans %}
{% else %} {% 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 %} {% 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 %} {% endif %}
@ -11,7 +11,7 @@
{% block page_title %}{% spaceless %} {% block page_title %}{% spaceless %}
{% if user == customer %} {% if user == customer %}
{% blocktrans %}Add new SSH Public Key{% endblocktrans %} {% blocktrans %}Add new SSH Public Key <small>for Operating System User {{ osuser }}</small>{% endblocktrans %}
{% else %} {% else %}
{% blocktrans with full_name=customer.get_full_name %}Add a new SSH Public Key <small>for Operating System User {{ osuser }} of Customer {{ full_name }}</small>{% endblocktrans %} {% blocktrans with full_name=customer.get_full_name %}Add a new SSH Public Key <small>for Operating System User {{ osuser }} of Customer {{ full_name }}</small>{% endblocktrans %}
{% endif %} {% endif %}

View file

@ -0,0 +1,30 @@
{% extends "osusers/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %}
{% blocktrans %}Edit Comment of SSH Public Key for Operating System User {{ osuser }}{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}Edit Comment of 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 %}Edit Comment of Public Key <small>for Operating System User {{ osuser }}</small>{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}Edit Comment of SSH Public Key <small>for Operating System User {{ osuser }} of Customer {{ full_name }}</small>{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock page_title %}
{% block content %}
{% crispy form %}
{% endblock content %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$('input[type=text]').first().focus().select();
});
</script>
{% endblock extra_js %}

View file

@ -0,0 +1,47 @@
{% extends "osusers/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %}
{% blocktrans %}SSH Public Keys for Operating System User {{ osuser }}{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}SSH Public Keys for Operating System User {{ osuser }} of Customer {{ full_name }}{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock title %}
{% block page_title %}{% spaceless %}
{% if user == customer %}
{% blocktrans %}SSH Public Keys <small>for Operating System User {{ osuser }}</small>{% endblocktrans %}
{% else %}
{% blocktrans with full_name=customer.get_full_name %}SSH Public Keys <small>for Operating System User {{ osuser }} of Customer {{ full_name }}</small>{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock page_title %}
{% block content %}
{% if keys %}
<table class="table">
<thead>
<tr>
<th class="name-column">{% trans "Algorithm" %}</th>
<th>{% trans "Comment" %}</th>
<th title="{% trans "SSH public key actions" %}" class="actions-column"><span class="sr-only">{% trans "Actions" %}</span></th>
</tr>
</thead>
<tbody>
{% for key in keys %}
<tr>
<td>{{ key.algorithm }}</td>
<td>{{ key.comment }}</td>
<td>
<a href="{% url 'delete_ssh_key' package=hostingpackage.id pk=key.id %}" title="{% trans "Delete this SSH public key" %}"><i class="glyphicon glyphicon-trash"></i><span class="sr-only"> {% trans "Delete" %}</span></a>
<a href="{% url 'edit_ssh_key_comment' package=hostingpackage.id pk=key.id %}" title="{% trans "Edit this SSH public key's comment" %}"><i class="glyphicon glyphicon-pencil"></i><span class="sr-only"> {% trans "Edit Comment" %}</span></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="bg-warning">{% trans "There are now SSH public keys set for this operating system user yet." %}</p>
{% endif %}
<p><a href="{% url 'add_ssh_key' package=hostingpackage.id %}" class="btn btn-primary">{% trans "Add SSH public key" %}</a></p>
{% endblock content %}