diff options
-rw-r--r-- | main/templatetags/pgp.py | 8 | ||||
-rw-r--r-- | public/views.py | 21 | ||||
-rw-r--r-- | sitestatic/archweb.css | 8 | ||||
-rw-r--r-- | templates/public/keys.html | 56 | ||||
-rw-r--r-- | visualize/views.py | 2 |
5 files changed, 82 insertions, 13 deletions
diff --git a/main/templatetags/pgp.py b/main/templatetags/pgp.py index 1ffc5241..50b1aa17 100644 --- a/main/templatetags/pgp.py +++ b/main/templatetags/pgp.py @@ -50,4 +50,12 @@ def pgp_fingerprint(key_id, autoescape=True): return mark_safe(format_key(esc(key_id))) pgp_fingerprint.needs_autoescape = True + +@register.assignment_tag +def signature_exists(signatures, signer, signee): + if not signer or not signee: + return False + lookup = (signer[-16:], signee[-16:]) + return lookup in signatures + # vim: set ts=4 sw=4 et: diff --git a/public/views.py b/public/views.py index 1e1ffc6c..a85d7389 100644 --- a/public/views.py +++ b/public/views.py @@ -1,6 +1,8 @@ +from datetime import datetime + from django.conf import settings from django.contrib.auth.models import User -from django.db.models import Count +from django.db.models import Count, Q from django.http import Http404 from django.views.decorators.cache import cache_control from django.views.generic import list_detail @@ -88,17 +90,30 @@ def feeds(request): @cache_control(max_age=300) def keys(request): + not_expired = Q(expires__gt=datetime.utcnow) | Q(expires__isnull=True) master_keys = MasterKey.objects.select_related('owner', 'revoker', 'owner__userprofile', 'revoker__userprofile').filter( revoked__isnull=True) - sig_counts = PGPSignature.objects.filter(valid=True, - expires__isnull=True).values_list('signer').annotate( + + sig_counts = PGPSignature.objects.filter( + not_expired, valid=True).values_list('signer').annotate( Count('signer')) sig_counts = dict((key_id[-16:], ct) for key_id, ct in sig_counts) + for key in master_keys: key.signature_count = sig_counts.get(key.pgp_key[-16:], 0) + + users = User.objects.filter(is_active=True).select_related( + 'userprofile__pgp_key').order_by('first_name', 'last_name') + + # frozenset because we are going to do lots of __contains__ lookups + signatures = frozenset(PGPSignature.objects.filter( + not_expired, valid=True).values_list('signer', 'signee')) + context = { 'keys': master_keys, + 'active_users': users, + 'signatures': signatures, } return direct_to_template(request, 'public/keys.html', context) diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css index d2286329..ac0dff52 100644 --- a/sitestatic/archweb.css +++ b/sitestatic/archweb.css @@ -957,6 +957,14 @@ ul.signoff-list { color: red; } +#key-status .signed-yes { + color: green; +} + +#key-status .signed-no { + color: red; +} + /* highlight current website in the navbar */ #archnavbar.anb-home ul li#anb-home a, #archnavbar.anb-packages ul li#anb-packages a, diff --git a/templates/public/keys.html b/templates/public/keys.html index 6b06cc32..a7c91c43 100644 --- a/templates/public/keys.html +++ b/templates/public/keys.html @@ -15,15 +15,6 @@ <p>The {{ keys|length }} key{{ keys|pluralize }} listed below should be regarded as the current set of master keys. They are available on public keyservers and should be signed by the owner of the key.</p> - <p>All official Arch Linux developers and trusted users should have their - key signed by at least three of these master keys. This is in accordance - with the PGP <em>web of trust</em> concept. If a user is willing to - marginally trust all of the master keys, three signatures from different - master keys will consider a given developer's key as valid. For more - information on trust, please consult the - <a href="http://www.gnupg.org/gph/en/manual.html">GNU Privacy Handbook</a> - and <a href="http://www.gnupg.org/gph/en/manual.html#AEN385">Using trust to - validate keys</a>.</p> <table class="pretty2"> <thead> @@ -55,5 +46,52 @@ {% endfor %} </tbody> </table> + + <p>The following table shows all active developers and trusted users along + with the status of their personal signing key. A 'Yes' indicates that the + personal key of the developer is signed by the given master key. A 'No' + indicates it has not been signed; however, this does not necessarily mean + the key should not be trusted.</p> + <p>All official Arch Linux developers and trusted users should have their + key signed by at least three master keys if they are responsible for + packaging software in the repositories. This is in accordance with the PGP + <em>web of trust</em> concept. If a user is willing to marginally trust all + of the master keys, three signatures from different master keys will + consider a given developer's key as valid. For more information on trust, + please consult the + <a href="http://www.gnupg.org/gph/en/manual.html">GNU Privacy Handbook</a> + and <a href="http://www.gnupg.org/gph/en/manual.html#AEN385">Using trust to + validate keys</a>.</p> + + <table class="pretty2" id="key-status"> + <thead> + <tr> + <th></th> + <th>PGP Key</th> + {% for key in keys %} + <th>{{ key.owner.get_full_name }}</th> + {% endfor %} + </tr> + <tr> + <th></th> + <th></th> + {% for key in keys %} + <th>{% pgp_key_link key.pgp_key %}</th> + {% endfor %} + </tr> + </thead> + <tbody> + {% for user in active_users %} + <tr> + <th>{{ user.get_full_name }}</th> + <td>{% pgp_key_link user.userprofile.pgp_key %}</td> + {% spaceless %}{% for key in keys %} + {% signature_exists signatures key.pgp_key user.userprofile.pgp_key as signed %} + <td class="signed-{{ signed|yesno }}">{{ signed|yesno|capfirst }}</td> + {% endfor %}{% endspaceless %} + </tr> + {% endfor %} + </tbody> + </table> </div> {% endblock %} diff --git a/visualize/views.py b/visualize/views.py index be6057b2..afc5429d 100644 --- a/visualize/views.py +++ b/visualize/views.py @@ -102,7 +102,7 @@ def pgp_keys(request): 'group': 'cacert', }) - not_expired = Q(expires__gt=datetime.now) | Q(expires__isnull=True) + not_expired = Q(expires__gt=datetime.utcnow) | Q(expires__isnull=True) signatures = PGPSignature.objects.filter(not_expired, valid=True) edge_list = [{ 'signee': sig.signee, 'signer': sig.signer } for sig in signatures] |