imbolc avatar imbolc committed bd641a9

middlewares process_view method and csrf_exempt decorator

Comments (0)

Files changed (6)

 from config import cfg
 from exceptions import BasicAuth, HttpError
 from routing import urls, add_apps, add_urls, url4, auto_routing
-from decorators import basic_auth, anticache, view
+from decorators import basic_auth, anticache, view, csrf_exempt
 from template import render_to_string, render
 from util import cached_property, cached_function
 from static import static_url

pysi/decorators.py

     wrapper._pysi_urlname = _get_urlname(func)
     return wrapper
 
+def csrf_exempt(func):
+    func._pysi_csrf_exempt = True
+    return func
+
 def _get_urlname(func):
     if not getattr(func, '_pysi_urlname', None):
         mod_name = func.func_globals['__name__']
         app_name = mod_name[:-6] if mod_name.endswith('.views') else None
         urlname = '%s.%s' % (app_name, func.__name__) if app_name else func.__name__
         setattr(func, '_pysi_urlname', urlname)
-    return func._pysi_urlname
+    return func._pysi_urlname

pysi/middlewares.py

     CSRF_TOKEN_POST_NAME = 'csrf',
     CSRF_TOKEN_TEMPLATE_NAME = 'csrf',
     CSRF_TOKEN_TEMPLATE_INPUT_NAME = 'csrf_token',
-    CSRF_EXEMPT_PREFIXES = (),
 )
 
 
 class CSRF(object):
-    def process_request(self, rq):
+    def process_view(self, rq, func, kwargs):
         token = rq.COOKIES.get(cfg.CSRF_TOKEN_COOKIE_NAME)
         if token:
             token = token.value
         if rq.method == 'POST':
-            if not rq.path.startswith(cfg.CSRF_EXEMPT_PREFIXES):
-                if token != rq.POST.get(cfg.CSRF_TOKEN_POST_NAME):
+            if not getattr(func, '_pysi_csrf_exempt', None):
+                if not token or token != rq.POST.get(cfg.CSRF_TOKEN_POST_NAME):
                     res = get_error_page(rq, 403)
                     if token is not None:
                         res.delete_cookie(cfg.CSRF_TOKEN_COOKIE_NAME)
                 # забыли закрывающий слеш?
                 func, kwargs = urls.find(rq.path + '/')
                 if func:
-                    return wsgi.redirect(rq.path + '/')
+                    raise wsgi.redirect(rq.path + '/')
             wsgi.abort(404)
-        return func(rq, **kwargs)
+        return func, kwargs
 
     def add_urls(*rules):
         ''' Добавление правил списком'''
         """
         expires = kwargs.get('expires')
         if expires and isinstance(expires, timedelta):
-            kwargs['expires'] = expires.days * 86400 + expires.seconds 
+            kwargs['expires'] = expires.days * 86400 + expires.seconds
         key = key.encode(self.charset, self.encoding_errors)
         self.COOKIES[key] = val.encode(self.charset, self.encoding_errors)
         self.COOKIES[key]['path'] = path
         '''
         def routing_queue(routing):
             list_obj_from_str(routing)
-            if len(routing) == 1:
-                return routing[0]
             def wrapper(rq):
-                for func in routing:
+                for find_view in routing:
                     try:
-                        return func(rq)
+                        view_func, view_kwargs = find_view(rq)
                     except HttpError, e:
                         if e[0] == 404:
                             continue
                         raise
+                    for middleware in self.view_middlewares:
+                        middleware(rq, view_func, view_kwargs)
+                    return view_func(rq, **view_kwargs)
                 abort(404)
             return wrapper
 
             if hasattr(m, 'process_request')]
         self.response_middlewares = [m().process_response for m in mdls
             if hasattr(m, 'process_response')]
+        self.view_middlewares = [m().process_view for m in mdls
+            if hasattr(m, 'process_view')]
         self.response_middlewares.reverse()
         self.routing = routing_queue(cfg.ROUTING_QUEUE)
 
 import os
 from setuptools import setup
 
-VERSION = '0.11.0'
+VERSION = '0.12.0'
 PACKAGE = 'pysi'
 
 if __name__ == '__main__':
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.