diff --git a/nsupdate/main/forms.py b/nsupdate/main/forms.py index 5d2dc5e..5823892 100644 --- a/nsupdate/main/forms.py +++ b/nsupdate/main/forms.py @@ -3,7 +3,13 @@ from django import forms from main.models import Host -class HostForm(forms.ModelForm): +class CreateHostForm(forms.ModelForm): class Meta: model = Host - fields = ['subdomain', 'domain', 'comment', 'update_secret'] + fields = ['subdomain', 'domain', 'comment'] + + +class EditHostForm(forms.ModelForm): + class Meta: + model = Host + fields = ['comment'] diff --git a/nsupdate/main/models.py b/nsupdate/main/models.py index 54cd677..0977cbf 100644 --- a/nsupdate/main/models.py +++ b/nsupdate/main/models.py @@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError from django.core.validators import RegexValidator from django.conf import settings from django.db.models.signals import post_save +from django.contrib.auth.hashers import make_password from main import dnstools import re @@ -25,7 +26,6 @@ class BlacklistedDomain(models.Model): def domain_blacklist_validator(value): for bd in BlacklistedDomain.objects.all(): - print bd.domain if re.search(bd.domain, value): raise ValidationError(u'This domain is not allowed') @@ -69,6 +69,19 @@ class Host(models.Model): def get_fqdn(self): return self.subdomain+'.'+self.domain.domain + def generate_secret(self): + # note: we use a quick hasher for the update_secret as expensive + # more modern hashes might put too much load on the servers. also + # many update clients might use http without ssl, so it is not too + # secure anyway. + secret = User.objects.make_random_password() + self.update_secret = make_password( + secret, + hasher='sha1' + ) + self.save() + return secret + def post_delete_host(sender, **kwargs): obj = kwargs['instance'] diff --git a/nsupdate/main/templates/main/generate_secret.html b/nsupdate/main/templates/main/generate_secret.html new file mode 100644 index 0000000..876f272 --- /dev/null +++ b/nsupdate/main/templates/main/generate_secret.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% load bootstrap %} + +{% block content %} + +
+

Host Secret Generated back to overview

+

New secret generated for you. We store it hashed, so save it now, or you have to generate a new one again.

+

secret: {{ update_secret }}

+
+ + +{% endblock %} diff --git a/nsupdate/main/templates/main/help.html b/nsupdate/main/templates/main/help.html index dae9cd8..1a654f1 100644 --- a/nsupdate/main/templates/main/help.html +++ b/nsupdate/main/templates/main/help.html @@ -2,11 +2,6 @@ {% load bootstrap %} {% block content %} - -
-

Help / FAQ

- I am the Architect. I created the Matrix. I've been waiting for you. You have many questions, and although the process has altered your consciousness, you remain irrevocably human. Ergo, some of my answers you will understand, and some of them you will not. Concordantly, while your first question may be the most pertinent, you may or may not realize it is also the most irrelevant. -
- - -{% endblock %} \ No newline at end of file +

Help

+This is the help page +{% endblock %} diff --git a/nsupdate/main/templates/main/host.html b/nsupdate/main/templates/main/host.html index eec4dcd..0952e77 100644 --- a/nsupdate/main/templates/main/host.html +++ b/nsupdate/main/templates/main/host.html @@ -7,21 +7,25 @@

Edit Horst back to overview

- Edit your host information. +

You can only change the comment. If you want to have another domain name, you have to delete this host and create a new one.

{% csrf_token %} {{ form|bootstrap }}
-
- +
+

Generate new secret

+

We store your update secret hashed, so if you forgot or lost it you have to create a new one.

+
+ +

Update Nameserver Entry

- Usually you configure your router to follow the dyndns protocol. But if you know what you are doing, and you want to update it by hand, you can do it here. +

Usually you configure your router to follow the dyndns protocol. But if you know what you are doing, and you want to update it by hand, you can do it here.

- +
diff --git a/nsupdate/main/urls.py b/nsupdate/main/urls.py index 1a176b7..2cf3e2a 100644 --- a/nsupdate/main/urls.py +++ b/nsupdate/main/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import patterns, url from django.views.generic import TemplateView from main.views import ( - HomeView, OverviewView, HostView, DeleteHostView, AboutView, HelpView) + HomeView, OverviewView, HostView, DeleteHostView, AboutView, HelpView, GenerateSecretView) from api.views import ( MyIpView, DetectIpView, NicUpdateView, AuthorizedNicUpdateView) @@ -14,6 +14,7 @@ urlpatterns = patterns( url(r'^help/$', HelpView.as_view(), name="help"), url(r'^overview/$', OverviewView.as_view(), name='overview'), url(r'^host/(?P\d+)/$', HostView.as_view(), name='host_view'), + url(r'^generate_secret/(?P\d+)/$', GenerateSecretView.as_view(), name='generate_secret_view'), url(r'^host/(?P\d+)/delete/$', DeleteHostView.as_view(), name='delete_host'), url(r'^myip$', MyIpView), diff --git a/nsupdate/main/views.py b/nsupdate/main/views.py index 49a7dc5..ebe5710 100644 --- a/nsupdate/main/views.py +++ b/nsupdate/main/views.py @@ -4,16 +4,39 @@ from django.views.generic.edit import UpdateView, DeleteView from django.http import HttpResponseRedirect from django.contrib.auth.decorators import login_required from django.contrib import messages -from django.contrib.auth.hashers import make_password from django.utils.decorators import method_decorator from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied import dns.inet -from main.forms import HostForm +from main.forms import CreateHostForm, EditHostForm from main.models import Host +class GenerateSecretView(UpdateView): + model = Host + template_name = "main/generate_secret.html" + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(GenerateSecretView, self).dispatch(*args, **kwargs) + + def get_object(self, *args, **kwargs): + obj = super(GenerateSecretView, self).get_object(*args, **kwargs) + if obj.created_by != self.request.user: + raise PermissionDenied() # or Http404 + return obj + + def get_context_data(self, *args, **kwargs): + context = super(GenerateSecretView, self).get_context_data(*args, **kwargs) + context['nav_overview'] = True + # generate secret, store it hashed and return the plain secret for the context + context['update_secret'] = self.object.generate_secret() + context['hosts'] = Host.objects.filter(created_by=self.request.user) + messages.add_message(self.request, messages.SUCCESS, 'Host secret created.') + return context + + class AboutView(TemplateView): template_name = "main/about.html" @@ -52,23 +75,18 @@ class HelpView(TemplateView): class OverviewView(CreateView): model = Host template_name = "main/overview.html" - form_class = HostForm + form_class = CreateHostForm @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(OverviewView, self).dispatch(*args, **kwargs) def get_success_url(self): - return reverse('overview') + return reverse('generate_secret_view', args=(self.object.pk,)) def form_valid(self, form): self.object = form.save(commit=False) self.object.created_by = self.request.user - # see comment in HostView about the quick hasher: - self.object.update_secret = make_password( - self.object.update_secret, - hasher='sha1' - ) self.object.save() messages.add_message(self.request, messages.SUCCESS, 'Host added.') return HttpResponseRedirect(self.get_success_url()) @@ -83,7 +101,7 @@ class OverviewView(CreateView): class HostView(UpdateView): model = Host template_name = "main/host.html" - form_class = HostForm + form_class = EditHostForm @method_decorator(login_required) def dispatch(self, *args, **kwargs): @@ -94,15 +112,6 @@ class HostView(UpdateView): def form_valid(self, form): self.object = form.save(commit=False) - self.object.created_by = self.request.user - # note: we use a quick hasher for the update_secret as expensive - # more modern hashes might put too much load on the servers. also - # many update clients might use http without ssl, so it is not too - # secure anyway. - self.object.update_secret = make_password( - self.object.update_secret, - hasher='sha1' - ) self.object.save() messages.add_message(self.request, messages.SUCCESS, 'Host updated.') return HttpResponseRedirect(self.get_success_url()) @@ -123,7 +132,7 @@ class HostView(UpdateView): class DeleteHostView(DeleteView): model = Host template_name = "main/delete_host.html" - form_class = HostForm + form_class = EditHostForm @method_decorator(login_required) def dispatch(self, *args, **kwargs):