summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README112
-rw-r--r--devel/management/commands/reporead.py2
-rw-r--r--main/models.py4
-rw-r--r--main/templatetags/pgp.py8
-rw-r--r--mirrors/views.py2
-rw-r--r--packages/views/__init__.py28
-rw-r--r--packages/views/signoff.py2
-rw-r--r--public/views.py21
-rw-r--r--requirements_prod.txt4
-rw-r--r--sitestatic/archweb.css8
-rw-r--r--templates/mirrors/status.html4
-rw-r--r--templates/mirrors/status_table.html4
-rw-r--r--templates/packages/search.html4
-rw-r--r--templates/packages/signoff_cell.html2
-rw-r--r--templates/packages/signoffs.html12
-rw-r--r--templates/public/keys.html56
-rw-r--r--templates/releng/result_section.html1
-rw-r--r--urls.py16
-rw-r--r--visualize/views.py2
19 files changed, 177 insertions, 115 deletions
diff --git a/README b/README
index de19db5e..32f9b2bb 100644
--- a/README
+++ b/README
@@ -1,4 +1,15 @@
# Parabolaweb README
+It is recommended that you just install the (parabola) package
+`parabolaweb-utils`, it
+
+ - depends on the dependencies of parabolaweb
+ - offers initscripts and systemd service files for parabolaweb
+ - has a `parabolaweb-update` script that does most of the things here.
+
+Following is Archweb's readme, as I figure it might be useful for some people,
+but I have given up on maintaining it for parabolaweb.
+
+# Archweb README
To get a pretty version of this document, run
@@ -15,97 +26,62 @@ See AUTHORS file.
# Dependencies
- python2
-- python2-virtualenv (if using pip to manage dependencies)
+- python2-virtualenv
# Python dependencies
-We're going to use pip to handle python dependencies, m'kay?
-Worry about that in step 3.
-
-If you really want to manage dependencies using something other than
-pip, look at `requirements.txt`, and at the comments on other
-dependiencies in step 3.
-
-# Testing Installation
-
-Throughout this, we assume that parabolaweb is installed in a
-directory called `parabolaweb`. This is not necessarily true. On the
-main server, it's in `/srv/http/web'. Wherever you see this in a
-command, know that you should just replace it with the correct path
-for your install.
-
-1. Run `virtualenv2`.
-
- $ cd /path/to/parabolaweb && virtualenv2 `pwd`-env
-
- Here I just had you use `pwd` to choose the environment
- directory. You can use anything, but it is recommended that it not
- be the same directory as the install.
+More detail in `requirements.txt` and `requirements_prod.txt`; it is best to
+use virtualenv and pip to handle these. But if you insist on (Arch Linux)
+packages, you will probably want the following:
-2. Activate the virtualenv.
+- mysql-python or python-pysqlite
+- django
+- python-markdown
+- python-south
+- python-memcached
- $ source `pwd`-env/bin/activate
-
-3. Fix symlink to the environment
-
- (parabolaweb-env) $ ln -sf ../../parabolaweb-env/lib/python2.7/site-packages/django/contrib/admin/media media/admin_media
-
- Of course change `../../parabolaweb-env` to the relative path to
- your environment. Keep in mind that the path is relative from
- inside the `media/` directory, not the current directory.
-
-4. Install dependencies through `pip`.
-
- To install base dependencies, run
-
- (parabolweb-env) $ pip install -r requirements.txt
-
- After that you will need to install a database engine for python
- This means `MySQL-python==1.2.3`, `pysqlite` or `psycopg2` for
- PostgreSQL. Eg:
+# Testing Installation
- (parabolweb-env) $ pip install MySQL-python==1.2.3
+1. Run `virtualenv2`.
- You may also want to install memcached
+ $ cd /path/to/archweb && virtualenv2 ../archweb-env
- (parabolweb-env) $ pip install python-memcached==1.47
+2. Activate the virtualenv.
- Alternately, to have psycopg2 and memcached installed automatically,
- run
+ $ source ../archweb-env/bin/activate
- (parabolweb-env) $ pip install -r requirements_prod.txt
+2. Install dependencies through `pip`.
- We use PostgreSQL on the main server, and you may have problems
- with other SQLs.
+ (archweb-env) $ pip install -r requirements.txt
-5. Copy `local_settings.py.example` to `local_settings.py` and modify.
- Make sure to uncomment the appropriate db section.
+3. Copy `local_settings.py.example` to `local_settings.py` and modify.
+ Make sure to uncomment the appropriate db section (either sqlite or mysql).
-6. Sync the database to create it.
+4. Sync the database to create it.
- (parabolaweb-env) $ ./manage.py syncdb
+ (archweb-env) $ ./manage.py syncdb
-7. Migrate changes.
+5. Migrate changes.
- (parabolaweb-env) $ ./manage.py migrate
+ (archweb-env) $ ./manage.py migrate
-8. Load the fixtures to prepopulate some data. If you don't want some
- of the provided data, adjust the file glob accordingly.
+6. Load the fixtures to prepopulate some data. If you don't want some of the
+ provided data, adjust the file glob accordingly.
- (parabolaweb-env) $ ./manage.py loaddata */fixtures/*.json
+ (archweb-env) $ ./manage.py loaddata */fixtures/*.json
-9. Use the following commands to start a service instance
+7. Use the following commands to start a service instance
- (parabolaweb-env) $ ./manage.py runserver
+ (archweb-env) $ ./manage.py runserver
-10. To optionally populate the database with real data:
+8. To optionally populate the database with real data:
- $ wget https://repo.parabolagnulinux.org/core/os/i686/core.db.tar.gz
- $ ./manage.py reporead i686 core.db.tar.gz
- $ ./manage.py syncisos
+ (archweb-env) $ wget ftp://ftp.archlinux.org/core/os/i686/core.db.tar.gz
+ (archweb-env) $ ./manage.py reporead i686 core.db.tar.gz
+ (archweb-env) $ ./manage.py syncisos
- Alter architecture and repo to get x86\_64 and packages from
- other repos if needed.
+Alter architecture and repo to get x86\_64 and packages from other repos if
+needed.
# Production Installation
diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py
index 57c8715a..cf98f004 100644
--- a/devel/management/commands/reporead.py
+++ b/devel/management/commands/reporead.py
@@ -234,7 +234,7 @@ def populate_pkg(dbpkg, repopkg, force=False, timestamp=None):
populate_files(dbpkg, repopkg, force=force)
- dbpkg.packagedepend_set.all().delete()
+ dbpkg.depends.all().delete()
deps = [create_depend(dbpkg, y) for y in repopkg.depends]
deps += [create_depend(dbpkg, y, True) for y in repopkg.optdepends]
PackageDepend.objects.bulk_create(deps)
diff --git a/main/models.py b/main/models.py
index 289cbb84..34cbcd17 100644
--- a/main/models.py
+++ b/main/models.py
@@ -288,7 +288,7 @@ class Package(models.Model):
if not self.arch.agnostic:
arches = self.applicable_arches()
# TODO: we can use list comprehension and an 'in' query to make this more effective
- for dep in self.packagedepend_set.order_by('optional', 'depname'):
+ for dep in self.depends.order_by('optional', 'depname'):
pkg = dep.get_best_satisfier(arches, testing=self.repo.testing,
staging=self.repo.staging)
providers = None
@@ -391,7 +391,7 @@ class PackageFile(models.Model):
db_table = 'package_files'
class PackageDepend(models.Model):
- pkg = models.ForeignKey(Package)
+ pkg = models.ForeignKey(Package, related_name='depends')
depname = models.CharField(max_length=255, db_index=True)
depvcmp = models.CharField(max_length=255, default='')
optional = models.BooleanField(default=False)
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/mirrors/views.py b/mirrors/views.py
index 2ef8654d..e93097a3 100644
--- a/mirrors/views.py
+++ b/mirrors/views.py
@@ -169,7 +169,7 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder):
def status_json(request):
status_info = get_mirror_statuses()
data = status_info.copy()
- data['version'] = 1
+ data['version'] = 2
to_json = simplejson.dumps(data, ensure_ascii=False,
cls=MirrorStatusJSONEncoder)
response = HttpResponse(to_json, mimetype='application/json')
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 08e0286c..aa2721af 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -1,3 +1,6 @@
+from string import Template
+from urllib import urlencode
+
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import User
@@ -9,12 +12,10 @@ from django.views.decorators.http import require_POST
from django.views.decorators.vary import vary_on_headers
from django.views.generic.simple import direct_to_template
-from string import Template
-from urllib import urlencode
-
-from main.models import Package, PackageFile, Arch, Repo
+from main.models import Package, PackageFile, PackageDepend, Arch, Repo
from mirrors.models import MirrorUrl
-from ..models import PackageRelation, PackageGroup
+from ..models import (PackageRelation, PackageGroup, License,
+ Conflict, Provision, Replacement)
from ..utils import (get_group_info, get_differences_info,
multilib_differences, get_wrong_permissions)
@@ -29,6 +30,8 @@ class PackageJSONEncoder(DjangoJSONEncoder):
'pkgrel', 'epoch', 'pkgdesc', 'url', 'filename', 'compressed_size',
'installed_size', 'build_date', 'last_update', 'flag_date',
'maintainers', 'packager' ]
+ pkg_list_attributes = [ 'groups', 'licenses', 'conflicts',
+ 'provides', 'replaces', 'depends' ]
def default(self, obj):
if hasattr(obj, '__iter__'):
@@ -37,13 +40,18 @@ class PackageJSONEncoder(DjangoJSONEncoder):
if isinstance(obj, Package):
data = dict((attr, getattr(obj, attr))
for attr in self.pkg_attributes)
- data['groups'] = obj.groups.all()
+ for attr in self.pkg_list_attributes:
+ data[attr] = getattr(obj, attr).all()
return data
if isinstance(obj, PackageFile):
filename = obj.filename or ''
return obj.directory + filename
- if isinstance(obj, (Repo, Arch, PackageGroup)):
+ if isinstance(obj, (Repo, Arch)):
return obj.name.lower()
+ if isinstance(obj, (PackageGroup, License)):
+ return obj.name
+ if isinstance(obj, (Conflict, Provision, Replacement, PackageDepend)):
+ return unicode(obj)
elif isinstance(obj, User):
return obj.username
return super(PackageJSONEncoder, self).default(obj)
@@ -177,7 +185,8 @@ def group_details(request, arch, name):
def files(request, name, repo, arch):
pkg = get_object_or_404(Package,
pkgname=name, repo__name__iexact=repo, arch__name=arch)
- fileslist = PackageFile.objects.filter(pkg=pkg).order_by('directory', 'filename')
+ # files are inserted in sorted order, so preserve that
+ fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
dir_count = sum(1 for f in fileslist if f.is_directory)
files_count = len(fileslist) - dir_count
context = {
@@ -201,7 +210,8 @@ def details_json(request, name, repo, arch):
def files_json(request, name, repo, arch):
pkg = get_object_or_404(Package,
pkgname=name, repo__name__iexact=repo, arch__name=arch)
- fileslist = PackageFile.objects.filter(pkg=pkg).order_by('directory', 'filename')
+ # files are inserted in sorted order, so preserve that
+ fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
data = {
'pkgname': pkg.pkgname,
'repo': pkg.repo.name.lower(),
diff --git a/packages/views/signoff.py b/packages/views/signoff.py
index cf00b0b9..63341a1d 100644
--- a/packages/views/signoff.py
+++ b/packages/views/signoff.py
@@ -180,7 +180,7 @@ class SignoffJSONEncoder(DjangoJSONEncoder):
def signoffs_json(request):
signoff_groups = sorted(get_signoff_groups(), key=attrgetter('pkgbase'))
data = {
- 'version': 1,
+ 'version': 2,
'signoff_groups': signoff_groups,
}
to_json = simplejson.dumps(data, ensure_ascii=False,
diff --git a/public/views.py b/public/views.py
index a8ce2fa7..e031201e 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.shortcuts import redirect
from django.views.decorators.cache import cache_control
@@ -71,17 +73,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/requirements_prod.txt b/requirements_prod.txt
index 80fa2b5b..bb67fc5b 100644
--- a/requirements_prod.txt
+++ b/requirements_prod.txt
@@ -1,8 +1,8 @@
-Django==1.4
+Django>=1.4
Markdown>=2.1.1
-psycopg2
South>=0.7.4
pgpdump>=1.1
+psycopg2>=2.4.4
pyinotify>=0.9.2
python-memcached>=1.48
pytz>=2012b
diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css
index 180cb05a..ced1fd2a 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/mirrors/status.html b/templates/mirrors/status.html
index 307b96dd..cce6d983 100644
--- a/templates/mirrors/status.html
+++ b/templates/mirrors/status.html
@@ -89,7 +89,7 @@
</thead>
<tbody>
{% for log in error_logs %}
- <tr class="{% cycle 'odd' 'even' %}">
+ {% spaceless %}<tr class="{% cycle 'odd' 'even' %}">
<td>{{ log.url__url }}</td>
<td>{{ log.url__protocol__protocol }}</td>
<td>{{ log.country }}</td>
@@ -97,7 +97,7 @@
<td>{{ log.last_occurred|date:'Y-m-d H:i' }}</td>
<td>{{ log.error_count }}</td>
</tr>
- {% endfor %}
+ {% endspaceless %}{% endfor %}
</tbody>
</table>
diff --git a/templates/mirrors/status_table.html b/templates/mirrors/status_table.html
index 72de25dc..bd70115c 100644
--- a/templates/mirrors/status_table.html
+++ b/templates/mirrors/status_table.html
@@ -15,7 +15,7 @@
</thead>
<tbody>
{% for m_url in urls %}
- <tr class="{% cycle 'odd' 'even' %}">
+ {% spaceless %}<tr class="{% cycle 'odd' 'even' %}">
<td>{{ m_url.url }}</td>
<td>{{ m_url.protocol }}</td>
<td>{{ m_url.real_country }}</td>
@@ -26,6 +26,6 @@
<td>{{ m_url.duration_stddev|floatformat:2 }}</td>
<td>{{ m_url.score|floatformat:1|default:'∞' }}</td>
</tr>
- {% endfor %}
+ {% endspaceless %}{% endfor %}
</tbody>
</table>
diff --git a/templates/packages/search.html b/templates/packages/search.html
index b344af1f..974c190b 100644
--- a/templates/packages/search.html
+++ b/templates/packages/search.html
@@ -77,7 +77,7 @@
</thead>
<tbody>
{% for pkg in package_list %}
- <tr class="{% cycle 'odd' 'even' %}">
+ {% spaceless %}<tr class="{% cycle 'odd' 'even' %}">
{% if perms.main.change_package %}
<td><input type="checkbox" name="pkgid" value="{{ pkg.id }}" /></td>
{% endif %}
@@ -94,7 +94,7 @@
<td>{{ pkg.last_update|date }}</td>
<td>{{ pkg.flag_date|date }}</td>
</tr>
- {% endfor %}
+ {% endspaceless %}{% endfor %}
</tbody>
</table>
{% include "packages/search_paginator.html" %}
diff --git a/templates/packages/signoff_cell.html b/templates/packages/signoff_cell.html
index 01a5d58d..7d9e1972 100644
--- a/templates/packages/signoff_cell.html
+++ b/templates/packages/signoff_cell.html
@@ -1,4 +1,3 @@
-{% spaceless %}
{% if group.signoffs %}
<ul class="signoff-list">
{% for signoff in group.signoffs %}
@@ -22,4 +21,3 @@
<a class="signoff-options" href="{{ group.package.get_absolute_url }}signoff/options/">Signoff Options</a>
</div>
{% endif %}
-{% endspaceless %}
diff --git a/templates/packages/signoffs.html b/templates/packages/signoffs.html
index 2d7b04cd..7b79c35b 100644
--- a/templates/packages/signoffs.html
+++ b/templates/packages/signoffs.html
@@ -52,6 +52,7 @@
<tbody id="tbody_signoffs">
{% for group in signoff_groups %}
<tr class="{% cycle 'odd' 'even' %} {{ group.arch.name }} {{ group.target_repo|lower }}">
+ {% spaceless %}
<td>{% pkg_details_link group.package %} {{ group.version }}</td>
<td>{{ group.arch.name }}</td>
<td>{{ group.target_repo }}</td>
@@ -68,12 +69,13 @@
{% endif %}
{% endif %}
<td>{% include "packages/signoff_cell.html" %}</td>
- <td class="wrap">{% if not group.default_spec %}{% with group.specification as spec %}
- {% if spec.required != 2 %}Required signoffs: {{ spec.required }}<br/>{% endif %}
- {% if not spec.enabled %}Signoffs are not currently enabled<br/>{% endif %}
- {% if spec.known_bad %}Package is known to be bad<br/>{% endif %}
- {{ spec.comments|default:""|linebreaksbr }}
+ <td class="wrap">{% if not group.default_spec %}{% with group.specification as spec %}{% comment %}
+ {% endcomment %}{% if spec.required != 2 %}Required signoffs: {{ spec.required }}<br/>{% endif %}{% comment %}
+ {% endcomment %}{% if not spec.enabled %}Signoffs are not currently enabled<br/>{% endif %}{% comment %}
+ {% endcomment %}{% if spec.known_bad %}Package is known to be bad<br/>{% endif %}{% comment %}
+ {% endcomment %}{{ spec.comments|default:""|linebreaksbr }}
{% endwith %}{% endif %}</td>
+ {% endspaceless %}
</tr>
{% endfor %}
</tbody>
diff --git a/templates/public/keys.html b/templates/public/keys.html
index 43b1b067..f0aa310e 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/templates/releng/result_section.html b/templates/releng/result_section.html
index 45838b86..91a75613 100644
--- a/templates/releng/result_section.html
+++ b/templates/releng/result_section.html
@@ -7,7 +7,6 @@
{% for item in option.values %}
<tr>
<td>
- <a href="{% url releng-results-for option.field_name item.value.pk %}">
<a href="{% url 'releng-results-for' option.field_name item.value.pk %}">
{{ item.value.name|lower }}
</a>
diff --git a/urls.py b/urls.py
index d7b3be9b..2ac8271e 100644
--- a/urls.py
+++ b/urls.py
@@ -93,9 +93,17 @@ urlpatterns += patterns('',
(r'^todolists/$','todolists.views.public_list'),
)
-if settings.DEBUG == True:
- urlpatterns += patterns('',
- (r'^media/(.*)$', 'django.views.static.serve',
- {'document_root': os.path.join(settings.DEPLOY_PATH, 'media')}))
+legacy_urls = (
+ ('^about.php', '/about/'),
+ ('^changelog.php', '/packages/?sort=-last_update'),
+ ('^download.php', '/download/'),
+ ('^index.php', '/'),
+ ('^logos.php', '/art/'),
+ ('^news.php', '/news/'),
+)
+
+for old_url, new_url in legacy_urls:
+ urlpatterns += patterns('django.views.generic.simple',
+ (old_url, 'redirect_to', {'url': new_url}))
# vim: set ts=4 sw=4 et:
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]