Beispiel #1
0
def discusses(request):
    possible_docs = Document.objects.filter(models.Q(states__type="draft-iesg",
                                                     states__slug__in=IESG_BALLOT_ACTIVE_STATES) |
                                            models.Q(states__type="charter",
                                                     states__slug__in=("intrev", "iesgrev")) |
                                            models.Q(states__type__in=("statchg", "conflrev"),
                                                     states__slug__in=("iesgeval", "defer")),
                                            docevent__ballotpositiondocevent__pos__blocking=True)
    possible_docs = possible_docs.select_related("stream", "group", "ad").distinct()

    docs = []
    for doc in possible_docs:
        ballot = doc.active_ballot()
        if not ballot:
            continue

        blocking_positions = [p for p in ballot.all_positions() if p.pos.blocking]

        if not blocking_positions:
            continue

        augment_events_with_revision(doc, blocking_positions)

        doc.by_me = bool([p for p in blocking_positions if user_is_person(request.user, p.ad)])
        doc.for_me = user_is_person(request.user, doc.ad)
        doc.milestones = doc.groupmilestone_set.filter(state="active").order_by("time").select_related("group")
        doc.blocking_positions = blocking_positions

        docs.append(doc)

    # latest first
    docs.sort(key=lambda d: min(p.time for p in d.blocking_positions), reverse=True)

    return render(request, 'iesg/discusses.html', { 'docs': docs })
Beispiel #2
0
def search_mail_archive(request, name, request_id):
    #doc = get_object_or_404(Document, name=name)
    review_req = get_object_or_404(ReviewRequest, pk=request_id)

    is_reviewer = user_is_person(request.user, review_req.reviewer.person)
    can_manage_request = can_manage_review_requests_for_team(
        request.user, review_req.team)

    if not (is_reviewer or can_manage_request):
        return HttpResponseForbidden(
            "You do not have permission to perform this action")

    res = mailarch.construct_query_urls(review_req,
                                        query=request.GET.get("query"))
    if not res:
        return JsonResponse({
            "error":
            "Couldn't do lookup in mail archive - don't know where to look"
        })

    MAX_RESULTS = 30

    try:
        res["messages"] = mailarch.retrieve_messages(
            res["query_data_url"])[:MAX_RESULTS]
    except Exception as e:
        res["error"] = "Retrieval from mail archive failed: {}".format(
            unicode(e))
        # raise # useful when debugging

    return JsonResponse(res)
Beispiel #3
0
def edit_shepherd_writeup(request, name):
    """Change this document's shepherd writeup"""
    doc = get_object_or_404(Document, type="draft", name=name)

    can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
    can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])

    if not can_edit_shepherd_writeup:
        return HttpResponseForbidden("You do not have the necessary permissions to view this page")

    login = request.user.get_profile()

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = ShepherdWriteupUploadForm(request.POST, request.FILES)
            if form.is_valid():
                
                from_file = form.cleaned_data['txt']
                if from_file:
                     writeup = from_file
                else:
                     writeup = form.cleaned_data['content']

                e = WriteupDocEvent(doc=doc, by=login, type="changed_protocol_writeup")
                e.desc = "Changed document writeup"
                e.text = writeup
                e.save()
            
                return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name}))

        elif "reset_text" in request.POST:

            init = { "content": render_to_string("doc/shepherd_writeup.txt",dict(doc=doc))}
            form = ShepherdWriteupUploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = { "content": ""}

        previous_writeup = doc.latest_event(WriteupDocEvent,type="changed_protocol_writeup")
        if previous_writeup:
            init["content"] = previous_writeup.text
        else:
            init["content"] = render_to_string("doc/shepherd_writeup.txt",
                                                dict(doc=doc),
                                              )
        form = ShepherdWriteupUploadForm(initial=init)

    return render_to_response('idrfc/change_shepherd_writeup.html',
                              {'form': form,
                               'doc' : doc,
                              },
                              context_instance=RequestContext(request))
Beispiel #4
0
def ballot_icon(context, doc):
    user = context.get("user")

    if not doc:
        return ""

    if not showballoticon(doc):
        return ""

    ballot = doc.active_ballot()
    if not ballot:
        return ""

    def sort_key(t):
        _, pos = t
        if not pos:
            return (2, 0)
        elif pos.pos.blocking:
            return (0, pos.pos.order)
        else:
            return (1, pos.pos.order)

    positions = list(doc.active_ballot().active_ad_positions().items())
    positions.sort(key=sort_key)

    right_click_string = ''
    if has_role(user, "Area Director"):
        right_click_string = 'oncontextmenu="window.location.href=\'%s\';return false;"' %  urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))

    res = ['<a %s href="%s" data-toggle="modal" data-target="#modal-%d" title="IESG positions (click to show more)" class="ballot-icon"><table>' % (
            right_click_string,
            urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            ballot.pk)]

    res.append("<tr>")

    for i, (ad, pos) in enumerate(positions):
        if i > 0 and i % 5 == 0:
            res.append("</tr><tr>")

        c = "position-%s" % (pos.pos.slug if pos else "norecord")

        if user_is_person(user, ad):
            c += " my"

        res.append('<td class="%s"></td>' % c)

    # add sufficient table calls to last row to avoid HTML validation warning
    while (i + 1) % 5 != 0:
        res.append('<td class="empty"></td>')
        i = i + 1

    res.append("</tr></table></a>")
    # XXX FACELIFT: Loading via href will go away in bootstrap 4.
    # See http://getbootstrap.com/javascript/#modals-usage
    res.append('<div id="modal-%d" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog modal-lg"><div class="modal-content"></div></div></div>' % ballot.pk)

    return "".join(res)
Beispiel #5
0
def ballot_icon(context, doc):
    user = context.get("user")

    if not doc:
        return ""

    if not showballoticon(doc):
        return ""

    ballot = doc.active_ballot()
    if not ballot:
        return ""

    def sort_key(t):
        _, pos = t
        if not pos:
            return (2, 0)
        elif pos.pos.blocking:
            return (0, pos.pos.order)
        else:
            return (1, pos.pos.order)

    positions = list(doc.active_ballot().active_ad_positions().items())
    positions.sort(key=sort_key)

    edit_position_url = ""
    if has_role(user, "Area Director"):
        edit_position_url = urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))

    title = "IESG positions (click to show more%s)" % (", right-click to edit position" if edit_position_url else "")

    res = ['<a href="%s" data-popup="%s" data-edit="%s" title="%s" class="ballot-icon"><table>' % (
            urlreverse("doc_ballot", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            edit_position_url,
            title
            )]

    res.append("<tr>")

    for i, (ad, pos) in enumerate(positions):
        if i > 0 and i % 5 == 0:
            res.append("</tr>")
            res.append("<tr>")

        c = "position-%s" % (pos.pos.slug if pos else "norecord")

        if user_is_person(user, ad):
            c += " my"

        res.append('<td class="%s" />' % c)

    res.append("</tr>")
    res.append("</table></a>")

    return "".join(res)
Beispiel #6
0
def discusses(request):
    possible_docs = Document.objects.filter(
        models.Q(states__type="draft-iesg",
                 states__slug__in=IESG_BALLOT_ACTIVE_STATES)
        | models.Q(states__type="charter",
                   states__slug__in=("intrev", "iesgrev"))
        | models.Q(states__type__in=("statchg", "conflrev"),
                   states__slug__in=("iesgeval", "defer")),
        docevent__ballotpositiondocevent__pos__blocking=True)
    possible_docs = possible_docs.select_related("stream", "group",
                                                 "ad").distinct()

    docs = []
    for doc in possible_docs:
        ballot = doc.active_ballot()
        if not ballot:
            continue

        blocking_positions = [
            p for p in ballot.all_positions() if p.pos.blocking
        ]

        if not blocking_positions:
            continue

        augment_events_with_revision(doc, blocking_positions)

        doc.by_me = bool([
            p for p in blocking_positions
            if user_is_person(request.user, p.ad)
        ])
        doc.for_me = user_is_person(request.user, doc.ad)
        doc.milestones = doc.groupmilestone_set.filter(
            state="active").order_by("time").select_related("group")
        doc.blocking_positions = blocking_positions

        docs.append(doc)

    # latest first
    docs.sort(key=lambda d: min(p.time for p in d.blocking_positions),
              reverse=True)

    return render(request, 'iesg/discusses.html', {'docs': docs})
Beispiel #7
0
def review_request(request, name, request_id):
    doc = get_object_or_404(Document, name=name)
    review_req = get_object_or_404(ReviewRequest, pk=request_id)

    is_reviewer = review_req.reviewer and user_is_person(
        request.user, review_req.reviewer.person)
    can_manage_request = can_manage_review_requests_for_team(
        request.user, review_req.team)

    can_close_request = (review_req.state_id in ["requested", "accepted"]
                         and (is_authorized_in_doc_stream(request.user, doc)
                              or can_manage_request))

    can_assign_reviewer = (review_req.state_id in ["requested", "accepted"]
                           and can_manage_request)

    can_accept_reviewer_assignment = (review_req.state_id == "requested"
                                      and review_req.reviewer
                                      and (is_reviewer or can_manage_request))

    can_reject_reviewer_assignment = (review_req.state_id
                                      in ["requested", "accepted"]
                                      and review_req.reviewer
                                      and (is_reviewer or can_manage_request))

    can_complete_review = (review_req.state_id in [
        "requested", "accepted", "overtaken", "no-response", "part-completed",
        "completed"
    ] and review_req.reviewer and (is_reviewer or can_manage_request))

    can_edit_comment = can_request_review_of_doc(request.user, doc)

    if request.method == "POST" and request.POST.get(
            "action") == "accept" and can_accept_reviewer_assignment:
        review_req.state = ReviewRequestStateName.objects.get(slug="accepted")
        review_req.save()

        return redirect(review_request,
                        name=review_req.doc.name,
                        request_id=review_req.pk)

    return render(
        request, 'doc/review/review_request.html', {
            'doc': doc,
            'review_req': review_req,
            'can_close_request': can_close_request,
            'can_reject_reviewer_assignment': can_reject_reviewer_assignment,
            'can_assign_reviewer': can_assign_reviewer,
            'can_accept_reviewer_assignment': can_accept_reviewer_assignment,
            'can_complete_review': can_complete_review,
            'can_edit_comment': can_edit_comment,
        })
Beispiel #8
0
def document_shepherd_writeup(request, name):
    doc = get_object_or_404(Document, docalias__name=name)
    lastwriteup = doc.latest_event(WriteupDocEvent,type="changed_protocol_writeup")
    if lastwriteup:
        writeup_text = lastwriteup.text
    else:
        writeup_text = "(There is no shepherd's writeup available for this document)"

    can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
    can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])

    return render_to_response("doc/shepherd_writeup.html",
                               dict(doc=doc,
                                    writeup=writeup_text,
                                    can_edit=can_edit_shepherd_writeup
                                   ),
                              context_instance=RequestContext(request))
Beispiel #9
0
def agenda_permissions(meeting, schedule, user):
    # do this in positive logic.
    cansee = False
    canedit = False
    secretariat = False

    if has_role(user, 'Secretariat'):
        cansee = True
        secretariat = True
        # NOTE: secretariat is not superuser for edit!
    elif schedule.public:
        cansee = True
    elif schedule.visible and has_role(user, ['Area Director', 'IAB Chair', 'IRTF Chair']):
        cansee = True

    if user_is_person(user, schedule.owner):
        cansee = True
        canedit = True

    return cansee, canedit, secretariat
Beispiel #10
0
def agenda_permissions(meeting, schedule, user):
    # do this in positive logic.
    cansee = False
    canedit = False
    secretariat = False

    if has_role(user, 'Secretariat'):
        cansee = True
        secretariat = True
        # NOTE: secretariat is not superuser for edit!
    elif schedule.public:
        cansee = True
    elif schedule.visible and has_role(user, ['Area Director', 'IAB Chair', 'IRTF Chair']):
        cansee = True

    if user_is_person(user, schedule.owner):
        cansee = True
        canedit = True

    return cansee, canedit, secretariat
Beispiel #11
0
def render_ballot_icon(user, doc):
    if not doc:
        return ""

    # FIXME: temporary backwards-compatibility hack
    from ietf.doc.models import Document
    if not isinstance(doc, Document):
        doc = doc._draft

    if doc.type_id == "draft":
        if doc.get_state_slug("draft-iesg") not in IESG_BALLOT_ACTIVE_STATES:
            return ""
    elif doc.type_id == "charter":
        if doc.get_state_slug() not in ("intrev", "iesgrev"):
            return ""
    elif doc.type_id == "conflrev":
       if doc.get_state_slug() not in ("iesgeval","defer"):
           return ""
    elif doc.type_id == "statchg":
       if doc.get_state_slug() not in ("iesgeval","defer"):
           return ""

    ballot = doc.active_ballot()
    if not ballot:
        return ""

    def sort_key(t):
        _, pos = t
        if not pos:
            return (2, 0)
        elif pos.pos.blocking:
            return (0, pos.pos.order)
        else:
            return (1, pos.pos.order)

    positions = list(doc.active_ballot().active_ad_positions().items())
    positions.sort(key=sort_key)

    edit_position_url = ""
    if has_role(user, "Area Director"):
        edit_position_url = urlreverse('ietf.idrfc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))

    title = "IESG positions (click to show more%s)" % (", right-click to edit position" if edit_position_url else "")

    res = ['<a href="%s" data-popup="%s" data-edit="%s" title="%s" class="ballot-icon"><table>' % (
            urlreverse("doc_ballot", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            edit_position_url,
            title
            )]

    res.append("<tr>")

    for i, (ad, pos) in enumerate(positions):
        if i > 0 and i % 5 == 0:
            res.append("</tr>")
            res.append("<tr>")

        c = "position-%s" % (pos.pos.slug if pos else "norecord")

        if user_is_person(user, ad):
            c += " my"

        res.append('<td class="%s" />' % c)

    res.append("</tr>")
    res.append("</table></a>")

    return "".join(res)
Beispiel #12
0
def document_main(request, name, rev=None):
    doc = get_object_or_404(Document.objects.select_related(), docalias__name=name)

    # take care of possible redirections
    aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True)
    if doc.type_id == "draft" and not name.startswith("rfc"):
        for a in aliases:
            if a.startswith("rfc"):
                return redirect("doc_view", name=a)

    group = doc.group
    if doc.type_id == 'conflrev':
        conflictdoc = doc.related_that_doc('conflrev')[0].document
    
    revisions = []
    for h in doc.history_set.order_by("time", "id"):
        if h.rev and not h.rev in revisions:
            revisions.append(h.rev)
    if not doc.rev in revisions:
        revisions.append(doc.rev)

    snapshot = False

    if rev != None:
        if rev == doc.rev:
            return redirect('doc_view', name=name)

        # find the entry in the history
        for h in doc.history_set.order_by("-time"):
            if rev == h.rev:
                snapshot = True
                doc = h
                break

        if not snapshot:
            return redirect('doc_view', name=name)

        if doc.type_id == "charter":
            # find old group, too
            gh = find_history_active_at(doc.group, doc.time)
            if gh:
                group = gh

    top = render_document_top(request, doc, "document", name)


    telechat = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
    if telechat and (not telechat.telechat_date or telechat.telechat_date < datetime.date.today()):
       telechat = None


    # specific document types
    if doc.type_id == "draft":
        split_content = not ( request.GET.get('include_text') or request.COOKIES.get("full_draft", "") == "on" )

        iesg_state = doc.get_state("draft-iesg")
        iesg_state_summary = doc.friendly_state()
        can_edit = has_role(request.user, ("Area Director", "Secretariat"))
        stream_slugs = StreamName.objects.values_list("slug", flat=True)
        can_change_stream = bool(can_edit or (
                request.user.is_authenticated() and
                Role.objects.filter(name__in=("chair", "secr", "auth", "delegate"),
                                    group__acronym__in=stream_slugs,
                                    person__user=request.user)))
        can_edit_iana_state = has_role(request.user, ("Secretariat", "IANA"))

        rfc_number = name[3:] if name.startswith("") else None
        draft_name = None
        for a in aliases:
            if a.startswith("draft"):
                draft_name = a

        rfc_aliases = [prettify_std_name(a) for a in aliases
                       if a.startswith("fyi") or a.startswith("std") or a.startswith("bcp")]

        latest_revision = None

        if doc.get_state_slug() == "rfc":
            # content
            filename = name + ".txt"

            content = get_document_content(filename, os.path.join(settings.RFC_PATH, filename),
                                           split_content, markup=True)

            # file types
            base_path = os.path.join(settings.RFC_PATH, name + ".")
            possible_types = ["txt", "pdf", "ps"]
            found_types = [t for t in possible_types if os.path.exists(base_path + t)]

            base = "http://www.rfc-editor.org/rfc/"

            file_urls = []
            for t in found_types:
                label = "plain text" if t == "txt" else t
                file_urls.append((label, base + name + "." + t))

            if "pdf" not in found_types and "txt" in found_types:
                file_urls.append(("pdf", base + "pdfrfc/" + name + ".txt.pdf"))

            if "txt" in found_types:
                file_urls.append(("html", "http://tools.ietf.org/html/" + name))

            if not found_types:
                content = "This RFC is not currently available online."
                split_content = False
            elif "txt" not in found_types:
                content = "This RFC is not available in plain text format."
                split_content = False
        else:
            filename = "%s-%s.txt" % (draft_name, doc.rev)

            content = get_document_content(filename, os.path.join(settings.INTERNET_DRAFT_PATH, filename),
                                           split_content, markup=True)

            # file types
            base_path = os.path.join(settings.INTERNET_DRAFT_PATH, doc.name + "-" + doc.rev + ".")
            possible_types = ["pdf", "xml", "ps"]
            found_types = ["txt"] + [t for t in possible_types if os.path.exists(base_path + t)]

            tools_base = "http://tools.ietf.org/"

            if doc.get_state_slug() == "active":
                base = "http://www.ietf.org/id/"
            else:
                base = tools_base + "id/"

            file_urls = []
            for t in found_types:
                label = "plain text" if t == "txt" else t
                file_urls.append((label, base + doc.name + "-" + doc.rev + "." + t))

            if "pdf" not in found_types:
                file_urls.append(("pdf", tools_base + "pdf/" + doc.name + "-" + doc.rev + ".pdf"))
            file_urls.append(("html", tools_base + "html/" + doc.name + "-" + doc.rev))

            # latest revision
            latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")

        # ballot
        ballot_summary = None
        if iesg_state and iesg_state.slug in IESG_BALLOT_ACTIVE_STATES:
            active_ballot = doc.active_ballot()
            if active_ballot:
                ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())

        # submission
        submission = ""
        if group is None:
            submission = "unknown"
        elif group.type_id == "individ":
            submission = "individual"
        elif group.type_id == "area" and doc.stream_id == "ietf":
            submission = "individual in %s area" % group.acronym
        elif group.type_id in ("rg", "wg"):
            submission = "%s %s" % (group.acronym, group.type)
            if group.type_id == "wg":
                submission = "<a href=\"%s\">%s</a>" % (urlreverse("group_home", kwargs=dict(group_type=doc.group.type_id, acronym=doc.group.acronym)), submission)
            if doc.stream_id and doc.get_state_slug("draft-stream-%s" % doc.stream_id) == "c-adopt":
                submission = "candidate for %s" % submission

        # resurrection
        resurrected_by = None
        if doc.get_state_slug() == "expired":
            e = doc.latest_event(type__in=("requested_resurrect", "completed_resurrect"))
            if e and e.type == "requested_resurrect":
                resurrected_by = e.by

        # stream info
        stream_state_type_slug = None
        stream_state = None
        if doc.stream:
            stream_state_type_slug = "draft-stream-%s" % doc.stream_id
            stream_state = doc.get_state(stream_state_type_slug)
        stream_tags = doc.tags.filter(slug__in=get_tags_for_stream_id(doc.stream_id))

        shepherd_writeup = doc.latest_event(WriteupDocEvent, type="changed_protocol_writeup")

        can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
        can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
        can_edit_consensus = False

        consensus = None
        if doc.stream_id == "ietf" and iesg_state:
            show_in_states = set(IESG_BALLOT_ACTIVE_STATES)
            show_in_states.update(('approved','ann','rfcqueue','pub'))
            if iesg_state.slug in show_in_states: 
                can_edit_consensus = can_edit
                e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
                consensus = nice_consensus(e and e.consensus)
        elif doc.stream_id in ("irtf", "iab"):
            can_edit_consensus = can_edit or can_edit_stream_info
            e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
            consensus = nice_consensus(e and e.consensus)

        # mailing list search archive
        search_archive = "www.ietf.org/mail-archive/web/"
        if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive:
            search_archive = group.list_archive

        search_archive = urllib.quote(search_archive, safe="~")

        # conflict reviews
        conflict_reviews = [d.document.name for d in doc.related_that("conflrev")]

        status_change_docs = doc.related_that(status_change_relationships)
        status_changes = [ rel.document for rel in status_change_docs  if rel.document.get_state_slug() in ('appr-sent','appr-pend')]
        proposed_status_changes = [ rel.document for rel in status_change_docs  if rel.document.get_state_slug() in ('needshep','adrev','iesgeval','defer','appr-pr')]

        # remaining actions
        actions = []

        if can_adopt_draft(request.user, doc):
            actions.append(("Adopt in Group", urlreverse('doc_adopt_draft', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() == "expired" and not resurrected_by and can_edit:
            actions.append(("Request Resurrect", urlreverse('doc_request_resurrect', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() == "expired" and has_role(request.user, ("Secretariat",)):
            actions.append(("Resurrect", urlreverse('doc_resurrect', kwargs=dict(name=doc.name))))

        if (doc.get_state_slug() != "expired" and doc.stream_id in ("ise", "irtf")
            and can_edit_stream_info and not conflict_reviews):
            label = "Begin IETF Conflict Review"
            if not doc.intended_std_level:
                label += " (note that intended status is not set)"
            actions.append((label, urlreverse('conflict_review_start', kwargs=dict(name=doc.name))))

        if (doc.get_state_slug() != "expired" and doc.stream_id in ("iab", "ise", "irtf")
            and can_edit_stream_info):
            label = "Request Publication"
            if not doc.intended_std_level:
                label += " (note that intended status is not set)"
            if iesg_state and iesg_state.slug != 'dead':
                label += " (Warning: the IESG state indicates ongoing IESG processing)"
            actions.append((label, urlreverse('doc_request_publication', kwargs=dict(name=doc.name))))

        if doc.get_state_slug() != "expired" and doc.stream_id in ("ietf",):
            if not iesg_state and can_edit:
                actions.append(("Begin IESG Processing", urlreverse('doc_edit_info', kwargs=dict(name=doc.name)) + "?new=1"))
            elif can_edit_stream_info and (not iesg_state or iesg_state.slug == 'watching'):
                actions.append(("Submit to IESG for Publication", urlreverse('doc_to_iesg', kwargs=dict(name=doc.name))))

        tracking_document = False
        if request.user.is_authenticated():
            try:
                clist = CommunityList.objects.get(user=request.user)
                clist.update()
                if clist.get_documents().filter(name=doc.name).count() > 0:
                    tracking_document = True
            except ObjectDoesNotExist:
                pass

        return render_to_response("doc/document_draft.html",
                                  dict(doc=doc,
                                       group=group,
                                       top=top,
                                       name=name,
                                       content=content,
                                       split_content=split_content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       latest_revision=latest_revision,

                                       can_edit=can_edit,
                                       can_change_stream=can_change_stream,
                                       can_edit_stream_info=can_edit_stream_info,
                                       can_edit_shepherd_writeup=can_edit_shepherd_writeup,
                                       can_edit_iana_state=can_edit_iana_state,
                                       can_edit_consensus=can_edit_consensus,

                                       rfc_number=rfc_number,
                                       draft_name=draft_name,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       submission=submission,
                                       resurrected_by=resurrected_by,

                                       replaces=[d.name for d in doc.related_that_doc("replaces")],
                                       replaced_by=[d.name for d in doc.related_that("replaces")],
                                       updates=[prettify_std_name(d.name) for d in doc.related_that_doc("updates")],
                                       updated_by=[prettify_std_name(d.document.canonical_name()) for d in doc.related_that("updates")],
                                       obsoletes=[prettify_std_name(d.name) for d in doc.related_that_doc("obs")],
                                       obsoleted_by=[prettify_std_name(d.document.canonical_name()) for d in doc.related_that("obs")],
                                       conflict_reviews=conflict_reviews,
                                       status_changes=status_changes,
                                       proposed_status_changes=proposed_status_changes,
                                       rfc_aliases=rfc_aliases,
                                       has_errata=doc.tags.filter(slug="errata"),
                                       published=doc.latest_event(type="published_rfc"),
                                       file_urls=file_urls,
                                       stream_state_type_slug=stream_state_type_slug,
                                       stream_state=stream_state,
                                       stream_tags=stream_tags,
                                       milestones=doc.groupmilestone_set.filter(state="active"),
                                       consensus=consensus,
                                       iesg_state=iesg_state,
                                       iesg_state_summary=iesg_state_summary,
                                       rfc_editor_state=doc.get_state("draft-rfceditor"),
                                       iana_review_state=doc.get_state("draft-iana-review"),
                                       iana_action_state=doc.get_state("draft-iana-action"),
                                       started_iesg_process=doc.latest_event(type="started_iesg_process"),
                                       shepherd_writeup=shepherd_writeup,
                                       search_archive=search_archive,
                                       actions=actions,
                                       tracking_document=tracking_document,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "charter":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)

        content = get_document_content(filename, os.path.join(settings.CHARTER_PATH, filename), split=False, markup=True)

        ballot_summary = None
        if doc.get_state_slug() in ("intrev", "iesgrev"):
            active_ballot = doc.active_ballot()
            if active_ballot:
                ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())
            else:
                ballot_summary = "No active ballot found."

        chartering = get_chartering_type(doc)

        # inject milestones from group
        milestones = None
        if chartering and not snapshot:
            milestones = doc.group.groupmilestone_set.filter(state="charter")

        can_manage = can_manage_group_type(request.user, doc.group.type_id)

        return render_to_response("doc/document_charter.html",
                                  dict(doc=doc,
                                       top=top,
                                       chartering=chartering,
                                       content=content,
                                       txt_url=doc.href(),
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       group=group,
                                       milestones=milestones,
                                       can_manage=can_manage,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "conflrev":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
        pathname = os.path.join(settings.CONFLICT_REVIEW_PATH,filename)

        if doc.rev == "00" and not os.path.isfile(pathname):
            # This could move to a template
            content = "A conflict review response has not yet been proposed."
        else:     
            content = get_document_content(filename, pathname, split=False, markup=True)

        ballot_summary = None
        if doc.get_state_slug() in ("iesgeval"):
            ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())

        return render_to_response("doc/document_conflict_review.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       conflictdoc=conflictdoc,
                                       ballot_summary=ballot_summary,
                                       approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent')
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id == "statchg":
        filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
        pathname = os.path.join(settings.STATUS_CHANGE_PATH,filename)

        if doc.rev == "00" and not os.path.isfile(pathname):
            # This could move to a template
            content = "Status change text has not yet been proposed."
        else:     
            content = get_document_content(filename, pathname, split=False)

        ballot_summary = None
        if doc.get_state_slug() in ("iesgeval"):
            ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
     
        if isinstance(doc,Document):
            sorted_relations=doc.relateddocument_set.all().order_by('relationship__name')
        elif isinstance(doc,DocHistory):
            sorted_relations=doc.relateddochistory_set.all().order_by('relationship__name')
        else:
            sorted_relations=None

        return render_to_response("doc/document_status_change.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       telechat=telechat,
                                       ballot_summary=ballot_summary,
                                       approved_states=('appr-pend','appr-sent'),
                                       sorted_relations=sorted_relations,
                                       ),
                                  context_instance=RequestContext(request))

    if doc.type_id in ("slides", "agenda", "minutes"):
        can_manage_material = can_manage_materials(request.user, doc.group)
        if doc.meeting_related():
            # disallow editing meeting-related stuff through this
            # interface for the time being
            can_manage_material = False
            basename = doc.canonical_name() # meeting materials are unversioned at the moment
            if doc.external_url:
                # we need to remove the extension for the globbing below to work
                basename = os.path.splitext(doc.external_url)[0]
        else:
            basename = "%s-%s" % (doc.canonical_name(), doc.rev)

        pathname = os.path.join(doc.get_file_path(), basename)

        content = None
        other_types = []
        globs = glob.glob(pathname + ".*")
        for g in globs:
            extension = os.path.splitext(g)[1]
            t = os.path.splitext(g)[1].lstrip(".")
            url = doc.href()
            if not url.endswith("/") and not url.endswith(extension):
                url += extension

            if extension == ".txt":
                content = get_document_content(basename, pathname + extension, split=False)
                t = "plain text"

            other_types.append((t, url))

        return render_to_response("doc/document_material.html",
                                  dict(doc=doc,
                                       top=top,
                                       content=content,
                                       revisions=revisions,
                                       snapshot=snapshot,
                                       can_manage_material=can_manage_material,
                                       other_types=other_types,
                                       ),
                                  context_instance=RequestContext(request))

    raise Http404
Beispiel #13
0
def complete_review(request, name, request_id):
    doc = get_object_or_404(Document, name=name)
    review_req = get_object_or_404(ReviewRequest, pk=request_id)

    revising_review = review_req.state_id not in ["requested", "accepted"]

    if not review_req.reviewer:
        return redirect(review_request,
                        name=review_req.doc.name,
                        request_id=review_req.pk)

    is_reviewer = user_is_person(request.user, review_req.reviewer.person)
    can_manage_request = can_manage_review_requests_for_team(
        request.user, review_req.team)

    if not (is_reviewer or can_manage_request):
        return HttpResponseForbidden(
            "You do not have permission to perform this action")

    (to, cc) = gather_address_lists('review_completed', review_req=review_req)

    if request.method == "POST":
        form = CompleteReviewForm(review_req, request.POST, request.FILES)
        if form.is_valid():
            review_submission = form.cleaned_data['review_submission']

            review = review_req.review
            if not review:
                # create review doc
                for i in range(1, 100):
                    name_components = [
                        "review",
                        strip_prefix(review_req.doc.name, "draft-"),
                        form.cleaned_data["reviewed_rev"],
                        review_req.team.acronym,
                        review_req.type.slug,
                        xslugify(review_req.reviewer.person.ascii_parts()[3]),
                        datetime.date.today().isoformat(),
                    ]
                    if i > 1:
                        name_components.append(str(i))

                    name = "-".join(c for c in name_components if c).lower()
                    if not Document.objects.filter(name=name).exists():
                        review = Document.objects.create(name=name)
                        DocAlias.objects.create(document=review,
                                                name=review.name)
                        break

                review.type = DocTypeName.objects.get(slug="review")
                review.group = review_req.team

            review.rev = "00" if not review.rev else "{:02}".format(
                int(review.rev) + 1)
            review.title = "{} Review of {}-{}".format(
                review_req.type.name, review_req.doc.name,
                form.cleaned_data["reviewed_rev"])
            review.time = datetime.datetime.now()
            if review_submission == "link":
                review.external_url = form.cleaned_data['review_url']

            e = NewRevisionDocEvent.objects.create(
                type="new_revision",
                doc=review,
                by=request.user.person,
                rev=review.rev,
                desc='New revision available',
                time=review.time,
            )

            review.set_state(State.objects.get(type="review", slug="active"))

            review.save_with_history([e])

            # save file on disk
            if review_submission == "upload":
                encoded_content = form.cleaned_data['review_file']
            else:
                encoded_content = form.cleaned_data['review_content'].encode(
                    "utf-8")

            filename = os.path.join(review.get_file_path(),
                                    '{}.txt'.format(review.name, review.rev))
            with open(filename, 'wb') as destination:
                destination.write(encoded_content)

            # close review request
            review_req.state = form.cleaned_data["state"]
            review_req.reviewed_rev = form.cleaned_data["reviewed_rev"]
            review_req.result = form.cleaned_data["result"]
            review_req.review = review
            review_req.save()

            need_to_email_review = review_submission != "link" and review_req.team.list_email and not revising_review

            desc = "Request for {} review by {} {}: {}. Reviewer: {}.".format(
                review_req.type.name,
                review_req.team.acronym.upper(),
                review_req.state.name,
                review_req.result.name,
                review_req.reviewer.person,
            )
            if need_to_email_review:
                desc += " " + "Sent review to list."

            completion_datetime = datetime.datetime.now()
            if "completion_date" in form.cleaned_data:
                completion_datetime = datetime.datetime.combine(
                    form.cleaned_data["completion_date"],
                    form.cleaned_data.get("completion_time")
                    or datetime.time.min)

            close_event = ReviewRequestDocEvent.objects.filter(
                type="closed_review_request",
                review_request=review_req).first()
            if not close_event:
                close_event = ReviewRequestDocEvent(
                    type="closed_review_request", review_request=review_req)

            close_event.doc = review_req.doc
            close_event.rev = review_req.doc.rev
            close_event.by = request.user.person
            close_event.desc = desc
            close_event.state = review_req.state
            close_event.time = completion_datetime
            close_event.save()

            if review_req.state_id == "part-completed" and not revising_review:
                existing_open_reqs = ReviewRequest.objects.filter(
                    doc=review_req.doc,
                    team=review_req.team,
                    state__in=("requested", "accepted"))

                new_review_req_url = new_review_req = None
                if not existing_open_reqs:
                    new_review_req = make_new_review_request_from_existing(
                        review_req)
                    new_review_req.save()

                    new_review_req_url = urlreverse(
                        "ietf.doc.views_review.review_request",
                        kwargs={
                            "name": new_review_req.doc.name,
                            "request_id": new_review_req.pk
                        })
                    new_review_req_url = request.build_absolute_uri(
                        new_review_req_url)

                subject = "Review of {}-{} completed partially".format(
                    review_req.doc.name, review_req.reviewed_rev)

                msg = render_to_string(
                    "review/partially_completed_review.txt", {
                        "new_review_req_url": new_review_req_url,
                        "existing_open_reqs": existing_open_reqs,
                        "by": request.user.person,
                    })

                email_review_request_change(request,
                                            review_req,
                                            subject,
                                            msg,
                                            request.user.person,
                                            notify_secretary=True,
                                            notify_reviewer=False,
                                            notify_requested_by=False)

            role = request.user.person.role_set.filter(
                group=review_req.team, name='reviewer').first()
            if role and role.email.active:
                author_email = role.email
                frm = role.formatted_email()
            else:
                author_email = request.user.person.email()
                frm = request.user.person.formatted_email()
            author, created = DocumentAuthor.objects.get_or_create(
                document=review,
                email=author_email,
                person=request.user.person)

            if need_to_email_review:
                # email the review
                subject = "{} {} {} of {}-{}".format(
                    review_req.team.acronym.capitalize(),
                    review_req.type.name.lower(), "partial review"
                    if review_req.state_id == "part-completed" else "review",
                    review_req.doc.name, review_req.reviewed_rev)
                related_groups = [
                    review_req.team,
                ]
                if review_req.doc.group:
                    related_groups.append(review_req.doc.group)
                msg = Message.objects.create(
                    by=request.user.person,
                    subject=subject,
                    frm=frm,
                    to=", ".join(to),
                    cc=form.cleaned_data["cc"],
                    body=render_to_string(
                        "review/completed_review.txt", {
                            "review_req": review_req,
                            "content": encoded_content.decode("utf-8"),
                        }),
                )
                msg.related_groups.add(*related_groups)
                msg.related_docs.add(review_req.doc)

                msg = send_mail_message(request, msg)

                list_name = mailarch.list_name_from_email(
                    review_req.team.list_email)
                if list_name:
                    review.external_url = mailarch.construct_message_url(
                        list_name, email.utils.unquote(msg["Message-ID"]))
                    review.save_with_history([close_event])

            return redirect("ietf.doc.views_doc.document_main",
                            name=review_req.review.name)
    else:
        initial = {
            "reviewed_rev": review_req.reviewed_rev,
            "result": review_req.result_id,
            "cc": ", ".join(cc),
        }

        try:
            initial['review_content'] = render_to_string(
                '/group/%s/review/content_templates/%s.txt' %
                (review_req.team.acronym, review_req.type.slug), {
                    'review_req': review_req,
                    'today': datetime.date.today()
                })
        except TemplateDoesNotExist:
            pass

        form = CompleteReviewForm(review_req, initial=initial)

    mail_archive_query_urls = mailarch.construct_query_urls(review_req)

    return render(
        request, 'doc/review/complete_review.html', {
            'doc': doc,
            'review_req': review_req,
            'form': form,
            'mail_archive_query_urls': mail_archive_query_urls,
            'revising_review': revising_review,
        })
Beispiel #14
0
def ballot_icon(context, doc):
    user = context.get("user")

    if not doc:
        return ""

    if not showballoticon(doc):
        return ""

    ballot = doc.active_ballot()
    if not ballot:
        return ""

    def sort_key(t):
        _, pos = t
        if not pos:
            return (2, 0)
        elif pos.pos.blocking:
            return (0, pos.pos.order)
        else:
            return (1, pos.pos.order)

    positions = list(doc.active_ballot().active_ad_positions().items())
    positions.sort(key=sort_key)

    right_click_string = ''
    if has_role(user, "Area Director"):
        right_click_string = 'oncontextmenu="window.location.href=\'%s\';return false;"' % urlreverse(
            'ietf.doc.views_ballot.edit_position',
            kwargs=dict(name=doc.name, ballot_id=ballot.pk))

    my_blocking = False
    for i, (ad, pos) in enumerate(positions):
        if user_is_person(user, ad) and pos and pos.pos.blocking:
            my_blocking = True
            break

    res = [
        '<a %s href="%s" data-toggle="modal" data-target="#modal-%d" title="IESG positions (click to show more)" class="ballot-icon"><table'
        % (
            right_click_string,
            urlreverse("ietf.doc.views_doc.ballot_popup",
                       kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
            ballot.pk,
        )
    ]
    if my_blocking:
        res.append(' class="is-blocking" ')
    res.append('>')

    res.append("<tr>")

    for i, (ad, pos) in enumerate(positions):
        if i > 0 and i % 5 == 0:
            res.append("</tr><tr>")

        c = "position-%s" % (pos.pos.slug if pos else "norecord")

        if user_is_person(user, ad):
            c += " my"

        res.append('<td class="%s"></td>' % c)

    # add sufficient table calls to last row to avoid HTML validation warning
    while (i + 1) % 5 != 0:
        res.append('<td class="empty"></td>')
        i = i + 1

    res.append("</tr></table></a>")
    # XXX FACELIFT: Loading via href will go away in bootstrap 4.
    # See http://getbootstrap.com/javascript/#modals-usage
    res.append(
        '<div id="modal-%d" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog modal-lg"><div class="modal-content"></div></div></div>'
        % ballot.pk)

    return mark_safe("".join(res))
Beispiel #15
0
def edit_shepherd_writeup(request, name):
    """Change this document's shepherd writeup"""
    doc = get_object_or_404(Document, type="draft", name=name)

    can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
    can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(
        request.user, doc.shepherd) or has_role(request.user,
                                                ["Area Director"])

    if not can_edit_shepherd_writeup:
        return HttpResponseForbidden(
            "You do not have the necessary permissions to view this page")

    login = request.user.get_profile()

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = ShepherdWriteupUploadForm(request.POST, request.FILES)
            if form.is_valid():

                from_file = form.cleaned_data['txt']
                if from_file:
                    writeup = from_file
                else:
                    writeup = form.cleaned_data['content']

                e = WriteupDocEvent(doc=doc,
                                    by=login,
                                    type="changed_protocol_writeup")
                e.desc = "Changed document writeup"
                e.text = writeup
                e.save()

                return HttpResponseRedirect(
                    urlreverse('doc_view', kwargs={'name': doc.name}))

        elif "reset_text" in request.POST:

            init = {
                "content":
                render_to_string("doc/shepherd_writeup.txt", dict(doc=doc))
            }
            form = ShepherdWriteupUploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = {"content": ""}

        previous_writeup = doc.latest_event(WriteupDocEvent,
                                            type="changed_protocol_writeup")
        if previous_writeup:
            init["content"] = previous_writeup.text
        else:
            init["content"] = render_to_string(
                "doc/shepherd_writeup.txt",
                dict(doc=doc),
            )
        form = ShepherdWriteupUploadForm(initial=init)

    return render_to_response('idrfc/change_shepherd_writeup.html', {
        'form': form,
        'doc': doc,
    },
                              context_instance=RequestContext(request))
Beispiel #16
0
def render_ballot_icon(user, doc):
    if not doc:
        return ""

    # FIXME: temporary backwards-compatibility hack
    from ietf.doc.models import Document
    if not isinstance(doc, Document):
        doc = doc._draft

    if doc.type_id == "draft":
        if doc.get_state_slug("draft-iesg") not in IESG_BALLOT_ACTIVE_STATES:
            return ""
    elif doc.type_id == "charter":
        if doc.get_state_slug() not in ("intrev", "iesgrev"):
            return ""
    elif doc.type_id == "conflrev":
        if doc.get_state_slug() not in ("iesgeval", "defer"):
            return ""
    elif doc.type_id == "statchg":
        if doc.get_state_slug() not in ("iesgeval", "defer"):
            return ""

    ballot = doc.active_ballot()
    if not ballot:
        return ""

    def sort_key(t):
        _, pos = t
        if not pos:
            return (2, 0)
        elif pos.pos.blocking:
            return (0, pos.pos.order)
        else:
            return (1, pos.pos.order)

    positions = list(doc.active_ballot().active_ad_positions().items())
    positions.sort(key=sort_key)

    edit_position_url = ""
    if has_role(user, "Area Director"):
        edit_position_url = urlreverse('ietf.idrfc.views_ballot.edit_position',
                                       kwargs=dict(name=doc.name,
                                                   ballot_id=ballot.pk))

    title = "IESG positions (click to show more%s)" % (
        ", right-click to edit position" if edit_position_url else "")

    res = [
        '<a href="%s" data-popup="%s" data-edit="%s" title="%s" class="ballot-icon"><table>'
        % (urlreverse("doc_ballot",
                      kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
           urlreverse("ietf.doc.views_doc.ballot_popup",
                      kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
           edit_position_url, title)
    ]

    res.append("<tr>")

    for i, (ad, pos) in enumerate(positions):
        if i > 0 and i % 5 == 0:
            res.append("</tr>")
            res.append("<tr>")

        c = "position-%s" % (pos.pos.slug if pos else "norecord")

        if user_is_person(user, ad):
            c += " my"

        res.append('<td class="%s" />' % c)

    res.append("</tr>")
    res.append("</table></a>")

    return "".join(res)
Beispiel #17
0
def reject_reviewer_assignment(request, name, request_id):
    doc = get_object_or_404(Document, name=name)
    review_req = get_object_or_404(ReviewRequest,
                                   pk=request_id,
                                   state__in=["requested", "accepted"])

    if not review_req.reviewer:
        return redirect(review_request,
                        name=review_req.doc.name,
                        request_id=review_req.pk)

    is_reviewer = user_is_person(request.user, review_req.reviewer.person)
    can_manage_request = can_manage_review_requests_for_team(
        request.user, review_req.team)

    if not (is_reviewer or can_manage_request):
        return HttpResponseForbidden(
            "You do not have permission to perform this action")

    if request.method == "POST" and request.POST.get("action") == "reject":
        form = RejectReviewerAssignmentForm(request.POST)
        if form.is_valid():
            # reject the request
            review_req.state = ReviewRequestStateName.objects.get(
                slug="rejected")
            review_req.save()

            ReviewRequestDocEvent.objects.create(
                type="closed_review_request",
                doc=review_req.doc,
                rev=review_req.doc.rev,
                by=request.user.person,
                desc=
                "Assignment of request for {} review by {} to {} was rejected".
                format(
                    review_req.type.name,
                    review_req.team.acronym.upper(),
                    review_req.reviewer.person,
                ),
                review_request=review_req,
                state=review_req.state,
            )

            # make a new unassigned review request
            new_review_req = make_new_review_request_from_existing(review_req)
            new_review_req.save()

            msg = render_to_string(
                "review/reviewer_assignment_rejected.txt", {
                    "by":
                    request.user.person,
                    "message_to_secretary":
                    form.cleaned_data.get("message_to_secretary")
                })

            email_review_request_change(request,
                                        review_req,
                                        "Reviewer assignment rejected",
                                        msg,
                                        by=request.user.person,
                                        notify_secretary=True,
                                        notify_reviewer=True,
                                        notify_requested_by=False)

            return redirect(review_request,
                            name=new_review_req.doc.name,
                            request_id=new_review_req.pk)
    else:
        form = RejectReviewerAssignmentForm()

    return render(request, 'doc/review/reject_reviewer_assignment.html', {
        'doc': doc,
        'review_req': review_req,
        'form': form,
    })