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
--- 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"""
--- 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:
--- 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:
--- 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)