Пример #1
0
    def __init__(self, user, doc, *args, **kwargs):
        super(RequestReviewForm, self).__init__(*args, **kwargs)

        self.doc = doc

        f = self.fields["team"]
        f.queryset = active_review_teams()
        f.initial = [
            group.pk for group in f.queryset
            if can_manage_review_requests_for_team(
                user, group, allow_personnel_outside_team=False)
        ]

        self.fields['type'].queryset = self.fields['type'].queryset.filter(
            used=True,
            reviewteamsettings__group__in=self.fields["team"].queryset
        ).distinct()
        self.fields['type'].widget = forms.RadioSelect(
            choices=[t for t in self.fields['type'].choices if t[0]])

        self.fields["requested_rev"].label = "Document revision"

        if has_role(user, "Secretariat"):
            self.fields["requested_by"] = SearchablePersonField()
        else:
            self.fields["requested_by"].widget = forms.HiddenInput()
            self.fields["requested_by"].initial = user.person.pk
Пример #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)
Пример #3
0
def assign_reviewer(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 can_manage_review_requests_for_team(request.user, review_req.team):
        return HttpResponseForbidden(
            "You do not have permission to perform this action")

    if request.method == "POST" and request.POST.get("action") == "assign":
        form = AssignReviewerForm(review_req, request.POST)
        if form.is_valid():
            reviewer = form.cleaned_data["reviewer"]
            add_skip = form.cleaned_data["add_skip"]
            assign_review_request_to_reviewer(request, review_req, reviewer,
                                              add_skip)

            return redirect(review_request,
                            name=review_req.doc.name,
                            request_id=review_req.pk)
    else:
        form = AssignReviewerForm(review_req)

    return render(request, 'doc/review/assign_reviewer.html', {
        'doc': doc,
        'review_req': review_req,
        'form': form,
    })
Пример #4
0
def close_request(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"])

    can_request = is_authorized_in_doc_stream(request.user, doc)
    can_manage_request = can_manage_review_requests_for_team(
        request.user, review_req.team)

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

    if request.method == "POST":
        form = CloseReviewRequestForm(can_manage_request, request.POST)
        if form.is_valid():
            close_review_request(request, review_req,
                                 form.cleaned_data["close_reason"])

        return redirect(review_request,
                        name=review_req.doc.name,
                        request_id=review_req.pk)
    else:
        form = CloseReviewRequestForm(can_manage_request)

    return render(request, 'doc/review/close_request.html', {
        'doc': doc,
        'review_req': review_req,
        'form': form,
    })
Пример #5
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,
        })
Пример #6
0
def construct_group_menu_context(request, group, selected, group_type, others):
    """Return context with info for the group menu filled in."""
    kwargs = dict(acronym=group.acronym)
    if group_type:
        kwargs["group_type"] = group_type

    # menu entries
    entries = []
    entries.append(
        ("About", urlreverse("ietf.group.views.group_about", kwargs=kwargs)))
    if group.features.has_documents:
        entries.append(("Documents",
                        urlreverse("ietf.group.views.group_documents",
                                   kwargs=kwargs)))
    if group.features.has_materials and get_group_materials(group).exists():
        entries.append(("Materials",
                        urlreverse("ietf.group.views.materials",
                                   kwargs=kwargs)))
    if group.features.has_reviews:
        import ietf.group.views
        entries.append(("Review requests",
                        urlreverse(ietf.group.views.review_requests,
                                   kwargs=kwargs)))
        entries.append(("Reviewers",
                        urlreverse(ietf.group.views.reviewer_overview,
                                   kwargs=kwargs)))
    if group.type_id in ('rg', 'wg', 'ag', 'team'):
        entries.append(
            ("Meetings", urlreverse("ietf.group.views.meetings",
                                    kwargs=kwargs)))
    entries.append(
        ("History", urlreverse("ietf.group.views.history", kwargs=kwargs)))
    entries.append(
        ("Photos", urlreverse("ietf.group.views.group_photos", kwargs=kwargs)))
    entries.append(
        ("Email expansions", urlreverse("ietf.group.views.email",
                                        kwargs=kwargs)))
    if group.list_archive.startswith("http:") or group.list_archive.startswith(
            "https:") or group.list_archive.startswith("ftp:"):
        if 'mailarchive.ietf.org' in group.list_archive:
            entries.append(("List archive",
                            urlreverse("ietf.group.views.derived_archives",
                                       kwargs=kwargs)))
        else:
            entries.append(
                (mark_safe("List archive »"), group.list_archive))
    if group.has_tools_page():
        entries.append(
            (mark_safe("Tools »"),
             "https://tools.ietf.org/%s/%s/" % (group.type_id, group.acronym)))

    # actions
    actions = []

    is_admin = group.has_role(request.user, group.features.admin_roles)
    can_manage = can_manage_group_type(request.user, group)
    can_edit_group = False  # we'll set this further down

    if group.features.has_milestones:
        if group.state_id != "proposed" and (is_admin or can_manage):
            actions.append(
                (u"Edit milestones",
                 urlreverse('ietf.group.milestones.edit_milestones;current',
                            kwargs=kwargs)))

    if group.features.has_documents:
        clist = CommunityList.objects.filter(group=group).first()
        if clist and can_manage_community_list(request.user, clist):
            import ietf.community.views
            actions.append((u'Manage document list',
                            urlreverse(ietf.community.views.manage_list,
                                       kwargs=kwargs)))

    if group.features.has_materials and can_manage_materials(
            request.user, group):
        actions.append(
            (u"Upload material",
             urlreverse("ietf.doc.views_material.choose_material_type",
                        kwargs=kwargs)))

    if group.features.has_reviews and can_manage_review_requests_for_team(
            request.user, group):
        import ietf.group.views
        actions.append((u"Manage unassigned reviews",
                        urlreverse(ietf.group.views.manage_review_requests,
                                   kwargs=dict(assignment_status="unassigned",
                                               **kwargs))))
        actions.append((u"Manage assigned reviews",
                        urlreverse(ietf.group.views.manage_review_requests,
                                   kwargs=dict(assignment_status="assigned",
                                               **kwargs))))

        if Role.objects.filter(name="secr",
                               group=group,
                               person__user=request.user).exists():
            actions.append(
                (u"Secretary settings",
                 urlreverse(ietf.group.views.change_review_secretary_settings,
                            kwargs=kwargs)))

    if group.state_id != "conclude" and (is_admin or can_manage):
        can_edit_group = True
        actions.append((u"Edit group",
                        urlreverse("ietf.group.views.edit",
                                   kwargs=dict(kwargs, action="edit"))))

    if group.features.customize_workflow and (is_admin or can_manage):
        actions.append((u"Customize workflow",
                        urlreverse("ietf.group.views.customize_workflow",
                                   kwargs=kwargs)))

    if group.state_id in ("active", "dormant") and not group.type_id in [
            "sdo",
            "rfcedtyp",
            "isoc",
    ] and can_manage:
        actions.append((u"Request closing group",
                        urlreverse("ietf.group.views.conclude",
                                   kwargs=kwargs)))

    d = {
        "group": group,
        "selected_menu_entry": selected,
        "menu_entries": entries,
        "menu_actions": actions,
        "group_type": group_type,
        "can_edit_group": can_edit_group,
    }

    d.update(others)

    return d
Пример #7
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,
        })
Пример #8
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,
    })