# HG changeset patch # User Sylvain Thénault # Date 1252416614 -7200 # Node ID 757d3616223557793dd1575ea9ee20a4a6fc5c19 # Parent 1d09765ee7200ded62bf41be6d30b45b4152fe49 enhance notification mecanism: recipients may return user entities, which will be used to create a fake session so one can check security during notification if necessary diff -r 1d09765ee720 -r 757d36162235 common/mail.py --- a/common/mail.py Thu Sep 03 14:08:17 2009 +0200 +++ b/common/mail.py Tue Sep 08 15:30:14 2009 +0200 @@ -21,6 +21,7 @@ return 'XXX' from cubicweb.view import EntityView +from cubicweb.entity import Entity def header(ustring): return Header(ustring.encode('UTF-8'), 'UTF-8') @@ -176,28 +177,38 @@ else: refs = () msgid = None - userdata = self.req.user_data() - origlang = self.req.lang - for emailaddr, lang in recipients: - self.req.set_language(lang) + req = self.req + self.user_data = req.user_data() + origlang = req.lang + for something in recipients: + if isinstance(something, Entity): + # hi-jack self.req to get a session for the returned user + self.req = self.req.hijack_user(something) + emailaddr = something.get_email() + else: + emailaddr, lang = something + self.req.set_language(lang) # since the same view (eg self) may be called multiple time and we # need a fresh stream at each iteration, reset it explicitly self.w = None # XXX call render before subject to set .row/.col attributes on the # view - content = self.render(row=0, col=0, **kwargs) - subject = self.subject() - msg = format_mail(userdata, [emailaddr], content, subject, + try: + content = self.render(row=0, col=0, **kwargs) + subject = self.subject() + except SkipEmail: + continue + msg = format_mail(self.user_data, [emailaddr], content, subject, config=self.config, msgid=msgid, references=refs) yield [emailaddr], msg # restore language - self.req.set_language(origlang) + req.set_language(origlang) # recipients / email sending ############################################### def recipients(self): - """return a list of 2-uple (email, language) to who this email should be - sent + """return a list of either 2-uple (email, language) or user entity to + who this email should be sent """ finder = self.vreg['components'].select('recipients_finder', self.req, rset=self.rset, @@ -230,7 +241,7 @@ subject = self.req._(self.message) etype = entity.dc_type() eid = entity.eid - login = self.user_login() + login = self.user_data['login'] return self.req._('%(subject)s %(etype)s #%(eid)s (%(login)s)') % locals() def context(self, **kwargs): @@ -238,17 +249,12 @@ for key, val in kwargs.iteritems(): if val and isinstance(val, unicode) and val.strip(): kwargs[key] = self.req._(val) - kwargs.update({'user': self.user_login(), + kwargs.update({'user': self.user_data['login'], 'eid': entity.eid, 'etype': entity.dc_type(), 'url': entity.absolute_url(), 'title': entity.dc_long_title(),}) return kwargs - def user_login(self): - try: - # if req is actually a session (we are on the server side), and we - # have to prevent nested internal session - return self.req.actual_session().user.login - except AttributeError: - return self.req.user.login +class SkipEmail(Exception): + """raise this if you decide to skip an email during its generation""" diff -r 1d09765ee720 -r 757d36162235 dbapi.py --- a/dbapi.py Thu Sep 03 14:08:17 2009 +0200 +++ b/dbapi.py Tue Sep 08 15:30:14 2009 +0200 @@ -284,6 +284,12 @@ # server session compat layer ############################################# + def hijack_user(self, user): + """return a fake request/session using specified user""" + req = DBAPIRequest(self.vreg) + req.set_connection(self.cnx, user) + return req + @property def user(self): if self._user is None and self.cnx: diff -r 1d09765ee720 -r 757d36162235 server/session.py --- a/server/session.py Thu Sep 03 14:08:17 2009 +0200 +++ b/server/session.py Tue Sep 08 15:30:14 2009 +0200 @@ -78,6 +78,12 @@ def schema(self): return self.repo.schema + def hijack_user(self, user): + """return a fake request/session using specified user""" + session = Session(user, self.repo) + session._threaddata = self._threaddata + return session + def _change_relation(self, cb, fromeid, rtype, toeid): if self.is_super_session: cb(self, fromeid, rtype, toeid) @@ -115,6 +121,8 @@ self._change_relation(self.repo.glob_delete_relation, fromeid, rtype, toeid) + # relations cache handling ################################################# + def update_rel_cache_add(self, subject, rtype, object, symetric=False): self._update_entity_rel_cache_add(subject, rtype, 'subject', object) if symetric: diff -r 1d09765ee720 -r 757d36162235 sobjects/notification.py --- a/sobjects/notification.py Thu Sep 03 14:08:17 2009 +0200 +++ b/sobjects/notification.py Tue Sep 08 15:30:14 2009 +0200 @@ -190,6 +190,6 @@ def subject(self): entity = self.entity(self.row or 0, self.col or 0) return u'%s #%s (%s)' % (self.req.__('New %s' % entity.e_schema), - entity.eid, self.user_login()) + entity.eid, self.user_data['login']) NormalizedTextView = class_renamed('NormalizedTextView', ContentAddedView)