Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 89 additions & 48 deletions ietf/secr/announcement/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,96 +14,133 @@
# Globals
# ---------------------------------------------

TO_LIST = ('IETF Announcement List <ietf-announce@ietf.org>',
'I-D Announcement List <i-d-announce@ietf.org>',
'RFP Announcement List <rfp-announce@ietf.org>',
'The IESG <iesg@ietf.org>',
'Working Group Chairs <wgchairs@ietf.org>',
'BOF Chairs <bofchairs@ietf.org>',
'Other...')
TO_LIST = (
"IETF Announcement List <ietf-announce@ietf.org>",
"I-D Announcement List <i-d-announce@ietf.org>",
"RFP Announcement List <rfp-announce@ietf.org>",
"The IESG <iesg@ietf.org>",
"Working Group Chairs <wgchairs@ietf.org>",
"BOF Chairs <bofchairs@ietf.org>",
"Other...",
)

# ---------------------------------------------
# Helper Functions
# ---------------------------------------------


def get_from_choices(user):
'''
"""
This function returns a choices tuple containing
all the Announced From choices. Including
leadership chairs and other entities.
'''
"""
addresses = []
if has_role(user,'Secretariat'):
addresses = AnnouncementFrom.objects.values_list('address', flat=True).order_by('address').distinct()
if has_role(user, "Secretariat"):
addresses = (
AnnouncementFrom.objects.values_list("address", flat=True)
.order_by("address")
.distinct()
)
else:
for role in user.person.role_set.all():
addresses.extend(AnnouncementFrom.objects.filter(name=role.name, group=role.group).values_list('address', flat=True).order_by('address'))
addresses.extend(
AnnouncementFrom.objects.filter(name=role.name, group=role.group)
.values_list("address", flat=True)
.order_by("address")
)

nomcom_choices = get_nomcom_choices(user)
if nomcom_choices:
addresses = list(addresses) + nomcom_choices

choices = list(zip(addresses, addresses))
if len(choices) > 1:
choices.insert(0, ('', '(Choose an option)'))
choices.insert(0, ("", "(Choose an option)"))
return choices


def get_nomcom_choices(user):
'''
"""
Returns the list of nomcom email addresses for given user
'''
nomcoms = Role.objects.filter(name="chair",
group__acronym__startswith="nomcom",
group__state="active",
group__type="nomcom",
person=user.person)
"""
nomcoms = Role.objects.filter(
name="chair",
group__acronym__startswith="nomcom",
group__state="active",
group__type="nomcom",
person=user.person,
)
addresses = []
for nomcom in nomcoms:
year = nomcom.group.acronym[-4:]
addresses.append('NomCom Chair %s <nomcom-chair-%s@ietf.org>' % (year,year))
addresses.append("NomCom Chair %s <nomcom-chair-%s@ietf.org>" % (year, year))

return addresses


def get_to_choices():
return list(zip(TO_LIST,TO_LIST))
return list(zip(TO_LIST, TO_LIST))


# ---------------------------------------------
# Forms
# ---------------------------------------------


class AnnounceForm(forms.ModelForm):
nomcom = forms.ModelChoiceField(queryset=Group.objects.filter(acronym__startswith='nomcom',type='nomcom',state='active'),required=False)
nomcom = forms.ModelChoiceField(
queryset=Group.objects.filter(
acronym__startswith="nomcom", type="nomcom", state="active"
),
required=False,
)
to_custom = MultiEmailField(required=False)

class Meta:
model = Message
fields = ('nomcom', 'to','to_custom','frm','cc','bcc','reply_to','subject','body')
fields = (
"nomcom",
"to",
"to_custom",
"frm",
"cc",
"bcc",
"reply_to",
"subject",
"body",
)
labels = {"frm": "From"}
help_texts = {
"to": "Select name OR select Other... and enter email below",
"cc": "Use comma separated lists for emails (Cc, Bcc, Reply To)",
}

def __init__(self, *args, **kwargs):
if 'hidden' in kwargs:
self.hidden = kwargs.pop('hidden')
if "hidden" in kwargs:
self.hidden = kwargs.pop("hidden")
else:
self.hidden = False
user = kwargs.pop('user')
user = kwargs.pop("user")
person = user.person
super(AnnounceForm, self).__init__(*args, **kwargs)
self.fields['to'].widget = forms.Select(choices=get_to_choices())
self.fields['to'].help_text = 'Select name OR select Other... and enter email below'
self.fields['cc'].help_text = 'Use comma separated lists for emails (Cc, Bcc, Reply To)'
self.fields['frm'].widget = forms.Select(choices=get_from_choices(user))
self.fields['frm'].label = 'From'
self.fields['reply_to'].required = True
self.fields['nomcom'].label = 'NomCom message:'
nomcom_roles = person.role_set.filter(group__in=self.fields['nomcom'].queryset,name='chair')
secr_roles = person.role_set.filter(group__acronym='secretariat',name='secr')
self.fields["to"].widget = forms.Select(choices=get_to_choices())
self.fields["frm"].widget = forms.Select(choices=get_from_choices(user))
self.fields["reply_to"].required = True
# nomcom field is defined declaratively so label and help_text must be set here
self.fields["nomcom"].label = "NomCom message:"
self.fields["nomcom"].help_text = (
"If this is a NomCom announcement specifiy which NomCom group here"
)
nomcom_roles = person.role_set.filter(
group__in=self.fields["nomcom"].queryset, name="chair"
)
secr_roles = person.role_set.filter(group__acronym="secretariat", name="secr")
if nomcom_roles:
self.initial['nomcom'] = nomcom_roles[0].group.pk
self.initial["nomcom"] = nomcom_roles[0].group.pk
if not nomcom_roles and not secr_roles:
self.fields['nomcom'].widget = forms.HiddenInput()
self.fields["nomcom"].widget = forms.HiddenInput()

if self.hidden:
for key in list(self.fields.keys()):
self.fields[key].widget = forms.HiddenInput()
Expand All @@ -113,25 +150,29 @@ def clean(self):
data = self.cleaned_data
if self.errors:
return self.cleaned_data
if data['to'] == 'Other...' and not data['to_custom']:
if data["to"] == "Other..." and not data["to_custom"]:
raise forms.ValidationError('You must enter a "To" email address')
for k in ['to', 'frm', 'cc',]:
for k in [
"to",
"frm",
"cc",
]:
data[k] = unescape(data[k])

return data

def save(self, *args, **kwargs):
user = kwargs.pop('user')
user = kwargs.pop("user")
message = super(AnnounceForm, self).save(commit=False)
message.by = user.person
if self.cleaned_data['to'] == 'Other...':
message.to = self.cleaned_data['to_custom']
if kwargs['commit']:
if self.cleaned_data["to"] == "Other...":
message.to = self.cleaned_data["to_custom"]
if kwargs["commit"]:
message.save()

# handle nomcom message
nomcom = self.cleaned_data.get('nomcom',False)
nomcom = self.cleaned_data.get("nomcom", False)
if nomcom:
message.related_groups.add(nomcom)

return message
return message
109 changes: 57 additions & 52 deletions ietf/secr/announcement/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from django.urls import reverse

import debug # pyflakes:ignore
import debug # pyflakes:ignore

from ietf.utils.test_utils import TestCase
from ietf.group.factories import RoleFactory
Expand All @@ -17,97 +17,102 @@
from ietf.message.models import AnnouncementFrom
from ietf.utils.mail import outbox, empty_outbox

SECR_USER='secretary'
WG_USER=''
AD_USER=''
SECR_USER = "secretary"
WG_USER = ""
AD_USER = ""


class SecrAnnouncementTestCase(TestCase):
def setUp(self):
super().setUp()
chair = RoleName.objects.get(slug='chair')
secr = RoleName.objects.get(slug='secr')
ietf = Group.objects.get(acronym='ietf')
iab = Group.objects.get(acronym='iab')
secretariat = Group.objects.get(acronym='secretariat')
AnnouncementFrom.objects.create(name=secr,group=secretariat,address='IETF Secretariat <ietf-secretariat@ietf.org>')
AnnouncementFrom.objects.create(name=chair,group=ietf,address='IETF Chair <chair@ietf.org>')
AnnouncementFrom.objects.create(name=chair,group=iab,address='IAB Chair <iab-chair@iab.org>')
chair = RoleName.objects.get(slug="chair")
secr = RoleName.objects.get(slug="secr")
ietf = Group.objects.get(acronym="ietf")
iab = Group.objects.get(acronym="iab")
secretariat = Group.objects.get(acronym="secretariat")
AnnouncementFrom.objects.create(
name=secr,
group=secretariat,
address="IETF Secretariat <ietf-secretariat@ietf.org>",
)
AnnouncementFrom.objects.create(
name=chair, group=ietf, address="IETF Chair <chair@ietf.org>"
)
AnnouncementFrom.objects.create(
name=chair, group=iab, address="IAB Chair <iab-chair@iab.org>"
)

def test_main(self):
"Main Test"
url = reverse('ietf.secr.announcement.views.main')
url = reverse("ietf.secr.announcement.views.main")
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)

def test_main_announce_from(self):
url = reverse('ietf.secr.announcement.views.main')
url = reverse("ietf.secr.announcement.views.main")

# Secretariat
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('#id_frm option')),4)
self.assertEqual(len(q("#id_frm option")), 4)

# IAB Chair
self.client.login(username="iab-chair", password="iab-chair+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('#id_frm option')),1)
self.assertTrue('<iab-chair@iab.org>' in q('#id_frm option').val())
self.assertEqual(len(q("#id_frm option")), 1)
self.assertTrue("<iab-chair@iab.org>" in q("#id_frm option").val())

# IETF Chair
self.client.login(username="ietf-chair", password="ietf-chair+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('#id_frm option')),1)
self.assertTrue('<chair@ietf.org>' in q('#id_frm option').val())
self.assertEqual(len(q("#id_frm option")), 1)
self.assertTrue("<chair@ietf.org>" in q("#id_frm option").val())


class UnauthorizedAnnouncementCase(TestCase):
def test_unauthorized(self):
"Unauthorized Test"
url = reverse('ietf.secr.announcement.views.main')
person = RoleFactory(name_id='chair',group__acronym='mars').person
self.client.login(username=person.user.username, password=person.user.username+"+password")
url = reverse("ietf.secr.announcement.views.main")
person = RoleFactory(name_id="chair", group__acronym="mars").person
self.client.login(
username=person.user.username, password=person.user.username + "+password"
)
r = self.client.get(url)
self.assertEqual(r.status_code, 403)



class SubmitAnnouncementCase(TestCase):
def test_invalid_submit(self):
"Invalid Submit"
url = reverse('ietf.secr.announcement.views.main')
post_data = {'id_subject':''}
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url,post_data)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)

def test_valid_submit(self):
"Valid Submit"
nomcom_test_data()
empty_outbox()
url = reverse('ietf.secr.announcement.views.main')
confirm_url = reverse('ietf.secr.announcement.views.confirm')
nomcom = Group.objects.get(type='nomcom')
post_data = {'nomcom': nomcom.pk,
'to':'Other...',
'to_custom':'rcross@amsl.com',
'frm':'IETF Secretariat &lt;ietf-secretariat@ietf.org&gt;',
'reply_to':'secretariat@ietf.org',
'subject':'Test Subject',
'body':'This is a test.'}
url = reverse("ietf.secr.announcement.views.main")
confirm_url = reverse("ietf.secr.announcement.views.confirm")
nomcom = Group.objects.get(type="nomcom")
post_data = {
"nomcom": nomcom.pk,
"to": "Other...",
"to_custom": "phil@example.com",
"frm": "IETF Secretariat &lt;ietf-secretariat@ietf.org&gt;",
"reply_to": "secretariat@ietf.org",
"subject": "Test Subject",
"body": "This is a test.",
}
self.client.login(username="secretary", password="secretary+password")
response = self.client.post(url,post_data)
self.assertContains(response, 'Confirm Announcement')
response = self.client.post(confirm_url,post_data,follow=True)
response = self.client.post(url, post_data)
self.assertContains(response, "Confirm Announcement")
response = self.client.post(confirm_url, post_data, follow=True)
self.assertRedirects(response, url)
self.assertEqual(len(outbox),1)
self.assertEqual(outbox[0]['subject'],'Test Subject')
self.assertEqual(outbox[0]['to'],'<rcross@amsl.com>')
message = Message.objects.filter(by__user__username='secretary').last()
self.assertEqual(message.subject,'Test Subject')
self.assertEqual(len(outbox), 1)
self.assertEqual(outbox[0]["subject"], "Test Subject")
self.assertEqual(outbox[0]["to"], "<phil@example.com>")
message = Message.objects.filter(by__user__username="secretary").last()
self.assertEqual(message.subject, "Test Subject")
self.assertTrue(nomcom in message.related_groups.all())
5 changes: 2 additions & 3 deletions ietf/secr/announcement/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

from ietf.secr.announcement import views
from ietf.utils.urls import url

urlpatterns = [
url(r'^$', views.main),
url(r'^confirm/$', views.confirm),
url(r"^$", views.main),
url(r"^confirm/$", views.confirm),
]
Loading