Ejemplo n.º 1
0
def test_full():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/:controller/:action/', id=None)
    m.connect('/:controller/:action/:id')
    m.create_regs(['content'])

    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_({'controller':'content','action':'index','id':None},
        m.match('/content/index/'))
    eq_({'controller':'content','action':'index','id':'4'},
        m.match('/content/index/4'))
    eq_({'controller':'content','action':'view','id':'4.html'},
        m.match('/content/view/4.html'))

    # Generate
    eq_(None, m.generate(controller='content'))

    # Looks odd, but only controller/action are set with non-explicit, so we
    # do need the id to match
    eq_('/content/index/', m.generate(controller='content', id=None))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content', action='view', id=3))
Ejemplo n.º 2
0
def test_full():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/:controller/:action/', id=None)
    m.connect('/:controller/:action/:id')
    m.create_regs(['content'])
    
    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_({'controller':'content','action':'index','id':None}, 
        m.match('/content/index/'))
    eq_({'controller':'content','action':'index','id':'4'}, 
        m.match('/content/index/4'))
    eq_({'controller':'content','action':'view','id':'4.html'},
        m.match('/content/view/4.html'))
    
    # Generate
    eq_(None, m.generate(controller='content'))
    
    # Looks odd, but only controller/action are set with non-explicit, so we
    # do need the id to match
    eq_('/content/index/', m.generate(controller='content', id=None))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content', action='view', id=3))
Ejemplo n.º 3
0
def test_basic():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/:controller/:action/:id')
    m.create_regs(['content'])

    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_(None, m.match('/content/index/'))
    eq_({
        'controller': 'content',
        'action': 'index',
        'id': '4'
    }, m.match('/content/index/4'))
    eq_({
        'controller': 'content',
        'action': 'view',
        'id': '4.html'
    }, m.match('/content/view/4.html'))

    # Generate
    eq_(None, m.generate(controller='content'))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content',
                                      action='view',
                                      id=3))
Ejemplo n.º 4
0
class URLMapper(object):
    """
    Maps the URLs users can access.
    """

    def __init__(self):
        self._map = Mapper(controller_scan=None)
        self._connect_urls()
        self._map.create_regs()

    def match(self, path, method):
        environ = {'PATH_INFO': path, 'REQUEST_METHOD': method}
        return self._map.match(environ=environ)

    def _connect(self, pattern, http_methods):
        self._map.connect(
            None, pattern, http_methods=http_methods,
            conditions=dict(method=http_methods),
            requirements={'dbname': DBNAME_CONSTRAINTS})

    def _connect_urls(self):
        """
        Register the authorization info in the mapper using C{SHARED_DB_NAME}
        as the user's database name.

        This method sets up the following authorization rules:

            URL path                        | Authorized actions
            ----------------------------------------------------
            /                               | GET
            /robots.txt                     | GET
            /shared-db                      | GET
            /shared-db/doc/{any_id}         | GET, PUT, DELETE
            /user-{uuid}/sync-from/{source} | GET, PUT, POST
            /blobs/{uuid}/{blob_id}         | GET, PUT, DELETE, POST
            /blobs/{uuid}                   | GET
            /incoming/                      | PUT
            /stream/{uuid}/                 | POST
        """
        # global resource
        self._connect('/', ['GET'])
        # robots
        self._connect('/robots.txt', ['GET'])
        # shared-db database resource
        self._connect('/%s' % SHARED_DB_NAME, ['GET'])
        # shared-db doc resource
        self._connect('/%s/doc/{id:.*}' % SHARED_DB_NAME,
                      ['GET', 'PUT', 'DELETE'])
        # user-db sync resource
        self._connect('/user-{uuid}/sync-from/{source_replica_uid}',
                      ['GET', 'PUT', 'POST'])
        # blobs resource
        self._connect('/blobs/{uuid}/{blob_id}',
                      ['GET', 'PUT', 'DELETE', 'POST'])
        self._connect('/blobs/{uuid}/', ['GET'])
        # streaming resource
        self._connect('/stream/{uuid}/', ['POST'])
        # incoming resource
        self._connect('/incoming/{target_user_uuid}/{incoming_id}', ['PUT'])
Ejemplo n.º 5
0
def test_syntax():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/{controller}/{action}/{id}')
    m.create_regs(['content'])

    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_(None, m.match('/content/index/'))
    eq_({'controller':'content','action':'index','id':'4'},
        m.match('/content/index/4'))

    # Generate
    eq_(None, m.generate(controller='content'))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content', action='view', id=3))
Ejemplo n.º 6
0
def test_syntax():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/{controller}/{action}/{id}')
    m.create_regs(['content'])
    
    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_(None, m.match('/content/index/'))
    eq_({'controller':'content','action':'index','id':'4'}, 
        m.match('/content/index/4'))
    
    # Generate
    eq_(None, m.generate(controller='content'))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content', action='view', id=3))
Ejemplo n.º 7
0
class URLMapper(object):
    """
    Maps the URLs users can access.
    """

    def __init__(self):
        self._map = Mapper(controller_scan=None)
        self._connect_urls()
        self._map.create_regs()

    def match(self, path, method):
        environ = {'PATH_INFO': path, 'REQUEST_METHOD': method}
        return self._map.match(environ=environ)

    def _connect(self, pattern, http_methods):
        self._map.connect(
            None, pattern, http_methods=http_methods,
            conditions=dict(method=http_methods),
            requirements={'dbname': DBNAME_CONSTRAINTS})

    def _connect_urls(self):
        """
        Register the authorization info in the mapper using C{SHARED_DB_NAME}
        as the user's database name.

        This method sets up the following authorization rules:

            URL path                        | Authorized actions
            ----------------------------------------------------
            /                               | GET
            /robots.txt                     | GET
            /shared-db                      | GET
            /shared-db/doc/{any_id}         | GET, PUT, DELETE
            /user-{uuid}/sync-from/{source} | GET, PUT, POST
            /blobs/{uuid}/{blob_id}         | GET, PUT, DELETE, POST
            /blobs/{uuid}                   | GET
            /incoming/                      | PUT
        """
        # global resource
        self._connect('/', ['GET'])
        # robots
        self._connect('/robots.txt', ['GET'])
        # shared-db database resource
        self._connect('/%s' % SHARED_DB_NAME, ['GET'])
        # shared-db doc resource
        self._connect('/%s/doc/{id:.*}' % SHARED_DB_NAME,
                      ['GET', 'PUT', 'DELETE'])
        # user-db sync resource
        self._connect('/user-{uuid}/sync-from/{source_replica_uid}',
                      ['GET', 'PUT', 'POST'])
        # blobs resource
        self._connect('/blobs/{uuid}/{blob_id}',
                      ['GET', 'PUT', 'DELETE', 'POST'])
        self._connect('/blobs/{uuid}/', ['GET'])
        # incoming resource
        self._connect('/incoming/{target_user_uuid}/{incoming_id}', ['PUT'])
Ejemplo n.º 8
0
def test_basic():
    m = Mapper(explicit=False)
    m.minimization = False
    m.connect('/:controller/:action/:id')
    m.create_regs(['content'])

    # Recognize
    eq_(None, m.match('/content'))
    eq_(None, m.match('/content/index'))
    eq_(None, m.match('/content/index/'))
    eq_({'controller':'content','action':'index','id':'4'},
        m.match('/content/index/4'))
    eq_({'controller':'content','action':'view','id':'4.html'},
        m.match('/content/view/4.html'))

    # Generate
    eq_(None, m.generate(controller='content'))
    eq_('/content/index/4', m.generate(controller='content', id=4))
    eq_('/content/view/3', m.generate(controller='content', action='view', id=3))
Ejemplo n.º 9
0
class RoutingController(web.core.Dialect):
    """Routes-based dispatch.

    Subclass and override __init__ to define your routes.  E.g.

        class RootController(RoutesController):
            def __init__(self):
                super(RootController, self).__init__()
                self._map.connect(None, "/error/{method}/{id}, action="error")
                # ...

    Methods to be called are named attributes or named attributes of
    nested controllers.  Nested controllers may be simple new-style
    class instances; they do not need to inherit from Dialect or
    RoutesController.

    In your route definitions, 'action' refers to the method,
    'controller' optionally refers to a nested controller and you can
    use dot notation to refer to sub-sub controllers, etc.
    """

    def __init__(self):
        self._map = Mapper()
        self._map.minimization = False

    def __call__(self, request):
        result = self._map.match(environ=request.environ)

        if not result:
            raise web.core.http.HTTPNotFound()

        parts = result.get("controller").split(".") if "controller" in result else []

        controller = self

        for part in parts:
            if not hasattr(controller, part):
                raise web.core.http.HTTPNotFound()

            controller = getattr(controller, part)

        method = result.get("action", None)

        if method is None:
            raise web.core.http.HTTPNotFound()

        try:
            del result["controller"]

        except:
            pass

        del result["action"]

        return getattr(controller, method)(**result)
Ejemplo n.º 10
0
class App(object):
    def __init__(self):
        self.url_map = Mapper()
        self.Request = BaitoRequest
        self.Response = Response

        self._renderer = None

        self.conf = imp.new_module('baito.conf')

    def load_conf(self, path):
        self.conf.__file__ = path
        execfile(path, self.conf.__dict__, self.conf.__dict__)

    def connect(self, name, rule, **kwargs):
        kwargs['_module'] = None
        self.url_map.connect(name, rule, **kwargs)

    def expose(self, rule, name=None, **kwargs):
        def decorator(func):
            kwargs['_endpoint'] = func
            kwargs['_module'] = None
            self.url_map.connect(name or func.__name__, rule, **kwargs)
            return func

        return decorator

    def __call__(self, environ, start_response):
        request = self.Request(self, environ)
        try:
            result = self.url_map.match(None, environ)
            if not result:
                raise HTTPNotFound()

            try:
                endpoint = result.pop('_endpoint')
            except KeyError:
                return result.pop('_wsgi')(environ, start_response)

            request.module = result.pop('_module', None)
            response = endpoint(request, **result)
            if isinstance(response, basestring):
                response = self.Response(response)
        except HTTPException, e:
            response = e

        if request.session is not None:
            request.session.save()

        return response(environ, start_response)
Ejemplo n.º 11
0
class WSGIApplication(object):
    def __init__(self):
        super(WSGIApplication, self).__init__()
        self.mapper = Mapper()
        self._match = lambda req: self.mapper.match(environ=req.environ)

    @WsgiHack
    def __call__(self, req, start_response):
        match = self._match(req)

        if not match:
            return HTTPNotFound()

        req.start_response = start_response
        req.urlvars = match

        name = match["controller"].__name__

        controller = match["controller"](req)

        return controller(req)
Ejemplo n.º 12
0
class URLToAuthorization(object):
    """
    Verify if actions can be performed by a user.
    """

    HTTP_METHOD_GET = 'GET'
    HTTP_METHOD_PUT = 'PUT'
    HTTP_METHOD_DELETE = 'DELETE'
    HTTP_METHOD_POST = 'POST'

    def __init__(self, uuid):
        """
        Initialize the mapper.

        The C{uuid} is used to create the rules that will either allow or
        disallow the user to perform specific actions.

        @param uuid: The user uuid.
        @type uuid: str
        @param user_db_prefix: The string prefix of users' databases.
        @type user_db_prefix: str
        """
        self._map = Mapper(controller_scan=None)
        self._user_db_name = "%s%s" % (USER_DB_PREFIX, uuid)
        self._uuid = uuid
        self._register_auth_info()

    def is_authorized(self, environ):
        """
        Return whether an HTTP request that produced the CGI C{environ}
        corresponds to an authorized action.

        @param environ: Dictionary containing CGI variables.
        @type environ: dict

        @return: Whether the action is authorized or not.
        @rtype: bool
        """
        return self._map.match(environ=environ) is not None

    def _register(self, pattern, http_methods):
        """
        Register a C{pattern} in the mapper as valid for C{http_methods}.

        @param pattern: The URL pattern that corresponds to the user action.
        @type pattern: str
        @param http_methods: A list of authorized HTTP methods.
        @type http_methods: list of str
        """
        self._map.connect(
            None, pattern, http_methods=http_methods,
            conditions=dict(method=http_methods),
            requirements={'dbname': DBNAME_CONSTRAINTS})

    def _register_auth_info(self):
        """
        Register the authorization info in the mapper using C{SHARED_DB_NAME}
        as the user's database name.

        This method sets up the following authorization rules:

            URL path                      | Authorized actions
            --------------------------------------------------
            /                             | GET
            /shared-db                    | GET
            /shared-db/docs               | -
            /shared-db/doc/{any_id}       | GET, PUT, DELETE
            /shared-db/sync-from/{source} | -
            /shared-db/lock/{uuid}        | PUT, DELETE
            /user-db                      | GET, PUT, DELETE
            /user-db/docs                 | -
            /user-db/doc/{id}             | -
            /user-db/sync-from/{source}   | GET, PUT, POST
        """
        # auth info for global resource
        self._register('/', [self.HTTP_METHOD_GET])
        # auth info for shared-db database resource
        self._register(
            '/%s' % SHARED_DB_NAME,
            [self.HTTP_METHOD_GET])
        # auth info for shared-db doc resource
        self._register(
            '/%s/doc/{id:.*}' % SHARED_DB_NAME,
            [self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT,
             self.HTTP_METHOD_DELETE])
        # auth info for shared-db lock resource
        self._register(
            '/%s/lock/%s' % (SHARED_DB_NAME, self._uuid),
            [self.HTTP_METHOD_PUT, self.HTTP_METHOD_DELETE])
        # auth info for user-db database resource
        self._register(
            '/%s' % self._user_db_name,
            [self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT,
             self.HTTP_METHOD_DELETE])
        # auth info for user-db sync resource
        self._register(
            '/%s/sync-from/{source_replica_uid}' % self._user_db_name,
            [self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT,
             self.HTTP_METHOD_POST])
        # generate the regular expressions
        self._map.create_regs()
Ejemplo n.º 13
0
class URLToAuthorization(object):
    """
    Verify if actions can be performed by a user.
    """

    HTTP_METHOD_GET = 'GET'
    HTTP_METHOD_PUT = 'PUT'
    HTTP_METHOD_DELETE = 'DELETE'
    HTTP_METHOD_POST = 'POST'

    def __init__(self, uuid):
        """
        Initialize the mapper.

        The C{uuid} is used to create the rules that will either allow or
        disallow the user to perform specific actions.

        @param uuid: The user uuid.
        @type uuid: str
        @param user_db_prefix: The string prefix of users' databases.
        @type user_db_prefix: str
        """
        self._map = Mapper(controller_scan=None)
        self._user_db_name = "%s%s" % (USER_DB_PREFIX, uuid)
        self._uuid = uuid
        self._register_auth_info()

    def is_authorized(self, environ):
        """
        Return whether an HTTP request that produced the CGI C{environ}
        corresponds to an authorized action.

        @param environ: Dictionary containing CGI variables.
        @type environ: dict

        @return: Whether the action is authorized or not.
        @rtype: bool
        """
        return self._map.match(environ=environ) is not None

    def _register(self, pattern, http_methods):
        """
        Register a C{pattern} in the mapper as valid for C{http_methods}.

        @param pattern: The URL pattern that corresponds to the user action.
        @type pattern: str
        @param http_methods: A list of authorized HTTP methods.
        @type http_methods: list of str
        """
        self._map.connect(None,
                          pattern,
                          http_methods=http_methods,
                          conditions=dict(method=http_methods),
                          requirements={'dbname': DBNAME_CONSTRAINTS})

    def _register_auth_info(self):
        """
        Register the authorization info in the mapper using C{SHARED_DB_NAME}
        as the user's database name.

        This method sets up the following authorization rules:

            URL path                      | Authorized actions
            --------------------------------------------------
            /                             | GET
            /shared-db                    | GET
            /shared-db/docs               | -
            /shared-db/doc/{any_id}       | GET, PUT, DELETE
            /shared-db/sync-from/{source} | -
            /shared-db/lock/{uuid}        | PUT, DELETE
            /user-db                      | GET, PUT, DELETE
            /user-db/docs                 | -
            /user-db/doc/{id}             | -
            /user-db/sync-from/{source}   | GET, PUT, POST
        """
        # auth info for global resource
        self._register('/', [self.HTTP_METHOD_GET])
        # auth info for shared-db database resource
        self._register('/%s' % SHARED_DB_NAME, [self.HTTP_METHOD_GET])
        # auth info for shared-db doc resource
        self._register('/%s/doc/{id:.*}' % SHARED_DB_NAME, [
            self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT, self.HTTP_METHOD_DELETE
        ])
        # auth info for shared-db lock resource
        self._register('/%s/lock/%s' % (SHARED_DB_NAME, self._uuid),
                       [self.HTTP_METHOD_PUT, self.HTTP_METHOD_DELETE])
        # auth info for user-db database resource
        self._register('/%s' % self._user_db_name, [
            self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT, self.HTTP_METHOD_DELETE
        ])
        # auth info for user-db sync resource
        self._register(
            '/%s/sync-from/{source_replica_uid}' % self._user_db_name, [
                self.HTTP_METHOD_GET, self.HTTP_METHOD_PUT,
                self.HTTP_METHOD_POST
            ])
        # generate the regular expressions
        self._map.create_regs()
Ejemplo n.º 14
0
def route_matches(route, request):
  m = RouteMapper()
  m.extend([route])
  return m.match(request["uri"])