summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2013-02-03 20:55:25 +0100
committerDan McGee <dan@archlinux.org>2013-02-03 20:56:35 +0100
commit9da8a63dd476fe3607a68a028655c9f9d0fee163 (patch)
tree6d16436917a3231845974171c3e06816feaad1c1
parent844ed8109317db882e5d2b2ae8fa6084f794d798 (diff)
downloadarchweb-9da8a63dd476fe3607a68a028655c9f9d0fee163.tar.gz
archweb-9da8a63dd476fe3607a68a028655c9f9d0fee163.tar.xz
Add DeveloperKey model
We're starting to see developers use subkeys of their primary key to sign packages, which we aren't handling well in the web interface. These subkeys show up as unknown, which isn't strictly true. Start the process of being able to handle these keys by adding a model that will store all known keys and subkeys and the relationships among them, as well as which developer owns each. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--devel/admin.py12
-rw-r--r--devel/migrations/0009_auto__add_developerkey.py126
-rw-r--r--devel/models.py15
3 files changed, 150 insertions, 3 deletions
diff --git a/devel/admin.py b/devel/admin.py
index 5a704c0..971933b 100644
--- a/devel/admin.py
+++ b/devel/admin.py
@@ -2,7 +2,7 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
-from .models import UserProfile, MasterKey, PGPSignature
+from .models import UserProfile, MasterKey, DeveloperKey, PGPSignature
class UserProfileInline(admin.StackedInline):
@@ -17,7 +17,14 @@ class UserProfileAdmin(UserAdmin):
class MasterKeyAdmin(admin.ModelAdmin):
list_display = ('pgp_key', 'owner', 'created', 'revoker', 'revoked')
- search_fields = ('pgp_key', 'owner', 'revoker')
+ search_fields = ('pgp_key', 'owner__username', 'revoker__username')
+ date_hierarchy = 'created'
+
+
+class DeveloperKeyAdmin(admin.ModelAdmin):
+ list_display = ('key', 'parent', 'owner', 'created', 'expires', 'revoked')
+ search_fields = ('key', 'owner__username')
+ list_filter = ('owner',)
date_hierarchy = 'created'
@@ -32,6 +39,7 @@ admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
admin.site.register(MasterKey, MasterKeyAdmin)
+admin.site.register(DeveloperKey, DeveloperKeyAdmin)
admin.site.register(PGPSignature, PGPSignatureAdmin)
# vim: set ts=4 sw=4 et:
diff --git a/devel/migrations/0009_auto__add_developerkey.py b/devel/migrations/0009_auto__add_developerkey.py
new file mode 100644
index 0000000..60d3f7b
--- /dev/null
+++ b/devel/migrations/0009_auto__add_developerkey.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ db.create_table('devel_developerkey', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('owner', self.gf('django.db.models.fields.related.ForeignKey')(related_name='all_keys', null=True, to=orm['auth.User'])),
+ ('key', self.gf('devel.fields.PGPKeyField')(unique=True, max_length=40)),
+ ('created', self.gf('django.db.models.fields.DateTimeField')()),
+ ('expires', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
+ ('revoked', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
+ ('parent', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['devel.DeveloperKey'], null=True, on_delete=models.SET_NULL)),
+ ))
+ db.send_create_signal('devel', ['DeveloperKey'])
+
+ def backwards(self, orm):
+ db.delete_table('devel_developerkey')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ '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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ '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': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ '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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ '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'}),
+ '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'})
+ },
+ 'devel.developerkey': {
+ 'Meta': {'object_name': 'DeveloperKey'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('devel.fields.PGPKeyField', [], {'unique': 'True', 'max_length': '40'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_keys'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['devel.DeveloperKey']", 'null': 'True', 'on_delete': 'models.SET_NULL'}),
+ 'revoked': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'devel.masterkey': {
+ 'Meta': {'ordering': "('created',)", 'object_name': 'MasterKey'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_owner'", 'to': "orm['auth.User']"}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'revoked': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'revoker': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'masterkey_revoker'", 'to': "orm['auth.User']"})
+ },
+ 'devel.pgpsignature': {
+ 'Meta': {'ordering': "('signer', 'signee')", 'object_name': 'PGPSignature'},
+ 'created': ('django.db.models.fields.DateField', [], {}),
+ 'expires': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'signee': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'signer': ('devel.fields.PGPKeyField', [], {'max_length': '40'}),
+ 'valid': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ 'devel.userprofile': {
+ 'Meta': {'object_name': 'UserProfile', 'db_table': "'user_profiles'"},
+ 'alias': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'allowed_repos': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Repo']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'favorite_distros': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'interests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'languages': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {}),
+ 'latin_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'notify': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'other_contact': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'pgp_key': ('devel.fields.PGPKeyField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+ 'picture': ('django.db.models.fields.files.FileField', [], {'default': "'devs/silhouette.png'", 'max_length': '100'}),
+ 'public_email': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'roles': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'time_zone': ('django.db.models.fields.CharField', [], {'default': "'UTC'", 'max_length': '100'}),
+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': "orm['auth.User']"}),
+ 'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'yob': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'main.repo': {
+ 'Meta': {'ordering': "('name',)", 'object_name': 'Repo', 'db_table': "'repos'"},
+ 'bugs_category': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}),
+ 'bugs_project': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'staging': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'svn_root': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'testing': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ }
+ }
+
+ complete_apps = ['devel']
diff --git a/devel/models.py b/devel/models.py
index 6689ca3..67de40a 100644
--- a/devel/models.py
+++ b/devel/models.py
@@ -68,7 +68,6 @@ class UserProfile(models.Model):
return '/%s/#%s' % (prefix, self.user.username)
-
class MasterKey(models.Model):
owner = models.ForeignKey(User, related_name='masterkey_owner',
help_text="The developer holding this master key")
@@ -88,6 +87,20 @@ class MasterKey(models.Model):
self.owner.get_full_name(), self.created)
+class DeveloperKey(models.Model):
+ owner = models.ForeignKey(User, related_name='all_keys', null=True,
+ help_text="The developer this key belongs to")
+ key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint",
+ unique=True)
+ created = models.DateTimeField()
+ expires = models.DateTimeField(null=True, blank=True)
+ revoked = models.DateTimeField(null=True, blank=True)
+ parent = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+
+ def __unicode__(self):
+ return self.key
+
+
class PGPSignature(models.Model):
signer = PGPKeyField(max_length=40, verbose_name="Signer key fingerprint")
signee = PGPKeyField(max_length=40, verbose_name="Signee key fingerprint")