Beispiel #1
0
def build_conflict_review_document(login, doc_to_review, ad, notify, create_in_state):
    if doc_to_review.name.startswith('draft-'):
        review_name = 'conflict-review-'+doc_to_review.name[6:]
    else:
        # This is a failsafe - and might be treated better as an error
        review_name = 'conflict-review-'+doc_to_review.name

    iesg_group = Group.objects.get(acronym='iesg')

    conflict_review = Document.objects.create(
        type_id="conflrev",
        title="IETF conflict review for %s" % doc_to_review.name,
        name=review_name,
        rev="00",
        ad=ad,
        notify=notify,
        stream_id='ietf',
        group=iesg_group,
    )
    conflict_review.set_state(create_in_state)

    DocAlias.objects.create( name=review_name , document=conflict_review )
            
    conflict_review.relateddocument_set.create(target=DocAlias.objects.get(name=doc_to_review.name),relationship_id='conflrev')

    c = DocEvent(type="added_comment", doc=conflict_review, rev=conflict_review.rev, by=login)
    c.desc = "IETF conflict review requested"
    c.save()

    c = DocEvent(type="added_comment", doc=doc_to_review, rev=doc_to_review.rev, by=login)
    # Is it really OK to put html tags into comment text?
    c.desc = 'IETF conflict review initiated - see <a href="%s">%s</a>' % (reverse('ietf.doc.views_doc.document_main', kwargs={'name':conflict_review.name}),conflict_review.name)
    c.save()

    return conflict_review
Beispiel #2
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this status_change."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():

            status_change.ad = form.cleaned_data['ad']
            status_change.save()
    
            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Shepherding AD changed to "+status_change.ad.name
            c.save()

            return redirect("doc_view", name=status_change.name)

    else:
        init = { "ad" : status_change.ad_id }
        form = AdForm(initial=init)

    titletext = '%s-%s.txt' % (status_change.canonical_name(),status_change.rev)
    return render_to_response('doc/change_ad.html',
                              {'form': form,
                               'doc': status_change,
                               'titletext' : titletext,
                              },
                              context_instance = RequestContext(request))
Beispiel #3
0
def edit_ad(request, name):
    """Change the responsible Area Director for this charter."""

    charter = get_object_or_404(Document, type="charter", name=name)
    login = request.user.person

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():
            new_ad = form.cleaned_data['ad']
            if new_ad != charter.ad:
                save_document_in_history(charter)
                e = DocEvent(doc=charter, by=login)
                e.desc = "Responsible AD changed to %s" % new_ad.plain_name()
                if charter.ad:
                   e.desc += " from %s" % charter.ad.plain_name()
                e.type = "changed_document"
                e.save()
                charter.ad = new_ad
                charter.time = e.time
                charter.save()

            return redirect('doc_view', name=charter.name)
    else:
        init = { "ad" : charter.ad_id }
        form = AdForm(initial=init)

    return render_to_response('doc/charter/change_ad.html',
                              {'form':   form,
                               'charter': charter,
                              },
                              context_instance = RequestContext(request))
Beispiel #4
0
def expire_draft(doc):
    # clean up files
    move_draft_files_to_archive(doc, doc.rev)

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

    # change the state
    save_document_in_history(doc)
    if doc.latest_event(type='started_iesg_process'):
        new_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
        prev_state = doc.get_state(new_state.type_id)
        prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
        if new_state != prev_state:
            doc.set_state(new_state)
            doc.tags.remove(*prev_tags)
            e = add_state_change_event(doc, system, prev_state, new_state, prev_tags=prev_tags, new_tags=[])

        e = DocEvent(doc=doc, by=system)
        e.type = "expired_document"
        e.desc = "Document has expired"
        e.save()

    doc.set_state(State.objects.get(used=True, type="draft", slug="expired"))
    doc.time = datetime.datetime.now()
    doc.save()
Beispiel #5
0
def change_state(request, name, option=None):
    """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary
    and logging the change as a comment."""
    review = get_object_or_404(Document, type="conflrev", name=name)

    login = request.user.get_profile()

    if request.method == 'POST':
        form = ChangeStateForm(request.POST)
        if form.is_valid():
            clean = form.cleaned_data
            review_state = clean['review_state']
            comment = clean['comment'].rstrip()

            if comment:
                c = DocEvent(type="added_comment", doc=review, by=login)
                c.desc = comment
                c.save()

            if review_state != review.get_state():
                save_document_in_history(review)

                old_description = review.friendly_state()
                review.set_state(review_state)
                new_description = review.friendly_state()

                log_state_changed(request, review, login, new_description, old_description)

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

                if review_state.slug == "iesgeval":
                    create_ballot_if_not_open(review, login, "conflrev")
                    ballot = review.latest_event(BallotDocEvent, type="created_ballot")
                    if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"):

                        # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes"
                        pos = BallotPositionDocEvent(doc=review, by=login)
                        pos.ballot = ballot
                        pos.type = "changed_ballot_position"
                        pos.ad = login
                        pos.pos_id = "yes"
                        pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
                        pos.save()
                    send_conflict_eval_email(request,review)


            return redirect('doc_view', name=review.name)
    else:
        s = review.get_state()
        init = dict(review_state=s.pk if s else None)
        form = ChangeStateForm(initial=init)

    return render_to_response('doc/change_state.html',
                              dict(form=form,
                                   doc=review,
                                   login=login,
                                   help_url=reverse('help_conflict_review_states'),
                                   ),
                              context_instance=RequestContext(request))
Beispiel #6
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this review."""

    review = get_object_or_404(Document, type="conflrev", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():
            review.ad = form.cleaned_data['ad']

            c = DocEvent(type="added_comment", doc=review, rev=review.rev, by=request.user.person)
            c.desc = "Shepherding AD changed to "+review.ad.name
            c.save()

            review.save_with_history([c])

            return redirect('ietf.doc.views_doc.document_main', name=review.name)

    else:
        init = { "ad" : review.ad_id }
        form = AdForm(initial=init)

    
    conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document
    titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),conflictdoc.rev)
    return render(request, 'doc/change_ad.html',
                              {'form': form,
                               'doc': review,
                               'titletext': titletext
                              },
                          )
Beispiel #7
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this review."""

    review = get_object_or_404(Document, type="conflrev", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():

            review.ad = form.cleaned_data['ad']
            review.save()

            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "Shepherding AD changed to " + review.ad.name
            c.save()

            return HttpResponseRedirect(
                reverse('doc_view', kwargs={'name': review.name}))

    else:
        init = {"ad": review.ad_id}
        form = AdForm(initial=init)

    conflictdoc = review.relateddocument_set.get(
        relationship__slug='conflrev').target.document
    titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),
                                                  conflictdoc.rev)
    return render_to_response('doc/change_ad.html', {
        'form': form,
        'doc': review,
        'titletext': titletext
    },
                              context_instance=RequestContext(request))
def edit_title(request, name):
    """Change the title for this status_change document."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = ChangeTitleForm(request.POST)
        if form.is_valid():

            status_change.title = form.cleaned_data['title']
            status_change.save()
    
            login = request.user.person
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Title changed to '%s'"%status_change.title
            c.save()

            return redirect("doc_view", name=status_change.name)

    else:
        init = { "title" : status_change.title }
        form = ChangeTitleForm(initial=init)

    titletext = '%s-%s.txt' % (status_change.canonical_name(),status_change.rev)
    return render_to_response('doc/change_title.html',
                              {'form': form,
                               'doc': status_change,
                               'titletext' : titletext,
                              },
                              context_instance = RequestContext(request))
Beispiel #9
0
def edit_notify(request, name):
    doc = get_object_or_404(Document, type="charter", name=name)
    login = request.user.person

    init = {'notify': doc.notify}

    if request.method == "POST":
        form = NotifyForm(request.POST, initial=init)
        if form.is_valid():
            n = form.cleaned_data["notify"]
            if n != doc.notify:
                save_document_in_history(doc)

                e = DocEvent(doc=doc, by=login)
                e.desc = "Notification list changed to %s" % (escape(n) or "none")
                if doc.notify:
                    e.desc += " from %s" % escape(doc.notify)
                e.type = "changed_document"
                e.save()

                doc.notify = n
                doc.time = e.time
                doc.save()

            return redirect("doc_view", name=doc.name)
    else:
        form = NotifyForm(initial=init)

    return render_to_response('doc/charter/edit_notify.html',
                              dict(doc=doc,
                                   form=form,
                                   user=request.user,
                                   login=login),
                              context_instance=RequestContext(request))
Beispiel #10
0
def add_comment(request, name):
    """Add comment to history of document."""
    doc = get_object_or_404(Document, docalias__name=name)

    login = request.user.person

    if request.method == 'POST':
        form = AddCommentForm(request.POST)
        if form.is_valid():
            c = form.cleaned_data['comment']
            
            e = DocEvent(doc=doc, by=login)
            e.type = "added_comment"
            e.desc = c
            e.save()

            if doc.type_id == "draft":
                email_ad(request, doc, doc.ad, login,
                            "A new comment added by %s" % login.name)
            return redirect("doc_history", name=doc.name)
    else:
        form = AddCommentForm()
  
    return render_to_response('doc/add_comment.html',
                              dict(doc=doc,
                                   form=form),
                              context_instance=RequestContext(request))
Beispiel #11
0
def edit_notices(request, name):
    """Change the set of email addresses document change notificaitions go to."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = NotifyForm(request.POST)
        if form.is_valid():

            status_change.notify = form.cleaned_data['notify']
            status_change.save()

            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Notification list changed to : "+status_change.notify
            c.save()

            return HttpResponseRedirect(reverse('doc_view', kwargs={'name': status_change.name}))

    else:

        init = { "notify" : status_change.notify }
        form = NotifyForm(initial=init)

    return render_to_response('doc/notify.html',
                              {'form': form,
                               'doc': status_change,
                               'titletext' : '%s-%s.txt' % (status_change.canonical_name(),status_change.rev)
                              },
                              context_instance = RequestContext(request))
Beispiel #12
0
def edit_notices(request, name):
    """Change the set of email addresses document change notificaitions go to."""

    review = get_object_or_404(Document, type="conflrev", name=name)

    if request.method == 'POST':
        form = NotifyForm(request.POST)
        if form.is_valid():

            review.notify = form.cleaned_data['notify']
            review.save()

            login = request.user.person
            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "Notification list changed to : "+review.notify
            c.save()

            return redirect('doc_view', name=review.name)

    else:

        init = { "notify" : review.notify }
        form = NotifyForm(initial=init)

    conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document
    titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),conflictdoc.rev)
    return render_to_response('doc/notify.html',
                              {'form': form,
                               'doc': review,
                               'titletext' : titletext
                              },
                              context_instance = RequestContext(request))
Beispiel #13
0
def edit_notices(request, name):
    """Change the set of email addresses document change notificaitions go to."""

    review = get_object_or_404(Document, type="conflrev", name=name)

    if request.method == 'POST':
        form = NotifyForm(request.POST)
        if form.is_valid():

            review.notify = form.cleaned_data['notify']
            review.save()

            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "Notification list changed to : " + review.notify
            c.save()

            return HttpResponseRedirect(
                reverse('doc_view', kwargs={'name': review.name}))

    else:

        init = {"notify": review.notify}
        form = NotifyForm(initial=init)

    conflictdoc = review.relateddocument_set.get(
        relationship__slug='conflrev').target.document
    titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),
                                                  conflictdoc.rev)
    return render_to_response('doc/notify.html', {
        'form': form,
        'doc': review,
        'titletext': titletext
    },
                              context_instance=RequestContext(request))
Beispiel #14
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this review."""

    review = get_object_or_404(Document, type="conflrev", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():

            review.ad = form.cleaned_data['ad']
            review.save()
    
            login = request.user.person
            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "Shepherding AD changed to "+review.ad.name
            c.save()

            return redirect('doc_view', name=review.name)

    else:
        init = { "ad" : review.ad_id }
        form = AdForm(initial=init)

    
    conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document
    titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),conflictdoc.rev)
    return render_to_response('doc/change_ad.html',
                              {'form': form,
                               'doc': review,
                               'titletext': titletext
                              },
                              context_instance = RequestContext(request))
Beispiel #15
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this status_change."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():

            status_change.ad = form.cleaned_data['ad']
            status_change.save()

            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Shepherding AD changed to " + status_change.ad.name
            c.save()

            return redirect("doc_view", name=status_change.name)

    else:
        init = {"ad": status_change.ad_id}
        form = AdForm(initial=init)

    titletext = '%s-%s.txt' % (status_change.canonical_name(),
                               status_change.rev)
    return render_to_response('doc/change_ad.html', {
        'form': form,
        'doc': status_change,
        'titletext': titletext,
    },
                              context_instance=RequestContext(request))
Beispiel #16
0
def edit_notices(request, name):
    """Change the set of email addresses document change notificaitions go to."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = NotifyForm(request.POST)
        if form.is_valid():

            status_change.notify = form.cleaned_data['notify']
            status_change.save()

            login = request.user.get_profile()
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Notification list changed to : " + status_change.notify
            c.save()

            return HttpResponseRedirect(
                reverse('doc_view', kwargs={'name': status_change.name}))

    else:

        init = {"notify": status_change.notify}
        form = NotifyForm(initial=init)

    return render_to_response('doc/notify.html', {
        'form':
        form,
        'doc':
        status_change,
        'titletext':
        '%s-%s.txt' % (status_change.canonical_name(), status_change.rev)
    },
                              context_instance=RequestContext(request))
Beispiel #17
0
def set_replaces_for_document(request, doc, new_replaces, by, email_subject, comment=""):
    addrs = gather_address_lists('doc_replacement_changed',doc=doc)
    to = set(addrs.to)
    cc = set(addrs.cc)

    relationship = DocRelationshipName.objects.get(slug='replaces')
    old_replaces = doc.related_that_doc("replaces")

    events = []

    e = DocEvent(doc=doc, rev=doc.rev, by=by, type='changed_document')
    new_replaces_names = u", ".join(d.name for d in new_replaces) or u"None"
    old_replaces_names = u", ".join(d.name for d in old_replaces) or u"None"
    e.desc = u"This document now replaces <b>%s</b> instead of %s" % (new_replaces_names, old_replaces_names)
    e.save()

    events.append(e)

    if comment:
        events.append(DocEvent.objects.create(doc=doc, rev=doc.rev, by=by, type="added_comment", desc=comment))

    for d in old_replaces:
        if d not in new_replaces:
            other_addrs = gather_address_lists('doc_replacement_changed',doc=d.document)
            to.update(other_addrs.to)
            cc.update(other_addrs.cc)
            RelatedDocument.objects.filter(source=doc, target=d, relationship=relationship).delete()
            if not RelatedDocument.objects.filter(target=d, relationship=relationship):
                s = 'active' if d.document.expires > datetime.datetime.now() else 'expired'
                d.document.set_state(State.objects.get(type='draft', slug=s))

    for d in new_replaces:
        if d not in old_replaces:
            other_addrs = gather_address_lists('doc_replacement_changed',doc=d.document)
            to.update(other_addrs.to)
            cc.update(other_addrs.cc)
            RelatedDocument.objects.create(source=doc, target=d, relationship=relationship)
            d.document.set_state(State.objects.get(type='draft', slug='repl'))

    # make sure there are no lingering suggestions duplicating new replacements
    RelatedDocument.objects.filter(source=doc, target__in=new_replaces, relationship="possibly-replaces").delete()

    email_desc = e.desc.replace(", ", "\n    ")

    if comment:
        email_desc += "\n" + comment

    from ietf.doc.mails import html_to_text

    send_mail(request, list(to),
              "DraftTracker Mail System <*****@*****.**>",
              email_subject,
              "doc/mail/change_notice.txt",
              dict(text=html_to_text(email_desc),
                   doc=doc,
                   url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()),
              cc=list(cc))

    return events
Beispiel #18
0
def log_state_changed(request, doc, by, prev_state):
    e = DocEvent(doc=doc, by=by)
    e.type = "changed_document"
    e.desc = u"State changed to <b>%s</b> from %s" % (
        doc.get_state().name,
        prev_state.name if prev_state else "None")
    e.save()
    return e
Beispiel #19
0
def change_state(request, name, option=None):
    """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary
    and logging the change as a comment."""
    review = get_object_or_404(Document, type="conflrev", name=name)

    login = request.user.person

    if request.method == 'POST':
        form = ChangeStateForm(request.POST)
        if form.is_valid():
            clean = form.cleaned_data
            new_state = clean['review_state']
            comment = clean['comment'].rstrip()

            if comment:
                c = DocEvent(type="added_comment", doc=review, rev=review.rev, by=login)
                c.desc = comment
                c.save()

            prev_state = review.get_state()
            if new_state != prev_state:
                events = []

                review.set_state(new_state)
                events.append(add_state_change_event(review, login, prev_state, new_state))

                review.save_with_history(events)

                if new_state.slug == "iesgeval":
                    create_ballot_if_not_open(review, login, "conflrev")
                    ballot = review.latest_event(BallotDocEvent, type="created_ballot")
                    if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"):

                        # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes"
                        pos = BallotPositionDocEvent(doc=review, rev=review.rev, by=login)
                        pos.ballot = ballot
                        pos.type = "changed_ballot_position"
                        pos.ad = login
                        pos.pos_id = "yes"
                        pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
                        pos.save()
                        # Consider mailing that position to 'ballot_saved'
                    send_conflict_eval_email(request,review)


            return redirect('ietf.doc.views_doc.document_main', name=review.name)
    else:
        s = review.get_state()
        init = dict(review_state=s.pk if s else None)
        form = ChangeStateForm(initial=init)

    return render(request, 'doc/change_state.html',
                              dict(form=form,
                                   doc=review,
                                   login=login,
                                   help_url=reverse('ietf.doc.views_help.state_help', kwargs=dict(type="conflict-review")),
                                   ))
Beispiel #20
0
def update_tags(request, obj, comment, person, set_tags=[], reset_tags=[], extra_notify=[]):
    if settings.USE_DB_REDESIGN_PROXY_CLASSES:
        doc = Document.objects.get(pk=obj.pk)
        save_document_in_history(doc)

        obj.tags.remove(*reset_tags)
        obj.tags.add(*set_tags)

        doc.time = datetime.datetime.now()

        e = DocEvent(type="changed_document", time=doc.time, by=person, doc=doc)
        l = []
        if set_tags:
            l.append(u"Annotation tag%s %s set." % (pluralize(set_tags), ", ".join(x.name for x in set_tags)))
        if reset_tags:
            l.append(u"Annotation tag%s %s cleared." % (pluralize(reset_tags), ", ".join(x.name for x in reset_tags)))
        e.desc = " ".join(l)
        e.save()

        receivers = get_notification_receivers(doc, extra_notify)
        send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                  u"Annotations tags changed for draft %s" % doc.name,
                  'ietfworkflows/annotation_tags_updated_mail.txt',
                  dict(doc=doc,
                       entry=dict(setted=", ".join(x.name for x in set_tags),
                                  unsetted=", ".join(x.name for x in reset_tags),
                                  change_date=doc.time,
                                  person=person,
                                  comment=comment)))
        return

    ctype = ContentType.objects.get_for_model(obj)
    setted = []
    resetted = []
    for tag in set_tags:
        if isinstance(tag, basestring):
            if set_tag_by_name(obj, tag):
                setted.append(tag)
        else:
            if set_tag(obj, tag):
                setted.append(tag.name)
    for tag in reset_tags:
        if isinstance(tag, basestring):
            if reset_tag_by_name(obj, tag):
                resetted.append(tag)
        else:
            if reset_tag(obj, tag):
                resetted.append(tag.name)
    entry = ObjectAnnotationTagHistoryEntry.objects.create(
        content_type=ctype,
        content_id=obj.pk,
        setted=','.join(setted),
        unsetted=','.join(resetted),
        date=datetime.datetime.now(),
        comment=comment,
        person=person)
    notify_tag_entry(entry, extra_notify)
Beispiel #21
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 #22
0
def change_title(request, name, option=None):
    """Change title of charter, notifying parties as necessary and
    logging the title as a comment."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group
    if not can_manage_group_type(request.user, group):
        return HttpResponseForbidden(
            "You don't have permission to access this view")
    by = request.user.person
    if request.method == 'POST':
        form = ChangeTitleForm(request.POST, charter=charter)
        if form.is_valid():
            clean = form.cleaned_data
            charter_rev = charter.rev
            new_title = clean['charter_title']
            comment = clean['comment'].rstrip()
            message = clean['message']
            prev_title = charter.title
            if new_title != prev_title:
                events = []
                charter.title = new_title
                charter.rev = charter_rev

                if not comment:
                    comment = "Changed charter title from '%s' to '%s'." % (
                        prev_title, new_title)
                e = DocEvent(type="added_comment",
                             doc=charter,
                             rev=charter.rev,
                             by=by)
                e.desc = comment
                e.save()
                events.append(e)

                charter.save_with_history(events)

                if message:
                    email_admin_re_charter(
                        request, group,
                        "Charter title changed to %s" % new_title, message,
                        'charter_state_edit_admin_needed')
                email_state_changed(request, charter,
                                    "Title changed to %s." % new_title,
                                    'doc_state_edited')
            return redirect('ietf.doc.views_doc.document_main',
                            name=charter.name)
    else:
        form = ChangeTitleForm(charter=charter)
    title = "Change charter title of %s %s" % (group.acronym, group.type.name)
    return render(request, 'doc/charter/change_title.html',
                  dict(
                      form=form,
                      doc=group.charter,
                      title=title,
                  ))
Beispiel #23
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 #24
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 #25
0
def edit_relations(request, name):
    """Change the affected set of RFCs"""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.get_profile()

    relation_slugs = DocRelationshipName.objects.filter(slug__in=RELATION_SLUGS)

    if request.method == 'POST':
        form = EditStatusChangeForm(request.POST)
        if 'Submit' in request.POST and form.is_valid():
    
            old_relations={}
            for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
                old_relations[rel.target.document.canonical_name()]=rel.relationship.slug
            new_relations=form.cleaned_data['relations']
            status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS).delete()
            for key in new_relations:
                status_change.relateddocument_set.create(target=DocAlias.objects.get(name=key),
                                                         relationship_id=new_relations[key])
            c = DocEvent(type="added_comment", doc=status_change, by=login)
            c.desc = "Affected RFC list changed.\nOLD:"
            for relname,relslug in (set(old_relations.items())-set(new_relations.items())):
                c.desc += "\n  "+relname+": "+DocRelationshipName.objects.get(slug=relslug).name
            c.desc += "\nNEW:"
            for relname,relslug in (set(new_relations.items())-set(old_relations.items())):
                c.desc += "\n  "+relname+": "+DocRelationshipName.objects.get(slug=relslug).name
            c.desc += "\n"
            c.save()

            return HttpResponseRedirect(status_change.get_absolute_url())

        elif 'Cancel' in request.POST:
            return HttpResponseRedirect(status_change.get_absolute_url())

    else: 
        relations={}
        for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
            relations[rel.target.document.canonical_name()]=rel.relationship.slug
        init = { "relations":relations, 
               }
        form = EditStatusChangeForm(initial=init)

    return render_to_response('doc/status_change/edit_relations.html',
                              {
                               'doc':            status_change, 
                               'form':           form,
                               'relation_slugs': relation_slugs,
                              },
                              context_instance = RequestContext(request))
Beispiel #26
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 #27
0
def build_conflict_review_document(login, doc_to_review, ad, notify, create_in_state):
    if doc_to_review.name.startswith('draft-'):
        review_name = 'conflict-review-'+doc_to_review.name[6:]
    else:
        # This is a failsafe - and might be treated better as an error
        review_name = 'conflict-review-'+doc_to_review.name

    iesg_group = Group.objects.get(acronym='iesg')

    conflict_review=Document( type_id = "conflrev",
                              title = "IETF conflict review for %s" % doc_to_review.name,
                              name = review_name,
                              rev = "00",
                              ad = ad,
                              notify = notify,
		              stream_id = 'ietf',
                              group = iesg_group,
                            )
    conflict_review.save()
    conflict_review.set_state(create_in_state)

    DocAlias.objects.create( name=review_name , document=conflict_review )
            
    conflict_review.relateddocument_set.create(target=DocAlias.objects.get(name=doc_to_review.name),relationship_id='conflrev')

    c = DocEvent(type="added_comment", doc=conflict_review, by=login)
    c.desc = "IETF conflict review requested"
    c.save()

    c = DocEvent(type="added_comment", doc=doc_to_review, by=login)
    # Is it really OK to put html tags into comment text?
    c.desc = 'IETF conflict review initiated - see <a href="%s">%s</a>' % (reverse('doc_view', kwargs={'name':conflict_review.name}),conflict_review.name)
    c.save()

    return conflict_review
Beispiel #28
0
def approve(request, name):
    """Approve this conflict review, setting the appropriate state and send the announcement to the right parties."""
    review = get_object_or_404(Document, type="conflrev", name=name)

    if review.get_state('conflrev').slug not in ('appr-reqnopub-pend','appr-noprob-pend'):
      raise Http404

    login = request.user.get_profile()

    if request.method == 'POST':

        form = AnnouncementForm(request.POST)

        if form.is_valid():

            new_state_slug = 'appr-reqnopub-sent' if review.get_state('conflrev').slug=='appr-reqnopub-pend' else 'appr-noprob-sent'
            new_review_state = State.objects.get(used=True, type="conflrev", slug=new_state_slug)
            save_document_in_history(review)
            old_description = review.friendly_state()
            review.set_state(new_review_state)
            new_description = review.friendly_state()

            log_state_changed(request, review, login, new_description, old_description)

            close_open_ballots(review, login)

            e = DocEvent(doc=review, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the conflict review response"
            e.save()

            review.time = e.time
            review.save()

            # send announcement
            send_mail_preformatted(request, form.cleaned_data['announcement_text'])

            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
            c.save()

            return HttpResponseRedirect(review.get_absolute_url())

    else:

        init = { "announcement_text" : default_approval_text(review) }
        form = AnnouncementForm(initial=init)
    
    return render_to_response('doc/conflict_review/approve.html',
                              dict(
                                   review = review,
                                   conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document,   
                                   form = form,
                                   ),
                              context_instance=RequestContext(request))
Beispiel #29
0
def set_replaces_for_document(request, doc, new_replaces, by, email_subject, email_comment=""):
    addrs = gather_address_lists('doc_replacement_changed',doc=doc)
    to = set(addrs.to)
    cc = set(addrs.cc)

    relationship = DocRelationshipName.objects.get(slug='replaces')
    old_replaces = doc.related_that_doc("replaces")

    for d in old_replaces:
        if d not in new_replaces:
            other_addrs = gather_address_lists('doc_replacement_changed',doc=d.document)
            to.update(other_addrs.to)
            cc.update(other_addrs.cc)
            RelatedDocument.objects.filter(source=doc, target=d, relationship=relationship).delete()
            if not RelatedDocument.objects.filter(target=d, relationship=relationship):
                s = 'active' if d.document.expires > datetime.datetime.now() else 'expired'
                d.document.set_state(State.objects.get(type='draft', slug=s))

    for d in new_replaces:
        if d not in old_replaces:
            other_addrs = gather_address_lists('doc_replacement_changed',doc=d.document)
            to.update(other_addrs.to)
            cc.update(other_addrs.cc)
            RelatedDocument.objects.create(source=doc, target=d, relationship=relationship)
            d.document.set_state(State.objects.get(type='draft', slug='repl'))

    e = DocEvent(doc=doc, by=by, type='changed_document')
    new_replaces_names = u", ".join(d.name for d in new_replaces) or u"None"
    old_replaces_names = u", ".join(d.name for d in old_replaces) or u"None"
    e.desc = u"This document now replaces <b>%s</b> instead of %s" % (new_replaces_names, old_replaces_names)
    e.save()

    # make sure there are no lingering suggestions duplicating new replacements
    RelatedDocument.objects.filter(source=doc, target__in=new_replaces, relationship="possibly-replaces").delete()

    email_desc = e.desc.replace(", ", "\n    ")

    if email_comment:
        email_desc += "\n" + email_comment

    from ietf.doc.mails import html_to_text

    send_mail(request, list(to),
              "DraftTracker Mail System <*****@*****.**>",
              email_subject,
              "doc/mail/change_notice.txt",
              dict(text=html_to_text(email_desc),
                   doc=doc,
                   url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()),
              cc=list(cc))
Beispiel #30
0
    def setUp(self):
        make_test_data()

        ise_draft = Document.objects.get(name="draft-imaginary-independent-submission")
        ise_draft.stream = StreamName.objects.get(slug="ise")
        ise_draft.save_with_history([DocEvent(doc=ise_draft, rev=ise_draft.rev, type="changed_stream", by=Person.objects.get(user__username="******"), desc="Test")])

        self.telechat_docs = {
            "ietf_draft": Document.objects.get(name="draft-ietf-mars-test"),
            "ise_draft": ise_draft,
            "conflrev": Document.objects.get(name="conflict-review-imaginary-irtf-submission"),
            "statchg": Document.objects.get(name="status-change-imaginary-mid-review"),
            "charter": Document.objects.filter(type="charter")[0],
            }

        by = Person.objects.get(name="Areað Irector")
        date = get_agenda_date()

        self.draft_dir = self.tempdir('agenda-draft')
        self.saved_internet_draft_path = settings.INTERNET_DRAFT_PATH
        settings.INTERNET_DRAFT_PATH = self.draft_dir

        for d in self.telechat_docs.values():
            TelechatDocEvent.objects.create(type="scheduled_for_telechat",
                                            doc=d,
                                            rev=d.rev,
                                            by=by,
                                            telechat_date=date,
                                            returning_item=True)
Beispiel #31
0
def change_title(request, name, option=None):
    """Change title of charter, notifying parties as necessary and
    logging the title as a comment."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group
    if not can_manage_group_type(request.user, group.type_id):
        return HttpResponseForbidden("You don't have permission to access this view")
    login = request.user.person
    if request.method == 'POST':
        form = ChangeTitleForm(request.POST, charter=charter)
        if form.is_valid():
            clean = form.cleaned_data
            charter_rev = charter.rev
            new_title = clean['charter_title']
            comment = clean['comment'].rstrip()
            message = clean['message']
            prev_title = charter.title
            if new_title != prev_title:
                # Charter title changed
                save_document_in_history(charter)
                charter.title=new_title
                charter.rev = charter_rev
                if not comment:
                    comment = "Changed charter title from '%s' to '%s'." % (prev_title, new_title)
                event = DocEvent(type="added_comment", doc=charter, by=login)
                event.desc = comment
                event.save()
                charter.time = datetime.datetime.now()
                charter.save()
                if message:
                    email_admin_re_charter(request, group, "Charter title changed to %s" % new_title, message,'charter_state_edit_admin_needed')
                email_state_changed(request, charter, "Title changed to %s." % new_title,'doc_state_edited')
            return redirect('doc_view', name=charter.name)
    else:
        form = ChangeTitleForm(charter=charter)
    title = "Change charter title of %s %s" % (group.acronym, group.type.name)
    return render_to_response('doc/charter/change_title.html',
                              dict(form=form,
                                   doc=group.charter,
                                   login=login,
                                   title=title,
                                   ),
                              context_instance=RequestContext(request))
Beispiel #32
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 #33
0
def expire_draft(doc):
    # clean up files
    move_draft_files_to_archive(doc, doc.rev)

    # change the state
    system = Person.objects.get(name="(System)")

    save_document_in_history(doc)
    if doc.latest_event(type='started_iesg_process'):
        dead_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
        prev = doc.get_state("draft-iesg")
        prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
        prev_tag = prev_tag[0] if prev_tag else None
        if prev != dead_state:
            doc.set_state(dead_state)
            if prev_tag:
                doc.tags.remove(prev_tag)
            log_state_changed(None, doc, system, prev, prev_tag)

        e = DocEvent(doc=doc, by=system)
        e.type = "expired_document"
        e.desc = "Document has expired"
        e.save()

    doc.set_state(State.objects.get(used=True, type="draft", slug="expired"))
    doc.time = datetime.datetime.now()
    doc.save()
Beispiel #34
0
def log_state_changed(request, doc, by, prev_state):
    e = DocEvent(doc=doc, by=by)
    e.type = "changed_document"
    e.desc = u"State changed to <b>%s</b> from %s" % (
        doc.get_state().name, prev_state.name if prev_state else "None")
    e.save()
    return e
Beispiel #35
0
def edit_ad(request, name):
    """Change the responsible Area Director for this charter."""

    charter = get_object_or_404(Document, type="charter", name=name)
    by = request.user.person

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():
            new_ad = form.cleaned_data['ad']
            if new_ad != charter.ad:
                events = []
                e = DocEvent(doc=charter, rev=charter.rev, by=by)
                e.desc = "Responsible AD changed to %s" % new_ad.plain_name()
                if charter.ad:
                    e.desc += " from %s" % charter.ad.plain_name()
                e.type = "changed_document"
                e.save()
                events.append(e)

                charter.ad = new_ad
                charter.save_with_history(events)

            return redirect('ietf.doc.views_doc.document_main',
                            name=charter.name)
    else:
        init = {"ad": charter.ad_id}
        form = AdForm(initial=init)

    return render(request, 'doc/charter/change_ad.html', {
        'form': form,
        'charter': charter,
    })
Beispiel #36
0
def update_stream(request, doc, comment, person, to_stream, extra_notify=[]):
    if settings.USE_DB_REDESIGN_PROXY_CLASSES:
        doc = Document.objects.get(pk=doc.pk)
        save_document_in_history(doc)

        doc.time = datetime.datetime.now()
        from_stream = doc.stream
        doc.stream = to_stream
        doc.save()

        e = DocEvent(type="changed_stream", time=doc.time, by=person, doc=doc)
        e.desc = u"Stream changed to <b>%s</b>" % to_stream.name
        if from_stream:
            e.desc += u"from %s" % from_stream.name
        e.save()

        receivers = get_notification_receivers(doc, extra_notify)
        send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                  u"Stream changed for draft %s" % doc.name,
                  'ietfworkflows/stream_updated_mail.txt',
                  dict(doc=doc,
                       entry=dict(from_stream=from_stream,
                                  to_stream=to_stream,
                                  transition_date=doc.time,
                                  person=person,
                                  comment=comment)))
        return

    ctype = ContentType.objects.get_for_model(doc)
    from_stream = get_stream_from_draft(doc)
    to_stream = set_stream_for_draft(doc, to_stream)
    entry = ObjectStreamHistoryEntry.objects.create(
        content_type=ctype,
        content_id=doc.pk,
        from_stream=from_stream and from_stream.name or '',
        to_stream=to_stream and to_stream.name or '',
        date=datetime.datetime.now(),
        comment=comment,
        person=person)
    notify_stream_entry(entry, extra_notify)
Beispiel #37
0
def make_notify_changed_event(request, doc, by, new_notify, time=None):

    # FOR REVIEW: This preserves the behavior from when
    # drafts and charters had separate edit_notify
    # functions. If it should be unified, there should
    # also be a migration function cause historic
    # events to match
    if doc.type.slug=='charter':
        event_type = 'changed_document'
        save_document_in_history(doc)
    else:
        event_type = 'added_comment'

    e = DocEvent(type=event_type, doc=doc, by=by)
    e.desc = "Notification list changed to %s" % (escape(new_notify) or "none")
    if doc.notify:
        e.desc += " from %s" % escape(doc.notify)
    if time:
        e.time = time
    e.save()

    return e
Beispiel #38
0
def edit_title(request, name):
    """Change the title for this status_change document."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = ChangeTitleForm(request.POST)
        if form.is_valid():

            status_change.title = form.cleaned_data['title']

            c = DocEvent(type="added_comment",
                         doc=status_change,
                         rev=status_change.rev,
                         by=request.user.person)
            c.desc = "Title changed to '%s'" % status_change.title
            c.save()

            status_change.save_with_history([c])

            return redirect("ietf.doc.views_doc.document_main",
                            name=status_change.name)

    else:
        init = {"title": status_change.title}
        form = ChangeTitleForm(initial=init)

    titletext = '%s-%s.txt' % (status_change.canonical_name(),
                               status_change.rev)
    return render(
        request,
        'doc/change_title.html',
        {
            'form': form,
            'doc': status_change,
            'titletext': titletext,
        },
    )
Beispiel #39
0
def downref_registry_add(request):
    title = "Add entry to the downref registry"
    login = request.user.person

    if request.method == 'POST':
        form = AddDownrefForm(request.POST)
        if form.is_valid():
            drafts = form.cleaned_data['drafts']
            rfc = form.cleaned_data['rfc']
            for da in drafts:
                RelatedDocument.objects.create(
                    source=da.document,
                    target=rfc,
                    relationship_id='downref-approval')
                c = DocEvent(type="downref_approved",
                             doc=da.document,
                             rev=da.document.rev,
                             by=login)
                c.desc = "Downref to RFC %s approved by Last Call for %s-%s" % (
                    rfc.document.rfc_number(), da.name, da.document.rev)
                c.save()
                c = DocEvent(type="downref_approved",
                             doc=rfc.document,
                             rev=rfc.document.rev,
                             by=login)
                c.desc = "Downref to RFC %s approved by Last Call for %s-%s" % (
                    rfc.document.rfc_number(), da.name, da.document.rev)
                c.save()

            return HttpResponseRedirect(
                urlreverse('ietf.doc.views_downref.downref_registry'))
    else:
        form = AddDownrefForm()

    return render(request, 'doc/downref_add.html', {
        "title": title,
        "add_downref_form": form,
    })
Beispiel #40
0
def edit_ad(request, name):
    """Change the shepherding Area Director for this status_change."""

    status_change = get_object_or_404(Document, type="statchg", name=name)

    if request.method == 'POST':
        form = AdForm(request.POST)
        if form.is_valid():
            status_change.ad = form.cleaned_data['ad']

            c = DocEvent(type="added_comment",
                         doc=status_change,
                         rev=status_change.rev,
                         by=request.user.person)
            c.desc = "Shepherding AD changed to " + status_change.ad.name
            c.save()

            status_change.save_with_history([c])

            return redirect("ietf.doc.views_doc.document_main",
                            name=status_change.name)

    else:
        init = {"ad": status_change.ad_id}
        form = AdForm(initial=init)

    titletext = '%s-%s.txt' % (status_change.canonical_name(),
                               status_change.rev)
    return render(
        request,
        'doc/change_ad.html',
        {
            'form': form,
            'doc': status_change,
            'titletext': titletext,
        },
    )
Beispiel #41
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 #42
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 #43
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 #44
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 #45
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 #46
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 #47
0
def log_state_changedREDESIGN(request, doc, by, prev_iesg_state,
                              prev_iesg_tag):
    from ietf.doc.models import DocEvent, IESG_SUBSTATE_TAGS

    state = doc.get_state("draft-iesg")

    state_name = state.name
    tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
    if tags:
        state_name += "::" + tags[0].name

    prev_state_name = prev_iesg_state.name if prev_iesg_state else "I-D Exists"
    if prev_iesg_tag:
        prev_state_name += "::" + prev_iesg_tag.name

    e = DocEvent(doc=doc, by=by)
    e.type = "changed_document"
    e.desc = u"State changed to <b>%s</b> from %s" % (state_name,
                                                      prev_state_name)
    e.save()
    return e
Beispiel #48
0
def make_notify_changed_event(request, doc, by, new_notify, time=None):

    # FOR REVIEW: This preserves the behavior from when
    # drafts and charters had separate edit_notify
    # functions. If it should be unified, there should
    # also be a migration function cause historic
    # events to match
    if doc.type.slug=='charter':
        event_type = 'changed_document'
    else:
        event_type = 'added_comment'

    e = DocEvent(type=event_type, doc=doc, rev=doc.rev, by=by)
    e.desc = "Notification list changed to %s" % (escape(new_notify) or "none")
    if doc.notify:
        e.desc += " from %s" % escape(doc.notify)
    if time:
        e.time = time
    e.save()

    return e
Beispiel #49
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 #50
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 #51
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 #52
0
def edit_material_presentations(request, name, acronym=None, date=None, seq=None, week_day=None):

    doc = get_object_or_404(Document, name=name)
    if not (doc.type_id=='slides' and doc.get_state('slides').slug=='active'):
        raise Http404

    group = doc.group
    if not (group.features.has_materials and can_manage_materials(request.user,group)):
        raise Http404

    sorted_sessions = get_upcoming_manageable_sessions(request.user, doc, acronym, date, seq, week_day)

    if len(sorted_sessions)!=1:
        raise Http404

    session = sorted_sessions[0]
    choices = [('notpresented','Not Presented')]
    choices.extend([(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)])
    initial = {'version' : session.version if hasattr(session,'version') else 'notpresented'}

    if request.method == 'POST':
        form = MaterialVersionForm(request.POST,choices=choices)
        if form.is_valid():
            new_selection = form.cleaned_data['version']
            if initial['version'] != new_selection:
                if initial['version'] == 'notpresented':
                    doc.sessionpresentation_set.create(session=session,rev=new_selection)
                    c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
                    c.desc = "Added version %s to session: %s" % (new_selection,session)
                    c.save()
                elif new_selection == 'notpresented':
                    doc.sessionpresentation_set.filter(session=session).delete()
                    c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
                    c.desc = "Removed from session: %s" % (session)
                    c.save()
                else:
                    doc.sessionpresentation_set.filter(session=session).update(rev=new_selection)
                    c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
                    c.desc = "Revision for session %s changed to  %s" % (session,new_selection)
                    c.save()
            return redirect('doc_view',name=doc.name)
    else:
        form = MaterialVersionForm(choices=choices,initial=initial)

    return render(request, 'doc/material/edit_material_presentations.html', {
        'session': session,
        'doc': doc,
        'form': form,
        })
Beispiel #53
0
def start_review(request, name):
    """Start the conflict review process, setting the initial shepherding AD, and possibly putting the review on a telechat."""

    doc_to_review = get_object_or_404(Document, type="draft", name=name)

    if not doc_to_review.stream_id in ('ise', 'irtf'):
        raise Http404

    # sanity check that there's not already a conflict review document for this document
    if [
            rel.source for alias in doc_to_review.docalias_set.all()
            for rel in alias.relateddocument_set.filter(
                relationship='conflrev')
    ]:
        raise Http404

    login = request.user.get_profile()

    if request.method == 'POST':
        form = StartReviewForm(request.POST)
        if form.is_valid():

            if doc_to_review.name.startswith('draft-'):
                review_name = 'conflict-review-' + doc_to_review.name[6:]
            else:
                # This is a failsafe - and might be treated better as an error
                review_name = 'conflict-review-' + doc_to_review.name

            iesg_group = Group.objects.get(acronym='iesg')

            conflict_review = Document(
                type_id="conflrev",
                title="IETF conflict review for %s" % doc_to_review.name,
                name=review_name,
                rev="00",
                ad=form.cleaned_data['ad'],
                notify=form.cleaned_data['notify'],
                stream_id='ietf',
                group=iesg_group,
            )
            conflict_review.save()
            conflict_review.set_state(form.cleaned_data['create_in_state'])

            DocAlias.objects.create(name=review_name, document=conflict_review)

            conflict_review.relateddocument_set.create(
                target=DocAlias.objects.get(name=doc_to_review.name),
                relationship_id='conflrev')

            c = DocEvent(type="added_comment", doc=conflict_review, by=login)
            c.desc = "IETF conflict review requested"
            c.save()

            c = DocEvent(type="added_comment", doc=doc_to_review, by=login)
            # Is it really OK to put html tags into comment text?
            c.desc = 'IETF conflict review initiated - see <a href="%s">%s</a>' % (
                reverse('doc_view', kwargs={'name': conflict_review.name
                                            }), conflict_review.name)
            c.save()

            tc_date = form.cleaned_data['telechat_date']
            if tc_date:
                update_telechat(request, conflict_review, login, tc_date)

            return HttpResponseRedirect(conflict_review.get_absolute_url())
    else:
        # Take care to do the right thing during ietf chair and stream owner transitions
        ietf_chair_id = Role.objects.filter(group__acronym='ietf',
                                            name='chair')[0].person.id
        notify_addresses = []
        notify_addresses.extend([
            x.person.formatted_email() for x in Role.objects.filter(
                group__acronym=doc_to_review.stream.slug, name='chair')
        ])
        notify_addresses.append("%s@%s" % (name, settings.TOOLS_SERVER))

        init = {
            "ad": ietf_chair_id,
            "notify": u', '.join(notify_addresses),
        }
        form = StartReviewForm(initial=init)

    return render_to_response('doc/conflict_review/start.html', {
        'form': form,
        'doc_to_review': doc_to_review,
    },
                              context_instance=RequestContext(request))
Beispiel #54
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    doc = get_object_or_404(Document, docalias__name=name)

    login = request.user.person

    existing = doc.latest_event(WriteupDocEvent,
                                type="changed_ballot_writeup_text")
    if not existing:
        existing = generate_ballot_writeup(request, doc)

    form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text))

    if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST:
        form = BallotWriteupForm(request.POST)
        if form.is_valid():
            t = form.cleaned_data["ballot_writeup"]
            if t != existing.text:
                e = WriteupDocEvent(doc=doc, rev=doc.rev, by=login)
                e.by = login
                e.type = "changed_ballot_writeup_text"
                e.desc = "Ballot writeup was changed"
                e.text = t
                e.save()
            elif existing.pk == None:
                existing.save()

            if "issue_ballot" in request.POST:
                create_ballot_if_not_open(doc, login, "approve")
                ballot = doc.latest_event(BallotDocEvent,
                                          type="created_ballot")

                if has_role(
                        request.user,
                        "Area Director") and not doc.latest_event(
                            BallotPositionDocEvent, ad=login, ballot=ballot):
                    # sending the ballot counts as a yes
                    pos = BallotPositionDocEvent(doc=doc,
                                                 rev=doc.rev,
                                                 by=login)
                    pos.ballot = ballot
                    pos.type = "changed_ballot_position"
                    pos.ad = login
                    pos.pos_id = "yes"
                    pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (
                        pos.pos.name, pos.ad.plain_name())
                    pos.save()

                    # Consider mailing this position to 'ballot_saved'

                approval = doc.latest_event(
                    WriteupDocEvent, type="changed_ballot_approval_text")
                if not approval:
                    approval = generate_approval_mail(request, doc)
                    approval.save()

                msg = generate_issue_ballot_mail(request, doc, ballot)

                addrs = gather_address_lists('ballot_issued',
                                             doc=doc).as_strings()
                override = {'To': addrs.to}
                if addrs.cc:
                    override['CC'] = addrs.cc
                send_mail_preformatted(request, msg, override=override)

                addrs = gather_address_lists('ballot_issued_iana',
                                             doc=doc).as_strings()
                override = {
                    "To": "IANA <%s>" % settings.IANA_EVAL_EMAIL,
                    "Bcc": None,
                    "Reply-To": None
                }
                if addrs.cc:
                    override['CC'] = addrs.cc
                send_mail_preformatted(request,
                                       msg,
                                       extra=extra_automation_headers(doc),
                                       override={
                                           "To": "IANA <%s>" %
                                           settings.IANA_EVAL_EMAIL,
                                           "CC": None,
                                           "Bcc": None,
                                           "Reply-To": None
                                       })

                e = DocEvent(doc=doc, rev=doc.rev, by=login)
                e.by = login
                e.type = "sent_ballot_announcement"
                e.desc = "Ballot has been issued"
                e.save()

                return render(request, 'doc/ballot/ballot_issued.html',
                              dict(doc=doc, back_url=doc.get_absolute_url()))

    need_intended_status = ""
    if not doc.intended_std_level:
        need_intended_status = doc.file_tag()

    return render(
        request, 'doc/ballot/writeupnotes.html',
        dict(
            doc=doc,
            back_url=doc.get_absolute_url(),
            ballot_issued=bool(
                doc.latest_event(type="sent_ballot_announcement")),
            ballot_writeup_form=form,
            need_intended_status=need_intended_status,
        ))
Beispiel #55
0
def approve(request, name):
    """Approve this status change, setting the appropriate state and send the announcements to the right parties."""
    status_change = get_object_or_404(Document, type="statchg", name=name)

    if status_change.get_state('statchg').slug not in ('appr-pend'):
      raise Http404

    login = request.user.get_profile()

    AnnouncementFormSet = formset_factory(AnnouncementForm,extra=0)        

    if request.method == 'POST':

        formset = AnnouncementFormSet(request.POST)

        if formset.is_valid():

            save_document_in_history(status_change)

            old_description = status_change.friendly_state()
            status_change.set_state(State.objects.get(type='statchg', slug='appr-sent'))
            new_description = status_change.friendly_state()
            log_state_changed(request, status_change, login, new_description, old_description)

            close_open_ballots(status_change, login)

            e = DocEvent(doc=status_change, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the status change"
            e.save()

            status_change.time = e.time
            status_change.save()


            for form in formset.forms:

                send_mail_preformatted(request,form.cleaned_data['announcement_text'])

                c = DocEvent(type="added_comment", doc=status_change, by=login)
                c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
                c.save()

            for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
                # Add a document event to each target
                c = DocEvent(type="added_comment", doc=rel.target.document, by=login)
                c.desc = "New status of %s approved by the IESG\n%s%s" % (newstatus(rel), settings.IDTRACKER_BASE_URL,reverse('doc_view', kwargs={'name': status_change.name}))
                c.save()

            return HttpResponseRedirect(status_change.get_absolute_url())

    else:

        init = []
        for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
            init.append({"announcement_text" : default_approval_text(status_change,rel),
                         "label": "Announcement text for %s to %s"%(rel.target.document.canonical_name(),newstatus(rel)),
                       })
        formset = AnnouncementFormSet(initial=init)
        for form in formset.forms:
           form.fields['announcement_text'].label=form.label
    
    return render_to_response('doc/status_change/approve.html',
                              dict(
                                   doc = status_change,
                                   formset = formset,
                                   ),
                              context_instance=RequestContext(request))
def change_state(request, name, option=None):
    """Change state of an status-change document, notifying parties as necessary
       and logging the change as a comment."""
    status_change = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.person

    if request.method == 'POST':
        form = ChangeStateForm(request.POST)
        if form.is_valid():
            clean = form.cleaned_data
            new_state = clean['new_state']
            comment = clean['comment'].rstrip()

            if comment:
                c = DocEvent(type="added_comment", doc=status_change, by=login)
                c.desc = comment
                c.save()

            prev_state = status_change.get_state()
            if new_state != prev_state:
                save_document_in_history(status_change)

                status_change.set_state(new_state)
                e = add_state_change_event(status_change, login, prev_state, new_state)

                status_change.time = e.time
                status_change.save()

                if new_state.slug == "iesgeval":
                    create_ballot_if_not_open(status_change, login, "statchg", e.time)
                    ballot = status_change.latest_event(BallotDocEvent, type="created_ballot")
                    if has_role(request.user, "Area Director") and not status_change.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"):

                        # The AD putting a status change into iesgeval who doesn't already have a position is saying "yes"
                        pos = BallotPositionDocEvent(doc=status_change, by=login)
                        pos.ballot = ballot
                        pos.type = "changed_ballot_position"
                        pos.ad = login
                        pos.pos_id = "yes"
                        pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
                        pos.save()

                    send_status_change_eval_email(request,status_change)


                if new_state.slug == "lc-req":
                    request_last_call(request, status_change)
                    return render_to_response('doc/draft/last_call_requested.html',
                                              dict(doc=status_change,
                                                   url = status_change.get_absolute_url(),
                                                  ),
                                              context_instance=RequestContext(request))

            return redirect('doc_view', name=status_change.name)
    else:
        s = status_change.get_state()
        init = dict(new_state=s.pk if s else None,
                    type='statchg',
                    label='Status Change Evaluation State',
                   )
        form = ChangeStateForm(initial=init)

    return render_to_response('doc/change_state.html',
                              dict(form=form,
                                   doc=status_change,
                                   login=login,
                                   help_url=reverse('state_help', kwargs=dict(type="status-change")),
                                   ),
                              context_instance=RequestContext(request))
Beispiel #57
0
def approve_ballot(request, name):
    """Approve ballot, sending out announcement, changing state."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not doc.get_state("draft-iesg"):
        raise Http404

    login = request.user.person

    approval_mail_event = doc.latest_event(WriteupDocEvent,
                                           type="changed_ballot_approval_text")
    if not approval_mail_event:
        approval_mail_event = generate_approval_mail(request, doc)
    approval_text = approval_mail_event.text

    ballot_writeup_event = doc.latest_event(WriteupDocEvent,
                                            type="changed_ballot_writeup_text")
    if not ballot_writeup_event:
        ballot_writeup_event = generate_ballot_writeup(request, doc)
    ballot_writeup = ballot_writeup_event.text

    error_duplicate_rfc_editor_note = False
    e = doc.latest_event(WriteupDocEvent, type="changed_rfc_editor_note_text")
    if e and (e.text != ""):
        if "RFC Editor Note" in ballot_writeup:
            error_duplicate_rfc_editor_note = True
        ballot_writeup += "\n\n" + e.text

    if error_duplicate_rfc_editor_note:
        return render(request, 'doc/draft/rfceditor_note_duplicate_error.html',
                      {'doc': doc})

    if "NOT be published" in approval_text:
        action = "do_not_publish"
    elif "To: RFC Editor" in approval_text:
        action = "to_rfc_editor"
    else:
        action = "to_announcement_list"

    # NOTE: according to Michelle Cotton <*****@*****.**>
    # (as per 2011-10-24) IANA is scraping these messages for
    # information so would like to know beforehand if the format
    # changes
    announcement = approval_text + "\n\n" + ballot_writeup

    if request.method == 'POST':
        if action == "do_not_publish":
            new_state = State.objects.get(used=True,
                                          type="draft-iesg",
                                          slug="dead")
        else:
            new_state = State.objects.get(used=True,
                                          type="draft-iesg",
                                          slug="ann")

        prev_state = doc.get_state("draft-iesg")
        prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
        events = []

        if approval_mail_event.pk == None:
            approval_mail_event.save()
        if ballot_writeup_event.pk == None:
            ballot_writeup_event.save()

        if new_state.slug == "ann" and new_state.slug != prev_state.slug and not request.POST.get(
                "skiprfceditorpost"):
            # start by notifying the RFC Editor
            import ietf.sync.rfceditor
            response, error = ietf.sync.rfceditor.post_approved_draft(
                settings.RFC_EDITOR_SYNC_NOTIFICATION_URL, doc.name)
            if error:
                return render(
                    request,
                    'doc/draft/rfceditor_post_approved_draft_failed.html',
                    dict(name=doc.name, response=response, error=error))

        doc.set_state(new_state)
        doc.tags.remove(*prev_tags)

        # fixup document
        close_open_ballots(doc, login)

        e = DocEvent(doc=doc, rev=doc.rev, by=login)
        if action == "do_not_publish":
            e.type = "iesg_disapproved"
            e.desc = "Do Not Publish note has been sent to the RFC Editor"
        else:
            e.type = "iesg_approved"
            e.desc = "IESG has approved the document"
        e.save()
        events.append(e)

        e = add_state_change_event(doc,
                                   login,
                                   prev_state,
                                   new_state,
                                   prev_tags=prev_tags,
                                   new_tags=[])

        if e:
            events.append(e)

        doc.save_with_history(events)

        # send announcement
        send_mail_preformatted(request, announcement)

        if action == "to_announcement_list":
            addrs = gather_address_lists(
                'ballot_approved_ietf_stream_iana').as_strings(compact=False)
            send_mail_preformatted(request,
                                   announcement,
                                   extra=extra_automation_headers(doc),
                                   override={
                                       "To": addrs.to,
                                       "CC": addrs.cc,
                                       "Bcc": None,
                                       "Reply-To": None
                                   })

        msg = infer_message(announcement)
        msg.by = login
        msg.save()
        msg.related_docs.add(doc)

        return HttpResponseRedirect(doc.get_absolute_url())

    return render(request, 'doc/ballot/approve_ballot.html',
                  dict(doc=doc, action=action, announcement=announcement))
Beispiel #58
0
def approve_ballot(request, name):
    """Approve ballot, sending out announcement, changing state."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not doc.get_state("draft-iesg"):
        raise Http404()

    login = request.user.person

    e = doc.latest_event(WriteupDocEvent, type="changed_ballot_approval_text")
    if not e:
        e = generate_approval_mail(request, doc)
    approval_text = e.text

    e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
    if not e:
        e = generate_ballot_writeup(request, doc)
    ballot_writeup = e.text
    
    if "NOT be published" in approval_text:
        action = "do_not_publish"
    elif "To: RFC Editor" in approval_text:
        action = "to_rfc_editor"
    else:
        action = "to_announcement_list"

    # NOTE: according to Michelle Cotton <*****@*****.**>
    # (as per 2011-10-24) IANA is scraping these messages for
    # information so would like to know beforehand if the format
    # changes
    announcement = approval_text + "\n\n" + ballot_writeup
        
    if request.method == 'POST':
        if action == "do_not_publish":
            new_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
        else:
            new_state = State.objects.get(used=True, type="draft-iesg", slug="ann")

        prev_state = doc.get_state("draft-iesg")
        prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)

        if new_state.slug == "ann" and new_state.slug != prev_state.slug and not request.REQUEST.get("skiprfceditorpost"):
            # start by notifying the RFC Editor
            import ietf.sync.rfceditor
            response, error = ietf.sync.rfceditor.post_approved_draft(settings.RFC_EDITOR_SYNC_NOTIFICATION_URL, doc.name)
            if error:
                return render_to_response('doc/draft/rfceditor_post_approved_draft_failed.html',
                                  dict(name=doc.name,
                                       response=response,
                                       error=error),
                                  context_instance=RequestContext(request))

        save_document_in_history(doc)

        doc.set_state(new_state)
        doc.tags.remove(*prev_tags)
        
        # fixup document
        close_open_ballots(doc, login)

        e = DocEvent(doc=doc, by=login)
        if action == "do_not_publish":
            e.type = "iesg_disapproved"
            e.desc = "Do Not Publish note has been sent to the RFC Editor"
        else:
            e.type = "iesg_approved"
            e.desc = "IESG has approved the document"

        e.save()
        
        change_description = e.desc + " and state has been changed to %s" % doc.get_state("draft-iesg").name
        
        e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=[])

        doc.time = (e and e.time) or datetime.datetime.now()
        doc.save()

        email_state_changed(request, doc, change_description)
        email_ad(request, doc, doc.ad, login, change_description)

        # send announcement

        send_mail_preformatted(request, announcement)

        if action == "to_announcement_list":
            send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
                                   override={ "To": "IANA <%s>"%settings.IANA_APPROVE_EMAIL, "CC": None, "Bcc": None, "Reply-To": None})

        msg = infer_message(announcement)
        msg.by = login
        msg.save()
        msg.related_docs.add(doc)

        return HttpResponseRedirect(doc.get_absolute_url())

    return render_to_response('doc/ballot/approve_ballot.html',
                              dict(doc=doc,
                                   action=action,
                                   announcement=announcement),
                              context_instance=RequestContext(request))