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
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)
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, })
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, })
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, })
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
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, })
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, })