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:
parent
444a57a266
commit
ff077f4b1f
|
@ -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'),
|
||||
)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
13
ietf/templates/sync/notify.html
Normal file
13
ietf/templates/sync/notify.html
Normal 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 %}
|
|
@ -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 %}
|
Loading…
Reference in a new issue