diff options
Diffstat (limited to 'public/views.py')
-rw-r--r-- | public/views.py | 181 |
1 files changed, 136 insertions, 45 deletions
diff --git a/public/views.py b/public/views.py index fa97adef..1002c8c7 100644 --- a/public/views.py +++ b/public/views.py @@ -1,62 +1,153 @@ +from datetime import datetime +import json +from operator import attrgetter + +from django.conf import settings +from django.contrib.auth.models import User +from django.db.models import Count, Q +from django.http import HttpResponse +from django.shortcuts import get_object_or_404, render +from django.views.decorators.cache import cache_control, cache_page + +from devel.models import MasterKey, DeveloperKey, PGPSignature, StaffGroup, UserProfile from main.models import Arch, Repo, Donor from mirrors.models import MirrorUrl from news.models import News -from . import utils - -from django.contrib.auth.models import User -from django.db.models import Q -from django.views.generic import list_detail -from django.views.generic.simple import direct_to_template +from releng.models import Release +from .utils import get_recent_updates +@cache_control(max_age=307) def index(request): - pkgs = utils.get_recent_updates() + if request.user.is_authenticated(): + def updates(): + return get_recent_updates(testing=True, staging=True) + else: + def updates(): + return get_recent_updates() + domain = "%s://%s" % (request.scheme, request.META.get('HTTP_HOST')) context = { - 'news_updates': News.objects.order_by('-postdate', '-id')[:10], - 'pkg_updates': pkgs, + 'news_updates': News.objects.order_by('-postdate', '-id')[:15], + 'pkg_updates': updates, + 'staff_groups': StaffGroup.objects.all(), + 'domain': domain, } - return direct_to_template(request, 'public/index.html', context) - -def userlist(request, type='Developers'): - users = User.objects.order_by('username') - if type == 'Developers': - users = users.filter(is_active=True, groups__name="Developers") - msg = "This is a list of the current Arch Linux Developers. They maintain the [core] and [extra] package repositories in addition to doing any other developer duties." - elif type == 'Trusted Users': - users = users.filter(is_active=True, groups__name="Trusted Users") - msg = "Here are all your friendly Arch Linux Trusted Users who are in charge of the [community] repository." - elif type == 'Fellows': - users = users.filter(is_active=False) - msg = "Below you can find a list of ex-developers (aka project fellows). These folks helped make Arch what it is today. Thanks!" + return render(request, 'public/index.html', context) - context = { - 'user_type': type, - 'description': msg, - 'users': users, - } - return direct_to_template(request, 'public/userlist.html', context) -def donate(request): - context = { - 'donors': Donor.objects.order_by('name'), - } - return direct_to_template(request, 'public/donate.html', context) - -def download(request): - qset = MirrorUrl.objects.filter( - Q(protocol__protocol__iexact='HTTP') | Q(protocol__protocol__iexact='FTP'), - mirror__public=True, mirror__active=True, mirror__isos=True - ) - return list_detail.object_list(request, - qset.order_by('mirror__country', 'mirror__name', 'protocol'), - template_name="public/download.html", - template_object_name="mirror_url") +@cache_control(max_age=307) +def people(request, slug): + group = get_object_or_404(StaffGroup, slug=slug) + users = User.objects.filter(groups=group.group).order_by( + 'first_name', 'last_name').select_related('userprofile') + + context = {'group': group, 'users': users} + return render(request, 'public/userlist.html', context) + + +def _mirror_urls(): + '''In order to ensure this is lazily evaluated since we can't do + sorting at the database level, make it a callable.''' + urls = MirrorUrl.objects.select_related('mirror').filter( + active=True, protocol__default=True, + mirror__public=True, mirror__active=True, mirror__isos=True) + sort_by = attrgetter('country.name', 'mirror.name') + return sorted(urls, key=sort_by) + +@cache_control(max_age=307) def feeds(request): + repos = Repo.objects.all() + if not request.user.is_authenticated(): + repos = repos.filter(staging=False) context = { 'arches': Arch.objects.all(), - 'repos': Repo.objects.all(), + 'repos': repos, } - return direct_to_template(request, 'public/feeds.html', context) + return render(request, 'public/feeds.html', context) + + +@cache_control(max_age=307) +def keys(request): + profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') + users = User.objects.filter( + is_active=True, userprofile__id__in=profile_ids).select_related( + 'userprofile__pgp_key').order_by('first_name', 'last_name') + user_key_ids = frozenset(user.userprofile.pgp_key[-16:] for user in users + if user.userprofile.pgp_key) + + 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(not_expired, revoked__isnull=True, + signee__in=user_key_ids).order_by().values_list('signer').annotate( + Count('signer')) + sig_counts = {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) + + # frozenset because we are going to do lots of __contains__ lookups + signatures = frozenset(PGPSignature.objects.filter( + not_expired, revoked__isnull=True).values_list('signer', 'signee')) + + restrict = Q(signer__in=user_key_ids) & Q(signee__in=user_key_ids) + cross_signatures = PGPSignature.objects.filter( + not_expired, revoked__isnull=True).order_by('created') + # filter in python so we aren't sending a crazy long query to the DB + cross_signatures = [s for s in cross_signatures + if s.signer in user_key_ids and s.signee in user_key_ids] + + developer_keys = DeveloperKey.objects.select_related( + 'owner').filter(owner__isnull=False) + developer_keys = {key.key[-16:]: key for key in developer_keys} + + context = { + 'keys': master_keys, + 'active_users': users, + 'signatures': signatures, + 'cross_signatures': cross_signatures, + 'developer_keys': developer_keys, + } + return render(request, 'public/keys.html', context) + + +@cache_page(1789) +def keys_json(request): + profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') + users = User.objects.filter( + is_active=True, userprofile__id__in=profile_ids).select_related( + 'userprofile__pgp_key').order_by('first_name', 'last_name') + node_list = [{ + 'name': user.get_full_name(), + 'key': user.userprofile.pgp_key, + 'group': 'packager' + } for user in users] + + master_keys = MasterKey.objects.select_related('owner').filter( + revoked__isnull=True) + node_list.extend({ + 'name': 'Master Key (%s)' % key.owner.get_full_name(), + 'key': key.pgp_key, + 'group': 'master' + } for key in master_keys) + + node_list.append({ + 'name': 'CA Cert Signing Authority', + 'key': 'A31D4F81EF4EBD07B456FA04D2BB0D0165D0FD58', + 'group': 'cacert', + }) + + not_expired = Q(expires__gt=datetime.utcnow) | Q(expires__isnull=True) + signatures = PGPSignature.objects.filter(not_expired, revoked__isnull=True) + edge_list = [{ 'signee': sig.signee, 'signer': sig.signer } + for sig in signatures] + + data = { 'nodes': node_list, 'edges': edge_list } + + to_json = json.dumps(data, ensure_ascii=False) + return HttpResponse(to_json, content_type='application/json') # vim: set ts=4 sw=4 et: |