datatracker/ietf/community/forms.py
Robert Sparks d9cc26be96
feat: replace references to User with references to Person (#6024)
* refactor: change references from User to Person (#5821)

* refactor: Change CommunityList reference from User to Person

* refactor: Convert more user references to person

* refactor: Change augment_docs_and_user_with_user_info to person

* refactor: Change Nomination and Feedback references from User to Person

* refactor: Change a few test case function signatures to be more pythonic

* refactor: Harmonize how profile and photo views look up email_or_name

* refactor: Rework community views to operate on Person instead of User (#5859)

* test: Update tests to try all of the person's emails and aliases

* fix: Recode a test case to avoid an exception if there's Unicode in the URL

This only happens using the form-filling and submission feature of
WebTest, which is only used in this one test case, so just it rip out.

* test: Add duplicate-person tests

* fix: If there are multiple matching users, prefer the logged-in one.

* chore: We no longer use WebTest, so don't include it.

* fix: Address review comments

* fix: case-insensitive person name or email matching (#6096)

* chore: Renumber migrations

* fix: Update merged code so tests pass (#6887)

* fix: Use refactored method

* fix: Don't assume user has person

* fix: Use new view param name

* chore: Drop community lists w/o person; cleanup (#6896)

* fix: Don't assume user has person

* fix: user->person in update_community_list_index.py

* feat: Remove CommunityLists without Person

* refactor: Speed up nomcom migrations

---------

Co-authored-by: Paul Selkirk <paul@painless-security.com>
Co-authored-by: Jennifer Richards <jennifer@staff.ietf.org>
2024-01-24 11:00:19 -06:00

140 lines
5.7 KiB
Python

# Copyright The IETF Trust 2012-2020, All Rights Reserved
# -*- coding: utf-8 -*-
import re
from django import forms
from django.db.models import Q
from ietf.community.models import SearchRule, EmailSubscription
from ietf.doc.fields import SearchableDocumentsField
from ietf.person.models import Person
from ietf.person.fields import SearchablePersonField
class AddDocumentsForm(forms.Form):
documents = SearchableDocumentsField(label="Add Internet-Drafts to track", doc_type="draft")
class SearchRuleTypeForm(forms.Form):
rule_type = forms.ChoiceField(choices=[('', '--------------')] + SearchRule.RULE_TYPES)
class SearchRuleForm(forms.ModelForm):
person = SearchablePersonField()
class Meta:
model = SearchRule
fields = ('state', 'group', 'person', 'text')
def __init__(self, clist, rule_type, *args, **kwargs):
kwargs["prefix"] = rule_type # add prefix to avoid mixups in the Javascript
super(SearchRuleForm, self).__init__(*args, **kwargs)
def restrict_state(state_type, slug=None):
if "state" not in self.fields:
raise RuntimeError(f"Rule type {rule_type} cannot include state filtering")
f = self.fields['state']
f.queryset = f.queryset.filter(used=True).filter(type=state_type)
if slug:
f.queryset = f.queryset.filter(slug=slug)
if len(f.queryset) == 1:
f.initial = f.queryset[0].pk
f.widget = forms.HiddenInput()
if rule_type.endswith("_rfc"):
del self.fields["state"] # rfc rules must not look at document states
if rule_type in ["group", "group_rfc", "area", "area_rfc", "group_exp"]:
if rule_type == "group_exp":
restrict_state("draft", "expired")
else:
if not rule_type.endswith("_rfc"):
restrict_state("draft", "active")
if rule_type.startswith("area"):
self.fields["group"].label = "Area"
self.fields["group"].queryset = self.fields["group"].queryset.filter(Q(type="area") | Q(acronym="irtf")).order_by("acronym")
else:
self.fields["group"].queryset = self.fields["group"].queryset.filter(type__in=("wg", "rg", "ag", "rag", "program" )).order_by("acronym")
del self.fields["person"]
del self.fields["text"]
elif rule_type.startswith("state_"):
mapping = {
"state_iab": "draft-stream-iab",
"state_iana": "draft-iana-review",
"state_iesg": "draft-iesg",
"state_irtf": "draft-stream-irtf",
"state_ise": "draft-stream-ise",
"state_rfceditor": "draft-rfceditor",
"state_ietf": "draft-stream-ietf",
}
restrict_state(mapping[rule_type])
del self.fields["group"]
del self.fields["person"]
del self.fields["text"]
elif rule_type in ["author", "author_rfc", "shepherd", "ad"]:
if not rule_type.endswith("_rfc"):
restrict_state("draft", "active")
if rule_type.startswith("author"):
self.fields["person"].label = "Author"
elif rule_type.startswith("shepherd"):
self.fields["person"].label = "Shepherd"
elif rule_type.startswith("ad"):
self.fields["person"].label = "Area Director"
self.fields["person"] = forms.ModelChoiceField(queryset=Person.objects.filter(role__name__in=("ad", "pre-ad"), role__group__state="active").distinct().order_by("name"))
del self.fields["group"]
del self.fields["text"]
elif rule_type == "name_contains":
if not rule_type.endswith("_rfc"):
restrict_state("draft", "active")
del self.fields["person"]
del self.fields["group"]
if 'group' in self.fields:
self.fields['group'].queryset = self.fields['group'].queryset.filter(state="active").order_by("acronym")
self.fields['group'].choices = [(g.pk, "%s - %s" % (g.acronym, g.name)) for g in self.fields['group'].queryset]
for name, f in self.fields.items():
f.required = True
def clean_text(self):
candidate_text = self.cleaned_data["text"].strip().lower() # names are always lower case
try:
re.compile(candidate_text)
except re.error as e:
raise forms.ValidationError(str(e))
return candidate_text
class SubscriptionForm(forms.ModelForm):
def __init__(self, person, clist, *args, **kwargs):
self.clist = clist
super(SubscriptionForm, self).__init__(*args, **kwargs)
self.fields["notify_on"].widget = forms.RadioSelect(choices=self.fields["notify_on"].choices)
self.fields["email"].queryset = self.fields["email"].queryset.filter(person=person, active=True).order_by("-primary")
self.fields["email"].widget = forms.RadioSelect(choices=[t for t in self.fields["email"].choices if t[0]])
if self.fields["email"].queryset:
self.fields["email"].initial = self.fields["email"].queryset[0]
def clean_email(self):
self.cleaned_data["email"].address = self.cleaned_data["email"].address.strip().lower()
return self.cleaned_data["email"]
def clean(self):
if EmailSubscription.objects.filter(community_list=self.clist, email=self.cleaned_data["email"], notify_on=self.cleaned_data["notify_on"]).exists():
raise forms.ValidationError("You already have a subscription like this.")
class Meta:
model = EmailSubscription
fields = ("notify_on", "email")