Rename /sync/iana|rfceditor/update/ to /sync/iana|rfceditor/notify/,

and put the thing to notify in the URL, like
/sync/iana/notify/changes/, instead of using POST parameters; refactor
the two sync views to use the same for IANA and RFC Editor; require
Secretariat or IANA/RFC Editor roles for triggering the updates and
support passing username and password for auth to make it easier in
the other end once we move away from HTTP Auth
 - Legacy-Id: 4868
This commit is contained in:
Ole Laursen 2012-09-20 11:53:56 +00:00
parent 444a57a266
commit ff077f4b1f
4 changed files with 88 additions and 80 deletions

View file

@ -2,7 +2,6 @@ from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('',
url(r'^discrepancies/$', 'ietf.sync.views.discrepancies'),
url(r'^iana/update/$', 'ietf.sync.views.update_iana'),
url(r'^rfc-editor/update/$', 'ietf.sync.views.update_rfc_editor'),
url(r'^(?P<org>\w+)/notify/(?P<notification>\w+)/$', 'ietf.sync.views.notify'),
)

View file

@ -1,13 +1,15 @@
import subprocess, os
from django.http import HttpResponse
from django.http import HttpResponse, HttpResponseForbidden
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.template.loader import render_to_string
from django.conf import settings
from django import forms
from django.db.models import Q
from django.contrib.auth.models import User
from ietf.ietfauth.decorators import role_required
from ietf.ietfauth.decorators import role_required, has_role
from ietf.doc.models import *
from ietf.sync import iana, rfceditor
from ietf.sync.discrepancies import find_discrepancies
@ -22,58 +24,79 @@ def discrepancies(request):
dict(sections=sections),
context_instance=RequestContext(request))
def notify(request, org, notification):
"""Notify that something has changed at another site to trigger a
run of one of the sync scripts."""
class UpdateIanaForm(forms.Form):
protocols_page = forms.BooleanField(initial=False, required=False, help_text="For when a reference to an RFC has been added to <a href=\"%s\">the IANA protocols page</a>" % iana.PROTOCOLS_URL)
changes = forms.BooleanField(initial=False, required=False, help_text="For new changes at <a href=\"%s\">the changes JSON dump</a>" % iana.CHANGES_URL)
known_orgs = {
"iana": "IANA",
"rfceditor": "RFC Editor",
}
def update_iana(request):
if request.method == 'POST':
form = UpdateIanaForm(request.POST)
if form.is_valid():
failed = False
if form.cleaned_data["protocols_page"]:
failed = failed or subprocess.call(["python", os.path.join(SYNC_BIN_PATH, "iana-protocols-updates")])
if form.cleaned_data["changes"]:
failed = failed or subprocess.call(["python", os.path.join(SYNC_BIN_PATH, "iana-changes-updates")])
if org not in known_orgs:
raise Http404
if failed:
return HttpResponse("FAIL")
else:
return HttpResponse("OK")
else:
form = UpdateIanaForm()
# handle auth, to make it easier for the other end, you can send
# the username/password as POST parameters instead of having to
# visit the login page
user = request.user
return render_to_response('sync/update.html',
dict(form=form,
org="IANA",
),
context_instance=RequestContext(request))
class UpdateRFCEditorForm(forms.Form):
queue = forms.BooleanField(initial=False, required=False, help_text="For when <a href=\"%s\">queue2.xml</a> has been updated" % rfceditor.QUEUE_URL)
index = forms.BooleanField(initial=False, required=False, help_text="For when <a href=\"%s\">rfc-index.xml</a> has been updated" % rfceditor.INDEX_URL)
def update_rfc_editor(request):
if request.method == 'POST':
form = UpdateRFCEditorForm(request.POST)
if form.is_valid():
failed = False
if form.cleaned_data["queue"]:
failed = failed or subprocess.call(["python", os.path.join(SYNC_BIN_PATH, "rfc-editor-queue-updates")])
if form.cleaned_data["index"]:
failed = failed or subprocess.call(["python", os.path.join(SYNC_BIN_PATH, "rfc-editor-index-updates")])
if failed:
return HttpResponse("FAIL")
else:
return HttpResponse("OK")
else:
form = UpdateRFCEditorForm()
return render_to_response('sync/update.html',
dict(form=form,
org="RFC Editor",
username = request.POST.get("username") or request.GET.get("username")
password = request.POST.get("password") or request.GET.get("password")
if username and password:
if settings.SERVER_MODE == "production" and not request.is_secure():
return HttpResponseForbidden("You must use HTTPS when sending username/password")
if not user.is_authenticated():
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
return HttpResponse("Invalid username/password")
if not user.check_password(password):
return HttpResponse("Invalid username/password")
if not has_role(user, ("Secretariat", known_orgs[org])):
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
known_notifications = {
"protocols": "an added reference to an RFC at <a href=\"%s\">the IANA protocols page</a>" % iana.PROTOCOLS_URL,
"changes": "new changes at <a href=\"%s\">the changes JSON dump</a>" % iana.CHANGES_URL,
"queue": "new changes to <a href=\"%s\">queue2.xml</a>" % rfceditor.QUEUE_URL,
"index": "new changes to <a href=\"%s\">rfc-index.xml</a>" % rfceditor.INDEX_URL,
}
if notification not in known_notifications:
raise Http404
if request.method == "POST":
def runscript(name):
p = subprocess.Popen(["python", os.path.join(SYNC_BIN_PATH, name)],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = p.communicate()
return (p.returncode, out)
if notification == "protocols":
failed, out = runscript("iana-protocols-updates")
if notification == "changes":
failed, out = runscript("iana-changes-updates")
if notification == "queue":
failed, out = runscript("rfc-editor-queue-updates")
if notification == "index":
failed, out = runscript("rfc-editor-index-updates")
if failed:
return HttpResponse("FAIL\n\n" + out, content_type="text/plain")
else:
return HttpResponse("OK", content_type="text/plain")
return render_to_response('sync/notify.html',
dict(org=known_orgs[org],
notification=notification,
help_text=known_notifications[notification],
),
context_instance=RequestContext(request))

View file

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block title %}Trigger {{ notification }} sync for {{ org }}{% endblock %}
{% block content %}
<h1>Trigger {{ notification }} sync for {{ org }}</h1>
<p>Update the Datatracker with {{ help_text|safe }} at {{ org }}.</p>
<form class="sync-form" notification="" method="post">
<input type="submit" value="Trigger {{ notification }} sync"/>
</form>
{% endblock %}

View file

@ -1,27 +0,0 @@
{% extends "base.html" %}
{% block title %}Trigger sync for {{ org }}{% endblock %}
{% block morecss %}
.sync-form .help { font-style: italic; padding-left: 2em; }
.sync-form input[type=submit] { margin-top: 1em; }
{% endblock %}
{% block content %}
<h1>Trigger sync for {{ org }}</h1>
<p>Update the Datatracker with information from {{ org }}. Select
which parts to trigger a sync for:</p>
<form class="sync-form" action="" method="post">
{% for field in form %}
<div>
{{ field }}
{{ field.label_tag }}
{% if field.help_text %}<span class="help">{{ field.help_text|safe }}</span>{% endif %}
</div>
{% endfor %}
<input type="submit" value="Trigger sync"/>
</form>
{% endblock %}