Make the submit tool use the access token framework with a bit of backwards compatibility glue

- Legacy-Id: 6717
This commit is contained in:
Ole Laursen 2013-11-15 16:09:05 +00:00
parent 6174e72036
commit 650d8316eb
8 changed files with 44 additions and 33 deletions

View file

@ -13,7 +13,7 @@ class SubmissionAdmin(admin.ModelAdmin):
def status_link(self, instance):
url = urlreverse('submit_submission_status_by_hash',
kwargs=dict(submission_id=instance.pk,
access_key=instance.access_key))
access_token=instance.access_token()))
return '<a href="%s">%s</a>' % (url, instance.state)
status_link.allow_tags = True

View file

@ -8,6 +8,7 @@ from ietf.doc.models import Document
from ietf.person.models import Person
from ietf.group.models import Role
from ietf.message.models import Message
from ietf.utils.accesstoken import generate_access_token
def submission_confirmation_email_list(submission):
try:
@ -25,8 +26,8 @@ def send_submission_confirmation(request, submission):
from_email = settings.IDSUBMIT_FROM_EMAIL
to_email = submission_confirmation_email_list(submission)
confirm_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_confirm_submission', kwargs=dict(submission_id=submission.pk, auth_key=submission.auth_key))
status_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash', kwargs=dict(submission_id=submission.pk, access_key=submission.access_key))
confirm_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_confirm_submission', kwargs=dict(submission_id=submission.pk, auth_token=generate_access_token(submission.auth_key)))
status_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash', kwargs=dict(submission_id=submission.pk, access_token=submission.access_token()))
send_mail(request, to_email, from_email, subject, 'submit/confirm_submission.txt', {
'submission': submission,
@ -40,9 +41,8 @@ def send_full_url(request, submission):
subject = 'Full URL for managing submission of draft %s' % submission.name
from_email = settings.IDSUBMIT_FROM_EMAIL
to_email = submission_confirmation_email_list(submission)
url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash',
kwargs=dict(submission_id=submission.pk,
access_key=submission.access_key))
url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash', kwargs=dict(submission_id=submission.pk, access_token=submission.access_token()))
send_mail(request, to_email, from_email, subject, 'submit/full_url.txt', {
'submission': submission,
'url': url,

View file

@ -6,7 +6,7 @@ from django.db import models
from ietf.person.models import Person
from ietf.group.models import Group
from ietf.name.models import DraftSubmissionStateName
from ietf.utils.uniquekey import generate_unique_key
from ietf.utils.accesstoken import generate_random_key, generate_access_token
def parse_email_line(line):
@ -21,7 +21,7 @@ class Submission(models.Model):
state = models.ForeignKey(DraftSubmissionStateName)
remote_ip = models.CharField(max_length=100, blank=True)
access_key = models.CharField(max_length=255, default=generate_unique_key)
access_key = models.CharField(max_length=255, default=generate_random_key)
auth_key = models.CharField(max_length=255, blank=True)
# draft metadata
@ -59,6 +59,9 @@ class Submission(models.Model):
def submitter_parsed(self):
return parse_email_line(self.submitter)
def access_token(self):
return generate_access_token(self.access_key)
class SubmissionEvent(models.Model):
submission = models.ForeignKey(Submission)

View file

@ -6,9 +6,9 @@ urlpatterns = patterns('ietf.submit.views',
url(r'^status/$', 'search_submission', name='submit_search_submission'),
url(r'^status/(?P<submission_id>\d+)/$', 'submission_status', name='submit_submission_status'),
url(r'^status/(?P<submission_id>\d+)/edit/$', 'edit_submission', name='submit_edit_submission'),
url(r'^status/(?P<submission_id>\d+)/confirm/(?P<auth_key>[a-f\d]+)/$', 'confirm_submission', name='submit_confirm_submission'),
url(r'^status/(?P<submission_id>\d+)/(?P<access_key>[a-f\d]*)/$', 'submission_status', name='submit_submission_status_by_hash'),
url(r'^status/(?P<submission_id>\d+)/(?P<access_key>[a-f\d]+)/edit/$', 'edit_submission', name='submit_edit_submission_by_hash'),
url(r'^status/(?P<submission_id>\d+)/confirm/(?P<auth_token>[a-f\d]+)/$', 'confirm_submission', name='submit_confirm_submission'),
url(r'^status/(?P<submission_id>\d+)/(?P<access_token>[a-f\d]*)/$', 'submission_status', name='submit_submission_status_by_hash'),
url(r'^status/(?P<submission_id>\d+)/(?P<access_token>[a-f\d]+)/edit/$', 'edit_submission', name='submit_edit_submission_by_hash'),
url(r'^note-well/$', 'note_well', name='submit_note_well'),
url(r'^tool-instructions/$', 'tool_instructions', name='submit_tool_instructions'),

View file

@ -21,7 +21,7 @@ from ietf.submit.utils import approvable_submissions_for_user, preapprovals_for_
from ietf.submit.utils import check_idnits, found_idnits, validate_submission, create_submission_event
from ietf.submit.utils import post_submission, cancel_submission, rename_submission_files
from ietf.submit.mail import send_full_url, send_approval_request_to_group, send_submission_confirmation, submission_confirmation_email_list, send_manual_post_request
from ietf.utils.uniquekey import generate_unique_key
from ietf.utils.accesstoken import generate_random_key, generate_access_token
def upload_submission(request):
if request.method == 'POST':
@ -89,7 +89,7 @@ def upload_submission(request):
create_submission_event(request, submission, desc="Uploaded submission")
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_key=submission.access_key)
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_token=submission.access_token())
except IOError as e:
if "read error" in str(e): # The server got an IOError when trying to read POST data
form = UploadForm(request=request)
@ -128,23 +128,26 @@ def search_submission(request):
'name': name},
context_instance=RequestContext(request))
def can_edit_submission(request, submission, access_key):
key_matched = access_key and submission.access_key == access_key
def can_edit_submission(request, submission, access_token):
key_matched = access_token and submission.access_token() == access_token
if not key_matched: key_matched = submission.access_key == access_token # backwards-compat
return key_matched or has_role(request.user, "Secretariat")
def submission_status(request, submission_id, access_key=None, message=None):
def submission_status(request, submission_id, access_token=None):
submission = get_object_or_404(Submission, pk=submission_id)
if access_key and submission.access_key != access_key:
key_matched = access_token and submission.access_token() == access_token
if not key_matched: key_matched = submission.access_key == access_token # backwards-compat
if access_token and not key_matched:
raise Http404
errors = validate_submission(submission)
passes_idnits = found_idnits(submission.idnits_message)
key_matched = access_key and submission.access_key == access_key
is_secretariat = has_role(request.user, "Secretariat")
is_chair = submission.group and submission.group.has_role(request.user, "chair")
can_edit = can_edit_submission(request, submission, access_key) and submission.state_id == "uploaded"
can_edit = can_edit_submission(request, submission, access_token) and submission.state_id == "uploaded"
can_cancel = (key_matched or is_secretariat) and submission.state.next_states.filter(slug="cancel")
can_group_approve = (is_secretariat or is_chair) and submission.state_id == "grp-appr"
can_force_post = is_secretariat and submission.state.next_states.filter(slug="posted")
@ -161,8 +164,10 @@ def submission_status(request, submission_id, access_key=None, message=None):
requires_prev_authors_approval = Document.objects.filter(name=submission.name)
message = None
if submission.state_id == "cancel":
message = ('error', 'This submission has been cancelled, modification is no longer possible.')
message = ('error', 'This submission has been canceled, modification is no longer possible.')
elif submission.state_id == "auth":
message = ('success', u'The submission is pending email authentication. An email has been sent to: %s' % ",".join(confirmation_list))
elif submission.state_id == "grp-appr":
@ -192,7 +197,7 @@ def submission_status(request, submission_id, access_key=None, message=None):
desc = "sent approval email to group chairs: %s" % u", ".join(sent_to)
else:
submission.auth_key = generate_unique_key()
submission.auth_key = generate_random_key()
if requires_prev_authors_approval:
submission.state = DraftSubmissionStateName.objects.get(slug="aut-appr")
else:
@ -208,11 +213,11 @@ def submission_status(request, submission_id, access_key=None, message=None):
create_submission_event(request, submission, u"Set submitter to \"%s\" and %s" % (submission.submitter, desc))
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_key=access_key)
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_token=access_token)
elif action == "edit" and submission.state_id == "uploaded":
if access_key:
return redirect("submit_edit_submission_by_hash", submission_id=submission.pk, access_key=access_key)
if access_token:
return redirect("submit_edit_submission_by_hash", submission_id=submission.pk, access_token=access_token)
else:
return redirect("submit_edit_submission", submission_id=submission.pk)
@ -229,7 +234,7 @@ def submission_status(request, submission_id, access_key=None, message=None):
cancel_submission(submission)
create_submission_event(request, submission, "Cancelled submission")
create_submission_event(request, submission, "Canceled submission")
return redirect("submit_submission_status", submission_id=submission_id)
@ -284,10 +289,10 @@ def submission_status(request, submission_id, access_key=None, message=None):
context_instance=RequestContext(request))
def edit_submission(request, submission_id, access_key=None):
def edit_submission(request, submission_id, access_token=None):
submission = get_object_or_404(Submission, pk=submission_id, state="uploaded")
if not can_edit_submission(request.user, submission, access_key):
if not can_edit_submission(request.user, submission, access_token):
return HttpResponseForbidden('You do not have permission to access this page')
errors = validate_submission(submission)
@ -360,10 +365,13 @@ def edit_submission(request, submission_id, access_key=None):
context_instance=RequestContext(request))
def confirm_submission(request, submission_id, auth_key):
def confirm_submission(request, submission_id, auth_token):
submission = get_object_or_404(Submission, pk=submission_id)
if request.method == 'POST' and submission.state_id in ("auth", "aut-appr") and auth_key == submission.auth_key:
key_matched = submission.auth_key and auth_token == generate_access_token(submission.auth_key)
if not key_matched: key_matched = auth_token == submission.auth_key # backwards-compat
if request.method == 'POST' and submission.state_id in ("auth", "aut-appr") and key_matched:
post_submission(request, submission)
create_submission_event(request, submission, "Confirmed and posted submission")
@ -372,7 +380,7 @@ def confirm_submission(request, submission_id, auth_key):
return render_to_response('submit/confirm_submission.html', {
'submission': submission,
'auth_key': auth_key,
'key_matched': key_matched,
}, context_instance=RequestContext(request))

View file

@ -4,7 +4,7 @@ Hi,
Chair approval is needed for posting of {{ submission.name }}-{{ submission.rev }}.
To approve the draft, go to this URL (note: you need to login to be able to approve):
https://{{ domain }}/submit/status/{{ submission.pk }}/{{ submission.access_key }}/
https://{{ domain }}{% url submit_submission_status_by_hash submission_id=submission.pk access_token=submission.access_token %}
File name : {{ submission.name }}
Revision : {{ submission.rev }}

View file

@ -28,7 +28,7 @@ table.preapprovals tr:hover td a.cancel { visibility: visible; }
</tr>
{% for s in approvals %}
<tr>
<td><a href="{% url submit_submission_status_by_hash submission_id=s.pk access_key=s.access_key %}">{{ s.name }}-{{ s.rev }}</a></td>
<td><a href="{% url submit_submission_status_by_hash submission_id=s.pk access_token=s.access_token %}">{{ s.name }}-{{ s.rev }}</a></td>
<td>{{ s.submission_date }}</td>
</tr>
{% endfor %}

View file

@ -23,7 +23,7 @@ p.error { color: red; font-weight: bold; font-size: 1.5em; }
{% endif %}
{% else %}
{% if auth_key != submission.auth_key %}
{% if not key_matched %}
<p class="error">Incorrect authorization key.</p>
<p>Double-check the link you followed. If everything fails, you can go to