Email IANA and RFC Editor when a draft is pulled from the queue at the
Datatracker, add page for editing IANA states, add more info to the /doc/draft-XXXXX/doc.json dump for the RFC Editor, add page for editing consensus, add page for requesting publication at the RFC Editor for alternate streams (this will email the RFC Editor and set the draft in the appropriate state), make it possible for alternate streams to change the intended RFC status of a draft in the stream, refactor how IANA copies are handled slightly so it's less code, put drafts automatically in IANA Review "Need Review" state upon last call, fix a bug in ballot issuing, remove a bit of dead code - Legacy-Id: 4857
This commit is contained in:
parent
5c89b8a51d
commit
6062e16c2d
|
@ -62,8 +62,26 @@ def email_stream_changed(request, doc, old_stream, new_stream, text=""):
|
|||
"idrfc/stream_changed_email.txt",
|
||||
dict(text=text,
|
||||
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()))
|
||||
|
||||
def email_pulled_from_rfc_queue(request, doc, comment, prev_state, next_state):
|
||||
send_mail(request, ['IANA <iana@iana.org>', 'rfc-editor@rfc-editor.org'], None,
|
||||
"%s changed state from %s to %s" % (doc.name, prev_state.name, next_state.name),
|
||||
"idrfc/pulled_from_rfc_queue_email.txt",
|
||||
dict(doc=doc,
|
||||
prev_state=prev_state,
|
||||
next_state=next_state,
|
||||
comment=comment,
|
||||
url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()),
|
||||
extra=extra_automation_headers(doc))
|
||||
|
||||
|
||||
def email_authors(request, doc, subject, text):
|
||||
to = [x.strip() for x in doc.author_list().split(',')]
|
||||
if not to:
|
||||
return
|
||||
|
||||
|
||||
send_mail_text(request, to, None, subject, text)
|
||||
|
||||
def html_to_text(html):
|
||||
return strip_tags(html.replace("<", "<").replace(">", ">").replace("&", "&").replace("<br>", "\n"))
|
||||
|
||||
|
@ -98,12 +116,15 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
|||
|
||||
|
||||
def generate_ballot_writeup(request, doc):
|
||||
e = doc.latest_event(type="iana_review")
|
||||
iana = e.desc if e else ""
|
||||
|
||||
e = WriteupDocEvent()
|
||||
e.type = "changed_ballot_writeup_text"
|
||||
e.by = request.user.get_profile()
|
||||
e.doc = doc
|
||||
e.desc = u"Ballot writeup was generated"
|
||||
e.text = unicode(render_to_string("idrfc/ballot_writeup.txt"))
|
||||
e.text = unicode(render_to_string("idrfc/ballot_writeup.txt", {'iana': iana}))
|
||||
e.save()
|
||||
|
||||
return e
|
||||
|
@ -263,6 +284,20 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
|||
generate_approval_mail = generate_approval_mailREDESIGN
|
||||
generate_approval_mail_rfc_editor = generate_approval_mail_rfc_editorREDESIGN
|
||||
|
||||
def generate_publication_request(request, doc):
|
||||
group_description = ""
|
||||
if doc.group and doc.group.acronym != "none":
|
||||
group_description = doc.group.name
|
||||
if doc.group.type_id in ("wg", "rg", "area"):
|
||||
group_description += " %s (%s)" % (doc.group.type, doc.group.acronym)
|
||||
|
||||
|
||||
return render_to_string("idrfc/publication_request.txt",
|
||||
dict(doc=doc,
|
||||
doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
|
||||
group_description=group_description,
|
||||
)
|
||||
)
|
||||
|
||||
def send_last_call_request(request, doc, ballot):
|
||||
to = "iesg-secretary@ietf.org"
|
||||
|
@ -425,39 +460,13 @@ def generate_issue_ballot_mailREDESIGN(request, doc, ballot):
|
|||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
generate_issue_ballot_mail = generate_issue_ballot_mailREDESIGN
|
||||
|
||||
def email_iana(request, doc, to, msg):
|
||||
# fix up message and send message to IANA for each in ballot set
|
||||
import email
|
||||
parsed_msg = email.message_from_string(msg.encode("utf-8"))
|
||||
|
||||
for i in doc.idinternal.ballot_set():
|
||||
extra = {}
|
||||
extra["Reply-To"] = "noreply@ietf.org"
|
||||
extra["X-IETF-Draft-string"] = i.document().filename
|
||||
extra["X-IETF-Draft-revision"] = i.document().revision_display()
|
||||
|
||||
send_mail_text(request, "To: IANA <%s>" % to,
|
||||
parsed_msg["From"], parsed_msg["Subject"],
|
||||
parsed_msg.get_payload(),
|
||||
extra=extra)
|
||||
|
||||
def email_ianaREDESIGN(request, doc, to, msg):
|
||||
# fix up message and send it with extra info on doc in headers
|
||||
import email
|
||||
parsed_msg = email.message_from_string(msg.encode("utf-8"))
|
||||
|
||||
def extra_automation_headers(doc):
|
||||
extra = {}
|
||||
extra["Reply-To"] = "noreply@ietf.org"
|
||||
extra["X-IETF-Draft-string"] = doc.name
|
||||
extra["X-IETF-Draft-revision"] = doc.rev
|
||||
|
||||
send_mail_text(request, "IANA <%s>" % to,
|
||||
parsed_msg["From"], parsed_msg["Subject"],
|
||||
parsed_msg.get_payload(),
|
||||
extra=extra)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
email_iana = email_ianaREDESIGN
|
||||
return extra
|
||||
|
||||
def email_last_call_expired(doc):
|
||||
text = "IETF Last Call has ended, and the state has been changed to\n%s." % doc.idinternal.cur_state.state
|
||||
|
|
|
@ -119,7 +119,61 @@ class ChangeStateTestCase(django.test.TestCase):
|
|||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('.prev-state form input[name="state"]')), 1)
|
||||
|
||||
def test_pull_from_rfc_queue(self):
|
||||
draft = make_test_data()
|
||||
draft.set_state(State.objects.get(type="draft-iesg", slug="rfcqueue"))
|
||||
|
||||
url = urlreverse('doc_change_state', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# change state
|
||||
mailbox_before = len(outbox)
|
||||
|
||||
r = self.client.post(url,
|
||||
dict(state=State.objects.get(type="draft-iesg", slug="review-e").pk,
|
||||
substate="",
|
||||
comment="Test comment"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.get_state_slug("draft-iesg"), "review-e")
|
||||
self.assertEquals(len(outbox), mailbox_before + 2 + 1)
|
||||
self.assertTrue(draft.name in outbox[-1]['Subject'])
|
||||
self.assertTrue("changed state" in outbox[-1]['Subject'])
|
||||
self.assertTrue("is no longer" in str(outbox[-1]))
|
||||
self.assertTrue("Test comment" in str(outbox[-1]))
|
||||
|
||||
def test_change_iana_state(self):
|
||||
draft = make_test_data()
|
||||
|
||||
first_state = State.objects.get(type="draft-iana-review", slug="need-rev")
|
||||
next_state = State.objects.get(type="draft-iana-review", slug="ok-noact")
|
||||
draft.set_state(first_state)
|
||||
|
||||
url = urlreverse('doc_change_iana_state', kwargs=dict(name=draft.name, state_type="iana-review"))
|
||||
login_testing_unauthorized(self, "iana", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form select[name=state]')), 1)
|
||||
|
||||
# faulty post
|
||||
r = self.client.post(url, dict(state="foobarbaz"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form ul.errorlist')) > 0)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.get_state("draft-iana-review"), first_state)
|
||||
|
||||
# change state
|
||||
r = self.client.post(url, dict(state=next_state.pk))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.get_state("draft-iana-review"), next_state)
|
||||
|
||||
def test_request_last_call(self):
|
||||
draft = make_test_data()
|
||||
draft.set_state(State.objects.get(type="draft-iesg", slug="ad-eval"))
|
||||
|
@ -202,7 +256,7 @@ class EditInfoTestCase(django.test.TestCase):
|
|||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.ad, new_ad)
|
||||
self.assertEquals(draft.note, "New note")
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="telechat_date"))
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
|
||||
self.assertEquals(draft.docevent_set.count(), events_before + 3)
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue(draft.name in outbox[-1]['Subject'])
|
||||
|
@ -221,14 +275,14 @@ class EditInfoTestCase(django.test.TestCase):
|
|||
)
|
||||
|
||||
# add to telechat
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, "scheduled_for_telechat"))
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
|
||||
data["telechat_date"] = TelechatDate.objects.active()[0].date.isoformat()
|
||||
r = self.client.post(url, data)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(draft.latest_event(TelechatDocEvent, "scheduled_for_telechat"))
|
||||
self.assertEquals(draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date, TelechatDate.objects.active()[0].date)
|
||||
self.assertTrue(draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
|
||||
self.assertEqual(draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date, TelechatDate.objects.active()[0].date)
|
||||
|
||||
# change telechat
|
||||
data["telechat_date"] = TelechatDate.objects.active()[1].date.isoformat()
|
||||
|
@ -236,7 +290,7 @@ class EditInfoTestCase(django.test.TestCase):
|
|||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date, TelechatDate.objects.active()[1].date)
|
||||
self.assertEqual(draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date, TelechatDate.objects.active()[1].date)
|
||||
|
||||
# remove from agenda
|
||||
data["telechat_date"] = ""
|
||||
|
@ -244,7 +298,7 @@ class EditInfoTestCase(django.test.TestCase):
|
|||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date)
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date)
|
||||
|
||||
def test_start_iesg_process_on_draft(self):
|
||||
make_test_data()
|
||||
|
@ -311,6 +365,18 @@ class EditInfoTestCase(django.test.TestCase):
|
|||
self.assertEquals(events[-3].type, "started_iesg_process")
|
||||
self.assertEquals(len(outbox), mailbox_before)
|
||||
|
||||
def test_edit_consensus(self):
|
||||
draft = make_test_data()
|
||||
|
||||
url = urlreverse('doc_edit_consensus', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
self.assertTrue(not draft.latest_event(ConsensusDocEvent, type="changed_consensus"))
|
||||
r = self.client.post(url, dict(consensus="Yes"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEqual(draft.latest_event(ConsensusDocEvent, type="changed_consensus").consensus, True)
|
||||
|
||||
|
||||
class ResurrectTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
@ -406,6 +472,16 @@ class AddCommentTestCase(django.test.TestCase):
|
|||
self.assertTrue("updated" in outbox[-1]['Subject'])
|
||||
self.assertTrue(draft.name in outbox[-1]['Subject'])
|
||||
|
||||
# Make sure we can also do it as IANA
|
||||
self.client.login(remote_user="iana")
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form textarea[name=comment]')), 1)
|
||||
|
||||
|
||||
class EditPositionTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
|
@ -670,12 +746,21 @@ class BallotWriteupsTestCase(django.test.TestCase):
|
|||
url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# add a IANA review note
|
||||
draft.set_state(State.objects.get(type="draft-iana-review", slug="not-ok"))
|
||||
DocEvent.objects.create(type="iana_review",
|
||||
doc=draft,
|
||||
by=Person.objects.get(user__username="iana"),
|
||||
desc="IANA does not approve of this document, it does not make sense.",
|
||||
)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('textarea[name=ballot_writeup]')), 1)
|
||||
self.assertEquals(len(q('input[type=submit][value*="Save Ballot Writeup"]')), 1)
|
||||
self.assertTrue("IANA does not" in r.content)
|
||||
|
||||
# save
|
||||
r = self.client.post(url, dict(
|
||||
|
@ -869,6 +954,44 @@ class MakeLastCallTestCase(django.test.TestCase):
|
|||
self.assertTrue("Last Call" in outbox[-3]['Subject'])
|
||||
self.assertTrue("Last Call" in draft.message_set.order_by("-time")[0].subject)
|
||||
|
||||
class RequestPublicationTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_request_publication(self):
|
||||
draft = make_test_data()
|
||||
draft.stream = StreamName.objects.get(slug="iab")
|
||||
draft.group = Group.objects.get(acronym="iab")
|
||||
draft.intended_std_level = IntendedStdLevelName.objects.get(slug="inf")
|
||||
draft.save()
|
||||
draft.set_state(State.objects.get(type="draft-stream-iab", slug="approved"))
|
||||
|
||||
url = urlreverse('doc_request_publication', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "iabchair", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
subject = q('input#id_subject')[0].get("value")
|
||||
self.assertTrue("Document Action" in subject)
|
||||
body = q('.request-publication #id_body').text()
|
||||
self.assertTrue("Informational" in body)
|
||||
self.assertTrue("IAB" in body)
|
||||
|
||||
# approve
|
||||
mailbox_before = len(outbox)
|
||||
|
||||
r = self.client.post(url, dict(subject=subject, body=body))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.get_state_slug("draft-stream-iab"), "rfc-edit")
|
||||
self.assertEquals(len(outbox), mailbox_before + 2)
|
||||
self.assertTrue("Document Action" in outbox[-2]['Subject'])
|
||||
self.assertTrue("Document Action" in draft.message_set.order_by("-time")[0].subject)
|
||||
# the IANA copy
|
||||
self.assertTrue("Document Action" in outbox[-1]['Subject'])
|
||||
|
||||
class ExpireIDsTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
|
@ -1099,341 +1222,6 @@ class ExpireLastCallTestCase(django.test.TestCase):
|
|||
self.assertEquals(draft.docevent_set.count(), events_before + 1)
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue("Last Call Expired" in outbox[-1]["Subject"])
|
||||
|
||||
|
||||
|
||||
TEST_RFC_INDEX = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rfc-index xmlns="http://www.rfc-editor.org/rfc-index"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.rfc-editor.org/rfc-index
|
||||
http://www.rfc-editor.org/rfc-index.xsd">
|
||||
<bcp-entry>
|
||||
<doc-id>BCP0110</doc-id>
|
||||
<is-also>
|
||||
<doc-id>RFC4170</doc-id>
|
||||
</is-also>
|
||||
</bcp-entry>
|
||||
<bcp-entry>
|
||||
<doc-id>BCP0111</doc-id>
|
||||
<is-also>
|
||||
<doc-id>RFC4181</doc-id>
|
||||
<doc-id>RFC4841</doc-id>
|
||||
</is-also>
|
||||
</bcp-entry>
|
||||
<fyi-entry>
|
||||
<doc-id>FYI0038</doc-id>
|
||||
<is-also>
|
||||
<doc-id>RFC3098</doc-id>
|
||||
</is-also>
|
||||
</fyi-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC1938</doc-id>
|
||||
<title>A One-Time Password System</title>
|
||||
<author>
|
||||
<name>N. Haller</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>C. Metz</name>
|
||||
</author>
|
||||
<date>
|
||||
<month>May</month>
|
||||
<year>1996</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>44844</char-count>
|
||||
<page-count>18</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>OTP</kw>
|
||||
<kw>authentication</kw>
|
||||
<kw>S/KEY</kw>
|
||||
</keywords>
|
||||
<abstract><p>This document describes a one-time password authentication system (OTP). [STANDARDS-TRACK]</p></abstract>
|
||||
<obsoleted-by>
|
||||
<doc-id>RFC2289</doc-id>
|
||||
</obsoleted-by>
|
||||
<current-status>PROPOSED STANDARD</current-status>
|
||||
<publication-status>PROPOSED STANDARD</publication-status>
|
||||
<stream>Legacy</stream>
|
||||
</rfc-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC2289</doc-id>
|
||||
<title>A One-Time Password System</title>
|
||||
<author>
|
||||
<name>N. Haller</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>C. Metz</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>P. Nesser</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>M. Straw</name>
|
||||
</author>
|
||||
<date>
|
||||
<month>February</month>
|
||||
<year>1998</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>56495</char-count>
|
||||
<page-count>25</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>ONE-PASS</kw>
|
||||
<kw>authentication</kw>
|
||||
<kw>OTP</kw>
|
||||
<kw>replay</kw>
|
||||
<kw>attach</kw>
|
||||
</keywords>
|
||||
<abstract><p>This document describes a one-time password authentication system (OTP). The system provides authentication for system access (login) and other applications requiring authentication that is secure against passive attacks based on replaying captured reusable passwords. [STANDARDS- TRACK]</p></abstract>
|
||||
<obsoletes>
|
||||
<doc-id>RFC1938</doc-id>
|
||||
</obsoletes>
|
||||
<is-also>
|
||||
<doc-id>STD0061</doc-id>
|
||||
</is-also>
|
||||
<current-status>STANDARD</current-status>
|
||||
<publication-status>DRAFT STANDARD</publication-status>
|
||||
<stream>Legacy</stream>
|
||||
</rfc-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC3098</doc-id>
|
||||
<title>How to Advertise Responsibly Using E-Mail and Newsgroups or - how NOT to $$$$$ MAKE ENEMIES FAST! $$$$$</title>
|
||||
<author>
|
||||
<name>T. Gavin</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>D. Eastlake 3rd</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>S. Hambridge</name>
|
||||
</author>
|
||||
<date>
|
||||
<month>April</month>
|
||||
<year>2001</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>64687</char-count>
|
||||
<page-count>28</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>internet</kw>
|
||||
<kw>marketing</kw>
|
||||
<kw>users</kw>
|
||||
<kw>service</kw>
|
||||
<kw>providers</kw>
|
||||
<kw>isps</kw>
|
||||
</keywords>
|
||||
<abstract><p>This memo offers useful suggestions for responsible advertising techniques that can be used via the internet in an environment where the advertiser, recipients, and the Internet Community can coexist in a productive and mutually respectful fashion. This memo provides information for the Internet community.</p></abstract>
|
||||
<draft>draft-ietf-run-adverts-02</draft>
|
||||
<is-also>
|
||||
<doc-id>FYI0038</doc-id>
|
||||
</is-also>
|
||||
<current-status>INFORMATIONAL</current-status>
|
||||
<publication-status>INFORMATIONAL</publication-status>
|
||||
<stream>Legacy</stream>
|
||||
</rfc-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC4170</doc-id>
|
||||
<title>Tunneling Multiplexed Compressed RTP (TCRTP)</title>
|
||||
<author>
|
||||
<name>B. Thompson</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>T. Koren</name>
|
||||
</author>
|
||||
<author>
|
||||
<name>D. Wing</name>
|
||||
</author>
|
||||
<date>
|
||||
<month>November</month>
|
||||
<year>2005</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>48990</char-count>
|
||||
<page-count>24</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>real-time transport protocol</kw>
|
||||
</keywords>
|
||||
<abstract><p>This document describes a method to improve the bandwidth utilization of RTP streams over network paths that carry multiple Real-time Transport Protocol (RTP) streams in parallel between two endpoints, as in voice trunking. The method combines standard protocols that provide compression, multiplexing, and tunneling over a network path for the purpose of reducing the bandwidth used when multiple RTP streams are carried over that path. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</p></abstract>
|
||||
<draft>draft-ietf-avt-tcrtp-08</draft>
|
||||
<is-also>
|
||||
<doc-id>BCP0110</doc-id>
|
||||
</is-also>
|
||||
<current-status>BEST CURRENT PRACTICE</current-status>
|
||||
<publication-status>BEST CURRENT PRACTICE</publication-status>
|
||||
<stream>IETF</stream>
|
||||
<area>rai</area>
|
||||
<wg_acronym>avt</wg_acronym>
|
||||
</rfc-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC4181</doc-id>
|
||||
<title>Guidelines for Authors and Reviewers of MIB Documents</title>
|
||||
<author>
|
||||
<name>C. Heard</name>
|
||||
<title>Editor</title>
|
||||
</author>
|
||||
<date>
|
||||
<month>September</month>
|
||||
<year>2005</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>102521</char-count>
|
||||
<page-count>42</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>standards-track specifications</kw>
|
||||
<kw>management information base</kw>
|
||||
<kw>review</kw>
|
||||
</keywords>
|
||||
<abstract><p>This memo provides guidelines for authors and reviewers of IETF standards-track specifications containing MIB modules. Applicable portions may be used as a basis for reviews of other MIB documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</p></abstract>
|
||||
<draft>draft-ietf-ops-mib-review-guidelines-04</draft>
|
||||
<updated-by>
|
||||
<doc-id>RFC4841</doc-id>
|
||||
</updated-by>
|
||||
<is-also>
|
||||
<doc-id>BCP0111</doc-id>
|
||||
</is-also>
|
||||
<current-status>BEST CURRENT PRACTICE</current-status>
|
||||
<publication-status>BEST CURRENT PRACTICE</publication-status>
|
||||
<stream>IETF</stream>
|
||||
<area>rtg</area>
|
||||
<wg_acronym>ospf</wg_acronym>
|
||||
<errata-url>http://www.rfc-editor.org/errata_search.php?rfc=4181</errata-url>
|
||||
</rfc-entry>
|
||||
<rfc-entry>
|
||||
<doc-id>RFC4841</doc-id>
|
||||
<title>RFC 4181 Update to Recognize the IETF Trust</title>
|
||||
<author>
|
||||
<name>C. Heard</name>
|
||||
<title>Editor</title>
|
||||
</author>
|
||||
<date>
|
||||
<month>March</month>
|
||||
<year>2007</year>
|
||||
</date>
|
||||
<format>
|
||||
<file-format>ASCII</file-format>
|
||||
<char-count>4414</char-count>
|
||||
<page-count>3</page-count>
|
||||
</format>
|
||||
<keywords>
|
||||
<kw>management information base</kw>
|
||||
<kw> standards-track specifications</kw>
|
||||
<kw>mib review</kw>
|
||||
</keywords>
|
||||
<abstract><p>This document updates RFC 4181, "Guidelines for Authors and Reviewers of MIB Documents", to recognize the creation of the IETF Trust. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</p></abstract>
|
||||
<draft>draft-heard-rfc4181-update-00</draft>
|
||||
<updates>
|
||||
<doc-id>RFC4181</doc-id>
|
||||
</updates>
|
||||
<is-also>
|
||||
<doc-id>BCP0111</doc-id>
|
||||
</is-also>
|
||||
<current-status>BEST CURRENT PRACTICE</current-status>
|
||||
<publication-status>BEST CURRENT PRACTICE</publication-status>
|
||||
<stream>IETF</stream>
|
||||
<wg_acronym>NON WORKING GROUP</wg_acronym>
|
||||
</rfc-entry>
|
||||
<std-entry>
|
||||
<doc-id>STD0061</doc-id>
|
||||
<title>A One-Time Password System</title>
|
||||
<is-also>
|
||||
<doc-id>RFC2289</doc-id>
|
||||
</is-also>
|
||||
</std-entry>
|
||||
</rfc-index>
|
||||
'''
|
||||
|
||||
TEST_QUEUE = '''<rfc-editor-queue xmlns="http://www.rfc-editor.org/rfc-editor-queue">
|
||||
<section name="IETF STREAM: WORKING GROUP STANDARDS TRACK">
|
||||
<entry xml:id="draft-ietf-sipping-app-interaction-framework">
|
||||
<draft>draft-ietf-sipping-app-interaction-framework-05.txt</draft>
|
||||
<date-received>2005-10-17</date-received>
|
||||
<state>EDIT</state>
|
||||
<normRef>
|
||||
<ref-name>draft-ietf-sip-gruu</ref-name>
|
||||
<ref-state>IN-QUEUE</ref-state>
|
||||
</normRef>
|
||||
<authors>J. Rosenberg</authors>
|
||||
<title>
|
||||
A Framework for Application Interaction in the Session Initiation Protocol (SIP)
|
||||
</title>
|
||||
<bytes>94672</bytes>
|
||||
<source>Session Initiation Proposal Investigation</source>
|
||||
</entry>
|
||||
</section>
|
||||
<section name="IETF STREAM: NON-WORKING GROUP STANDARDS TRACK">
|
||||
<entry xml:id="draft-ietf-sip-gruu">
|
||||
<draft>draft-ietf-sip-gruu-15.txt</draft>
|
||||
<date-received>2007-10-15</date-received>
|
||||
<state>MISSREF</state>
|
||||
<normRef>
|
||||
<ref-name>draft-ietf-sip-outbound</ref-name>
|
||||
<ref-state>NOT-RECEIVED</ref-state>
|
||||
</normRef>
|
||||
<authors>J. Rosenberg</authors>
|
||||
<title>
|
||||
Obtaining and Using Globally Routable User Agent (UA) URIs (GRUU) in the Session Initiation Protocol (SIP)
|
||||
</title>
|
||||
<bytes>95501</bytes>
|
||||
<source>Session Initiation Protocol</source>
|
||||
</entry>
|
||||
</section>
|
||||
<section name="IETF STREAM: WORKING GROUP INFORMATIONAL/EXPERIMENTAL/BCP">
|
||||
</section>
|
||||
<section name="IETF STREAM: NON-WORKING GROUP INFORMATIONAL/EXPERIMENTAL/BCP">
|
||||
<entry xml:id="draft-thomson-beep-async">
|
||||
<draft>draft-thomson-beep-async-02.txt</draft>
|
||||
<date-received>2009-05-12</date-received>
|
||||
<state>EDIT</state>
|
||||
<state>IANA</state>
|
||||
<authors>M. Thomson</authors>
|
||||
<title>
|
||||
Asynchronous Channels for the Blocks Extensible Exchange Protocol (BEEP)
|
||||
</title>
|
||||
<bytes>17237</bytes>
|
||||
<source>IETF - NON WORKING GROUP</source>
|
||||
</entry>
|
||||
</section>
|
||||
<section name="IAB STREAM">
|
||||
</section>
|
||||
<section name="IRTF STREAM">
|
||||
</section>
|
||||
<section name="INDEPENDENT SUBMISSIONS">
|
||||
</section>
|
||||
</rfc-editor-queue>
|
||||
'''
|
||||
|
||||
class MirrorScriptTestCases(unittest.TestCase,RealDatabaseTest):
|
||||
|
||||
def setUp(self):
|
||||
self.setUpRealDatabase()
|
||||
def tearDown(self):
|
||||
self.tearDownRealDatabase()
|
||||
|
||||
def testRfcIndex(self):
|
||||
print " Testing rfc-index.xml parsing"
|
||||
from ietf.idrfc.mirror_rfc_index import parse
|
||||
data = parse(StringIO.StringIO(TEST_RFC_INDEX))
|
||||
self.assertEquals(len(data), 6)
|
||||
print "OK"
|
||||
|
||||
def testRfcEditorQueue(self):
|
||||
print " Testing queue2.xml parsing"
|
||||
from ietf.idrfc.mirror_rfc_editor_queue import parse_all
|
||||
(drafts,refs) = parse_all(StringIO.StringIO(TEST_QUEUE))
|
||||
self.assertEquals(len(drafts), 3)
|
||||
self.assertEquals(len(refs), 3)
|
||||
print "OK"
|
||||
|
||||
|
||||
class IndividualInfoFormsTestCase(django.test.TestCase):
|
||||
|
||||
|
|
|
@ -49,12 +49,13 @@ urlpatterns = patterns('',
|
|||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot/(?P<ballot_id>[0-9]+)/emailposition/$', views_ballot.send_ballot_comment, name='doc_send_ballot_comment'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot/(?P<ballot_id>[0-9]+)/$', views_doc.document_ballot, name="doc_ballot"),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot/$', views_doc.document_ballot, name="doc_ballot"),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/doc.json$', views_doc.document_debug),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/doc.json$', views_doc.document_json),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballotpopup/$', views_doc.ballot_for_popup),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.tsv$', views_doc.ballot_tsv),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json),
|
||||
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/$', views_edit.change_state, name='doc_change_state'), # IESG state
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/(?P<state_type>iana-action|iana-review)/$', views_edit.change_iana_state, name='doc_change_iana_state'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/info/$', views_edit.edit_info, name='doc_edit_info'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/requestresurrect/$', views_edit.request_resurrect, name='doc_request_resurrect'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/resurrect/$', views_edit.resurrect, name='doc_resurrect'),
|
||||
|
@ -66,6 +67,8 @@ urlpatterns = patterns('',
|
|||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/telechat/$', views_edit.telechat_date, name='doc_change_telechat_date'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/iesgnote/$', views_edit.edit_iesg_note, name='doc_change_iesg_note'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/ad/$', views_edit.edit_ad, name='doc_change_ad'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/consensus/$', views_edit.edit_consensus, name='doc_edit_consensus'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/requestpublication/$', views_edit.request_publication, name='doc_request_publication'),
|
||||
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/clearballot/$', views_ballot.clear_ballot, name='doc_clear_ballot'),
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/deferballot/$', views_ballot.defer_ballot, name='doc_defer_ballot'),
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.conf import settings
|
|||
|
||||
from ietf.idtracker.models import InternetDraft, DocumentComment, BallotInfo, IESGLogin
|
||||
from ietf.idrfc.mails import *
|
||||
from ietf.ietfauth.decorators import has_role
|
||||
|
||||
def add_document_comment(request, doc, text, ballot=None):
|
||||
if request:
|
||||
|
@ -175,3 +176,24 @@ def update_telechatREDESIGN(request, doc, by, new_telechat_date, new_returning_i
|
|||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
update_telechat = update_telechatREDESIGN
|
||||
|
||||
def can_edit_intended_std_level(doc, user):
|
||||
return user.is_authenticated() and (
|
||||
has_role(user, ["Secretariat", "Area Director"]) or
|
||||
doc.group.role_set.filter(name__in=("chair", "auth", "delegate"), person__user=user)
|
||||
)
|
||||
|
||||
def can_edit_consensus(doc, user):
|
||||
return user.is_authenticated() and (
|
||||
has_role(user, ["Secretariat", "Area Director"]) or
|
||||
doc.group.role_set.filter(name__in=("chair", "auth", "delegate"), person__user=user)
|
||||
)
|
||||
|
||||
def nice_consensus(consensus):
|
||||
mapping = {
|
||||
None: "Unknown",
|
||||
True: "Yes",
|
||||
False: "No"
|
||||
}
|
||||
return mapping[consensus]
|
||||
|
||||
|
|
|
@ -818,8 +818,8 @@ def ballot_writeupnotesREDESIGN(request, name):
|
|||
|
||||
msg = generate_issue_ballot_mail(request, doc, ballot)
|
||||
send_mail_preformatted(request, msg)
|
||||
|
||||
email_iana(request, doc, 'drafts-eval@icann.org', msg)
|
||||
send_mail_preformatted(request, msg, extra=extra_automation_headers(doc),
|
||||
override={ "To": "IANA <drafts-eval@icann.org>" })
|
||||
|
||||
e = DocEvent(doc=doc, by=login)
|
||||
e.by = login
|
||||
|
@ -1106,7 +1106,8 @@ def approve_ballotREDESIGN(request, name):
|
|||
send_mail_preformatted(request, announcement)
|
||||
|
||||
if action == "to_announcement_list":
|
||||
email_iana(request, doc, "drafts-approval@icann.org", announcement)
|
||||
send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
|
||||
override={ "To": "IANA <drafts-approval@icann.org>" })
|
||||
|
||||
msg = infer_message(announcement)
|
||||
msg.by = login
|
||||
|
@ -1131,62 +1132,10 @@ class MakeLastCallForm(forms.Form):
|
|||
|
||||
@group_required('Secretariat')
|
||||
def make_last_call(request, name):
|
||||
"""Make last call for Internet Draft, sending out announcement."""
|
||||
doc = get_object_or_404(InternetDraft, filename=name)
|
||||
if not doc.idinternal:
|
||||
raise Http404()
|
||||
|
||||
login = IESGLogin.objects.get(login_name=request.user.username)
|
||||
|
||||
ballot = doc.idinternal.ballot
|
||||
docs = [i.document() for i in doc.idinternal.ballot_set()]
|
||||
|
||||
announcement = ballot.last_call_text
|
||||
|
||||
if request.method == 'POST':
|
||||
form = MakeLastCallForm(request.POST)
|
||||
if form.is_valid():
|
||||
send_mail_preformatted(request, announcement)
|
||||
email_iana(request, doc, "drafts-lastcall@icann.org", announcement)
|
||||
|
||||
doc.idinternal.change_state(IDState.objects.get(document_state_id=IDState.IN_LAST_CALL), None)
|
||||
doc.idinternal.event_date = date.today()
|
||||
doc.idinternal.save()
|
||||
|
||||
log_state_changed(request, doc, login)
|
||||
|
||||
doc.lc_sent_date = form.cleaned_data['last_call_sent_date']
|
||||
doc.lc_expiration_date = form.cleaned_data['last_call_expiration_date']
|
||||
doc.save()
|
||||
|
||||
comment = "Last call has been made for %s ballot and state has been changed to %s" % (doc.filename, doc.idinternal.cur_state.state)
|
||||
email_owner(request, doc, doc.idinternal.job_owner, login, comment)
|
||||
|
||||
return HttpResponseRedirect(doc.idinternal.get_absolute_url())
|
||||
else:
|
||||
initial = {}
|
||||
initial["last_call_sent_date"] = date.today()
|
||||
expire_days = 14
|
||||
if doc.group_id == Acronym.INDIVIDUAL_SUBMITTER:
|
||||
expire_days = 28
|
||||
|
||||
initial["last_call_expiration_date"] = date.today() + timedelta(days=expire_days)
|
||||
|
||||
form = MakeLastCallForm(initial=initial)
|
||||
|
||||
return render_to_response('idrfc/make_last_call.html',
|
||||
dict(doc=doc,
|
||||
docs=docs,
|
||||
form=form),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@group_required('Secretariat')
|
||||
def make_last_callREDESIGN(request, name):
|
||||
"""Make last call for Internet Draft, sending out announcement."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
if not doc.get_state("draft-iesg"):
|
||||
raise Http404()
|
||||
raise Http404
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
@ -1199,7 +1148,8 @@ def make_last_callREDESIGN(request, name):
|
|||
form = MakeLastCallForm(request.POST)
|
||||
if form.is_valid():
|
||||
send_mail_preformatted(request, announcement)
|
||||
email_iana(request, doc, "drafts-lastcall@icann.org", announcement)
|
||||
send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
|
||||
override={ "To": "IANA <drafts-lastcall@icann.org>" })
|
||||
|
||||
msg = infer_message(announcement)
|
||||
msg.by = login
|
||||
|
@ -1234,7 +1184,14 @@ def make_last_callREDESIGN(request, name):
|
|||
e.time = datetime.datetime.combine(form.cleaned_data['last_call_sent_date'], e.time.time())
|
||||
e.expires = form.cleaned_data['last_call_expiration_date']
|
||||
e.save()
|
||||
|
||||
|
||||
# update IANA Review state
|
||||
prev_state = doc.get_state("draft-iana-review")
|
||||
if not prev_state:
|
||||
next_state = State.objects.get(type="draft-iana-review", slug="need-rev")
|
||||
doc.set_state(next_state)
|
||||
add_state_change_event(doc, login, prev_state, next_state)
|
||||
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
else:
|
||||
initial = {}
|
||||
|
@ -1251,7 +1208,3 @@ def make_last_callREDESIGN(request, name):
|
|||
dict(doc=doc,
|
||||
form=form),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
make_last_call = make_last_callREDESIGN
|
||||
|
|
|
@ -46,6 +46,7 @@ from django.conf import settings
|
|||
from ietf.idtracker.models import InternetDraft, IDInternal, BallotInfo, DocumentComment
|
||||
from ietf.idtracker.templatetags.ietf_filters import format_textarea, fill
|
||||
from ietf.idrfc import markup_txt
|
||||
from ietf.idrfc.utils import *
|
||||
from ietf.idrfc.models import RfcIndex, DraftVersions
|
||||
from ietf.idrfc.idrfc_wrapper import BallotWrapper, IdWrapper, RfcWrapper
|
||||
from ietf.ietfworkflows.utils import get_full_info_for_draft
|
||||
|
@ -371,7 +372,8 @@ def document_ballot(request, name, ballot_id=None):
|
|||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_debug(request, name):
|
||||
def document_json(request, name):
|
||||
# old interface
|
||||
r = re.compile("^rfc([1-9][0-9]*)$")
|
||||
m = r.match(name)
|
||||
if m:
|
||||
|
@ -381,7 +383,36 @@ def document_debug(request, name):
|
|||
else:
|
||||
id = get_object_or_404(InternetDraft, filename=name)
|
||||
doc = IdWrapper(draft=id)
|
||||
return HttpResponse(doc.to_json(), mimetype='text/plain')
|
||||
|
||||
from idrfc_wrapper import jsonify_helper
|
||||
|
||||
if isinstance(doc, RfcWrapper):
|
||||
data = jsonify_helper(doc, ['rfc_number', 'title', 'publication_date', 'maturity_level', 'obsoleted_by','obsoletes','updated_by','updates','also','has_errata','stream_name','file_types','in_ietf_process', 'friendly_state'])
|
||||
else:
|
||||
data = jsonify_helper(doc, ['draft_name', 'draft_status', 'latest_revision', 'rfc_number', 'title', 'tracker_id', 'publication_date','rfc_editor_state', 'replaced_by', 'replaces', 'in_ietf_process', 'file_types', 'group_acronym', 'stream_id','friendly_state', 'abstract', 'ad_name'])
|
||||
if doc.in_ietf_process():
|
||||
data['ietf_process'] = doc.ietf_process.dict()
|
||||
|
||||
# add some more fields using the new interface
|
||||
d = get_object_or_404(Document, docalias__name=name)
|
||||
data["authors"] = [
|
||||
dict(name=e.person.name,
|
||||
email=e.address,
|
||||
affiliation=e.person.affiliation)
|
||||
for e in Email.objects.filter(documentauthor__document=d).select_related("person").order_by("documentauthor__order")
|
||||
]
|
||||
e = d.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
data["consensus"] = e.consensus if e else None
|
||||
data["stream"] = d.stream.name if d.stream else None
|
||||
data["shepherd"] = d.shepherd.formatted_email() if d.shepherd else None
|
||||
|
||||
def state_name(s):
|
||||
return s.name if s else None
|
||||
|
||||
data["iana_review_state"] = state_name(d.get_state("draft-iana-review"))
|
||||
data["iana_action_state"] = state_name(d.get_state("draft-iana-action"))
|
||||
|
||||
return HttpResponse(json.dumps(data, indent=2), mimetype='text/plain')
|
||||
|
||||
def _get_html(key, filename, split=True):
|
||||
return get_document_content(key, filename, split=split, markup=True)
|
||||
|
@ -437,7 +468,14 @@ def document_main_idrfc(request, name, tab):
|
|||
info['is_rfc'] = False
|
||||
|
||||
info['conflict_reviews'] = [ rel.source for alias in id.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]
|
||||
|
||||
info['rfc_editor_state'] = id.get_state("draft-rfceditor")
|
||||
info['iana_review_state'] = id.get_state("draft-iana-review")
|
||||
info['iana_action_state'] = id.get_state("draft-iana-action")
|
||||
e = id.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
info["consensus"] = nice_consensus(e and e.consensus)
|
||||
info["can_edit_consensus"] = can_edit_consensus(id, request.user)
|
||||
info["can_edit_intended_std_level"] = can_edit_intended_std_level(id, request.user)
|
||||
|
||||
(content1, content2) = _get_html(
|
||||
str(name)+","+str(id.revision)+",html",
|
||||
os.path.join(settings.INTERNET_DRAFT_PATH, name+"-"+id.revision+".txt"))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import re, os
|
||||
from datetime import datetime, date, time, timedelta
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.template.loader import render_to_string
|
||||
|
@ -13,10 +13,10 @@ from django.utils.html import strip_tags
|
|||
from django.db.models import Max
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.utils.mail import send_mail_text
|
||||
from ietf.utils.mail import send_mail_text, send_mail_message
|
||||
from ietf.ietfauth.decorators import group_required
|
||||
from ietf.idtracker.templatetags.ietf_filters import in_group
|
||||
from ietf.ietfauth.decorators import has_role
|
||||
from ietf.ietfauth.decorators import has_role, role_required
|
||||
from ietf.idtracker.models import *
|
||||
from ietf.iesg.models import *
|
||||
from ietf.idrfc.mails import *
|
||||
|
@ -26,10 +26,13 @@ from ietf.idrfc.lastcall import request_last_call
|
|||
from ietf.ietfworkflows.models import Stream
|
||||
from ietf.ietfworkflows.utils import update_stream
|
||||
from ietf.ietfworkflows.streams import get_stream_from_draft
|
||||
from ietf.ietfworkflows.accounts import can_edit_state
|
||||
|
||||
from ietf.doc.models import *
|
||||
from ietf.doc.utils import *
|
||||
from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName
|
||||
from ietf.person.models import Person, Email
|
||||
from ietf.message.models import Message
|
||||
|
||||
class ChangeStateForm(forms.Form):
|
||||
pass
|
||||
|
@ -58,20 +61,21 @@ def change_stateREDESIGN(request, name):
|
|||
if request.method == 'POST':
|
||||
form = ChangeStateForm(request.POST)
|
||||
if form.is_valid():
|
||||
state = form.cleaned_data['state']
|
||||
next_state = form.cleaned_data['state']
|
||||
prev_state = doc.get_state("draft-iesg")
|
||||
|
||||
tag = form.cleaned_data['substate']
|
||||
comment = form.cleaned_data['comment'].strip()
|
||||
prev = doc.get_state("draft-iesg")
|
||||
|
||||
# tag handling is a bit awkward since the UI still works
|
||||
# as if IESG tags are a substate
|
||||
prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
|
||||
prev_tag = prev_tag[0] if prev_tag else None
|
||||
|
||||
if state != prev or tag != prev_tag:
|
||||
if next_state != prev_state or tag != prev_tag:
|
||||
save_document_in_history(doc)
|
||||
|
||||
doc.set_state(state)
|
||||
doc.set_state(next_state)
|
||||
|
||||
if prev_tag:
|
||||
doc.tags.remove(prev_tag)
|
||||
|
@ -79,7 +83,7 @@ def change_stateREDESIGN(request, name):
|
|||
if tag:
|
||||
doc.tags.add(tag)
|
||||
|
||||
e = log_state_changed(request, doc, login, prev, prev_tag)
|
||||
e = log_state_changed(request, doc, login, prev_state, prev_tag)
|
||||
|
||||
if comment:
|
||||
c = DocEvent(type="added_comment")
|
||||
|
@ -96,7 +100,15 @@ def change_stateREDESIGN(request, name):
|
|||
email_state_changed(request, doc, e.desc)
|
||||
email_owner(request, doc, doc.ad, login, e.desc)
|
||||
|
||||
if state.slug == "lc-req":
|
||||
|
||||
if prev_state and prev_state.slug in ("ann", "rfcqueue") and next_state.slug not in ("rfcqueue", "pub"):
|
||||
email_pulled_from_rfc_queue(request, doc, comment, prev_state, next_state)
|
||||
|
||||
if next_state.slug in ("iesg-eva", "lc"):
|
||||
if not doc.get_state_slug("draft-iana-review"):
|
||||
doc.set_state(State.objects.get(type="draft-iana-review", slug="rev-need"))
|
||||
|
||||
if next_state.slug == "lc-req":
|
||||
request_last_call(request, doc)
|
||||
|
||||
return render_to_response('idrfc/last_call_requested.html',
|
||||
|
@ -129,6 +141,7 @@ def change_stateREDESIGN(request, name):
|
|||
return render_to_response('idrfc/change_stateREDESIGN.html',
|
||||
dict(form=form,
|
||||
doc=doc,
|
||||
state=state,
|
||||
prev_state=prev_state,
|
||||
next_states=next_states,
|
||||
to_iesg_eval=to_iesg_eval),
|
||||
|
@ -138,6 +151,52 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
|||
change_state = change_stateREDESIGN
|
||||
ChangeStateForm = ChangeStateFormREDESIGN
|
||||
|
||||
class ChangeIanaStateForm(forms.Form):
|
||||
state = forms.ModelChoiceField(State.objects.all(), required=False)
|
||||
|
||||
def __init__(self, state_type, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
choices = State.objects.filter(type=state_type).order_by("order").values_list("pk", "name")
|
||||
self.fields['state'].choices = [("", "-------")] + list(choices)
|
||||
|
||||
@role_required('Secretariat', 'IANA')
|
||||
def change_iana_state(request, name, state_type):
|
||||
"""Change IANA review state of Internet Draft. Normally, this is done via
|
||||
automatic sync, but this form allows one to set it manually."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
||||
state_type = doc.type_id + "-" + state_type
|
||||
|
||||
prev_state = doc.get_state(state_type)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ChangeIanaStateForm(state_type, request.POST)
|
||||
if form.is_valid():
|
||||
next_state = form.cleaned_data['state']
|
||||
|
||||
if next_state != prev_state:
|
||||
save_document_in_history(doc)
|
||||
|
||||
doc.set_state(next_state)
|
||||
|
||||
e = add_state_change_event(doc, request.user.get_profile(), prev_state, next_state)
|
||||
|
||||
doc.time = e.time
|
||||
doc.save()
|
||||
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
|
||||
else:
|
||||
form = ChangeIanaStateForm(state_type, initial=dict(state=prev_state.pk if prev_state else None))
|
||||
|
||||
return render_to_response('idrfc/change_iana_state.html',
|
||||
dict(form=form,
|
||||
doc=doc),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
|
||||
class ChangeStreamForm(forms.Form):
|
||||
stream = forms.ModelChoiceField(StreamName.objects.exclude(slug="legacy"), required=False)
|
||||
comment = forms.CharField(widget=forms.Textarea, required=False)
|
||||
|
@ -197,13 +256,15 @@ class ChangeIntentionForm(forms.Form):
|
|||
intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.filter(used=True), empty_label="(None)", required=True, label="Intended RFC status")
|
||||
comment = forms.CharField(widget=forms.Textarea, required=False)
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def change_intention(request, name):
|
||||
"""Change the intended publication status of a Document of type 'draft' , notifying parties
|
||||
as necessary and logging the change as a comment."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
if not doc.type_id=='draft':
|
||||
raise Http404()
|
||||
if doc.type_id != 'draft':
|
||||
raise Http404
|
||||
|
||||
if not can_edit_intended_std_level(doc, request.user):
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
@ -617,7 +678,7 @@ def add_comment(request, name):
|
|||
back_url=doc.idinternal.get_absolute_url()),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
@group_required('Area_Director', 'Secretariat', 'IANA')
|
||||
@group_required('Area_Director', 'Secretariat', 'IANA', 'RFC Editor')
|
||||
def add_commentREDESIGN(request, name):
|
||||
"""Add comment to history of document."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
@ -827,3 +888,116 @@ def edit_ad(request, name):
|
|||
},
|
||||
context_instance = RequestContext(request))
|
||||
|
||||
class ConsensusForm(forms.Form):
|
||||
consensus = forms.ChoiceField(choices=(("", "Unknown"), ("Yes", "Yes"), ("No", "No")), required=True)
|
||||
|
||||
def edit_consensus(request, name):
|
||||
"""Change whether the draft is a consensus document or not."""
|
||||
|
||||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
|
||||
if not can_edit_consensus(doc, request.user):
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
prev_consensus = e and e.consensus
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ConsensusForm(request.POST)
|
||||
if form.is_valid():
|
||||
if form.cleaned_data["consensus"] != bool(prev_consensus):
|
||||
e = ConsensusDocEvent(doc=doc, type="changed_consensus", by=request.user.get_profile())
|
||||
e.consensus = form.cleaned_data["consensus"] == "Yes"
|
||||
|
||||
e.desc = "Changed consensus to <b>%s</b> from %s" % (nice_consensus(e.consensus),
|
||||
nice_consensus(prev_consensus))
|
||||
|
||||
e.save()
|
||||
|
||||
return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name}))
|
||||
|
||||
else:
|
||||
form = ConsensusForm(initial=dict(consensus=nice_consensus(prev_consensus).replace("Unknown", "")))
|
||||
|
||||
return render_to_response('idrfc/change_consensus.html',
|
||||
{'form': form,
|
||||
'doc': doc,
|
||||
},
|
||||
context_instance = RequestContext(request))
|
||||
|
||||
class PublicationForm(forms.Form):
|
||||
subject = forms.CharField(max_length=200, required=True)
|
||||
body = forms.CharField(widget=forms.Textarea, required=True)
|
||||
|
||||
def request_publication(request, name):
|
||||
"""Request publication by RFC Editor for a document which hasn't
|
||||
been through the IESG ballot process."""
|
||||
|
||||
doc = get_object_or_404(Document, type="draft", name=name, stream__in=("iab", "ise", "irtf"))
|
||||
|
||||
if not can_edit_state(request.user, doc):
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
m = Message()
|
||||
m.frm = request.user.get_profile().formatted_email()
|
||||
m.to = "RFC Editor <rfc-editor@rfc-editor.org>"
|
||||
m.by = request.user.get_profile()
|
||||
|
||||
next_state = State.objects.get(type="draft-stream-%s" % doc.stream.slug, slug="rfc-edit")
|
||||
|
||||
if request.method == 'POST' and not request.POST.get("reset"):
|
||||
form = PublicationForm(request.POST)
|
||||
if form.is_valid():
|
||||
m.subject = form.cleaned_data["subject"]
|
||||
m.body = form.cleaned_data["body"]
|
||||
m.save()
|
||||
|
||||
if doc.group.acronym != "none":
|
||||
m.related_groups = [doc.group]
|
||||
m.related_docs = [doc]
|
||||
|
||||
send_mail_message(request, m)
|
||||
|
||||
# IANA copy
|
||||
m.to = "IANA <drafts-approval@icann.org>"
|
||||
send_mail_message(request, m, extra=extra_automation_headers(doc))
|
||||
|
||||
e = DocEvent(doc=doc, type="requested_publication", by=request.user.get_profile())
|
||||
e.desc = "Sent request for publication to the RFC Editor"
|
||||
e.save()
|
||||
|
||||
# change state
|
||||
prev_state = doc.get_state(next_state.type)
|
||||
|
||||
doc.set_state(next_state)
|
||||
|
||||
e = add_state_change_event(doc, request.user.get_profile(), prev_state, next_state)
|
||||
|
||||
doc.time = e.time
|
||||
doc.save()
|
||||
|
||||
return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name}))
|
||||
|
||||
else:
|
||||
if doc.intended_std_level_id in ("std", "ds", "ps", "bcp"):
|
||||
action = "Protocol Action"
|
||||
else:
|
||||
action = "Document Action"
|
||||
|
||||
from ietf.idrfc.templatetags.mail_filters import std_level_prompt
|
||||
|
||||
subject = "%s: '%s' to %s (%s-%s.txt)" % (action, doc.title, std_level_prompt(doc), doc.name, doc.rev)
|
||||
|
||||
body = generate_publication_request(request, doc)
|
||||
|
||||
form = PublicationForm(initial=dict(subject=subject,
|
||||
body=body))
|
||||
|
||||
return render_to_response('idrfc/request_publication.html',
|
||||
dict(form=form,
|
||||
doc=doc,
|
||||
message=m,
|
||||
next_state=next_state,
|
||||
),
|
||||
context_instance = RequestContext(request))
|
||||
|
||||
|
|
|
@ -108,14 +108,6 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
|||
|
||||
|
||||
def can_edit_state(user, draft):
|
||||
streamed = get_streamed_draft(draft)
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES and (not streamed or not streamed.stream):
|
||||
person = get_person_for_user(user)
|
||||
if not person:
|
||||
return False
|
||||
return (is_secretariat(user) or
|
||||
is_wgchair(person) or
|
||||
is_wgdelegate(person))
|
||||
return (is_secretariat(user) or
|
||||
is_authorized_in_draft_stream(user, draft))
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ def edit_actions(context, wrapper):
|
|||
|
||||
if can_edit_state(user, draft):
|
||||
actions.append(("Change stream state", urlreverse('edit_state', kwargs=dict(name=doc.draft_name))))
|
||||
if draft.stream_id in ("iab", "ise", "irtf"):
|
||||
actions.append(("Request publication", urlreverse('doc_request_publication', kwargs=dict(name=doc.draft_name))))
|
||||
|
||||
if can_manage_shepherd_of_a_document(user, draft):
|
||||
actions.append(("Change shepherd", urlreverse('doc_managing_shepherd', kwargs=dict(acronym=draft.group.acronym, name=draft.filename))))
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="iana-crd" model="name.doctagname">
|
||||
<object pk="iana" model="name.doctagname">
|
||||
<field type="CharField" name="name">IANA coordination</field>
|
||||
<field type="TextField" name="desc">RFC-Editor/IANA Registration Coordination</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
|
@ -325,36 +325,6 @@
|
|||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="no" model="name.groupballotpositionname">
|
||||
<field type="CharField" name="name">No</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="yes" model="name.groupballotpositionname">
|
||||
<field type="CharField" name="name">Yes</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="abstain" model="name.groupballotpositionname">
|
||||
<field type="CharField" name="name">Abstain</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="block" model="name.groupballotpositionname">
|
||||
<field type="CharField" name="name">Block</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="norecord" model="name.groupballotpositionname">
|
||||
<field type="CharField" name="name">No record</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
</object>
|
||||
<object pk="bof" model="name.groupstatename">
|
||||
<field type="CharField" name="name">BOF</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
|
@ -751,8 +721,11 @@
|
|||
<object pk="draft-iesg" model="doc.statetype">
|
||||
<field type="CharField" name="label">IESG state</field>
|
||||
</object>
|
||||
<object pk="draft-iana" model="doc.statetype">
|
||||
<field type="CharField" name="label">IANA state</field>
|
||||
<object pk="draft-iana-action" model="doc.statetype">
|
||||
<field type="CharField" name="label">IANA Action state</field>
|
||||
</object>
|
||||
<object pk="draft-iana-review" model="doc.statetype">
|
||||
<field type="CharField" name="label">IANA Review state</field>
|
||||
</object>
|
||||
<object pk="draft-rfceditor" model="doc.statetype">
|
||||
<field type="CharField" name="label">RFC Editor state</field>
|
||||
|
@ -1003,6 +976,141 @@
|
|||
<field type="IntegerField" name="order">6</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="104" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">rfcedack</field>
|
||||
<field type="CharField" name="name">RFC-Ed-Ack</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Request completed. The RFC Editor has acknowledged receipt of IANA's message that the actions have been completed</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="103" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">waitrfc</field>
|
||||
<field type="CharField" name="name">Waiting on RFC Editor</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA has notified the RFC Editor that the actions have been completed</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="102" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">waitwgc</field>
|
||||
<field type="CharField" name="name">Waiting on WGC</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA is waiting on the IETF Working Group Chairs to respond</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="101" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">waitad</field>
|
||||
<field type="CharField" name="name">Waiting on ADs</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA is waiting on the IETF Area Directors to respond</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="100" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">waitauth</field>
|
||||
<field type="CharField" name="name">Waiting on Authors</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA is waiting on the document's authors to respond</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="99" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">inprog</field>
|
||||
<field type="CharField" name="name">In Progress</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA is currently processing the actions for this document</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="98" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">newdoc</field>
|
||||
<field type="CharField" name="name">New Document</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">A new document has been received by IANA, but no actions have been taken</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="105" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">onhold</field>
|
||||
<field type="CharField" name="name">On Hold</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA has suspended work on the document</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="106" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-action</field>
|
||||
<field type="SlugField" name="slug">noic</field>
|
||||
<field type="CharField" name="name">No IC</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Request completed. There were no IANA actions for this document</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="107" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-review</field>
|
||||
<field type="SlugField" name="slug">need-rev</field>
|
||||
<field type="CharField" name="name">IANA Review Needed</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
<field type="IntegerField" name="order">1</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="108" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-review</field>
|
||||
<field type="SlugField" name="slug">ok-act</field>
|
||||
<field type="CharField" name="name">IANA OK - Actions Needed</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Document requires IANA actions, and the IANA Considerations section indicates the details of the actions correctly.</field>
|
||||
<field type="IntegerField" name="order">2</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="109" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-review</field>
|
||||
<field type="SlugField" name="slug">ok-noact</field>
|
||||
<field type="CharField" name="name">IANA OK - No Actions Needed</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Document requires no IANA action, and the IANA Considerations section indicates this correctly.</field>
|
||||
<field type="IntegerField" name="order">3</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="110" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-review</field>
|
||||
<field type="SlugField" name="slug">not-ok</field>
|
||||
<field type="CharField" name="name">IANA Not OK</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">IANA has issues with the text of the IANA Considerations section of the document.</field>
|
||||
<field type="IntegerField" name="order">4</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="111" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iana-review</field>
|
||||
<field type="SlugField" name="slug">changed</field>
|
||||
<field type="CharField" name="name">Version Changed - Review Needed</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Document revision has changed after review by IANA.</field>
|
||||
<field type="IntegerField" name="order">5</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="112" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-rfceditor</field>
|
||||
<field type="SlugField" name="slug">auth48-done</field>
|
||||
<field type="CharField" name="name">AUTH48-DONE</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">Final approvals are complete</field>
|
||||
<field type="IntegerField" name="order">0</field>
|
||||
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
|
||||
</object>
|
||||
<object pk="16" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-iesg</field>
|
||||
<field type="SlugField" name="slug">pub-req</field>
|
||||
|
@ -1185,7 +1293,7 @@
|
|||
</object>
|
||||
<object pk="27" model="doc.state">
|
||||
<field to="doc.statetype" name="type" rel="ManyToOneRel">draft-rfceditor</field>
|
||||
<field type="SlugField" name="slug">iana-crd</field>
|
||||
<field type="SlugField" name="slug">iana</field>
|
||||
<field type="CharField" name="name">IANA</field>
|
||||
<field type="BooleanField" name="used">True</field>
|
||||
<field type="TextField" name="desc">RFC-Editor/IANA Registration Coordination</field>
|
||||
|
@ -1780,4 +1888,4 @@
|
|||
<field type="IntegerField" name="order">3</field>
|
||||
<field to="name.ballotpositionname" name="positions" rel="ManyToManyRel"><object pk="yes"></object><object pk="noobj"></object><object pk="block"></object><object pk="abstain"></object><object pk="norecord"></object></field>
|
||||
</object>
|
||||
</django-objects>
|
||||
</django-objects>
|
||||
|
|
|
@ -45,6 +45,8 @@ IESG Note
|
|||
(Insert IESG Note here or remove section)
|
||||
|
||||
IANA Note
|
||||
|
||||
{% if iana %}
|
||||
{% load ietf_filters %}{% filter wordwrap:"68"|indent:2 %}{{ iana }}{% endfilter %}
|
||||
{% endif %}
|
||||
(Insert IANA Note here or remove section)
|
||||
{% endautoescape%}
|
||||
|
|
21
ietf/templates/idrfc/change_consensus.html
Normal file
21
ietf/templates/idrfc/change_consensus.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Change whether {{ doc.name }}-{{ doc.rev }} is the result of a consensus process{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Change whether {{ doc.name }}-{{ doc.rev }} is the result of a consensus process</h1>
|
||||
|
||||
<form action="" method="POST">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{% url doc_view name=doc.name %}">Back</a>
|
||||
<input type="submit" value="Submit"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
24
ietf/templates/idrfc/change_iana_state.html
Normal file
24
ietf/templates/idrfc/change_iana_state.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Change IANA state of {{ doc }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form table .actions { text-align: right; padding-top: 1em; }
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Change IANA state of {{ doc }}</h1>
|
||||
|
||||
<form action="" method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
<tr>
|
||||
<td colspan="2" class="actions">
|
||||
<a href="{{ doc.get_absolute_url }}">Back</a>
|
||||
<input type="submit" value="Save"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
|
@ -3,9 +3,9 @@
|
|||
{% block title %}Change state of {{ doc }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.change-state select {
|
||||
width: 22em;
|
||||
}
|
||||
form.change-state select { width: 22em; }
|
||||
form.change-state #id_comment { width: 30em; }
|
||||
form.change-state .cancel-pub-note { width: 30em; color: #a00; }
|
||||
form.change-state .actions {
|
||||
text-align: right;
|
||||
padding-top: 10px;
|
||||
|
@ -29,6 +29,14 @@ form.change-state .actions {
|
|||
<form class="change-state" action="" method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
{% if state and state.slug == "rfcqueue" %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="cancel-pub-note">Note: if you pull the draft out of the
|
||||
{{ state.name }} state, the RFC Editor and IANA will be notified
|
||||
by email with this comment so they can update their queues.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td colspan="2" class="actions">
|
||||
<a href="{{ doc.get_absolute_url }}">Back</a>
|
||||
|
|
|
@ -56,12 +56,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% with info.conflict_reviews as r %}{% if r %}<tr><td>IETF Conflict Review:</td><td> {% filter urlize_ietf_docs %}{{ r|join:","}}{% endfilter %}</td></tr>{% endif %} {% endwith %}
|
||||
|
||||
<tr><td>Intended RFC status:</td><td>
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_intended_status name=doc.draft_name %}">{% endif %}
|
||||
<a{% if info.can_edit_intended_std_level %} class="editlink" href="{% url doc_change_intended_status name=doc.draft_name %}"{% endif %}>
|
||||
{{ doc.underlying_document.intended_std_level|default:"-" }}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
{% endwith %}
|
||||
</td></tr>
|
||||
</a>
|
||||
</td></tr>
|
||||
|
||||
<tr><td>Other versions:</td>
|
||||
{% ifequal doc.draft_status "Active" %}
|
||||
|
@ -118,6 +116,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% endif %}
|
||||
<tr><td>Document shepherd:</td><td>{{ stream_info.shepherd|default:"" }}</td></tr>
|
||||
|
||||
<tr><td>Consensus:</td><td><a title="Whether the document is the result of a community consensus process as defined in RFC 5741" {% if info.can_edit_consensus %}class="editlink" href="{% url doc_edit_consensus name=doc.draft_name %}"{% endif %}>{{ info.consensus }}</a></td></tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
|
||||
|
@ -127,7 +127,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% else %}
|
||||
{{ doc.friendly_state|safe }}
|
||||
{% endif %}
|
||||
{% if doc.rfc_editor_state %}<br />RFC Editor State: <a href="http://www.rfc-editor.org/queue2.html#{{doc.draft_name}}">{{ doc.rfc_editor_state|escape }}</a>{% endif %}
|
||||
{% if info.iana_review_state %}<br />IANA Review State: <a class="editlink" {% if user|in_group:"Secretariat,IANA" %}href="{% url doc_change_iana_state name=doc.draft_name state_type="iana-review" %}"{% endif %}>{{ info.iana_review_state.name|escape }}</a>{% endif %}
|
||||
{% if info.iana_action_state %}<br />IANA Action State: <a class="editlink" {% if user|in_group:"Secretariat,IANA" %}href="{% url doc_change_iana_state name=doc.draft_name state_type="iana-action" %}"{% endif %}>{{ info.iana_action_state.name|escape }}</a>{% endif %}
|
||||
{% if info.rfc_editor_state %}<br />RFC Editor State: <a href="http://www.rfc-editor.org/queue2.html#{{ doc.draft_name }}">{{ info.rfc_editor_state|escape }}</a>{% endif %}
|
||||
{% ifequal doc.draft_status "Expired" %}
|
||||
{% if doc.resurrect_requested_by %}(resurrect requested by {{ doc.resurrect_requested_by }}){% endif %}
|
||||
{% endifequal %}
|
||||
|
|
|
@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% include "idrfc/doc_diffs.html" %}
|
||||
{% endif %}
|
||||
<h2 style="margin-top:1em;">Document history</h2>
|
||||
{% if user|in_group:"Area_Director,Secretariat,IANA" and doc.in_ietf_process %}
|
||||
{% if user|in_group:"Area_Director,Secretariat,IANA,RFC Editor" and doc.in_ietf_process %}
|
||||
<div style="margin-bottom:8px" id="history_actions">
|
||||
<span id="doc_add_comment_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url doc_add_comment name=doc.draft_name %}">Add comment</a></span></span>
|
||||
</div>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
{% endif %}
|
||||
|
||||
<h2>Document history</h2>
|
||||
{% if user|has_role:"Area Director,Secretariat,IANA" %}
|
||||
{% if user|has_role:"Area Director,Secretariat,IANA,RFC Editor" %}
|
||||
<div class="history-actions">
|
||||
<a href="{% url doc_add_comment name=doc.name %}">Add comment</a>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@ with no "Discuss" positions, are needed for approval.
|
|||
|
||||
DISCUSSES AND COMMENTS
|
||||
======================
|
||||
{% filter wordwrap:79 %}{% for pos in ad_feedback %}{{ pos.ad.get_name }}:
|
||||
{% filter wordwrap:79 %}{% for pos in ad_feedback %}{{ pos.ad }}:
|
||||
|
||||
{% if pos.discuss %}Discuss [{{ pos.discuss_time|date:"Y-m-d" }}]:
|
||||
{{ pos.discuss }}
|
||||
|
|
16
ietf/templates/idrfc/publication_request.txt
Normal file
16
ietf/templates/idrfc/publication_request.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% load mail_filters %}{% autoescape off %}{% filter wordwrap:73 %}
|
||||
The document "{{ doc.title }}" <{{ doc.name }}> from the {{ doc.stream }} stream is ready for publication as {{ doc|std_level_prompt }}.{% if group_description %}
|
||||
|
||||
This document is the product of the {{ group_description }}.{% endif %}{% endfilter %}
|
||||
|
||||
URL: {{ doc_url }}
|
||||
|
||||
No IANA allocation in the document requires IETF Consensus or Standards Action.
|
||||
|
||||
|
||||
[OPTIONAL: include summary of related discussion of this document in an IETF WG or in the IESG.]
|
||||
|
||||
[OPTIONAL: include statement of the purpose of publishing this document, its intended audience, its merits and significance.]
|
||||
|
||||
[OPTIONAL: include suggested names and contact information for one or more competent and independent potential reviewers for the document (this can speed the review and approval process).]
|
||||
{% endautoescape %}
|
9
ietf/templates/idrfc/pulled_from_rfc_queue_email.txt
Normal file
9
ietf/templates/idrfc/pulled_from_rfc_queue_email.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
{% autoescape off %}{{ doc.name }} is no longer in the {{ prev_state.name }} state.
|
||||
|
||||
{% if comment %}Explanation:
|
||||
|
||||
{{ comment }}
|
||||
{% endif %}
|
||||
|
||||
URL: {{ url }}
|
||||
{% endautoescape %}
|
37
ietf/templates/idrfc/request_publication.html
Normal file
37
ietf/templates/idrfc/request_publication.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Request publication for {{ doc }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.request-publication #id_subject,
|
||||
form.request-publication #id_body { width: 50em; }
|
||||
|
||||
form.request-publication #id_body { height: 30em; }
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Request publication for {{ doc }}</h1>
|
||||
|
||||
<p>Send a publication request to the RFC Editor for {{ doc }} and move
|
||||
it to the <em>{{ next_state.name }}</em> stream state.</p>
|
||||
|
||||
<p>Please edit the message and remove any parts in brackets you do not
|
||||
fill in. For independent submissions, see the <a
|
||||
href="http://www.rfc-editor.org/indsubs.html">guidelines</a>.</p>
|
||||
|
||||
<form class="request-publication" action="" method="POST">
|
||||
<table>
|
||||
<tr><td>From:</td> <td>{{ message.frm }}</td></tr>
|
||||
<tr><td>To:</td> <td>{{ message.to }}</td></tr>
|
||||
<tr><td>Subject:</td> <td>{{ form.subject }} {{ form.subject.errors }}</td></tr>
|
||||
<tr><td style="vertical-align: top">Message:</td> <td>{{ form.body }} {{ form.body.errors }}</td></tr>
|
||||
<tr class="actions"><td></td>
|
||||
<td>
|
||||
<a href="{% url doc_view name=doc.name %}">Back</a>
|
||||
<input name="reset" type="submit" value="Reset"/>
|
||||
<input type="submit" value="Send request to the RFC Editor"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -26,7 +26,7 @@ test_mode = False
|
|||
outbox = []
|
||||
|
||||
def empty_outbox():
|
||||
outbox[:] = []
|
||||
outbox[:] = []
|
||||
|
||||
def add_headers(msg):
|
||||
if not(msg.has_key('Message-ID')):
|
||||
|
@ -187,16 +187,34 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F
|
|||
msg['X-Tracker-Bcc']=bcc
|
||||
copy_email(msg, copy_to)
|
||||
|
||||
def send_mail_preformatted(request, preformatted):
|
||||
def send_mail_preformatted(request, preformatted, extra={}, override={}):
|
||||
"""Parse preformatted string containing mail with From:, To:, ...,
|
||||
and send it through the standard IETF mail interface (inserting
|
||||
extra headers as needed)."""
|
||||
msg = message_from_string(preformatted.encode("utf-8"))
|
||||
extra = copy.copy(msg)
|
||||
for key in ['To', 'From', 'Subject', ]:
|
||||
del extra[key]
|
||||
send_mail_text(request, msg['To'], msg["From"], msg["Subject"], msg.get_payload(), extra=extra)
|
||||
|
||||
def send_mail_message(request, message):
|
||||
for k, v in override.iteritems():
|
||||
if k in msg:
|
||||
del msg[k]
|
||||
msg[k] = v
|
||||
|
||||
headers = copy.copy(msg)
|
||||
for key in ['To', 'From', 'Subject']:
|
||||
del headers[key]
|
||||
for k, v in extra.iteritems():
|
||||
if k in headers:
|
||||
del headers[k]
|
||||
headers[k] = v
|
||||
|
||||
send_mail_text(request, msg['To'], msg["From"], msg["Subject"], msg.get_payload(), extra=headers)
|
||||
|
||||
def send_mail_message(request, message, extra={}):
|
||||
"""Send a Message object."""
|
||||
# note that this doesn't handle MIME messages at the moment
|
||||
send_mail_text(request, message.to, message.frm, message.subject, message.body, cc=message.cc, bcc=message.bcc, extra={ 'Reply-to': message.reply_to })
|
||||
|
||||
e = extra.copy()
|
||||
if message.reply_to:
|
||||
e['Reply-to'] = message.reply_to
|
||||
|
||||
send_mail_text(request, message.to, message.frm, message.subject,
|
||||
message.body, cc=message.cc, bcc=message.bcc, extra=e)
|
||||
|
|
Loading…
Reference in a new issue