def _validate_subscription(self, **kw): """ Validate add/edit subscription for authorized and anonymous users """ if (kw['notif_type'] not in self.available_notif_types(kw['location']) and not (kw['notif_type'] == 'administrative' and self.checkPermissionPublishObjects())): raise i18n_exception(ValueError, 'Subscribing to ${notif_type} ' 'notifications in "${location}" not allowed', location=kw['location'] or self.getSite().title, notif_type=kw['notif_type']) try: obj = self.getSite().restrictedTraverse(kw['location']) except: raise i18n_exception(ValueError, 'This path is invalid or protected') try: subscription_container = ISubscriptionContainer(obj) except: raise i18n_exception(ValueError, 'Cannot subscribe to this folder') if kw.get('anonymous', False): #Check if subscription exists for this anonymous subscriber if not is_valid_email(kw.get('email', '')): raise i18n_exception(ValueError, 'Your e-mail address does not appear to be valid.') for id, subscription in subscription_container.list_with_keys(): #Normal subscriptions don't have e-mail if isinstance(subscription, AnonymousSubscription): if (subscription.email == kw['email'] and subscription.notif_type == kw['notif_type'] and subscription.lang == kw['lang']): raise i18n_exception(ValueError, 'Subscription already exists')
def walk_subscriptions(obj, cutoff_level=None): """ Get subscriptions on `obj` and all of its children. Returns a generator that yields tuples in the form `(obj, n, subscription)`. If `cutoff_level` is set to an integer x, than at most x levels will be walked, first included. """ if cutoff_level == 0: return elif cutoff_level is not None: cutoff_level -= 1 try: sc = ISubscriptionContainer(obj) except TypeError: # we reached an object that does not support subscription return for n, subscription in sc.list_with_keys(): yield (obj, n, subscription) for child_obj in obj.objectValues(): for item in walk_subscriptions(child_obj, cutoff_level): yield item
def change_user_roles(event): """Update subscriptions when a user's roles were updated: If he now gets the Administrator role, he should be subscribed to administrative notifications. If he loses the role, his subscription should be revoked""" notif_tool = event.context.getNotificationTool() portal = event.context.getSite() if 'Administrator' in event.assigned: if not utils.match_account_subscription(ISubscriptionContainer(event.context), event.user_id, 'administrative', 'en'): notif_tool.add_account_subscription(event.user_id, path_in_site(event.context), 'administrative', 'en', []) if 'Administrator' in event.unassigned: if utils.match_account_subscription(ISubscriptionContainer(event.context), event.user_id, 'administrative', 'en'): notif_tool.remove_account_subscription(event.user_id, path_in_site(event.context), 'administrative', 'en')
def remove_account_subscription(self, user_id, location, notif_type, lang, content_types=None): obj = self.getSite().restrictedTraverse(location) subscription_container = ISubscriptionContainer(obj) n = utils.match_account_subscription(subscription_container, user_id, notif_type, lang, content_types) if n is None: raise ValueError('Subscription not found') subscription_container.remove(n)
def confirm(self, REQUEST=None, key=''): """ Verify confirmation key and redirect to success page """ if key: subscriptions = ISubscriptionContainer(self.getSite()) # Check if the key is in the temporary list for subscription in self.pending_anonymous_subscriptions: if str(key) == subscription.key: # Verify if the email is not already subscribed for existing_subscription in subscriptions: if subscription.email == existing_subscription.email: return REQUEST.RESPONSE.redirect( self.absolute_url() + '/my_subscriptions_html') container = ISubscriptionContainer( self.getSite().restrictedTraverse( subscription.location)) container.add(subscription) # Add to subscribed list # Remove from temporary list self.pending_anonymous_subscriptions.remove(subscription) if REQUEST is not None: self.setSessionInfoTrans( 'You succesfully subscribed to ${notif_type} ' 'notifications for any changes in "${location}".', notif_type=subscription.notif_type, location=subscription.location or self.getSite().title) break else: if REQUEST is not None: self.setSessionErrorsTrans("Confirmation key not found") else: raise ValueError("Confirmation key not found") else: if REQUEST is not None: self.setSessionErrorsTrans("Confirmation key is invalid") else: raise ValueError("Confirmation key is invalid") if REQUEST is not None: return REQUEST.RESPONSE.redirect(self.absolute_url() + '/my_subscriptions_html')
def fetch_subscriptions(obj, inherit): """ Get subscriptions on `obj`. If `inherit` is True then recurse into parents, up to site level. """ try: sc = ISubscriptionContainer(obj) for subscription in sc: yield subscription except TypeError: pass if inherit: if hasattr(obj, 'aq_parent'): for subscription in fetch_subscriptions(obj.aq_parent, inherit=True): yield subscription
def add_account_subscription(self, user_id, location, notif_type, lang, content_types=[]): """ Subscribe the user `user_id` """ self._validate_subscription(user_id=user_id, location=location, notif_type=notif_type, lang=lang, content_types=content_types) try: self.remove_account_subscription(user_id, location, notif_type, lang) except ValueError: pass obj = self.getSite().restrictedTraverse(location) subscription_container = ISubscriptionContainer(obj) subscription = AccountSubscription(user_id, notif_type, lang, content_types) subscription_container.add(subscription)
def fix_subscriptions(obj): try: sc = ISubscriptionContainer(obj) except TypeError: pass # object does not support subscription else: assert isinstance(sc, SubscriptionContainer) for sub_id, sub in sc.subscriptions.items(): if not isinstance(sub, AccountSubscription): continue user_id = sub.user_id if user_id != user_id.strip(): self.log.info('fixing user_id %r', user_id) sub.user_id = user_id.strip() # AccountSubscription is not Persistent, so we must # invalidate its container. sc.subscriptions._p_changed = True for child_obj in obj.objectValues(): fix_subscriptions(child_obj)
def remove_anonymous_subscription(self, email, location, notif_type, lang): try: obj = self.getSite().restrictedTraverse(location) except: raise i18n_exception(ValueError, 'Invalid location') try: subscription_container = ISubscriptionContainer(obj) except: raise i18n_exception(ValueError, 'Invalid container') anonymous_subscriptions = [ (n, s) for n, s in subscription_container.list_with_keys() if hasattr(s, 'email') ] subscriptions = filter( lambda s: (s[1].email == email and s[1].location == location and s[ 1].notif_type == notif_type), anonymous_subscriptions) if len(subscriptions) == 1: subscription_container.remove(subscriptions[0][0]) else: raise i18n_exception(ValueError, 'Subscription not found')
def _update(self, portal): notif_tool = portal.getNotificationTool() auth_tool = portal.getAuthenticationTool() admins = auth_tool.search_users('', role='Administrator', rkey=0, skey='name', all_users=True, location='_all_') self.log.debug('Started update in %s' % portal.getId()) for admin in admins: for role in admin.roles: if 'Administrator' in role[0]: user_id = admin.user_id own_site_location = path_in_site(role[1]) this_site_location = relative_object_path(role[1], portal) if own_site_location != this_site_location: self.log.debug( 'Location %s is probably in a subportal' % own_site_location) continue obj = portal.restrictedTraverse(this_site_location) if match_account_subscription(ISubscriptionContainer(obj), user_id, 'administrative', 'en'): self.log.debug( 'Subscription for user %s already present ' 'in location %s' % (user_id, this_site_location or '/')) else: notif_tool.add_account_subscription( user_id, this_site_location, 'administrative', 'en', []) self.log.debug( 'Subscription added for user %s in location %s' % (user_id, this_site_location or '/')) return True
def admin_remove_account_subscription(self, REQUEST, location, sub_id): """ """ obj = self.getSite().restrictedTraverse(location) subscription_container = ISubscriptionContainer(obj) subscription_container.remove(sub_id) REQUEST.RESPONSE.redirect(self.absolute_url() + '/admin_html')