def test_post_notification(self): """Post a comment that sends a notification. """ testing.enable_subscription(self.root.forum) testing.set_member_email('dummy', '*****@*****.**') subscriptions = ISubscriptionManager(self.root.forum.topic) subscriptions.subscribe('*****@*****.**') browser = self.layer.get_browser(topic_settings) browser.login('dummy', 'dummy') self.assertEqual(browser.open('/root/forum'), 200) self.assertEqual(browser.get_link('Test Topic').click(), 200) # Post a comment. We don't use a title, so the topic one is used form = browser.get_form('post') form.get_control("title").value = "I am good" form.get_control("text").value = "very, very good" # We are already subscribed, so no option to subscribe self.assertRaises(AssertionError, form.get_control, 'subscribe') self.assertEqual(form.get_control("action.post").click(), 200) self.assertEqual(browser.inspect.feedback, ["Comment added."]) # A mail should have been sent to dummy message = self.root.service_mailhost.read_last_message() self.assertNotEqual(message, None) self.assertEqual(message.content_type, 'text/plain') self.assertEqual(message.charset, 'utf-8') self.assertEqual(message.mto, ['*****@*****.**']) self.assertEqual(message.mfrom, '*****@*****.**') self.assertEqual(message.subject, 'New comment in "Test Topic"')
def test_subscription_failures(self): """Test cases where you can't request subscription to a content. """ service = getUtility(ISubscriptionService) service.enable_subscriptions() # first use something not subscribable at all self.assertRaises( errors.NotSubscribableError, service.request_subscription, self.root.file, "*****@*****.**") # even if all parameters are correct, content has to have its # subscribability set self.assertRaises( errors.NotSubscribableError, service.request_subscription, self.root.document, "*****@*****.**") # Set subscribability, invalid emailaddress though manager = ISubscriptionManager(self.root.document) manager.subscribability = SUBSCRIBABLE self.assertRaises( errors.InvalidEmailaddressError, service.request_subscription, self.root.document, "lekker zalm") # emailaddress already subscribed manager.subscribe("*****@*****.**") self.assertRaises( errors.AlreadySubscribedError, service.request_subscription, self.root.document, "*****@*****.**")
def is_subscribable(self): if self.data.subscribability == NOT_SUBSCRIBABLE: return False if self.data.subscribability == SUBSCRIBABLE: return True parent = ISubscriptionManager(aq_parent(self.context)) return parent.is_subscribable()
def request_subscription(self, content, email): # Send out request for subscription # NOTE: no doc string, so, not *publishable* TTW # if not self.are_subscriptions_enabled(): raise errors.NotSubscribableError() manager = ISubscriptionManager(content, None) # see if content is subscribable if manager is None or not manager.is_subscribable(): raise errors.NotSubscribableError() # validate address if not isValidMailAddress(email): raise errors.InvalidEmailaddressError() # check if not yet subscribed subscription = manager.get_subscription(email) if subscription is not None: # send an email informing about this situation self._send_confirmation( content, subscription.content, email, 'already_subscribed_template', 'confirm_subscription') raise errors.AlreadySubscribedError() # send confirmation email to emailaddress self._send_confirmation( content, content, email, 'subscription_confirmation_template', 'confirm_subscription')
def are_subscriptions_enabled(self, context=None): if not self._enabled: return False if context is not None: manager = ISubscriptionManager(context, None) if manager is None: return False return manager.is_subscribable() return True
def update(self): settings = ISubscriptionManager(self.context) self.is_enabled = settings.is_subscribable() self.all_subscribers = len(settings.subscriptions) self.locally_subscribers = len(settings.locally_subscribed_emails) self.above_subscribers = self.all_subscribers - self.locally_subscribers if self.is_enabled: url = absoluteURL(self.context, self.request) self.subscribe_url = url + "/subscriptions.html"
def unsubscribe(self, content_id, email, token): # Check and confirm cancellation # NOTE: no doc string, so, not *publishable* TTW # content = get_subscribable_content(content_id) manager = ISubscriptionManager(content, None) if manager is None: raise errors.CancellationError() email = urllib.unquote(email) if not self._validate_token( content_id, email, 'confirm_cancellation', token): raise errors.CancellationError() manager.unsubscribe(email)
def send_notification( self, content, template_id='publication_event_template'): if not self.are_subscriptions_enabled(): return template = self._get_template(content, template_id) data = self._get_default_data(content) manager = ISubscriptionManager(content) for subscription in manager.get_subscriptions(): content_url = subscription.content.absolute_url() data['subscribed_content'] = subscription.content data['service_url'] = content_url + '/subscriptions.html' data['to'] = subscription.email self._send_email(template, data)
def test_post_and_subscribe(self): """Post and subscribe to a topic. """ testing.enable_subscription(self.root.forum) testing.set_member_email('dummy', '*****@*****.**') subscriptions = ISubscriptionManager(self.root.forum.topic) self.assertEqual(subscriptions.is_subscribed('*****@*****.**'), False) self.assertEqual(len(self.root.service_mailhost.messages), 0) browser = self.layer.get_browser(topic_settings) browser.login('dummy', 'dummy') self.assertEqual(browser.open('/root/forum'), 200) self.assertEqual(browser.get_link('Test Topic').click(), 200) # Post a comment. We don't use a title, so the topic one is used form = browser.get_form('post') form.get_control("text").value = "How are you ?" self.assertEqual(form.get_control('subscribe').checked, True) self.assertEqual(form.get_control("action.post").click(), 200) # The comment is added, and the request for subscription is triggred. self.assertEqual(browser.inspect.feedback, [ "Comment added.", "A confirmation mail have been sent for your subscription." ]) subscription_request = self.root.service_mailhost.read_last_message() self.assertNotEqual(subscription_request, None) self.assertEqual(subscription_request.mto, ['*****@*****.**']) self.assertEqual(subscription_request.mfrom, '*****@*****.**') self.assertEqual(subscription_request.subject, 'Subscription confirmation to "Test Topic"') self.assertEqual(len(subscription_request.urls), 2) # the confirmation link is the last url in the mail confirmation_url = subscription_request.urls[-1] self.assertEqual(browser.open(confirmation_url), 200) self.assertEqual( browser.location, '/root/forum/topic/subscriptions.html/@@confirm_subscription') self.assertEqual( browser.html.xpath('//p[@class="subscription-result"]/text()'), [ 'You have been successfully subscribed. ' 'You will now receive email notifications.' ]) self.assertEqual(subscriptions.is_subscribed('*****@*****.**'), True)
def test_post_and_subscribe(self): """Post and subscribe to a topic. """ testing.enable_subscription(self.root.forum) testing.set_member_email('dummy', '*****@*****.**') subscriptions = ISubscriptionManager(self.root.forum.topic) self.assertEqual( subscriptions.is_subscribed('*****@*****.**'), False) self.assertEqual(len(self.root.service_mailhost.messages), 0) browser = self.layer.get_browser(topic_settings) browser.login('dummy', 'dummy') self.assertEqual(browser.open('/root/forum'), 200) self.assertEqual(browser.get_link('Test Topic').click(), 200) # Post a comment. We don't use a title, so the topic one is used form = browser.get_form('post') form.get_control("text").value = "How are you ?" self.assertEqual(form.get_control('subscribe').checked, True) self.assertEqual(form.get_control("action.post").click(), 200) # The comment is added, and the request for subscription is triggred. self.assertEqual( browser.inspect.feedback, ["Comment added.", "A confirmation mail have been sent for your subscription."]) subscription_request = self.root.service_mailhost.read_last_message() self.assertNotEqual(subscription_request, None) self.assertEqual(subscription_request.mto, ['*****@*****.**']) self.assertEqual(subscription_request.mfrom, '*****@*****.**') self.assertEqual( subscription_request.subject, 'Subscription confirmation to "Test Topic"') self.assertEqual(len(subscription_request.urls), 2) # the confirmation link is the last url in the mail confirmation_url = subscription_request.urls[-1] self.assertEqual(browser.open(confirmation_url), 200) self.assertEqual( browser.location, '/root/forum/topic/subscriptions.html/@@confirm_subscription') self.assertEqual( browser.html.xpath('//p[@class="subscription-result"]/text()'), ['You have been successfully subscribed. ' 'You will now receive email notifications.']) self.assertEqual(subscriptions.is_subscribed('*****@*****.**'), True)
def _get_subscribable_parents(self, subscribables=None, last_explicit=0): # The purpose of last_explicit is to prevent to collect # subscribables where the non-subscribabiliy is acquired. if subscribables is None: subscribables = [] if self.data.subscribability == NOT_SUBSCRIBABLE: # Empty list from the point without explicit # subscribability onwards. del subscribables[last_explicit:] return subscribables subscribables.append(self) if self.data.subscribability == SUBSCRIBABLE: # Keep a last_explicit for the object with explicit # subscribability set. last_explicit = len(subscribables) parent = ISubscriptionManager(aq_parent(self.context)) return parent._get_subscribable_parents(subscribables, last_explicit)
def test_subscribe(self): """Test request_subscription sends a mail, and we can get subscribed with it. """ browser = self.layer.get_browser() manager = ISubscriptionManager(self.root.document) manager.subscribability = SUBSCRIBABLE self.assertEqual(manager.is_subscribed('*****@*****.**'), False) self.assertEqual(self.root.service_mailhost.messages, []) service = getUtility(ISubscriptionService) service.enable_subscriptions() service.request_subscription(self.root.document, "*****@*****.**") message = self.root.service_mailhost.read_last_message() self.assertNotEqual(message, None) self.assertEqual(message.content_type, 'text/plain') self.assertEqual(message.charset, 'utf-8') self.assertEqual(message.mto, ['*****@*****.**']) self.assertEqual( message.mfrom, 'Subscription Service <*****@*****.**>') self.assertEqual( message.subject, 'Subscription confirmation to "document"') self.assertEqual(len(message.urls), 2) # XXX it is a bit hardcoded on the template, the confirmation # is the second like in the mail. confirmation_url = message.urls[-1] self.assertEqual(browser.open(confirmation_url), 200) self.assertEqual( browser.location, '/root/document/subscriptions.html/@@confirm_subscription') self.assertEqual( browser.html.xpath('//p[@class="subscription-result"]/text()'), ['You have been successfully subscribed. ' 'You will now receive email notifications.']) # Torvald is now subscribed self.assertEqual(manager.is_subscribed('*****@*****.**'), True)
def test_publication_notification(self): """We verify that if a document is publish, and the notification are enabled, a mail is sent to the susbcribed people. """ service = getUtility(ISubscriptionService) service.enable_subscriptions() service._from = '*****@*****.**' manager = ISubscriptionManager(self.root) manager.subscribability = SUBSCRIBABLE manager.subscribe('*****@*****.**') self.assertEqual(len(self.root.service_mailhost.messages), 0) IPublicationWorkflow(self.root.document).publish() # We have two notification, one for the document, one for the ghost self.assertEqual(len(self.root.service_mailhost.messages), 2) message = self.root.service_mailhost.messages[0] self.assertEqual(message.content_type, 'text/plain') self.assertEqual(message.charset, 'utf-8') self.assertEqual(message.mto, ['*****@*****.**']) self.assertEqual(message.mfrom, '*****@*****.**') self.assertEqual(message.subject, 'Change notification for "Document"') message = self.root.service_mailhost.messages[1] self.assertEqual(message.content_type, 'text/plain') self.assertEqual(message.charset, 'utf-8') self.assertEqual(message.mto, ['*****@*****.**']) self.assertEqual(message.mfrom, '*****@*****.**') self.assertEqual(message.subject, 'Change notification for "ghost"') self.root.service_mailhost.reset() self.assertEqual(len(self.root.service_mailhost.messages), 0) # We now disable the subscription. And publish a new version. service.disable_subscriptions() self.root.document.create_copy() IPublicationWorkflow(self.root.document).publish() # No notification have been sent self.assertEqual(len(self.root.service_mailhost.messages), 0)
def request_cancellation(self, content, email): # Send out request for cancellation of the subscription # NOTE: no doc string, so, not *publishable* TTW # manager = ISubscriptionManager(content, None) if manager is None: raise errors.NotSubscribableError() # validate address if not isValidMailAddress(email): raise errors.InvalidEmailaddressError() # check if indeed subscribed subscription = manager.get_subscription(email) if subscription is None: # send an email informing about this situation self._send_information(content, email, 'not_subscribed_template') raise errors.NotSubscribedError() self._send_confirmation( content, subscription.content, email, 'cancellation_confirmation_template', 'confirm_cancellation')
def test_service(self): """Test service settings. """ service = getUtility(ISubscriptionService) self.assertTrue(verifyObject(ISubscriptionService, service)) self.assertEqual(self.root.service_subscriptions, service) # By default subscription are off, but you can change it self.assertEqual(service.are_subscriptions_enabled(), False) service.enable_subscriptions() self.assertEqual(service.are_subscriptions_enabled(), True) # You can now if at one given context they are enabled self.assertEqual(service.are_subscriptions_enabled(self.root), False) manager = ISubscriptionManager(self.root) manager.subscribability = SUBSCRIBABLE self.assertEqual(service.are_subscriptions_enabled(self.root), True) # And we disable them globaly now service.disable_subscriptions() self.assertEqual(service.are_subscriptions_enabled(), False) self.assertEqual(service.are_subscriptions_enabled(self.root), False)
def update(self): super(ContainerViewBase, self).update() user = getSecurityManager().getUser() self.captcha_posting = self.context.unauthenticated_posting_allowed() self.anonymous_posting = self.context.anonymous_posting_allowed() self.is_logged_in = user.has_role(MINIMAL_ADD_ROLE) self.need_captcha = self.captcha_posting and not self.is_logged_in self.need_anonymous_option = (self.anonymous_posting and not self.need_captcha) self.can_post = self.captcha_posting or self.is_logged_in self.have_subscriptions = False service = queryUtility(ISubscriptionService) if service is not None: self.have_subscriptions = service.are_subscriptions_enabled( self.context) self.inline_subscription = False if self.have_subscriptions: email = self.get_user_email() if email: if not ISubscriptionManager(self.context).is_subscribed(email): self.inline_subscription = True self.messages = []
def test_is_subscribed(self): """is_subscribed returns True if you are subscribed on of the parents. """ manager_root = ISubscriptionManager(self.root) manager_root.subscribability = SUBSCRIBABLE manager_root.subscribe("*****@*****.**") self.assertEqual(manager_root.is_subscribed("*****@*****.**"), True) self.assertEqual(manager_root.is_subscribed("*****@*****.**"), False) manager = ISubscriptionManager(self.root.folder) self.assertEqual(manager.is_subscribed("*****@*****.**"), True) self.assertEqual(manager.is_subscribed("*****@*****.**"), False) # If you turn off subscription off at the folder level, you # are no longer subscribed manager.subscribability = NOT_SUBSCRIBABLE self.assertEqual(manager.is_subscribed("*****@*****.**"), False) # That didn't changed anything on the parent self.assertEqual(manager_root.is_subscribed("*****@*****.**"), True)
def tests_get_subscription(self): """Test retrieving subscriptions information. """ manager_root = ISubscriptionManager(self.root) manager_root.subscribability = SUBSCRIBABLE manager_root.subscribe("*****@*****.**") manager_folder = ISubscriptionManager(self.root.folder) manager_folder.subscribe("*****@*****.**") manager = ISubscriptionManager(self.root.folder.index) manager.subscribability = SUBSCRIBABLE manager.subscribe("*****@*****.**") self.assertEqual(manager.get_subscription("*****@*****.**"), None) subscription = manager.get_subscription("*****@*****.**") self.assertTrue(verifyObject(ISubscription, subscription)) self.assertEqual(subscription.email, "*****@*****.**") self.assertEqual(subscription.content, self.root) self.assertEqual(len(manager.get_subscriptions()), 3) manager_root.subscribability = NOT_SUBSCRIBABLE self.assertEqual(manager.get_subscription("*****@*****.**"), None) subscription = manager.get_subscription("*****@*****.**") self.assertTrue(verifyObject(ISubscription, subscription)) self.assertEqual(subscription.email, "*****@*****.**") self.assertEqual(subscription.content, self.root.folder.index) self.assertEqual(len(manager.get_subscriptions()), 1)
def test_subscribe_unsubscribe(self): manager = ISubscriptionManager(self.root.document) manager.subscribability = SUBSCRIBABLE self.assertEqual(manager.locally_subscribed_emails, set([])) self.assertEqual(manager.is_subscribed("*****@*****.**"), False) # we can subscribe some emails manager.subscribe("*****@*****.**") manager.subscribe("*****@*****.**") manager.subscribe("*****@*****.**") self.assertEqual(manager.locally_subscribed_emails, set(["*****@*****.**", "*****@*****.**"])) self.assertEqual(manager.is_subscribed("*****@*****.**"), True) # and unscribe others manager.unsubscribe("*****@*****.**") manager.unsubscribe("*****@*****.**") self.assertEqual(manager.locally_subscribed_emails, set(["*****@*****.**"])) self.assertEqual(manager.is_subscribed("*****@*****.**"), False)
def test_subscribability(self): """Test the subscribability setting. """ manager = ISubscriptionManager(self.root.document) self.assertEqual(manager.is_subscribable(), False) self.assertEqual(manager.subscribability, ACQUIRE_SUBSCRIBABILITY) # You can enable or disable that setting manager.subscribability = SUBSCRIBABLE self.assertEqual(manager.is_subscribable(), True) self.assertEqual(manager.subscribability, SUBSCRIBABLE) manager.subscribability = NOT_SUBSCRIBABLE self.assertEqual(manager.is_subscribable(), False) self.assertEqual(manager.subscribability, NOT_SUBSCRIBABLE) # You can set the setting on the parent root manager_root = ISubscriptionManager(self.root) self.assertEqual(manager_root.is_subscribable(), False) self.assertEqual(manager_root.subscribability, NOT_SUBSCRIBABLE) # You can change the setting. Not to acquired. manager_root.subscribability = SUBSCRIBABLE self.assertEqual(manager_root.is_subscribable(), True) self.assertEqual(manager_root.subscribability, SUBSCRIBABLE) self.assertRaises(AssertionError, setattr, manager_root, "subscribability", ACQUIRE_SUBSCRIBABILITY) self.assertEqual(manager_root.is_subscribable(), True) self.assertEqual(manager_root.subscribability, SUBSCRIBABLE) # The setting was disabled on the document, it is still is. # However if we set it to acquired it will be enabled (since root is) self.assertEqual(manager.is_subscribable(), False) self.assertEqual(manager.subscribability, NOT_SUBSCRIBABLE) manager.subscribability = ACQUIRE_SUBSCRIBABILITY self.assertEqual(manager.is_subscribable(), True) self.assertEqual(manager.subscribability, ACQUIRE_SUBSCRIBABILITY)