web/views/basecontrollers.py
changeset 11057 0b59724cb3f2
parent 11052 058bb3dc685f
child 11058 23eb30449fe5
--- a/web/views/basecontrollers.py	Mon Jan 04 18:40:30 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Set of base controllers, which are directly plugged into the application
-object to handle publication.
-"""
-
-__docformat__ = "restructuredtext en"
-from cubicweb import _
-
-from warnings import warn
-
-from six import text_type
-
-from logilab.common.deprecation import deprecated
-
-from cubicweb import (NoSelectableObject, ObjectNotFound, ValidationError,
-                      AuthenticationError, UndoTransactionException,
-                      Forbidden)
-from cubicweb.utils import json_dumps
-from cubicweb.predicates import (authenticated_user, anonymous_user,
-                                match_form_params)
-from cubicweb.web import Redirect, RemoteCallFailed
-from cubicweb.web.controller import Controller, append_url_params
-from cubicweb.web.views import vid_from_rset
-import cubicweb.transaction as tx
-
-@deprecated('[3.15] jsonize is deprecated, use AjaxFunction appobjects instead')
-def jsonize(func):
-    """decorator to sets correct content_type and calls `json_dumps` on
-    results
-    """
-    def wrapper(self, *args, **kwargs):
-        self._cw.set_content_type('application/json')
-        return json_dumps(func(self, *args, **kwargs))
-    wrapper.__name__ = func.__name__
-    return wrapper
-
-@deprecated('[3.15] xhtmlize is deprecated, use AjaxFunction appobjects instead')
-def xhtmlize(func):
-    """decorator to sets correct content_type and calls `xmlize` on results"""
-    def wrapper(self, *args, **kwargs):
-        self._cw.set_content_type(self._cw.html_content_type())
-        result = func(self, *args, **kwargs)
-        return ''.join((u'<div>', result.strip(),
-                        u'</div>'))
-    wrapper.__name__ = func.__name__
-    return wrapper
-
-@deprecated('[3.15] check_pageid is deprecated, use AjaxFunction appobjects instead')
-def check_pageid(func):
-    """decorator which checks the given pageid is found in the
-    user's session data
-    """
-    def wrapper(self, *args, **kwargs):
-        data = self._cw.session.data.get(self._cw.pageid)
-        if data is None:
-            raise RemoteCallFailed(self._cw._('pageid-not-found'))
-        return func(self, *args, **kwargs)
-    return wrapper
-
-
-class LoginController(Controller):
-    __regid__ = 'login'
-    __select__ = anonymous_user()
-
-    def publish(self, rset=None):
-        """log in the instance"""
-        if self._cw.vreg.config['auth-mode'] == 'http':
-            # HTTP authentication
-            raise AuthenticationError()
-        else:
-            # Cookie authentication
-            return self.appli.need_login_content(self._cw)
-
-class LoginControllerForAuthed(Controller):
-    __regid__ = 'login'
-    __select__ = ~anonymous_user()
-
-    def publish(self, rset=None):
-        """log in the instance"""
-        path = self._cw.form.get('postlogin_path', '')
-        # Redirect expects a URL, not a path. Also path may contain a query
-        # string, hence should not be given to _cw.build_url()
-        raise Redirect(self._cw.base_url() + path)
-
-
-class LogoutController(Controller):
-    __regid__ = 'logout'
-
-    def publish(self, rset=None):
-        """logout from the instance"""
-        return self.appli.session_handler.logout(self._cw, self.goto_url())
-
-    def goto_url(self):
-        # * in http auth mode, url will be ignored
-        # * in cookie mode redirecting to the index view is enough : either
-        #   anonymous connection is allowed and the page will be displayed or
-        #   we'll be redirected to the login form
-        msg = self._cw._('you have been logged out')
-        return self._cw.build_url('view', vid='loggedout')
-
-
-class ViewController(Controller):
-    """standard entry point :
-    - build result set
-    - select and call main template
-    """
-    __regid__ = 'view'
-    template = 'main-template'
-
-    def publish(self, rset=None):
-        """publish a request, returning an encoded string"""
-        view, rset = self._select_view_and_rset(rset)
-        view.set_http_cache_headers()
-        if self._cw.is_client_cache_valid():
-            return b''
-        template = self.appli.main_template_id(self._cw)
-        return self._cw.vreg['views'].main_template(self._cw, template,
-                                                    rset=rset, view=view)
-
-    def _select_view_and_rset(self, rset):
-        req = self._cw
-        if rset is None and not hasattr(req, '_rql_processed'):
-            req._rql_processed = True
-            if req.cnx:
-                rset = self.process_rql()
-            else:
-                rset = None
-        vid = req.form.get('vid') or vid_from_rset(req, rset, self._cw.vreg.schema)
-        try:
-            view = self._cw.vreg['views'].select(vid, req, rset=rset)
-        except ObjectNotFound:
-            self.warning("the view %s could not be found", vid)
-            req.set_message(req._("The view %s could not be found") % vid)
-            vid = vid_from_rset(req, rset, self._cw.vreg.schema)
-            view = self._cw.vreg['views'].select(vid, req, rset=rset)
-        except NoSelectableObject:
-            if rset:
-                req.set_message(req._("The view %s can not be applied to this query") % vid)
-            else:
-                req.set_message(req._("You have no access to this view or it can not "
-                                      "be used to display the current data."))
-            vid = req.form.get('fallbackvid') or vid_from_rset(req, rset, req.vreg.schema)
-            view = req.vreg['views'].select(vid, req, rset=rset)
-        return view, rset
-
-    def execute_linkto(self, eid=None):
-        """XXX __linkto parameter may cause security issue
-
-        defined here since custom application controller inheriting from this
-        one use this method?
-        """
-        req = self._cw
-        if not '__linkto' in req.form:
-            return
-        if eid is None:
-            eid = int(req.form['eid'])
-        for linkto in req.list_form_param('__linkto', pop=True):
-            rtype, eids, target = linkto.split(':')
-            assert target in ('subject', 'object')
-            eids = eids.split('_')
-            if target == 'subject':
-                rql = 'SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % rtype
-            else:
-                rql = 'SET Y %s X WHERE X eid %%(x)s, Y eid %%(y)s' % rtype
-            for teid in eids:
-                req.execute(rql, {'x': eid, 'y': int(teid)})
-
-
-def _validation_error(req, ex):
-    req.cnx.rollback()
-    ex.translate(req._) # translate messages using ui language
-    # XXX necessary to remove existant validation error?
-    # imo (syt), it's not necessary
-    req.session.data.pop(req.form.get('__errorurl'), None)
-    foreid = ex.entity
-    eidmap = req.data.get('eidmap', {})
-    for var, eid in eidmap.items():
-        if foreid == eid:
-            foreid = var
-            break
-    return (foreid, ex.errors)
-
-
-def _validate_form(req, vreg):
-    # XXX should use the `RemoteCallFailed` mechanism
-    try:
-        ctrl = vreg['controllers'].select('edit', req=req)
-    except NoSelectableObject:
-        return (False, {None: req._('not authorized')}, None)
-    try:
-        ctrl.publish(None)
-    except ValidationError as ex:
-        return (False, _validation_error(req, ex), ctrl._edited_entity)
-    except Redirect as ex:
-        try:
-            txuuid = req.cnx.commit() # ValidationError may be raised on commit
-        except ValidationError as ex:
-            return (False, _validation_error(req, ex), ctrl._edited_entity)
-        except Exception as ex:
-            req.cnx.rollback()
-            req.exception('unexpected error while validating form')
-            return (False, str(ex).decode('utf-8'), ctrl._edited_entity)
-        else:
-            if txuuid is not None:
-                req.data['last_undoable_transaction'] = txuuid
-            # complete entity: it can be used in js callbacks where we might
-            # want every possible information
-            if ctrl._edited_entity:
-                ctrl._edited_entity.complete()
-            return (True, ex.location, ctrl._edited_entity)
-    except Exception as ex:
-        req.cnx.rollback()
-        req.exception('unexpected error while validating form')
-        return (False, text_type(ex), ctrl._edited_entity)
-    return (False, '???', None)
-
-
-class FormValidatorController(Controller):
-    __regid__ = 'validateform'
-
-    def response(self, domid, status, args, entity):
-        callback = str(self._cw.form.get('__onsuccess', 'null'))
-        errback = str(self._cw.form.get('__onfailure', 'null'))
-        cbargs = str(self._cw.form.get('__cbargs', 'null'))
-        self._cw.set_content_type('text/html')
-        jsargs = json_dumps((status, args, entity))
-        return """<script type="text/javascript">
- window.parent.handleFormValidationResponse('%s', %s, %s, %s, %s);
-</script>""" %  (domid, callback, errback, jsargs, cbargs)
-
-    def publish(self, rset=None):
-        self._cw.ajax_request = True
-        # XXX unclear why we have a separated controller here vs
-        # js_validate_form on the json controller
-        status, args, entity = _validate_form(self._cw, self._cw.vreg)
-        domid = self._cw.form.get('__domid', 'entityForm')
-        return self.response(domid, status, args, entity).encode(self._cw.encoding)
-
-
-class JSonController(Controller):
-    __regid__ = 'json'
-
-    def publish(self, rset=None):
-        warn('[3.15] JSONController is deprecated, use AjaxController instead',
-             DeprecationWarning)
-        ajax_controller = self._cw.vreg['controllers'].select('ajax', self._cw, appli=self.appli)
-        return ajax_controller.publish(rset)
-
-
-class MailBugReportController(Controller):
-    __regid__ = 'reportbug'
-    __select__ = match_form_params('description')
-
-    def publish(self, rset=None):
-        req = self._cw
-        desc = req.form['description']
-        # The description is generated and signed by cubicweb itself, check
-        # description's signature so we don't want to send spam here
-        sign = req.form.get('__signature', '')
-        if not (sign and req.vreg.config.check_text_sign(desc, sign)):
-            raise Forbidden('Invalid content')
-        self.sendmail(req.vreg.config['submit-mail'],
-                      req._('%s error report') % req.vreg.config.appid,
-                      desc)
-        raise Redirect(req.build_url(__message=req._('bug report sent')))
-
-
-class UndoController(Controller):
-    __regid__ = 'undo'
-    __select__ = authenticated_user() & match_form_params('txuuid')
-
-    def publish(self, rset=None):
-        txuuid = self._cw.form['txuuid']
-        try:
-            self._cw.cnx.undo_transaction(txuuid)
-        except UndoTransactionException as exc:
-            errors = exc.errors
-            #This will cause a rollback in main_publish
-            raise ValidationError(None, {None: '\n'.join(errors)})
-        else :
-            self.redirect() # Will raise Redirect
-
-    def redirect(self, msg=None):
-        req = self._cw
-        msg = msg or req._("transaction undone")
-        self._redirect({'_cwmsgid': req.set_redirect_message(msg)})