plug users and hosting packages together

- document new feature in changelog
- add autogenerated documentation for osusers.urls and osusers.views
- add osuser URLs to gnuviechadmin.urls
- implement get_absolute_url in hostingpackages.models.CustomerHostingPackage
- use set_ldap_user_password instead of create_ldap_user for existing OS users
  in osusers.models.User.set_password
- add URL pattern set_osuser_password in osusers.urls
- implement osusers.views.SetOsUserPassword to set the password of an existing
  operating system user
- link to hosting package detail view on user dashboard
- add template hostingpackages/customerhostingpackage_detail.html
- add template osusers/user_setpassword.html
This commit is contained in:
Jan Dittberner 2015-01-24 16:26:32 +01:00
parent 0d08d9876b
commit 150366a524
11 changed files with 181 additions and 6 deletions

View file

@ -1,6 +1,8 @@
Changelog Changelog
========= =========
* :feature:`-` add frontend functionality to set an os users' sftp password
(needs gvaldap >= 0.4.0 on the LDAP side)
* :support:`-` remove unused dashboard.views.LogoutView and the corresponding * :support:`-` remove unused dashboard.views.LogoutView and the corresponding
URL in dashboard.urls URL in dashboard.urls
* :feature:`-` add new task stub to set an ldap user's password * :feature:`-` add new task stub to set an ldap user's password

View file

@ -30,3 +30,16 @@
.. automodule:: osusers.models .. automodule:: osusers.models
:members: :members:
:py:mod:`urls <osusers.urls>`
-----------------------------
.. automodule:: osusers.urls
:py:mod:`views <osusers.views>`
-------------------------------
.. automodule:: osusers.views
:members:

View file

@ -11,6 +11,7 @@ urlpatterns = patterns(
url(r'', include('dashboard.urls')), url(r'', include('dashboard.urls')),
url(r'^accounts/', include('allauth.urls')), url(r'^accounts/', include('allauth.urls')),
url(r'^hosting/', include('hostingpackages.urls')), url(r'^hosting/', include('hostingpackages.urls')),
url(r'^osuser/', include('osusers.urls')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
) )

View file

@ -5,6 +5,7 @@ This module contains the hosting package models.
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.db import models from django.db import models
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@ -218,6 +219,12 @@ class CustomerHostingPackage(HostingPackageBase):
name=self.name, customer=self.customer name=self.name, customer=self.customer
) )
def get_absolute_url(self):
return reverse('hosting_package_details', kwargs={
'user': self.customer.username,
'pk': self.id,
})
def copy_template_attributes(self): def copy_template_attributes(self):
""" """
Copy the attributes of the hosting package's template to the package. Copy the attributes of the hosting package's template to the package.

View file

@ -29,6 +29,7 @@ from ldaptasks.tasks import (
delete_ldap_group, delete_ldap_group,
delete_ldap_user, delete_ldap_user,
remove_ldap_user_from_group, remove_ldap_user_from_group,
set_ldap_user_password,
) )
from fileservertasks.tasks import ( from fileservertasks.tasks import (
@ -245,6 +246,15 @@ class User(TimeStampedModel, models.Model):
""" """
if hasattr(self, 'shadow'): if hasattr(self, 'shadow'):
self.shadow.set_password(password) self.shadow.set_password(password)
success = set_ldap_user_password.delay(
self.username, password).get()
if success:
_LOGGER.info(
"successfully set LDAP password for %s", self.username)
else:
_LOGGER.error(
"setting the LDAP password for %s failed", self.username)
return success
else: else:
self.shadow = Shadow.objects.create_shadow( self.shadow = Shadow.objects.create_shadow(
user=self, password=password user=self, password=password
@ -253,7 +263,9 @@ class User(TimeStampedModel, models.Model):
self.username, self.uid, self.group.gid, self.gecos, self.username, self.uid, self.group.gid, self.gecos,
self.homedir, self.shell, password self.homedir, self.shell, password
).get() ).get()
logging.info("set LDAP password for %s", dn) _LOGGER.info("set LDAP password for %s", dn)
return True
@transaction.atomic @transaction.atomic
def save(self, *args, **kwargs): def save(self, *args, **kwargs):

View file

@ -0,0 +1,16 @@
"""
This module defines the URL patterns for operating system user related views.
"""
from __future__ import absolute_import, unicode_literals
from django.conf.urls import patterns, url
from .views import SetOsUserPassword
urlpatterns = patterns(
'',
url(r'^(?P<slug>[\w0-9@.+-_]+)/setpassword$', SetOsUserPassword.as_view(),
name='set_osuser_password'),
)

View file

@ -0,0 +1,45 @@
"""
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.utils.translation import ugettext as _
from django.contrib import messages
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from .forms import ChangeOsUserPasswordForm
from .models import User
class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView):
"""
This view is used for setting a new operating system user password.
"""
model = User
slug_field = 'username'
template_name_suffix = '_setpassword'
context_object_name = 'osuser'
form_class = ChangeOsUserPasswordForm
def get_customer_object(self):
return self.get_object().customer
def get_context_data(self, *args, **kwargs):
context = super(SetOsUserPassword, self).get_context_data(
*args, **kwargs)
context['customer'] = self.get_customer_object()
return context
def form_valid(self, form):
osuser = form.save()
messages.success(
self.request,
_("New password for {username} has been set successfully.").format(
username=osuser.username
))
return redirect(osuser.customerhostingpackage)

View file

@ -22,7 +22,7 @@
<tbody> <tbody>
{% for package in hosting_packages %} {% for package in hosting_packages %}
<tr> <tr>
<th>{{ package.name }}</th> <th><a href="{{ package.get_absolute_url }}" title="{% blocktrans with packagename=package.name %}Show details for {{ packagename }}{% endblocktrans %}">{{ package.name }}</a></th>
<th> <th>
{% with diskspace=package.get_disk_space %} {% with diskspace=package.get_disk_space %}
<span title="{% blocktrans %}The reserved disk space for your hosting package is {{ diskspace }} bytes.{% endblocktrans %}">{{ diskspace|filesizeformat }}</span> <span title="{% blocktrans %}The reserved disk space for your hosting package is {{ diskspace }} bytes.{% endblocktrans %}">{{ diskspace|filesizeformat }}</span>

View file

@ -0,0 +1,48 @@
{% extends "hostingpackages/base.html" %}
{% load i18n %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %}
{% blocktrans with package=hostingpackage.name %}Details for your Hosting Package {{ package }}{% endblocktrans %}
{% else %}
{% blocktrans with package=hostingpackage.name full_name=customer.get_full_name %}Details for Hosting Package {{ package }} of {{ full_name }}{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock title %}
{% block page_title %}{% blocktrans with package=hostingpackage.name %}Details of Hosting Package {{ package }}{% endblocktrans %}{% endblock page_title %}
{% block content %}
<div class="row">
<div class="col-lg-6 col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
{% trans "Hosting Package Information" %}<div class="pull-right"><a class="panel-title" href="#" title="{% trans "Edit Hosting Package Information" %}"><i class="glyphicon glyphicon-cog"></i></a></div>
</div>
<dl class="panel-body dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ hostingpackage.name }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ hostingpackage.description|default:"-" }}</dd>
<dt>{% trans "Disk space" %}</dt>
{% with diskspace=hostingpackage.get_disk_space %}
<dd title="{% blocktrans %}The reserved disk space for your hosting package is {{ diskspace }} bytes.{% endblocktrans %}">{{ diskspace|filesizeformat }}</dd>
{% endwith %}
<dt>{% trans "Mailboxes" %}</dt>
<dd>{% blocktrans with num=hostingpackage.get_used_mailboxes total=hostingpackage.get_mailboxes %}{{ num }} of {{ total }} in use{% endblocktrans %}</dd>
<dt>{% if hostingpackage.osuser.is_sftp_user %}{% trans "SFTP username" %}{% else %}{% trans "SSH/SFTP username" %}{% endif %}</dt>
<dd>{{ hostingpackage.osuser.username }}</dd>
<dt>{% trans "Upload server" %}</dt>
<dd>{{ uploadserver }}</dd>
</dl>
</div>
</div>
<div class="col-lg-6 col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">{% trans "Hosting Package Actions" %}</div>
<ul class="list-group">
<li class="list-group-item"><a href="{% url "set_osuser_password" slug=hostingpackage.osuser.username %}">{% if hostingpackage.osuser.is_sftp %}{% trans "Set SFTP password" %}{% else %}{% trans "Set SSH/SFTP password" %}{% endif %}</a></li>
</ul>
</div>
</div>
</div>
{% endblock content %}

View file

@ -0,0 +1 @@
{% extends "base.html" %}

View file

@ -0,0 +1,30 @@
{% extends "osusers/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if customer == user %}
{% blocktrans with osuser=osuser.username %}Set new password for user {{ osuser }}{% endblocktrans %}
{% else %}
{% blocktrans with osuser=osuser.username full_name=customer.get_full_name %}Set new password for user {{ osuser }} of customer {{ full_name }}{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock title %}
{% block page_title %}{% spaceless %}
{% if customer == user %}
{% blocktrans with osuser=osuser.username %}Set new password for user {{ osuser }}{% endblocktrans %}
{% else %}
{% blocktrans with osuser=osuser.username full_name=customer.get_full_name %}Set new password for user {{ osuser }} of customer {{ full_name }}{% endblocktrans %}
{% endif %}
{% endspaceless %}{% endblock page_title %}
{% block content %}
{% crispy form %}
{% endblock content %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$('input[type=password]').val('');
$('input[type=password]').first().focus();
});
</script>
{% endblock extra_js %}