From a4e49d8ec00d3a394b81cf832072336f36fd076e Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Tue, 22 Oct 2019 12:23:07 +0000 Subject: [PATCH] Merged in [16853] from rjsparks@nostrum.com: Add submitted and posted dates to several ipr notification email messages. Fixes #2807. - Legacy-Id: 16899 Note: SVN reference [16853] has been migrated to Git commit f39d1568f0c4a8f4b1ebd3dee887fff6b3d8049b --- ietf/ipr/factories.py | 11 ++- ietf/ipr/models.py | 6 ++ ietf/ipr/tests.py | 71 +++++++++++++++---- ietf/templates/ipr/posted_document_email.txt | 2 +- ietf/templates/ipr/posted_generic_email.txt | 2 +- ietf/templates/ipr/posted_submitter_email.txt | 2 +- 6 files changed, 76 insertions(+), 18 deletions(-) diff --git a/ietf/ipr/factories.py b/ietf/ipr/factories.py index 038117f75..cf07d6d24 100644 --- a/ietf/ipr/factories.py +++ b/ietf/ipr/factories.py @@ -10,7 +10,7 @@ import factory from ietf.ipr.models import ( IprDisclosureBase, HolderIprDisclosure, ThirdPartyIprDisclosure, NonDocSpecificIprDisclosure, - GenericIprDisclosure, IprDocRel, RelatedIpr + GenericIprDisclosure, IprDocRel, RelatedIpr, IprEvent ) def _fake_patent_info(): @@ -85,3 +85,12 @@ class GenericIprDisclosureFactory(IprDisclosureBaseFactory): holder_contact_email = factory.Faker('email') holder_contact_name = factory.Faker('name') +class IprEventFactory(factory.DjangoModelFactory): + class Meta: + model = IprEvent + + type_id = 'submitted' + by = factory.SubFactory('ietf.person.factories.PersonFactory') + disclosure = factory.SubFactory(IprDisclosureBaseFactory) + desc = factory.Faker('sentence') + diff --git a/ietf/ipr/models.py b/ietf/ipr/models.py index 4b70dbe3c..6f14412fc 100644 --- a/ietf/ipr/models.py +++ b/ietf/ipr/models.py @@ -56,6 +56,12 @@ class IprDisclosureBase(models.Model): """Returns the latest IprEvent of type msgout. For use in templates.""" return self.latest_event(type='msgout') + def get_latest_event_submitted(self): + return self.latest_event(type='submitted') + + def get_latest_event_posted(self): + return self.latest_event(type='posted') + def has_legacy_event(self): """Returns True if there is one or more LegacyMigrationIprEvents for this disclosure""" diff --git a/ietf/ipr/tests.py b/ietf/ipr/tests.py index faf4d7fe4..e782ae5ef 100644 --- a/ietf/ipr/tests.py +++ b/ietf/ipr/tests.py @@ -16,7 +16,8 @@ import debug # pyflakes:ignore from ietf.doc.models import DocAlias from ietf.doc.factories import DocumentFactory, WgDraftFactory, IndividualDraftFactory, WgRfcFactory -from ietf.ipr.factories import HolderIprDisclosureFactory +from ietf.group.factories import RoleFactory +from ietf.ipr.factories import HolderIprDisclosureFactory, GenericIprDisclosureFactory, IprEventFactory from ietf.ipr.mail import (process_response_email, get_reply_to, get_update_submitter_emails, get_pseudo_submitter, get_holders, get_update_cc_addrs) from ietf.ipr.models import (IprDisclosureBase,GenericIprDisclosure,HolderIprDisclosure, @@ -29,6 +30,24 @@ from ietf.utils.test_utils import TestCase, login_testing_unauthorized from ietf.utils.text import text_to_dict +def extract_message_content(message): + return message.get_payload(decode=True).decode(str(message.get_charset())) + +def make_data_from_content(content): + q = PyQuery(content) + data = dict() + for name in ['form-TOTAL_FORMS','form-INITIAL_FORMS','form-MIN_NUM_FORMS','form-MAX_NUM_FORMS']: + data[name] = q('form input[name=%s]'%name).val() + for i in range(0,int(data['form-TOTAL_FORMS'])): + name = 'form-%d-type' % i + data[name] = q('form input[name=%s]'%name).val() + text_name = 'form-%d-text' % i + data[text_name] = q('form textarea[name=%s]'%text_name).html().strip() + # Do not try to use + #data[text_name] = q('form textarea[name=%s]'%text_name).text() + # .text does not work - the field will likely contain <> characters + return data + class IprTests(TestCase): def setUp(self): pass @@ -527,8 +546,24 @@ I would like to revoke this declaration. pass def test_post(self): + ipr = HolderIprDisclosureFactory(state_id='pending') + url = urlreverse('ietf.ipr.views.state', kwargs={'id':ipr.id}) + login_testing_unauthorized(self,"secretary",url) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + r = self.client.post(url,{'state':'posted'}) + self.assertEqual(r.status_code, 302) + ipr = HolderIprDisclosure.objects.get(id=ipr.id) + self.assertTrue(ipr.iprevent_set.filter(type='posted').exists()) + + def test_notify(self): doc = WgDraftFactory(group__acronym='mars-wg', name='draft-ietf-mars-test') - ipr = HolderIprDisclosureFactory(docs=[doc,], submitter_email='george@acme.com') + old_ipr = HolderIprDisclosureFactory(docs=[doc,], submitter_email='george@acme.com') + IprEventFactory(type_id='submitted', disclosure=old_ipr) + IprEventFactory(type_id='posted', disclosure=old_ipr) + ipr = HolderIprDisclosureFactory(docs=[doc,], submitter_email='george@acme.com', updates=[old_ipr]) + IprEventFactory(type_id='submitted', disclosure=ipr) + IprEventFactory(type_id='posted', disclosure=ipr) url = urlreverse('ietf.ipr.views.post', kwargs={ "id": ipr.id }) login_testing_unauthorized(self, "secretary", url) @@ -543,24 +578,32 @@ I would like to revoke this declaration. self.assertEqual(ipr.state.slug,'posted') url = urlreverse('ietf.ipr.views.notify',kwargs={ 'id':ipr.id, 'type':'posted'}) r = self.client.get(url,follow=True) - q = PyQuery(r.content) - data = dict() - for name in ['form-TOTAL_FORMS','form-INITIAL_FORMS','form-MIN_NUM_FORMS','form-MAX_NUM_FORMS']: - data[name] = q('form input[name=%s]'%name).val() - for i in range(0,int(data['form-TOTAL_FORMS'])): - name = 'form-%d-type' % i - data[name] = q('form input[name=%s]'%name).val() - text_name = 'form-%d-text' % i - data[text_name] = q('form textarea[name=%s]'%text_name).html().strip() - # Do not try to use - #data[text_name] = q('form textarea[name=%s]'%text_name).text() - # .text does not work - the field will likely contain <> characters + self.assertEqual(r.status_code,200) + data = make_data_from_content(r.content) r = self.client.post(url, data ) self.assertEqual(r.status_code,302) self.assertEqual(len(outbox),len_before+2) self.assertTrue('george@acme.com' in outbox[len_before]['To']) + self.assertIn('posted on '+datetime.date.today().strftime("%Y-%m-%d"), extract_message_content(outbox[len_before]).replace('\n',' ')) self.assertTrue('draft-ietf-mars-test@ietf.org' in outbox[len_before+1]['To']) self.assertTrue('mars-wg@ietf.org' in outbox[len_before+1]['Cc']) + self.assertIn('Secretariat on '+ipr.get_latest_event_submitted().time.strftime("%Y-%m-%d"), extract_message_content(outbox[len_before+1]).replace('\n',' ')) + + def test_notify_generic(self): + RoleFactory(name_id='ad',group__acronym='gen') + ipr = GenericIprDisclosureFactory(submitter_email='foo@example.com') + IprEventFactory(type_id='submitted', disclosure=ipr) + IprEventFactory(type_id='posted', disclosure=ipr) + url = urlreverse('ietf.ipr.views.notify',kwargs={ 'id':ipr.id, 'type':'posted'}) + empty_outbox() + login_testing_unauthorized(self, 'secretary', url) + r = self.client.get(url, follow=True) + self.assertTrue(r.status_code, 200) + data = make_data_from_content(r.content) + r = self.client.post(url, data ) + self.assertEqual(r.status_code,302) + self.assertEqual(len(outbox),2) + self.assertIn('Secretariat on '+ipr.get_latest_event_submitted().time.strftime("%Y-%m-%d"), extract_message_content(outbox[1]).replace('\n',' ')) def test_process_response_email(self): # first send a mail diff --git a/ietf/templates/ipr/posted_document_email.txt b/ietf/templates/ipr/posted_document_email.txt index f94a2ba0b..c612a00ef 100644 --- a/ietf/templates/ipr/posted_document_email.txt +++ b/ietf/templates/ipr/posted_document_email.txt @@ -6,7 +6,7 @@ Cc: {{ cc_email }} Dear {{ to_name }}: {% filter wordwrap:78 %} -An IPR disclosure that pertains to your {{ doc_info }} was submitted to the IETF Secretariat on {{ ipr.submitted_date|date:"Y-m-d" }} and has been posted on the "IETF Page of Intellectual Property Rights Disclosures" (https://datatracker.ietf.org/ipr/{{ ipr.pk }}/). The title of the IPR disclosure is "{{ ipr.title }}" +An IPR disclosure that pertains to your {{ doc_info }} was submitted to the IETF Secretariat on {{ ipr.get_latest_event_submitted.time|date:"Y-m-d" }} and has been posted on the "IETF Page of Intellectual Property Rights Disclosures" (https://datatracker.ietf.org/ipr/{{ ipr.pk }}/). The title of the IPR disclosure is "{{ ipr.title }}" {% endfilter %} Thank you diff --git a/ietf/templates/ipr/posted_generic_email.txt b/ietf/templates/ipr/posted_generic_email.txt index d0b71896c..f3c0ae6b0 100644 --- a/ietf/templates/ipr/posted_generic_email.txt +++ b/ietf/templates/ipr/posted_generic_email.txt @@ -5,7 +5,7 @@ Cc: Dear {{ to_name }}: -A generic IPR disclosure was submitted to the IETF Secretariat on {{ ipr.submitted_date|date:"Y-m-d" }} +A generic IPR disclosure was submitted to the IETF Secretariat on {{ ipr.get_latest_event_submitted.time|date:"Y-m-d" }} and has been posted on the "IETF Page of Intellectual Property Rights Disclosures" (https://datatracker.ietf.org/ipr/). The title of the IPR disclosure is {{ ipr.title }}. diff --git a/ietf/templates/ipr/posted_submitter_email.txt b/ietf/templates/ipr/posted_submitter_email.txt index a87d4f6a2..a473c61aa 100644 --- a/ietf/templates/ipr/posted_submitter_email.txt +++ b/ietf/templates/ipr/posted_submitter_email.txt @@ -11,7 +11,7 @@ has been posted on the "IETF Page of Intellectual Property Rights Disclosures" Your IPR disclosure updates: {% for rel in ipr.updates %} -IPR disclosure ID #{{ rel.target.pk }}, "{{ rel.target.title }}", which was posted on {{ rel.target.submitted_date }} +IPR disclosure ID #{{ rel.target.pk }}, "{{ rel.target.title }}", which was posted on {{ rel.target.get_latest_event_posted.time|date:"Y-m-d" }} {% endfor %} {% endif %}