# HG changeset patch # User neko259 # Date 2014-08-14 15:14:52 # Node ID 6e2f495adc3657f464901bd10ca975840bacf9ca # Parent e6c8be6a02f1b9c74c08994f03b484570f6c8f3a Added 'primary' parameter for the key to indicate this key would be used in ID. Other keys will be used for signing only and can be shared. diff --git a/boards/migrations/0033_auto__add_field_keypair_primary.py b/boards/migrations/0033_auto__add_field_keypair_primary.py new file mode 100644 --- /dev/null +++ b/boards/migrations/0033_auto__add_field_keypair_primary.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'KeyPair.primary' + db.add_column('boards_keypair', 'primary', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'KeyPair.primary' + db.delete_column('boards_keypair', 'primary') + + + models = { + 'boards.ban': { + 'Meta': {'object_name': 'Ban'}, + 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'}) + }, + 'boards.keypair': { + 'Meta': {'object_name': 'KeyPair'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key_type': ('django.db.models.fields.TextField', [], {}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'private_key': ('django.db.models.fields.TextField', [], {}), + 'public_key': ('django.db.models.fields.TextField', [], {}) + }, + 'boards.post': { + 'Meta': {'object_name': 'Post', 'ordering': "('id',)"}, + '_text_rendered': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'images': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'symmetrical': 'False', 'db_index': 'True', 'to': "orm['boards.PostImage']", 'null': 'True', 'related_name': "'ip+'"}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'poster_user_agent': ('django.db.models.fields.TextField', [], {}), + 'pub_time': ('django.db.models.fields.DateTimeField', [], {}), + 'public_key': ('django.db.models.fields.TextField', [], {'blank': 'True', 'null': 'True'}), + 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'symmetrical': 'False', 'db_index': 'True', 'to': "orm['boards.Post']", 'null': 'True', 'related_name': "'rfp+'"}), + 'refmap': ('django.db.models.fields.TextField', [], {'blank': 'True', 'null': 'True'}), + 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}), + 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'bbcode'", 'max_length': '30'}), + 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Thread']", 'default': 'None', 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'boards.postimage': { + 'Meta': {'object_name': 'PostImage', 'ordering': "('id',)"}, + 'hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}), + 'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('boards.thumbs.ImageWithThumbsField', [], {'blank': 'True', 'max_length': '100'}), + 'pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'width': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'boards.tag': { + 'Meta': {'object_name': 'Tag', 'ordering': "('name',)"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '100'}), + 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Thread']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True', 'related_name': "'tag+'"}) + }, + 'boards.thread': { + 'Meta': {'object_name': 'Thread'}, + 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'bump_time': ('django.db.models.fields.DateTimeField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Post']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True', 'related_name': "'tre+'"}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'}) + } + } + + complete_apps = ['boards'] \ No newline at end of file diff --git a/boards/models/sync_key.py b/boards/models/sync_key.py --- a/boards/models/sync_key.py +++ b/boards/models/sync_key.py @@ -8,7 +8,10 @@ APP_LABEL_BOARDS = 'boards' class KeyPairManager(models.Manager): - def generate_key(self, key_type=TYPE_ECDSA): + def generate_key(self, key_type=TYPE_ECDSA, primary=False): + if primary and self.filter(primary=True).exists(): + raise Exception('There can be only one primary key') + if key_type == TYPE_ECDSA: private = SigningKey.generate() public = private.get_verifying_key() @@ -18,9 +21,9 @@ class KeyPairManager(models.Manager): return self.create(public_key=public_key_str, private_key=private_key_str, - key_type=TYPE_ECDSA) + key_type=TYPE_ECDSA, primary=primary) else: - return None + raise Exception('Key type not supported') def verify(self, public_key_str, string, signature, key_type=TYPE_ECDSA): if key_type == TYPE_ECDSA: @@ -32,7 +35,7 @@ class KeyPairManager(models.Manager): except BadSignatureError: return False else: - return False + raise Exception('Key type not supported') class KeyPair(models.Model): @@ -44,6 +47,7 @@ class KeyPair(models.Model): public_key = models.TextField() private_key = models.TextField() key_type = models.TextField() + primary = models.BooleanField(default=False) def __str__(self): return '%s: %s' % (self.key_type, self.public_key) diff --git a/boards/tests.py b/boards/tests.py --- a/boards/tests.py +++ b/boards/tests.py @@ -277,3 +277,12 @@ class KeyTest(TestCase): key_type='ecdsa') self.assertTrue(valid, 'Message verification failed.') + + def test_primary_constraint(self): + KeyPair.objects.generate_key(key_type='ecdsa', primary=True) + + try: + KeyPair.objects.generate_key(key_type='ecdsa', primary=True) + self.fail('Exception should be thrown indicating there can be only one primary key.') + except Exception: + pass