diff --git a/c2cgeoportal/pyramid_.py b/c2cgeoportal/pyramid_.py index e05698ff91..83469d135f 100644 --- a/c2cgeoportal/pyramid_.py +++ b/c2cgeoportal/pyramid_.py @@ -111,8 +111,8 @@ def add_interface( ) -def add_interface_cgxp(config, interface_name, route_names, routes, renderers, - permission=None): # pragma: no cover +def add_interface_cgxp( + config, interface_name, route_names, routes, renderers, permission=None): # pragma: no cover # Cannot be at the header to don"t load the model too early from c2cgeoportal.views.entry import Entry @@ -162,8 +162,8 @@ def new_f(root, request): ngeo_static_init = False -def add_interface_ngeo(config, interface_name, route_name, route, renderer, - permission=None): # pragma: no cover +def add_interface_ngeo( + config, interface_name, route_name, route, renderer, permission=None): # pragma: no cover # Cannot be at the header to do not load the model too early from c2cgeoportal.views.entry import Entry @@ -285,7 +285,7 @@ def _is_valid_referer(request, settings): def _create_get_user_from_request(settings): - def get_user_from_request(request): + def get_user_from_request(request, username=None): """ Return the User object for the request. Return ``None`` if: @@ -304,7 +304,8 @@ def get_user_from_request(request): if not hasattr(request, "_user"): request._user = None - username = request.authenticated_userid + if username is None: + username = request.authenticated_userid if username is not None: # We know we will need the role object of the # user so we use joined loading @@ -443,8 +444,9 @@ def includeme(config): call_hook(settings, "after_settings", settings) - config.add_request_method(_create_get_user_from_request(settings), - name="user", property=True) + get_user_from_request = _create_get_user_from_request(settings) + config.add_request_method(get_user_from_request, name="user", property=True) + config.add_request_method(get_user_from_request, name="get_user") # configure 'locale' dir as the translation dir for c2cgeoportal app config.add_translation_dirs("c2cgeoportal:locale/") diff --git a/c2cgeoportal/tests/functional/__init__.py b/c2cgeoportal/tests/functional/__init__.py index f439509e6d..284bc973cb 100644 --- a/c2cgeoportal/tests/functional/__init__.py +++ b/c2cgeoportal/tests/functional/__init__.py @@ -125,6 +125,12 @@ def create_default_ogcserver(): return ogcserver, ogcserver_external +def _get_user(username): + from c2cgeoportal.models import DBSession, User + + return DBSession.query(User).filter(User.username == username).one() + + def create_dummy_request(additional_settings=None, *args, **kargs): if additional_settings is None: additional_settings = {} @@ -148,6 +154,7 @@ def create_dummy_request(additional_settings=None, *args, **kargs): request.headers["Host"] = host request.user = None request.interface_name = "main" + request.get_user = _get_user request.registry.validate_user = default_user_validator request.client_addr = None return request diff --git a/c2cgeoportal/views/entry.py b/c2cgeoportal/views/entry.py index 9820e3e859..1e1d70f853 100644 --- a/c2cgeoportal/views/entry.py +++ b/c2cgeoportal/views/entry.py @@ -1496,7 +1496,7 @@ def login(self): return set_common_headers( self.request, "login", NO_CACHE, response=Response(json.dumps(self._user( - DBSession.query(User).filter(User.username == user).one() + self.request.get_user(user) )), headers=headers), ) else: diff --git a/doc/integrator/authentication.rst b/doc/integrator/authentication.rst index 3d69ece5b4..3b0ce40f46 100644 --- a/doc/integrator/authentication.rst +++ b/doc/integrator/authentication.rst @@ -116,17 +116,18 @@ You may for example add to ``__init__.py``: .. code:: python - def get_user_from_request(request): + def get_user_from_request(request, username): from c2cgeoportal.models import DBSession, Role class O: pass - username = request.unauthenticated_userid + if username is None: + username = request.unauthenticated_userid if username is not None: user = O() user.username = username rolename = request.environ.get('rolename') - user.role = DBSession.query(Role).filter_by( - name=rolename).one() + user.role_name = rolename + user.role = DBSession.query(Role).filter_by(name=rolename).one() user.functionalities = [] return user @@ -134,15 +135,10 @@ And then, in the application's ``main`` function: .. code:: python - config.set_request_property(get_user_from_request, - name='user', reify=True - ) - -The ``reify`` argument is to ``True`` to cache the function's return value and -actually execute the function only once per request. In this example the user -name is obtained by calling ``unauthenticated_userid``, itself relying on the -authentication policy set in the application. The role object is obtained from -the value of the ``rolename`` environment variable by querying the database. + config.set_request_property( + get_user_from_request, name='user', property=True) + config.set_request_property( + get_user_from_request, name='get_user') Please note that ``c2cgeoportal`` expects the admin role to be ``role_admin``. If for some reason you need to use another name for this role, you may define @@ -263,14 +259,14 @@ Full example using pyramid_ldap, see `# LDAP` / `# END LDAP` blocs. # get custom user data from request and link with existing c2cgeoportal # role in your project - def custom_get_user_from_request(request): + def custom_get_user_from_request(request, identity): class O: pass from c2cgeoportal.models import DBSession, Role - if hasattr(request, '_user'): + if hasattr(request, '_user') and identity is None: # avoid recursive calls from # get_user_from_request -> request.authenticated_userid -> ... return request._user @@ -278,13 +274,15 @@ Full example using pyramid_ldap, see `# LDAP` / `# END LDAP` blocs. user = get_user_from_request(request) if user is None: log.debug("user is not authenticated or is a ldap user") - identity = request.unauthenticated_userid + if identity is None: + identity = request.unauthenticated_userid if identity is not None: identity = loads(identity) user = O() user.username = identity['username'] user.functionalities = [] user.is_password_changed = True + user.role_name = identity['role'] user.role = DBSession.query(Role).filter_by(name=identity['role']).one() user.id = -1 request._user = user @@ -340,7 +338,8 @@ Full example using pyramid_ldap, see `# LDAP` / `# END LDAP` blocs. # LDAP # register the customized function config.set_user_validator(custom_user_validator) - config.add_request_method(custom_get_user_from_request, 'user', reify=True) + config.add_request_method(custom_get_user_from_request, 'user', property=True) + config.add_request_method(custom_get_user_from_request, 'get_user') # END LDAP return config.make_wsgi_app()