diff --git a/nsupdate/accounts/templates/registration/activation_email.txt b/nsupdate/accounts/templates/registration/activation_email.txt index 38912fb..87adf20 100644 --- a/nsupdate/accounts/templates/registration/activation_email.txt +++ b/nsupdate/accounts/templates/registration/activation_email.txt @@ -5,7 +5,7 @@ and your address will be removed from our records. To activate this account, please click the following link within the next {{ expiration_days }} days: -http://{{ site.domain }}{% url 'registration_activate' %} +http://{{ site.domain }}{% url 'registration_activate' activation_key %} Sincerely, {{ site.name }} Management diff --git a/nsupdate/api/views.py b/nsupdate/api/views.py index b20d548..59bcac0 100644 --- a/nsupdate/api/views.py +++ b/nsupdate/api/views.py @@ -87,7 +87,7 @@ def check_api_auth(username, password): :return: True if authenticated, False otherwise. """ fqdn = username - hosts = Host.objects.filter(fqdn=fqdn) + hosts = Host.filter_by_fqdn(fqdn) num_hosts = len(hosts) if num_hosts == 0: return False @@ -106,7 +106,8 @@ def check_session_auth(user, hostname): :param hostname: fqdn :return: True if hostname is owned by this user, False otherwise. """ - hosts = Host.objects.filter(fqdn=hostname, created_by=user) + fqdn = hostname + hosts = Host.filter_by_fqdn(fqdn, created_by=user) num_hosts = len(hosts) if num_hosts == 0: return False diff --git a/nsupdate/main/migrations/0008_auto__chg_field_domain_created_by.py b/nsupdate/main/migrations/0008_auto__chg_field_domain_created_by.py new file mode 100644 index 0000000..30349e1 --- /dev/null +++ b/nsupdate/main/migrations/0008_auto__chg_field_domain_created_by.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Changing field 'Domain.created_by' + db.alter_column(u'main_domain', 'created_by_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)) + + def backwards(self, orm): + + # User chose to not deal with backwards NULL issues for 'Domain.created_by' + raise RuntimeError("Cannot reverse this migration. 'Domain.created_by' and its values cannot be restored.") + + # The following code is provided here to aid in writing a correct migration + # Changing field 'Domain.created_by' + db.alter_column(u'main_domain', 'created_by_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])) + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'main.blacklisteddomain': { + 'Meta': {'object_name': 'BlacklistedDomain'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'main.domain': { + 'Meta': {'object_name': 'Domain'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'main.host': { + 'Meta': {'unique_together': "(('subdomain', 'domain'),)", 'object_name': 'Host'}, + 'comment': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': u"orm['auth.User']"}), + 'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['main.Domain']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'subdomain': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'update_secret': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + } + } + + complete_apps = ['main'] \ No newline at end of file diff --git a/nsupdate/main/models.py b/nsupdate/main/models.py index 0977cbf..0a188a7 100644 --- a/nsupdate/main/models.py +++ b/nsupdate/main/models.py @@ -67,7 +67,16 @@ class Host(models.Model): unique_together = (('subdomain', 'domain'),) def get_fqdn(self): - return self.subdomain+'.'+self.domain.domain + return '%s.%s' % (self.subdomain, self.domain.domain) + + @classmethod + def filter_by_fqdn(cls, fqdn, **kwargs): + # Assuming subdomain has no dots (.) the fqdn is split at the first dot + splitted = fqdn.split('.', 1) + if not len(splitted) == 2: + raise NotImplemented("FQDN has to contain a dot") + return Host.objects.filter( + subdomain=splitted[0], domain__domain=splitted[1], **kwargs) def generate_secret(self): # note: we use a quick hasher for the update_secret as expensive diff --git a/nsupdate/main/templates/main/about.html b/nsupdate/main/templates/main/about.html index 8066e1c..199e8ae 100644 --- a/nsupdate/main/templates/main/about.html +++ b/nsupdate/main/templates/main/about.html @@ -2,20 +2,52 @@ {% load bootstrap %} {% block content %} -
You take the blue pill, the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill, you stay in Wonderland, and I show you how deep the rabbit hole goes.
-nsupdate.info is the idea of a really simple single purpose dynamic dns -service. Unlike other dynamic dns services its intention is that you do not -have to click a link every 30 days to keep your domain enabled or other -jokes like this.
-+ nsupdate.info is a dynamic dns service. +
++ You usually need it so your router (or other dyndns2-compatible + client) can update a hostname, so you don't need to know or find + out your current IP address. +
++ We wanted a simple, usable, secure and free dynamic dns service. + That is not nagging its users with advertisements, spam, having + to log in regularly or cancelling his hosts after a short time of non-usage. + That is not hiding the few free features almost undiscoverable between + a ton of features that are only for paying users. +
++ Just some geeks wanting some free and open source software and a free service. +
+ ++ The only thing we expect from you is fair use of this service: +
+ We reserve the right to remove any account or hostname(s) that are + related to unfair use of the service - at any time and without prior notice. +
+ ++ This is a free service, there are no warranties. If it breaks, it breaks. +
+ +