web/views/basecontrollers.py
changeset 5223 6abd6e3599f4
parent 5201 2b4267157f85
child 5244 5467674ad101
equal deleted inserted replaced
5216:4f4369e63f5e 5223:6abd6e3599f4
     8 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     8 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     9 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     9 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
    10 """
    10 """
    11 __docformat__ = "restructuredtext en"
    11 __docformat__ = "restructuredtext en"
    12 
    12 
    13 from smtplib import SMTP
       
    14 
       
    15 import simplejson
    13 import simplejson
    16 
    14 
    17 from logilab.common.decorators import cached
    15 from logilab.common.decorators import cached
    18 from logilab.common.date import strptime
    16 from logilab.common.date import strptime
    19 
    17 
    20 from cubicweb import (NoSelectableObject, ValidationError, ObjectNotFound,
    18 from cubicweb import (NoSelectableObject, ObjectNotFound, ValidationError,
    21                       typed_eid)
    19                       AuthenticationError, typed_eid)
    22 from cubicweb.utils import CubicWebJsonEncoder
    20 from cubicweb.utils import CubicWebJsonEncoder
    23 from cubicweb.selectors import authenticated_user, match_form_params
    21 from cubicweb.selectors import authenticated_user, match_form_params
    24 from cubicweb.mail import format_mail
    22 from cubicweb.mail import format_mail
    25 from cubicweb.web import ExplicitLogin, Redirect, RemoteCallFailed, DirectResponse, json_dumps
    23 from cubicweb.web import Redirect, RemoteCallFailed, DirectResponse, json_dumps
    26 from cubicweb.web.controller import Controller
    24 from cubicweb.web.controller import Controller
    27 from cubicweb.web.views import vid_from_rset
    25 from cubicweb.web.views import vid_from_rset, formrenderers
    28 from cubicweb.web.views.formrenderers import FormRenderer
       
    29 
    26 
    30 try:
    27 try:
    31     from cubicweb.web.facet import (FilterRQLBuilder, get_facet,
    28     from cubicweb.web.facet import (FilterRQLBuilder, get_facet,
    32                                     prepare_facets_rqlst)
    29                                     prepare_facets_rqlst)
    33     HAS_SEARCH_RESTRICTION = True
    30     HAS_SEARCH_RESTRICTION = True
    57 def check_pageid(func):
    54 def check_pageid(func):
    58     """decorator which checks the given pageid is found in the
    55     """decorator which checks the given pageid is found in the
    59     user's session data
    56     user's session data
    60     """
    57     """
    61     def wrapper(self, *args, **kwargs):
    58     def wrapper(self, *args, **kwargs):
    62         data = self._cw.get_session_data(self._cw.pageid)
    59         data = self._cw.session.data.get(self._cw.pageid)
    63         if data is None:
    60         if data is None:
    64             raise RemoteCallFailed(self._cw._('pageid-not-found'))
    61             raise RemoteCallFailed(self._cw._('pageid-not-found'))
    65         return func(self, *args, **kwargs)
    62         return func(self, *args, **kwargs)
    66     return wrapper
    63     return wrapper
    67 
    64 
    71 
    68 
    72     def publish(self, rset=None):
    69     def publish(self, rset=None):
    73         """log in the instance"""
    70         """log in the instance"""
    74         if self._cw.vreg.config['auth-mode'] == 'http':
    71         if self._cw.vreg.config['auth-mode'] == 'http':
    75             # HTTP authentication
    72             # HTTP authentication
    76             raise ExplicitLogin()
    73             raise AuthenticationError()
    77         else:
    74         else:
    78             # Cookie authentication
    75             # Cookie authentication
    79             return self.appli.need_login_content(self._cw)
    76             return self.appli.need_login_content(self._cw)
    80 
    77 
    81 
    78 
   117 
   114 
   118     def _select_view_and_rset(self, rset):
   115     def _select_view_and_rset(self, rset):
   119         req = self._cw
   116         req = self._cw
   120         if rset is None and not hasattr(req, '_rql_processed'):
   117         if rset is None and not hasattr(req, '_rql_processed'):
   121             req._rql_processed = True
   118             req._rql_processed = True
   122             rset = self.process_rql(req.form.get('rql'))
   119             if req.cnx is None:
       
   120                 rset = None
       
   121             else:
       
   122                 rset = self.process_rql(req.form.get('rql'))
   123         if rset and rset.rowcount == 1 and '__method' in req.form:
   123         if rset and rset.rowcount == 1 and '__method' in req.form:
   124             entity = rset.get_entity(0, 0)
   124             entity = rset.get_entity(0, 0)
   125             try:
   125             try:
   126                 method = getattr(entity, req.form.pop('__method'))
   126                 method = getattr(entity, req.form.pop('__method'))
   127                 method()
   127                 method()
   185 
   185 
   186 def _validation_error(req, ex):
   186 def _validation_error(req, ex):
   187     req.cnx.rollback()
   187     req.cnx.rollback()
   188     # XXX necessary to remove existant validation error?
   188     # XXX necessary to remove existant validation error?
   189     # imo (syt), it's not necessary
   189     # imo (syt), it's not necessary
   190     req.get_session_data(req.form.get('__errorurl'), pop=True)
   190     req.session.data.pop(req.form.get('__errorurl'), None)
   191     foreid = ex.entity
   191     foreid = ex.entity
   192     eidmap = req.data.get('eidmap', {})
   192     eidmap = req.data.get('eidmap', {})
   193     for var, eid in eidmap.items():
   193     for var, eid in eidmap.items():
   194         if foreid == eid:
   194         if foreid == eid:
   195             foreid = var
   195             foreid = var
   378         entity.eid = varname
   378         entity.eid = varname
   379         entity['pkey'] = propkey
   379         entity['pkey'] = propkey
   380         form = self._cw.vreg['forms'].select('edition', self._cw, entity=entity)
   380         form = self._cw.vreg['forms'].select('edition', self._cw, entity=entity)
   381         form.build_context()
   381         form.build_context()
   382         vfield = form.field_by_name('value')
   382         vfield = form.field_by_name('value')
   383         renderer = FormRenderer(self._cw)
   383         renderer = formrenderers.FormRenderer(self._cw)
   384         return vfield.render(form, renderer, tabindex=tabindex) \
   384         return vfield.render(form, renderer, tabindex=tabindex) \
   385                + renderer.render_help(form, vfield)
   385                + renderer.render_help(form, vfield)
   386 
   386 
   387     @xhtmlize
   387     @xhtmlize
   388     def js_component(self, compid, rql, registry='components', extraargs=None):
   388     def js_component(self, compid, rql, registry='components', extraargs=None):
   472         return self._cw.external_resource(resource)
   472         return self._cw.external_resource(resource)
   473 
   473 
   474     @check_pageid
   474     @check_pageid
   475     @jsonize
   475     @jsonize
   476     def js_user_callback(self, cbname):
   476     def js_user_callback(self, cbname):
   477         page_data = self._cw.get_session_data(self._cw.pageid, {})
   477         page_data = self._cw.session.data.get(self._cw.pageid, {})
   478         try:
   478         try:
   479             cb = page_data[cbname]
   479             cb = page_data[cbname]
   480         except KeyError:
   480         except KeyError:
   481             return None
   481             return None
   482         return cb(self._cw)
   482         return cb(self._cw)
   501 
   501 
   502     def js_unregister_user_callback(self, cbname):
   502     def js_unregister_user_callback(self, cbname):
   503         self._cw.unregister_callback(self._cw.pageid, cbname)
   503         self._cw.unregister_callback(self._cw.pageid, cbname)
   504 
   504 
   505     def js_unload_page_data(self):
   505     def js_unload_page_data(self):
   506         self._cw.del_session_data(self._cw.pageid)
   506         self._cw.session.data.pop(self._cw.pageid, None)
   507 
   507 
   508     def js_cancel_edition(self, errorurl):
   508     def js_cancel_edition(self, errorurl):
   509         """cancelling edition from javascript
   509         """cancelling edition from javascript
   510 
   510 
   511         We need to clear associated req's data :
   511         We need to clear associated req's data :
   546 
   546 
   547     # relations edition stuff ##################################################
   547     # relations edition stuff ##################################################
   548 
   548 
   549     def _add_pending(self, eidfrom, rel, eidto, kind):
   549     def _add_pending(self, eidfrom, rel, eidto, kind):
   550         key = 'pending_%s' % kind
   550         key = 'pending_%s' % kind
   551         pendings = self._cw.get_session_data(key, set())
   551         pendings = self._cw.session.data.setdefault(key, set())
   552         pendings.add( (typed_eid(eidfrom), rel, typed_eid(eidto)) )
   552         pendings.add( (typed_eid(eidfrom), rel, typed_eid(eidto)) )
   553         self._cw.set_session_data(key, pendings)
       
   554 
   553 
   555     def _remove_pending(self, eidfrom, rel, eidto, kind):
   554     def _remove_pending(self, eidfrom, rel, eidto, kind):
   556         key = 'pending_%s' % kind
   555         key = 'pending_%s' % kind
   557         pendings = self._cw.get_session_data(key)
   556         pendings = self._cw.session.data[key]
   558         pendings.remove( (typed_eid(eidfrom), rel, typed_eid(eidto)) )
   557         pendings.remove( (typed_eid(eidfrom), rel, typed_eid(eidto)) )
   559         self._cw.set_session_data(key, pendings)
       
   560 
   558 
   561     def js_remove_pending_insert(self, (eidfrom, rel, eidto)):
   559     def js_remove_pending_insert(self, (eidfrom, rel, eidto)):
   562         self._remove_pending(eidfrom, rel, eidto, 'insert')
   560         self._remove_pending(eidfrom, rel, eidto, 'insert')
   563 
   561 
   564     def js_add_pending_inserts(self, tripletlist):
   562     def js_add_pending_inserts(self, tripletlist):
   611         body = self._cw.form['mailbody']
   609         body = self._cw.form['mailbody']
   612         subject = self._cw.form['subject']
   610         subject = self._cw.form['subject']
   613         for recipient in self.recipients():
   611         for recipient in self.recipients():
   614             text = body % recipient.as_email_context()
   612             text = body % recipient.as_email_context()
   615             self.sendmail(recipient.get_email(), subject, text)
   613             self.sendmail(recipient.get_email(), subject, text)
   616         # breadcrumbs = self._cw.get_session_data('breadcrumbs', None)
   614         #breadcrumbs = self._cw.session.data.get('breadcrumbs', None)
   617         url = self._cw.build_url(__message=self._cw._('emails successfully sent'))
   615         url = self._cw.build_url(__message=self._cw._('emails successfully sent'))
   618         raise Redirect(url)
   616         raise Redirect(url)
   619 
   617 
   620 
   618 
   621 class MailBugReportController(SendMailController):
   619 class MailBugReportController(SendMailController):
   642         else:
   640         else:
   643             self.redirect()
   641             self.redirect()
   644 
   642 
   645     def redirect(self):
   643     def redirect(self):
   646         req = self._cw
   644         req = self._cw
   647         breadcrumbs = req.get_session_data('breadcrumbs', None)
   645         breadcrumbs = req.session.data.get('breadcrumbs', None)
   648         if breadcrumbs is not None and len(breadcrumbs) > 1:
   646         if breadcrumbs is not None and len(breadcrumbs) > 1:
   649             url = req.rebuild_url(breadcrumbs[-2],
   647             url = req.rebuild_url(breadcrumbs[-2],
   650                                   __message=req._('transaction undoed'))
   648                                   __message=req._('transaction undoed'))
   651         else:
   649         else:
   652             url = req.build_url(__message=req._('transaction undoed'))
   650             url = req.build_url(__message=req._('transaction undoed'))