def create_and_return_decision(self, description='Decision Time', status=Decision.PROPOSAL_STATUS): decision = Decision(description=description, status=status) decision.save(self.user) return decision
def test_model_feedbackcount_changes(self): decision = Decision(description="Decision test data") decision.save(self.user) self.instance_attribute_has_value(decision, "feedbackcount", 0) feedback = Feedback(description="Feedback test data", decision=decision) feedback.save() self.instance_attribute_has_value(decision, "feedbackcount", 1)
def test_emails_arent_sent_to_author(self): """ We want to make sure that when a user creates or changes an item they are not sent an email. The email goes to those that do not already know the item has changed! """ andy = User.objects.create_user("Andy", "*****@*****.**", password='******') billy = User.objects.create_user("Billy", "*****@*****.**", password='******') chris = User.objects.create_user("Chris", "*****@*****.**", password='******') decision = Decision(description='Test', status=0) decision.save(andy) #billy decides he wants to watch... decision.watchers = [billy] #andy changes the content mymail = OpenConsentEmailMessage('content_change', decision) #only watchers get mail, not the author self.assertNotIn(andy.email, mymail.to) self.assertIn(billy.email, mymail.to) self.assertNotIn(chris.email, mymail.to)
def test_emails_dont_contain_escaped_characters(self): """ We want to verify that the emails sent out do not contain confusing text like '&' instead of '&' or ''<' instead of '<' All plaintext emails should be marked 'safe' in the Django template. """ decision = Decision(description='&', status=0) decision.save(self.user) mymail = OpenConsentEmailMessage('new', decision) self.assertNotIn('&', mymail.subject) self.assertNotIn('&', mymail.body) mymail = OpenConsentEmailMessage('status_change', decision, old_obj=decision) self.assertNotIn('&', mymail.subject) self.assertNotIn('&', mymail.body) mymail = OpenConsentEmailMessage('content_change', decision) self.assertNotIn('&', mymail.subject) self.assertNotIn('&', mymail.body)
def test_status_is_set_in_decision_detail_context(self): """ Same as test_status_is_set_in_decision_list_context but for decision_detail view. """ dd = DecisionDetail() manual_status = 'i set the status' decision = Decision(status=manual_status, organization=Organization()) dd.object = decision context = dd.get_context_data() self.assertEqual(context['tab'], manual_status)
def create_and_return_decision(self, description='Decision Time', status=Decision.PROPOSAL_STATUS, deadline=now().date()): decision = Decision(description=description, status=status, organization=self.bettysorg, deadline=deadline) decision.author = self.user decision.save() return decision
def test_decisions_can_be_sorted_by_id(self): id_list = [] for i in range(5, 0, -1): decision = Decision(description='Decision %d' % i) decision.save(self.user) id_list.append(decision.id) response = self.client.get(reverse('list', args=['proposal']), {'sort': 'id'}) object_list = response.context['object_list'] for i in range(1, 6): self.assertEquals(id_list[i - 1], object_list[i - 1].id)
def assert_decisions_sorted_by_date_column(self, column): # Create test decisions in reverse date order. for i in range(5, 0, -1): decision = Decision(description='Decision %d' % i, status=Decision.DECISION_STATUS) setattr(decision, column, datetime.date(2001, 3, i)) decision.save(self.user) response = self.client.get(reverse('list', args=['decision']), dict(sort=column)) object_list = response.context['object_list'] for i in range(1, 6): self.assertEquals(datetime.date(2001, 3, i), getattr(object_list[i - 1], column))
def _process_email(self, mail, verbosity): # pylint: disable=R0914 logger = logging.getLogger('econsensus') #handle multipart mails, cycle through mail #until find text type with a full payload. if mail.is_multipart(): for message in mail.get_payload(): if message.get_content_maintype() == 'text': msg_string = self._strip_string(message.get_payload(), verbosity) if msg_string: break else: msg_string = self._strip_string(mail.get_payload(), verbosity) if not msg_string: logger.error( "[EMAIL REJECTED] From '%s' Reason: Email payload empty" % mail['From']) return #Must match email 'from' address to user from_match = re.search('([\w\-\.]+@\w[\w\-]+\.+[\w\-]+)', mail['From']) if from_match: self._print_if_verbose( verbosity, "Found email 'from' '%s'" % from_match.group(1)) try: user = User.objects.get(email=from_match.group(1)) except ObjectDoesNotExist: logger.error("[EMAIL REJECTED] From '%s' Reason: id '%s' does not correspond to any known User" \ % (mail['From'], from_match.group(1))) return except MultipleObjectsReturned: logger.error("[EMAIL REJECTED] From '%s' Reason: Query returned several Users for id '%s'" \ % (mail['From'], from_match.group(1))) return self._print_if_verbose(verbosity, "Matched email to user '%s'" % user) else: logger.error( "[EMAIL REJECTED] From '%s' Reason: Unrecognised email address format" % mail['From']) return #Must match email 'to' address to organization org_match = re.search('([\w\-\.]+)@\w[\w\-]+\.+[\w\-]+', mail['To']) if org_match: self._print_if_verbose( verbosity, "Found email 'to' '%s'" % org_match.group(1)) try: organization = Organization.objects.get( slug=org_match.group(1)) except ObjectDoesNotExist: logger.error("[EMAIL REJECTED] From '%s' Reason: id '%s' does not correspond to any known Organization" \ % (mail['From'], org_match.group(1))) return except MultipleObjectsReturned: logger.error("[EMAIL REJECTED] From '%s' Reason: Query returned several Organizations for id '%s'" \ % (mail['From'], org_match.group(1))) return self._print_if_verbose( verbosity, "Matched email to organization '%s'" % organization.name) else: logger.error( "[EMAIL REJECTED] From '%s' Reason: Couldn't pull Organization from '%s'" % (mail['From'], mail['To'])) return #User must be a member of the Organization if organization not in Organization.active.get_for_user(user): self._print_if_verbose( verbosity, "User %s is not a member of Organization %s" % (user.username, organization.name)) logger.error("[EMAIL REJECTED] From '%s' Reason: User '%s' is not a member of Organization '%s'" \ % (mail['From'], user.username, organization.name)) return #Look for feedback types in the message body rating = Feedback.COMMENT_STATUS description = msg_string parse_feedback = re.match('(\w+)\s*:\s*([\s\S]*)', msg_string, re.IGNORECASE) if parse_feedback: description = parse_feedback.group(2) rating_match = re.match('question|danger|concerns|consent|comment', parse_feedback.group(1), re.IGNORECASE) if rating_match: self._print_if_verbose( verbosity, "Found feedback rating '%s'" % rating_match.group()) rating = dict(Feedback.RATING_CHOICES).values().index( rating_match.group().lower()) # Determine whether email is in reply to a notification subject_match = re.search('\[EC#(\d+)(?:\\\\(\d+)(?:\\\\(\d+))?)?\]', mail['Subject']) if subject_match: #Check that the user has the right to comment against the decision. if subject_match.group(1): self._print_if_verbose( verbosity, "Found decision id '%s' in Subject" % subject_match.group(1)) try: decision = Decision.objects.get(pk=subject_match.group(1)) except ObjectDoesNotExist: logger.error("[EMAIL REJECTED] From '%s' Reason: id '%s' does not correspond to any known Decision" \ % (mail['From'], subject_match.group(1))) return except MultipleObjectsReturned: logger.error("[EMAIL REJECTED] From '%s' Reason: Query returned several Decisions for id '%s'" \ % (mail['From'], subject_match.group(1))) return if user not in decision.organization.users.all(): logger.error("[EMAIL REJECTED] From '%s' Reason: User cannot reply to decision #%s because they are not a member of that organization." \ % (mail['From'], subject_match.group(1))) return #process comment or feedback against feedback if subject_match.group(2): self._print_if_verbose( verbosity, "Found feedback id '%s' in Subject" % subject_match.group(2)) try: feedback = Feedback.objects.get(pk=subject_match.group(2)) except ObjectDoesNotExist: logger.error("[EMAIL REJECTED] From '%s' Reason: id '%s' does not correspond to any known Feedback" \ % (mail['From'], subject_match.group(2))) return except MultipleObjectsReturned: logger.error("[EMAIL REJECTED] From '%s' Reason: Query returned more than one Feedback for id '%s'" \ % (mail['From'], subject_match.group(2))) return if parse_feedback and rating_match: decision = feedback.decision self._print_if_verbose( verbosity, "Creating feedback with rating '%s' and description '%s'." % (rating, description)) feedback = Feedback(author=user, decision=decision, rating=rating, description=description) feedback.save() logger.info( "User '%s' added feedback via email to decision #%s" % (user, decision.id)) self._print_if_verbose( verbosity, "Found corresponding object '%s'" % decision.excerpt) else: comment_text = msg_string self._print_if_verbose( verbosity, "Creating comment '%s'." % (comment_text)) comment = Comment(user=user, user_name=user.get_full_name(), user_email=user.email, comment=comment_text, content_object=feedback, object_pk=feedback.id, content_type=ContentType.objects.get( app_label="publicweb", model="feedback"), submit_date=timezone.now(), site=Site.objects.get_current()) comment.save() logger.info( "User '%s' added comment via email to feedback #%s" % (user, feedback.id)) self._print_if_verbose( verbosity, "Found corresponding object '%s'" % feedback.description) #process feedback against decision elif subject_match.group(1): self._print_if_verbose( verbosity, "Creating feedback with rating '%s' and description '%s'." % (rating, description)) feedback = Feedback(author=user, decision=decision, rating=rating, description=description) feedback.save() logger.info( "User '%s' added feedback via email to decision #%s" % (user, decision.id)) self._print_if_verbose( verbosity, "Found corresponding object '%s'" % decision.excerpt) else: self._print_if_verbose( verbosity, "No id found in message subject: %s" % mail['Subject']) logger.error("[EMAIL REJECTED] From '%s' Reason: No id present." \ % mail['From']) # Email was not in reply to a notification so create a new proposal else: proposal_match = re.search('proposal', mail['Subject'], re.IGNORECASE) if proposal_match: decision = Decision(author=user, editor=user, status=Decision.PROPOSAL_STATUS, organization=organization, \ description=msg_string) decision.save() self._print_if_verbose( verbosity, "User '%s' created decision #%s via email" % (user, decision.id)) logger.info("User '%s' created decision #%s via email" % (user, decision.id)) else: logger.error("[EMAIL REJECTED] From '%s' Reason: Email was not in reply to a notification and body didn't contain keyword 'proposal'" \ % mail['From'])
def test_feedback_can_have_empty_description(self): decision = Decision(description='Test', status=Decision.DECISION_STATUS) decision.save(self.user) feedback = Feedback(rating=Feedback.CONSENT_STATUS, decision=decision) self.instance_validates(feedback)
def test_decision_has_archived_date(self): decision = Decision(description="Decision test data") self.model_has_attribute(decision, "archived_date")
def test_decision_has_feedbackcount(self): decision = Decision(description="Decision test data") self.model_has_attribute(decision, "feedbackcount")