Beispiel #1
0
def assign_shepherd(user, internetdraft, shepherd):
    if internetdraft.shepherd == shepherd:
        return
    
    from ietf.doc.models import save_document_in_history, DocEvent, Document

    # saving the proxy object is a bit of a mess, so convert it to a
    # proper document
    doc = Document.objects.get(name=internetdraft.name)
    
    save_document_in_history(doc)

    doc.time = datetime.datetime.now()
    doc.shepherd = shepherd
    doc.save()

    e = DocEvent(type="changed_document")
    e.time = doc.time
    e.doc = doc
    e.by = user.get_profile()
    if not shepherd:
        e.desc = u"Unassigned shepherd"
    else:
        e.desc = u"Changed shepherd to %s" % shepherd.plain_name()
    e.save()

    # update proxy too
    internetdraft.shepherd = shepherd
Beispiel #2
0
def assign_shepherd(user, internetdraft, shepherd):
    if internetdraft.shepherd == shepherd:
        return

    from ietf.doc.models import save_document_in_history, DocEvent, Document

    # saving the proxy object is a bit of a mess, so convert it to a
    # proper document
    doc = Document.objects.get(name=internetdraft.name)

    save_document_in_history(doc)

    doc.time = datetime.datetime.now()
    doc.shepherd = shepherd
    doc.save()

    e = DocEvent(type="changed_document")
    e.time = doc.time
    e.doc = doc
    e.by = user.get_profile()
    if not shepherd:
        e.desc = u"Unassigned shepherd"
    else:
        e.desc = u"Changed shepherd to %s" % shepherd.plain_name()
    e.save()

    # update proxy too
    internetdraft.shepherd = shepherd
Beispiel #3
0
def add_review_comment(doc_name, review_time, by, comment):
    try:
        e = DocEvent.objects.get(doc__name=doc_name, time=review_time, type="iana_review")
    except DocEvent.DoesNotExist:
        doc = Document.objects.get(name=doc_name)
        e = DocEvent(doc=doc, time=review_time, type="iana_review")

    e.desc = comment
    e.by = by

    e.save()
Beispiel #4
0
def add_review_comment(doc_name, review_time, by, comment):
    if comment:
        try:
            e = DocEvent.objects.get(doc__name=doc_name, time=review_time, type="iana_review")
        except DocEvent.DoesNotExist:
            doc = Document.objects.get(name=doc_name)
            e = DocEvent(doc=doc, rev=doc.rev, time=review_time, type="iana_review")

        e.desc = comment
        e.by = by

        e.save()
Beispiel #5
0
    def test_review_decisions(self):
        draft = make_test_data()

        e = DocEvent(type="iesg_approved")
        e.doc = draft
        e.by = Person.objects.get(name="Aread Irector")
        e.save()

        url = urlreverse('ietf.iesg.views.review_decisions')

        r = self.client.get(url)
        self.assertEqual(r.status_code, 200)
        self.assertTrue(draft.name in r.content)
Beispiel #6
0
    def save(self):
        self.save_tags()
        if 'only_tags' not in self.data.keys():
            self.save_state()

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            comment = self.cleaned_data.get('comment').strip()
            if comment:
                e = DocEvent(type="added_comment")
                e.time = datetime.datetime.now()
                e.by = self.person
                e.doc_id = self.draft.pk
                e.desc = comment
                e.save()
Beispiel #7
0
    def save(self):
        self.save_tags()
        if 'only_tags' not in self.data.keys():
            self.save_state()

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            comment = self.cleaned_data.get('comment').strip()
            if comment:
                e = DocEvent(type="added_comment")
                e.time = datetime.datetime.now()
                e.by = self.person
                e.doc_id = self.draft.pk
                e.desc = comment
                e.save()
Beispiel #8
0
    def test_review_decisions(self):
        draft = make_test_data()

        e = DocEvent(type="iesg_approved")
        e.doc = draft
        e.rev = draft.rev
        e.by = Person.objects.get(name="Areað Irector")
        e.save()

        url = urlreverse('ietf.iesg.views.review_decisions')

        r = self.client.get(url)
        self.assertEqual(r.status_code, 200)
        self.assertTrue(draft.name in unicontent(r))
Beispiel #9
0
def request_last_call(request, doc):
    if not doc.latest_event(type="changed_ballot_writeup_text"):
        generate_ballot_writeup(request, doc)
    if not doc.latest_event(type="changed_ballot_approval_text"):
        generate_approval_mail(request, doc)
    if not doc.latest_event(type="changed_last_call_text"):
        generate_last_call_announcement(request, doc)
    
    send_last_call_request(request, doc)
    
    e = DocEvent()
    e.type = "requested_last_call"
    e.by = request.user.person
    e.doc = doc
    e.desc = "Last call was requested"
    e.save()
Beispiel #10
0
def request_last_call(request, doc):
    if not doc.latest_event(type="changed_ballot_writeup_text"):
        e = generate_ballot_writeup(request, doc)
        e.save()
    if not doc.latest_event(type="changed_ballot_approval_text"):
        e = generate_approval_mail(request, doc)
        e.save()
    if not doc.latest_event(type="changed_last_call_text"):
        e = generate_last_call_announcement(request, doc)
        e.save()

    send_last_call_request(request, doc)

    e = DocEvent()
    e.type = "requested_last_call"
    e.by = request.user.person
    e.doc = doc
    e.rev = doc.rev
    e.desc = "Last call was requested"
    e.save()
Beispiel #11
0
def update_rfc_log_from_protocol_page(rfc_names, rfc_must_published_later_than):
    """Add notices to RFC history log that IANA is now referencing the RFC."""
    system = Person.objects.get(name="(System)")

    updated = []

    docs = Document.objects.filter(docalias__name__in=rfc_names).exclude(
        docevent__type="rfc_in_iana_registry").filter(
        # only take those that were published after cutoff since we
        # have a big bunch of old RFCs that we unfortunately don't have data for
        docevent__type="published_rfc", docevent__time__gte=rfc_must_published_later_than
        ).distinct()

    for d in docs:
        e = DocEvent(doc=d, rev=d.rev)
        e.by = system
        e.type = "rfc_in_iana_registry"
        e.desc = "IANA registries were updated to include %s" % d.display_name()
        e.save()

        updated.append(d)

    return updated
Beispiel #12
0
def update_rfc_log_from_protocol_page(rfc_names, rfc_must_published_later_than):
    """Add notices to RFC history log that IANA is now referencing the RFC."""
    system = Person.objects.get(name="(System)")

    updated = []

    docs = Document.objects.filter(docalias__name__in=rfc_names).exclude(
        docevent__type="rfc_in_iana_registry").filter(
        # only take those that were published after cutoff since we
        # have a big bunch of old RFCs that we unfortunately don't have data for
        docevent__type="published_rfc", docevent__time__gte=rfc_must_published_later_than
        ).distinct()

    for d in docs:
        e = DocEvent(doc=d)
        e.by = system
        e.type = "rfc_in_iana_registry"
        e.desc = "IANA registries were updated to include %s" % d.display_name()
        e.save()

        updated.append(d)

    return updated
Beispiel #13
0
def edit_position(request, name, ballot_id):
    """Vote and edit discuss and comment on document as Area Director."""
    doc = get_object_or_404(Document, docalias__name=name)
    ballot = get_object_or_404(BallotDocEvent,
                               type="created_ballot",
                               pk=ballot_id,
                               doc=doc)

    ad = login = request.user.person

    if 'ballot_edit_return_point' in request.session:
        return_to_url = request.session['ballot_edit_return_point']
    else:
        return_to_url = urlreverse("ietf.doc.views_doc.document_ballot",
                                   kwargs=dict(name=doc.name,
                                               ballot_id=ballot_id))

    # if we're in the Secretariat, we can select an AD to act as stand-in for
    if has_role(request.user, "Secretariat"):
        ad_id = request.GET.get('ad')
        if not ad_id:
            raise Http404
        ad = get_object_or_404(Person, pk=ad_id)

    old_pos = doc.latest_event(BallotPositionDocEvent,
                               type="changed_ballot_position",
                               ad=ad,
                               ballot=ballot)

    if request.method == 'POST':
        if not has_role(
                request.user, "Secretariat") and not ad.role_set.filter(
                    name="ad", group__type="area", group__state="active"):
            # prevent pre-ADs from voting
            return HttpResponseForbidden(
                "Must be a proper Area Director in an active area to cast ballot"
            )

        form = EditPositionForm(request.POST, ballot_type=ballot.ballot_type)
        if form.is_valid():
            # save the vote
            clean = form.cleaned_data

            pos = BallotPositionDocEvent(doc=doc, rev=doc.rev, by=login)
            pos.type = "changed_ballot_position"
            pos.ballot = ballot
            pos.ad = ad
            pos.pos = clean["position"]
            pos.comment = clean["comment"].rstrip()
            pos.comment_time = old_pos.comment_time if old_pos else None
            pos.discuss = clean["discuss"].rstrip()
            if not pos.pos.blocking:
                pos.discuss = ""
            pos.discuss_time = old_pos.discuss_time if old_pos else None

            changes = []
            added_events = []
            # possibly add discuss/comment comments to history trail
            # so it's easy to see what's happened
            old_comment = old_pos.comment if old_pos else ""
            if pos.comment != old_comment:
                pos.comment_time = pos.time
                changes.append("comment")

                if pos.comment:
                    e = DocEvent(doc=doc, rev=doc.rev)
                    e.by = ad  # otherwise we can't see who's saying it
                    e.type = "added_comment"
                    e.desc = "[Ballot comment]\n" + pos.comment
                    added_events.append(e)

            old_discuss = old_pos.discuss if old_pos else ""
            if pos.discuss != old_discuss:
                pos.discuss_time = pos.time
                changes.append("discuss")

                if pos.pos.blocking:
                    e = DocEvent(doc=doc, rev=doc.rev, by=login)
                    e.by = ad  # otherwise we can't see who's saying it
                    e.type = "added_comment"
                    e.desc = "[Ballot %s]\n" % pos.pos.name.lower()
                    e.desc += pos.discuss
                    added_events.append(e)

            # figure out a description
            if not old_pos and pos.pos.slug != "norecord":
                pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (
                    pos.pos.name, pos.ad.plain_name())
            elif old_pos and pos.pos != old_pos.pos:
                pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (
                    pos.ad.plain_name(), pos.pos.name, old_pos.pos.name)

            if not pos.desc and changes:
                pos.desc = u"Ballot %s text updated for %s" % (
                    u" and ".join(changes), ad.plain_name())

            # only add new event if we actually got a change
            if pos.desc:
                if login != ad:
                    pos.desc += u" by %s" % login.plain_name()

                pos.save()

                for e in added_events:
                    e.save(
                    )  # save them after the position is saved to get later id for sorting order

            if request.POST.get("send_mail"):
                qstr = ""
                if request.GET.get('ad'):
                    qstr += "?ad=%s" % request.GET.get('ad')
                return HttpResponseRedirect(
                    urlreverse('ietf.doc.views_ballot.send_ballot_comment',
                               kwargs=dict(name=doc.name, ballot_id=ballot_id))
                    + qstr)
            elif request.POST.get("Defer"):
                return redirect('ietf.doc.views_ballot.defer_ballot', name=doc)
            elif request.POST.get("Undefer"):
                return redirect('ietf.doc.views_ballot.undefer_ballot',
                                name=doc)
            else:
                return HttpResponseRedirect(return_to_url)
    else:
        initial = {}
        if old_pos:
            initial['position'] = old_pos.pos.slug
            initial['discuss'] = old_pos.discuss
            initial['comment'] = old_pos.comment

        form = EditPositionForm(initial=initial,
                                ballot_type=ballot.ballot_type)

    blocking_positions = dict((p.pk, p.name)
                              for p in form.fields["position"].queryset.all()
                              if p.blocking)

    ballot_deferred = doc.active_defer_event()

    return render(
        request, 'doc/ballot/edit_position.html',
        dict(
            doc=doc,
            form=form,
            ad=ad,
            return_to_url=return_to_url,
            old_pos=old_pos,
            ballot_deferred=ballot_deferred,
            ballot=ballot,
            show_discuss_text=old_pos and old_pos.pos.blocking,
            blocking_positions=json.dumps(blocking_positions),
        ))
Beispiel #14
0
def post_submission(request, submission, approvedDesc):
    system = Person.objects.get(name="(System)")
    submitter_parsed = submission.submitter_parsed()
    if submitter_parsed["name"] and submitter_parsed["email"]:
        submitter, _ = ensure_person_email_info_exists(
            submitter_parsed["name"], submitter_parsed["email"])
        submitter_info = u'%s <%s>' % (submitter_parsed["name"],
                                       submitter_parsed["email"])
    else:
        submitter = system
        submitter_info = system.name

    # update draft attributes
    try:
        draft = Document.objects.get(name=submission.name)
    except Document.DoesNotExist:
        draft = Document.objects.create(name=submission.name, type_id="draft")

    prev_rev = draft.rev

    draft.type_id = "draft"
    draft.title = submission.title
    group = submission.group or Group.objects.get(type="individ")
    if not (group.type_id == "individ" and draft.group
            and draft.group.type_id == "area"):
        # don't overwrite an assigned area if it's still an individual
        # submission
        draft.group = group
    draft.rev = submission.rev
    draft.pages = submission.pages
    draft.abstract = submission.abstract
    was_rfc = draft.get_state_slug() == "rfc"

    if not draft.stream:
        stream_slug = None
        if draft.name.startswith("draft-iab-"):
            stream_slug = "iab"
        elif draft.name.startswith("draft-irtf-"):
            stream_slug = "irtf"
        elif draft.name.startswith("draft-ietf-") and (
                draft.group.type_id != "individ" or was_rfc):
            stream_slug = "ietf"

        if stream_slug:
            draft.stream = StreamName.objects.get(slug=stream_slug)

    draft.expires = datetime.datetime.now() + datetime.timedelta(
        settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)

    events = []

    if draft.rev == '00':
        # Add all the previous submission events as docevents
        events += post_rev00_submission_events(draft, submission, submitter)

    # Add an approval docevent
    e = SubmissionDocEvent.objects.create(
        type="new_submission",
        doc=draft,
        by=system,
        desc=approvedDesc,
        submission=submission,
        rev=submission.rev,
    )
    events.append(e)

    # new revision event
    e = NewRevisionDocEvent.objects.create(
        type="new_revision",
        doc=draft,
        rev=draft.rev,
        by=submitter,
        desc="New version available: <b>%s-%s.txt</b>" %
        (draft.name, draft.rev),
    )
    events.append(e)

    # update related objects
    DocAlias.objects.get_or_create(name=submission.name, document=draft)

    draft.set_state(State.objects.get(used=True, type="draft", slug="active"))

    update_authors(draft, submission)

    draft.formal_languages = submission.formal_languages.all()

    trouble = rebuild_reference_relations(
        draft,
        filename=os.path.join(settings.IDSUBMIT_STAGING_PATH,
                              '%s-%s.txt' % (submission.name, submission.rev)))
    if trouble:
        log.log('Rebuild_reference_relations trouble: %s' % trouble)

    if draft.stream_id == "ietf" and draft.group.type_id == "wg" and draft.rev == "00":
        # automatically set state "WG Document"
        draft.set_state(
            State.objects.get(used=True,
                              type="draft-stream-%s" % draft.stream_id,
                              slug="wg-doc"))

    # automatic state changes for IANA review
    if draft.get_state_slug("draft-iana-review") in ("ok-act", "ok-noact",
                                                     "not-ok"):
        prev_state = draft.get_state("draft-iana-review")
        next_state = State.objects.get(used=True,
                                       type="draft-iana-review",
                                       slug="changed")
        draft.set_state(next_state)
        e = add_state_change_event(draft, system, prev_state, next_state)
        if e:
            events.append(e)

    state_change_msg = ""

    if not was_rfc and draft.tags.filter(slug="need-rev"):
        draft.tags.remove("need-rev")
        draft.tags.add("ad-f-up")

        e = DocEvent(type="changed_document", doc=draft, rev=draft.rev)
        e.desc = "Sub state has been changed to <b>AD Followup</b> from <b>Revised ID Needed</b>"
        e.by = system
        e.save()
        events.append(e)

        state_change_msg = e.desc

    if draft.stream_id == "ietf" and draft.group.type_id == "wg" and draft.rev == "00":
        # automatically set state "WG Document"
        draft.set_state(
            State.objects.get(used=True,
                              type="draft-stream-%s" % draft.stream_id,
                              slug="wg-doc"))

    # save history now that we're done with changes to the draft itself
    draft.save_with_history(events)

    # clean up old files
    if prev_rev != draft.rev:
        from ietf.doc.expire import move_draft_files_to_archive
        move_draft_files_to_archive(draft, prev_rev)

    move_files_to_repository(submission)
    submission.state = DraftSubmissionStateName.objects.get(slug="posted")

    new_replaces, new_possibly_replaces = update_replaces_from_submission(
        request, submission, draft)

    update_name_contains_indexes_with_new_doc(draft)

    announce_to_lists(request, submission)
    announce_new_version(request, submission, draft, state_change_msg)
    announce_to_authors(request, submission)

    if new_possibly_replaces:
        send_review_possibly_replaces_request(request, draft, submitter_info)

    submission.draft = draft
    submission.save()
Beispiel #15
0
    def submit_existing(self, formats):
        # submit new revision of existing -> supply submitter info -> prev authors confirm
        draft = make_test_data()
        prev_author = draft.documentauthor_set.all()[0]

        # Make it such that one of the previous authors has an invalid email address
        bogus_email = ensure_person_email_info_exists('Bogus Person',None)  
        DocumentAuthor.objects.create(document=draft,author=bogus_email,order=draft.documentauthor_set.latest('order').order+1)

        # pretend IANA reviewed it
        draft.set_state(State.objects.get(used=True, type="draft-iana-review", slug="not-ok"))

        # pretend it was approved to check that we notify the RFC Editor
        e = DocEvent(type="iesg_approved", doc=draft)
        e.time = draft.time
        e.by = Person.objects.get(name="(System)")
        e.desc = "The IESG approved the document"
        e.save()

        # make a discuss to see if the AD gets an email
        ballot_position = BallotPositionDocEvent()
        ballot_position.ballot = draft.latest_event(BallotDocEvent, type="created_ballot")
        ballot_position.pos_id = "discuss"
        ballot_position.type = "changed_ballot_position"
        ballot_position.doc = draft
        ballot_position.ad = ballot_position.by = Person.objects.get(user__username="******")
        ballot_position.save()

        name = draft.name
        rev = "%02d" % (int(draft.rev) + 1)
        group = draft.group

        # write the old draft in a file so we can check it's moved away
        old_rev = draft.rev
        with open(os.path.join(self.repository_dir, "%s-%s.txt" % (name, old_rev)), 'w') as f:
            f.write("a" * 2000)

        status_url = self.do_submission(name, rev, group, formats)

        # supply submitter info, then previous authors get a confirmation email
        mailbox_before = len(outbox)
        r = self.supply_extra_metadata(name, status_url, "Submitter Name", "*****@*****.**", replaces="")
        self.assertEqual(r.status_code, 302)
        status_url = r["Location"]
        r = self.client.get(status_url)
        self.assertEqual(r.status_code, 200)
        self.assertTrue("The submission is pending approval by the authors" in unicontent(r))

        self.assertEqual(len(outbox), mailbox_before + 1)
        confirm_email = outbox[-1]
        self.assertTrue("Confirm submission" in confirm_email["Subject"])
        self.assertTrue(name in confirm_email["Subject"])
        self.assertTrue(prev_author.author.address in confirm_email["To"])
        # submitter and new author can't confirm
        self.assertTrue("*****@*****.**" not in confirm_email["To"])
        self.assertTrue("*****@*****.**" not in confirm_email["To"])
        # Verify that mail wasn't sent to know invalid addresses
        self.assertTrue("unknown-email-" not in confirm_email["To"])

        confirm_url = self.extract_confirm_url(confirm_email)

        # go to confirm page
        r = self.client.get(confirm_url)
        q = PyQuery(r.content)
        self.assertEqual(len(q('[type=submit]:contains("Confirm")')), 1)

        # confirm
        mailbox_before = len(outbox)
        r = self.client.post(confirm_url)
        self.assertEqual(r.status_code, 302)

        draft = Document.objects.get(docalias__name=name)
        self.assertEqual(draft.rev, rev)
        self.assertEqual(draft.group.acronym, name.split("-")[2])
        self.assertEqual(draft.docevent_set.all()[1].type, "new_revision")
        self.assertEqual(draft.docevent_set.all()[1].by.name, "Submitter Name")
        self.assertTrue(not os.path.exists(os.path.join(self.repository_dir, "%s-%s.txt" % (name, old_rev))))
        self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "%s-%s.txt" % (name, old_rev))))
        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
        self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
        self.assertEqual(draft.type_id, "draft")
        self.assertEqual(draft.stream_id, "ietf")
        self.assertEqual(draft.get_state_slug("draft-stream-%s" % draft.stream_id), "wg-doc")
        self.assertEqual(draft.get_state_slug("draft-iana-review"), "changed")
        self.assertEqual(draft.authors.count(), 1)
        self.assertEqual(draft.authors.all()[0].get_name(), "Author Name")
        self.assertEqual(draft.authors.all()[0].address, "*****@*****.**")
        self.assertEqual(len(outbox), mailbox_before + 3)
        self.assertTrue((u"I-D Action: %s" % name) in outbox[-3]["Subject"])
        self.assertTrue((u"I-D Action: %s" % name) in draft.message_set.order_by("-time")[0].subject)
        self.assertTrue("Author Name" in unicode(outbox[-3]))
        self.assertTrue("i-d-announce@" in outbox[-3]['To'])
        self.assertTrue("New Version Notification" in outbox[-2]["Subject"])
        self.assertTrue(name in unicode(outbox[-2]))
        self.assertTrue("mars" in unicode(outbox[-2]))
        self.assertTrue(draft.ad.role_email("ad").address in unicode(outbox[-2]))
        self.assertTrue(ballot_position.ad.role_email("ad").address in unicode(outbox[-2]))
        self.assertTrue("New Version Notification" in outbox[-1]["Subject"])
        self.assertTrue(name in unicode(outbox[-1]))
        self.assertTrue("mars" in unicode(outbox[-1]))
Beispiel #16
0
def edit_position(request, name, ballot_id):
    """Vote and edit discuss and comment on document as Area Director."""
    doc = get_object_or_404(Document, docalias__name=name)
    ballot = get_object_or_404(BallotDocEvent, type="created_ballot", pk=ballot_id, doc=doc)

    ad = login = request.user.person

    if 'HTTP_REFERER' in request.META:
        return_to_url = request.META['HTTP_REFERER']
    else:
        return_to_url = urlreverse("doc_ballot", kwargs=dict(name=doc.name, ballot_id=ballot_id))

    # if we're in the Secretariat, we can select an AD to act as stand-in for
    if has_role(request.user, "Secretariat"):
        ad_id = request.GET.get('ad')
        if not ad_id:
            raise Http404()
        ad = get_object_or_404(Person, pk=ad_id)

    old_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=ad, ballot=ballot)

    if request.method == 'POST':
        if not has_role(request.user, "Secretariat") and not ad.role_set.filter(name="ad", group__type="area", group__state="active"):
            # prevent pre-ADs from voting
            return HttpResponseForbidden("Must be a proper Area Director in an active area to cast ballot")
        
        form = EditPositionForm(request.POST, ballot_type=ballot.ballot_type)
        if form.is_valid():
            # save the vote
            clean = form.cleaned_data

            if clean['return_to_url']:
              return_to_url = clean['return_to_url']

            pos = BallotPositionDocEvent(doc=doc, by=login)
            pos.type = "changed_ballot_position"
            pos.ballot = ballot
            pos.ad = ad
            pos.pos = clean["position"]
            pos.comment = clean["comment"].rstrip()
            pos.comment_time = old_pos.comment_time if old_pos else None
            pos.discuss = clean["discuss"].rstrip()
            if not pos.pos.blocking:
                pos.discuss = ""
            pos.discuss_time = old_pos.discuss_time if old_pos else None

            changes = []
            added_events = []
            # possibly add discuss/comment comments to history trail
            # so it's easy to see what's happened
            old_comment = old_pos.comment if old_pos else ""
            if pos.comment != old_comment:
                pos.comment_time = pos.time
                changes.append("comment")

                if pos.comment:
                    e = DocEvent(doc=doc)
                    e.by = ad # otherwise we can't see who's saying it
                    e.type = "added_comment"
                    e.desc = "[Ballot comment]\n" + pos.comment
                    added_events.append(e)

            old_discuss = old_pos.discuss if old_pos else ""
            if pos.discuss != old_discuss:
                pos.discuss_time = pos.time
                changes.append("discuss")

                if pos.pos.blocking:
                    e = DocEvent(doc=doc, by=login)
                    e.by = ad # otherwise we can't see who's saying it
                    e.type = "added_comment"
                    e.desc = "[Ballot %s]\n" % pos.pos.name.lower()
                    e.desc += pos.discuss
                    added_events.append(e)

            # figure out a description
            if not old_pos and pos.pos.slug != "norecord":
                pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
            elif old_pos and pos.pos != old_pos.pos:
                pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos.ad.plain_name(), pos.pos.name, old_pos.pos.name)

            if not pos.desc and changes:
                pos.desc = u"Ballot %s text updated for %s" % (u" and ".join(changes), ad.plain_name())

            # only add new event if we actually got a change
            if pos.desc:
                if login != ad:
                    pos.desc += u" by %s" % login.plain_name()

                pos.save()

                for e in added_events:
                    e.save() # save them after the position is saved to get later id for sorting order
                        
            if request.POST.get("send_mail"):
                qstr = "?return_to_url=%s" % return_to_url
                if request.GET.get('ad'):
                    qstr += "&ad=%s" % request.GET.get('ad')
                return HttpResponseRedirect(urlreverse("doc_send_ballot_comment", kwargs=dict(name=doc.name, ballot_id=ballot_id)) + qstr)
            elif request.POST.get("Defer"):
                return redirect("doc_defer_ballot", name=doc)
            elif request.POST.get("Undefer"):
                return redirect("doc_undefer_ballot", name=doc)
            else:
                return HttpResponseRedirect(return_to_url)
    else:
        initial = {}
        if old_pos:
            initial['position'] = old_pos.pos.slug
            initial['discuss'] = old_pos.discuss
            initial['comment'] = old_pos.comment
            
        if return_to_url:
            initial['return_to_url'] = return_to_url
            
        form = EditPositionForm(initial=initial, ballot_type=ballot.ballot_type)

    blocking_positions = dict((p.pk, p.name) for p in form.fields["position"].queryset.all() if p.blocking)

    ballot_deferred = doc.active_defer_event()

    return render_to_response('doc/ballot/edit_position.html',
                              dict(doc=doc,
                                   form=form,
                                   ad=ad,
                                   return_to_url=return_to_url,
                                   old_pos=old_pos,
                                   ballot_deferred=ballot_deferred,
                                   ballot = ballot,
                                   show_discuss_text=old_pos and old_pos.pos.blocking,
                                   blocking_positions=json.dumps(blocking_positions),
                                   ),
                              context_instance=RequestContext(request))
Beispiel #17
0
def update_docs_from_rfc_index(data, skip_older_than_date=None):
    std_level_mapping = {
        "Standard": StdLevelName.objects.get(slug="std"),
        "Internet Standard": StdLevelName.objects.get(slug="std"),
        "Draft Standard": StdLevelName.objects.get(slug="ds"),
        "Proposed Standard": StdLevelName.objects.get(slug="ps"),
        "Informational": StdLevelName.objects.get(slug="inf"),
        "Experimental": StdLevelName.objects.get(slug="exp"),
        "Best Current Practice": StdLevelName.objects.get(slug="bcp"),
        "Historic": StdLevelName.objects.get(slug="hist"),
        "Unknown": StdLevelName.objects.get(slug="unkn"),
        }

    stream_mapping = {
        "IETF": StreamName.objects.get(slug="ietf"),
        "INDEPENDENT": StreamName.objects.get(slug="ise"),
        "IRTF": StreamName.objects.get(slug="irtf"),
        "IAB": StreamName.objects.get(slug="iab"),
        "Legacy": StreamName.objects.get(slug="legacy"),
    }

    tag_has_errata = DocTagName.objects.get(slug='errata')
    relationship_obsoletes = DocRelationshipName.objects.get(slug="obs")
    relationship_updates = DocRelationshipName.objects.get(slug="updates")

    system = Person.objects.get(name="(System)")

    results = []
    new_rfcs = []

    for rfc_number, title, authors, rfc_published_date, current_status, updates, updated_by, obsoletes, obsoleted_by, also, draft, has_errata, stream, wg, file_formats, pages, abstract in data:

        if skip_older_than_date and rfc_published_date < skip_older_than_date:
            # speed up the process by skipping old entries
            continue

        # we assume two things can happen: we get a new RFC, or an
        # attribute has been updated at the RFC Editor (RFC Editor
        # attributes take precedence over our local attributes)

        # make sure we got the document and alias
        doc = None
        name = "rfc%s" % rfc_number
        a = DocAlias.objects.filter(name=name).select_related("document")
        if a:
            doc = a[0].document
        else:
            if draft:
                try:
                    doc = Document.objects.get(name=draft)
                except Document.DoesNotExist:
                    pass

            if not doc:
                results.append("created document %s" % name)
                doc = Document.objects.create(name=name, type=DocTypeName.objects.get(slug="draft"))

            # add alias
            DocAlias.objects.get_or_create(name=name, document=doc)
            results.append("created alias %s to %s" % (name, doc.name))

        # check attributes
        changed_attributes = {}
        changed_states = []
        created_relations = []
        other_changes = False
        if title != doc.title:
            changed_attributes["title"] = title

        if abstract and abstract != doc.abstract:
            changed_attributes["abstract"] = abstract

        if pages and int(pages) != doc.pages:
            changed_attributes["pages"] = int(pages)

        if std_level_mapping[current_status] != doc.std_level:
            changed_attributes["std_level"] = std_level_mapping[current_status]

        if doc.get_state_slug() != "rfc":
            changed_states.append(State.objects.get(used=True, type="draft", slug="rfc"))
            move_draft_files_to_archive(doc, doc.rev)

        if doc.stream != stream_mapping[stream]:
            changed_attributes["stream"] = stream_mapping[stream]

        if not doc.group: # if we have no group assigned, check if RFC Editor has a suggestion
            if wg:
                changed_attributes["group"] = Group.objects.get(acronym=wg)
            else:
                changed_attributes["group"] = Group.objects.get(type="individ")

        if not doc.latest_event(type="published_rfc"):
            e = DocEvent(doc=doc, type="published_rfc")
            # unfortunately, rfc_published_date doesn't include the correct day
            # at the moment because the data only has month/year, so
            # try to deduce it
            d = datetime.datetime.combine(rfc_published_date, datetime.time())
            synthesized = datetime.datetime.now()
            if abs(d - synthesized) > datetime.timedelta(days=60):
                synthesized = d
            else:
                direction = -1 if (d - synthesized).total_seconds() < 0 else +1
                while synthesized.month != d.month or synthesized.year != d.year:
                    synthesized += datetime.timedelta(days=direction)
            e.time = synthesized
            e.by = system
            e.desc = "RFC published"
            e.save()
            other_changes = True

            results.append("Added RFC published event: %s" % e.time.strftime("%Y-%m-%d"))
            new_rfcs.append(doc)

        for t in ("draft-iesg", "draft-stream-iab", "draft-stream-irtf", "draft-stream-ise"):
            slug = doc.get_state_slug(t)
            if slug and slug != "pub":
                changed_states.append(State.objects.get(used=True, type=t, slug="pub"))

        def parse_relation_list(l):
            res = []
            for x in l:
                if x[:3] in ("NIC", "IEN", "STD", "RTR"):
                    # try translating this to RFCs that we can handle
                    # sensibly; otherwise we'll have to ignore them
                    l = DocAlias.objects.filter(name__startswith="rfc", document__docalias__name=x.lower())
                else:
                    l = DocAlias.objects.filter(name=x.lower())

                for a in l:
                    if a not in res:
                        res.append(a)
            return res

        for x in parse_relation_list(obsoletes):
            if not RelatedDocument.objects.filter(source=doc, target=x, relationship=relationship_obsoletes):
                created_relations.append(RelatedDocument(source=doc, target=x, relationship=relationship_obsoletes))

        for x in parse_relation_list(updates):
            if not RelatedDocument.objects.filter(source=doc, target=x, relationship=relationship_updates):
                created_relations.append(RelatedDocument(source=doc, target=x, relationship=relationship_updates))

        if also:
            for a in also:
                a = a.lower()
                if not DocAlias.objects.filter(name=a):
                    DocAlias.objects.create(name=a, document=doc)
                    other_changes = True
                    results.append("Created alias %s to %s" % (a, doc.name))

        if has_errata:
            if not doc.tags.filter(pk=tag_has_errata.pk):
                changed_attributes["tags"] = list(doc.tags.all()) + [tag_has_errata]
        else:
            if doc.tags.filter(pk=tag_has_errata.pk):
                changed_attributes["tags"] = set(doc.tags.all()) - set([tag_has_errata])

        if changed_attributes or changed_states or created_relations or other_changes:
            # apply changes
            save_document_in_history(doc)
            for k, v in changed_attributes.iteritems():
                setattr(doc, k, v)
                results.append("Changed %s to %s on %s" % (k, v, doc.name))

            for s in changed_states:
                doc.set_state(s)
                results.append("Set state %s on %s" % (s, doc.name))

            for o in created_relations:
                o.save()
                results.append("Created %s" % o)

            doc.time = datetime.datetime.now()
            doc.save()

    return results, new_rfcs
Beispiel #18
0
    def save(self):
        comment = self.cleaned_data.get('comment').strip()
        weeks = self.cleaned_data.get('weeks')
        group = IETFWG.objects.get(pk=self.cleaned_data.get('group'))
        estimated_date = None
        if weeks:
            now = datetime.date.today()
            estimated_date = now + datetime.timedelta(weeks=weeks)
        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            # do changes on real Document object instead of proxy to avoid trouble
            doc = Document.objects.get(pk=self.draft.pk)
            save_document_in_history(doc)

            doc.time = datetime.datetime.now()

            if group.type.slug == "rg":
                new_stream = StreamName.objects.get(slug="irtf")
            else:
                new_stream = StreamName.objects.get(slug="ietf")

            if doc.stream != new_stream:
                e = DocEvent(type="changed_stream")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed to <b>%s</b>" % new_stream.name
                if doc.stream:
                    e.desc += u" from %s" % doc.stream.name
                e.save()
                doc.stream = new_stream

            if doc.group.pk != group.pk:
                e = DocEvent(type="changed_group")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed group to <b>%s (%s)</b>" % (
                    group.name, group.acronym.upper())
                if doc.group.type_id != "individ":
                    e.desc += " from %s (%s)" % (doc.group.name,
                                                 doc.group.acronym)
                e.save()
                doc.group_id = group.pk

            doc.save()
            self.draft = InternetDraft.objects.get(
                pk=doc.pk)  # make sure proxy object is updated
        else:
            workflow = get_workflow_for_wg(wg)
            set_workflow_for_object(self.draft, workflow)
            stream = get_stream_by_name(IETF_STREAM)
            streamed = get_streamed_draft(self.draft)
            if not streamed:
                set_stream_for_draft(self.draft, stream)
                streamed = get_streamed_draft(self.draft)
            streamed.stream = stream
            streamed.group = wg
            streamed.save()

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            from ietf.doc.models import State
            if self.draft.stream_id == "irtf":
                to_state = State.objects.get(used=True,
                                             slug="active",
                                             type="draft-stream-irtf")
            else:
                to_state = State.objects.get(used=True,
                                             slug="c-adopt",
                                             type="draft-stream-%s" %
                                             self.draft.stream_id)
        else:
            to_state = get_state_by_name(CALL_FOR_ADOPTION)
        update_state(self.request,
                     self.draft,
                     comment=comment,
                     person=self.person,
                     to_state=to_state,
                     estimated_date=estimated_date)

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            if comment:
                e = DocEvent(type="added_comment")
                e.time = self.draft.time
                e.by = self.person
                e.doc_id = self.draft.pk
                e.desc = comment
                e.save()
Beispiel #19
0
    def save(self):
        comment = self.cleaned_data.get('comment').strip()
        weeks = self.cleaned_data.get('weeks')
        group = IETFWG.objects.get(pk=self.cleaned_data.get('group'))
        estimated_date = None
        if weeks:
            now = datetime.date.today()
            estimated_date = now + datetime.timedelta(weeks=weeks)
        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            # do changes on real Document object instead of proxy to avoid trouble
            doc = Document.objects.get(pk=self.draft.pk)
            save_document_in_history(doc)

            doc.time = datetime.datetime.now()

            if group.type.slug == "rg":
                new_stream = StreamName.objects.get(slug="irtf")                
            else:
                new_stream = StreamName.objects.get(slug="ietf")                

            if doc.stream != new_stream:
                e = DocEvent(type="changed_stream")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed to <b>%s</b>" % new_stream.name
                if doc.stream:
                    e.desc += u" from %s" % doc.stream.name
                e.save()
                doc.stream = new_stream

            if doc.group.pk != group.pk:
                e = DocEvent(type="changed_group")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed group to <b>%s (%s)</b>" % (group.name, group.acronym.upper())
                if doc.group.type_id != "individ":
                    e.desc += " from %s (%s)" % (doc.group.name, doc.group.acronym)
                e.save()
                doc.group_id = group.pk

            doc.save()
            self.draft = InternetDraft.objects.get(pk=doc.pk) # make sure proxy object is updated
        else:
            workflow = get_workflow_for_wg(wg)
            set_workflow_for_object(self.draft, workflow)
            stream = get_stream_by_name(IETF_STREAM)
            streamed = get_streamed_draft(self.draft)
            if not streamed:
                set_stream_for_draft(self.draft, stream)
                streamed = get_streamed_draft(self.draft)
            streamed.stream = stream
            streamed.group = wg
            streamed.save()

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            from ietf.doc.models import State
            if self.draft.stream_id == "irtf":
                to_state = State.objects.get(used=True, slug="active", type="draft-stream-irtf")
            else:
                to_state = State.objects.get(used=True, slug="c-adopt", type="draft-stream-%s" % self.draft.stream_id)
        else:
            to_state = get_state_by_name(CALL_FOR_ADOPTION)
        update_state(self.request, self.draft,
                     comment=comment,
                     person=self.person,
                     to_state=to_state,
                     estimated_date=estimated_date)

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            if comment:
                e = DocEvent(type="added_comment")
                e.time = self.draft.time
                e.by = self.person
                e.doc_id = self.draft.pk
                e.desc = comment
                e.save()
Beispiel #20
0
def update_docs_from_rfc_index(data, skip_older_than_date=None):
    """Given parsed data from the RFC Editor index, update the documents
    in the database. Yields a list of change descriptions for each
    document, if any."""

    std_level_mapping = {
        "Standard": StdLevelName.objects.get(slug="std"),
        "Internet Standard": StdLevelName.objects.get(slug="std"),
        "Draft Standard": StdLevelName.objects.get(slug="ds"),
        "Proposed Standard": StdLevelName.objects.get(slug="ps"),
        "Informational": StdLevelName.objects.get(slug="inf"),
        "Experimental": StdLevelName.objects.get(slug="exp"),
        "Best Current Practice": StdLevelName.objects.get(slug="bcp"),
        "Historic": StdLevelName.objects.get(slug="hist"),
        "Unknown": StdLevelName.objects.get(slug="unkn"),
    }

    stream_mapping = {
        "IETF": StreamName.objects.get(slug="ietf"),
        "INDEPENDENT": StreamName.objects.get(slug="ise"),
        "IRTF": StreamName.objects.get(slug="irtf"),
        "IAB": StreamName.objects.get(slug="iab"),
        "Legacy": StreamName.objects.get(slug="legacy"),
    }

    tag_has_errata = DocTagName.objects.get(slug='errata')
    relationship_obsoletes = DocRelationshipName.objects.get(slug="obs")
    relationship_updates = DocRelationshipName.objects.get(slug="updates")

    system = Person.objects.get(name="(System)")

    for rfc_number, title, authors, rfc_published_date, current_status, updates, updated_by, obsoletes, obsoleted_by, also, draft, has_errata, stream, wg, file_formats, pages, abstract in data:

        if skip_older_than_date and rfc_published_date < skip_older_than_date:
            # speed up the process by skipping old entries
            continue

        # we assume two things can happen: we get a new RFC, or an
        # attribute has been updated at the RFC Editor (RFC Editor
        # attributes take precedence over our local attributes)
        events = []
        changes = []
        rfc_published = False

        # make sure we got the document and alias
        doc = None
        name = "rfc%s" % rfc_number
        a = DocAlias.objects.filter(name=name).select_related("document")
        if a:
            doc = a[0].document
        else:
            if draft:
                try:
                    doc = Document.objects.get(name=draft)
                except Document.DoesNotExist:
                    pass

            if not doc:
                changes.append("created document %s" % prettify_std_name(name))
                doc = Document.objects.create(
                    name=name, type=DocTypeName.objects.get(slug="draft"))

            # add alias
            DocAlias.objects.get_or_create(name=name, document=doc)
            changes.append("created alias %s" % prettify_std_name(name))

        # check attributes
        if title != doc.title:
            doc.title = title
            changes.append("changed title to '%s'" % doc.title)

        if abstract and abstract != doc.abstract:
            doc.abstract = abstract
            changes.append("changed abstract to '%s'" % doc.abstract)

        if pages and int(pages) != doc.pages:
            doc.pages = int(pages)
            changes.append("changed pages to %s" % doc.pages)

        if std_level_mapping[current_status] != doc.std_level:
            doc.std_level = std_level_mapping[current_status]
            changes.append("changed standardization level to %s" %
                           doc.std_level)

        if doc.get_state_slug() != "rfc":
            doc.set_state(
                State.objects.get(used=True, type="draft", slug="rfc"))
            move_draft_files_to_archive(doc, doc.rev)
            changes.append("changed state to %s" % doc.get_state())

        if doc.stream != stream_mapping[stream]:
            doc.stream = stream_mapping[stream]
            changes.append("changed stream to %s" % doc.stream)

        if not doc.group:  # if we have no group assigned, check if RFC Editor has a suggestion
            if wg:
                doc.group = Group.objects.get(acronym=wg)
                changes.append("set group to %s" % doc.group)
            else:
                doc.group = Group.objects.get(
                    type="individ")  # fallback for newly created doc

        if not doc.latest_event(type="published_rfc"):
            e = DocEvent(doc=doc, rev=doc.rev, type="published_rfc")
            # unfortunately, rfc_published_date doesn't include the correct day
            # at the moment because the data only has month/year, so
            # try to deduce it
            d = datetime.datetime.combine(rfc_published_date, datetime.time())
            synthesized = datetime.datetime.now()
            if abs(d - synthesized) > datetime.timedelta(days=60):
                synthesized = d
            else:
                direction = -1 if (d - synthesized).total_seconds() < 0 else +1
                while synthesized.month != d.month or synthesized.year != d.year:
                    synthesized += datetime.timedelta(days=direction)
            e.time = synthesized
            e.by = system
            e.desc = "RFC published"
            e.save()
            events.append(e)

            changes.append("added RFC published event at %s" %
                           e.time.strftime("%Y-%m-%d"))
            rfc_published = True

        for t in ("draft-iesg", "draft-stream-iab", "draft-stream-irtf",
                  "draft-stream-ise"):
            slug = doc.get_state_slug(t)
            if slug and slug != "pub":
                new_state = State.objects.select_related("type").get(
                    used=True, type=t, slug="pub")
                doc.set_state(new_state)
                changes.append("changed %s to %s" %
                               (new_state.type.label, new_state))

        def parse_relation_list(l):
            res = []
            for x in l:
                if x[:3] in ("NIC", "IEN", "STD", "RTR"):
                    # try translating this to RFCs that we can handle
                    # sensibly; otherwise we'll have to ignore them
                    l = DocAlias.objects.filter(
                        name__startswith="rfc",
                        document__docalias__name=x.lower())
                else:
                    l = DocAlias.objects.filter(name=x.lower())

                for a in l:
                    if a not in res:
                        res.append(a)
            return res

        for x in parse_relation_list(obsoletes):
            if not RelatedDocument.objects.filter(
                    source=doc, target=x, relationship=relationship_obsoletes):
                r = RelatedDocument.objects.create(
                    source=doc, target=x, relationship=relationship_obsoletes)
                changes.append("created %s relation between %s and %s" %
                               (r.relationship.name.lower(),
                                prettify_std_name(r.source.name),
                                prettify_std_name(r.target.name)))

        for x in parse_relation_list(updates):
            if not RelatedDocument.objects.filter(
                    source=doc, target=x, relationship=relationship_updates):
                r = RelatedDocument.objects.create(
                    source=doc, target=x, relationship=relationship_updates)
                changes.append("created %s relation between %s and %s" %
                               (r.relationship.name.lower(),
                                prettify_std_name(r.source.name),
                                prettify_std_name(r.target.name)))

        if also:
            for a in also:
                a = a.lower()
                if not DocAlias.objects.filter(name=a):
                    DocAlias.objects.create(name=a, document=doc)
                    changes.append("created alias %s" % prettify_std_name(a))

        if has_errata:
            if not doc.tags.filter(pk=tag_has_errata.pk):
                doc.tags.add(tag_has_errata)
                changes.append("added Errata tag")
        else:
            if doc.tags.filter(pk=tag_has_errata.pk):
                doc.tags.remove(tag_has_errata)
                changes.append("removed Errata tag")

        if changes:
            events.append(
                DocEvent.objects.create(
                    doc=doc,
                    rev=doc.rev,
                    by=system,
                    type="sync_from_rfc_editor",
                    desc=u"Received changes through RFC Editor sync (%s)" %
                    u", ".join(changes),
                ))

            doc.save_with_history(events)

        if changes:
            yield changes, doc, rfc_published