We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'_Globals' has no attribute 'user' : exception when using an IAuthenticator on CKAN 2.8.0
I'm putting together a new deployment based on the new CKAN v2.8.0 release. I'm using ckanext-ldap as an authenticator, though it looks like this bug would apply to any authenticator plugin.
This exact setup worked fine on CKAN v2.7.3.

### CKAN Version if known (or site URL)
CKAN v 2.8.0
ckanext-ldap @ `ckan-upgrade-2.8.0a`

### Please describe the expected behaviour
If the IAuthenticator plugin cannot authenticate the user, it does not set `g.user`, and CKAN should run the default authenticator.

### Please describe the actual behaviour
If the IAuthenticator plugin cannot authenticate the user, it does not set `g.user`, and CKAN tries to lookup `g.user` and crashes with traceback:
```
Traceback (most recent call last):
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py", line 1610, in full_dispatch_request
    rv = self.preprocess_request()
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py", line 1831, in preprocess_request
    rv = func()
  File "/usr/lib/ckan/venv/src/ckan/ckan/config/middleware/flask_app.py", line 281, in ckan_before_request
    identify_user()
  File "/usr/lib/ckan/venv/src/ckan/ckan/views/__init__.py", line 101, in identify_user
    if g.user:
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/usr/lib/ckan/venv/local/lib/python2.7/site-packages/werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/usr/lib/ckan/venv/src/ckan/ckan/config/middleware/flask_app.py", line 334, in __getattr__
    return getattr(app_globals.app_globals, name)
AttributeError: '_Globals' object has no attribute 'user'
```
### What steps can be taken to reproduce the issue? 
* Install CKAN v2.8.0 as per documented instructions
* Install a plugin that implements IAuthenticator (In this case I am using the ckanext-ldap plugin in the 2.8.0 branch), that may not be able to authenticate the user, so may not set `g.user`.
* Run CKAN normally
* Attempt to load any page. 

What is odd is that this section of code at `identify_user` in `ckan/views/__init__.py` has not changed between v2.7.3 and v2.8.0. And the way the authenticator plugin handles/sets `g.user` has not changed either. I'm guessing this is caused by a change in the way the _Globals object behaves when it cannot find an attribute.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ckan/views/__init__.py`
Content:
```
1 # encoding: utf-8
2 
3 from paste.deploy.converters import asbool
4 from six import text_type
5 
6 import ckan.model as model
7 from ckan.common import g, request, config, session
8 from ckan.lib.helpers import redirect_to as redirect
9 import ckan.plugins as p
10 
11 import logging
12 log = logging.getLogger(__name__)
13 
14 APIKEY_HEADER_NAME_KEY = u'apikey_header_name'
15 APIKEY_HEADER_NAME_DEFAULT = u'X-CKAN-API-Key'
16 
17 
18 def check_session_cookie(response):
19     u'''
20     The cookies for auth (auth_tkt) and session (ckan) are separate. This
21     checks whether a user is logged in, and determines the validity of the
22     session cookie, removing it if necessary.
23     '''
24     for cookie in request.cookies:
25         # Remove the ckan session cookie if logged out.
26         if cookie == u'ckan' and not getattr(g, u'user', None):
27             # Check session for valid data (including flash messages)
28             is_valid_cookie_data = False
29             for key, value in session.items():
30                 if not key.startswith(u'_') and value:
31                     is_valid_cookie_data = True
32                     break
33             if not is_valid_cookie_data:
34                 if session.id:
35                     log.debug(u'No valid session data - deleting session')
36                     log.debug(u'Session: %r', session.items())
37                     session.delete()
38                 else:
39                     log.debug(u'No session id - deleting session cookie')
40                     response.delete_cookie(cookie)
41         # Remove auth_tkt repoze.who cookie if user not logged in.
42         elif cookie == u'auth_tkt' and not session.id:
43             response.delete_cookie(cookie)
44 
45     return response
46 
47 
48 def set_cors_headers_for_response(response):
49     u'''
50     Set up Access Control Allow headers if either origin_allow_all is True, or
51     the request Origin is in the origin_whitelist.
52     '''
53     if config.get(u'ckan.cors.origin_allow_all') \
54        and request.headers.get(u'Origin'):
55 
56         cors_origin_allowed = None
57         if asbool(config.get(u'ckan.cors.origin_allow_all')):
58             cors_origin_allowed = b'*'
59         elif config.get(u'ckan.cors.origin_whitelist') and \
60                 request.headers.get(u'Origin') \
61                 in config[u'ckan.cors.origin_whitelist'].split(u' '):
62             # set var to the origin to allow it.
63             cors_origin_allowed = request.headers.get(u'Origin')
64 
65         if cors_origin_allowed is not None:
66             response.headers[b'Access-Control-Allow-Origin'] = \
67                 cors_origin_allowed
68             response.headers[b'Access-Control-Allow-Methods'] = \
69                 b'POST, PUT, GET, DELETE, OPTIONS'
70             response.headers[b'Access-Control-Allow-Headers'] = \
71                 b'X-CKAN-API-KEY, Authorization, Content-Type'
72 
73     return response
74 
75 
76 def identify_user():
77     u'''Try to identify the user
78     If the user is identified then:
79       g.user = user name (unicode)
80       g.userobj = user object
81       g.author = user name
82     otherwise:
83       g.user = None
84       g.userobj = None
85       g.author = user's IP address (unicode)
86 
87     Note: Remember, when running under Pylons, `g` is the Pylons `c` object
88     '''
89     # see if it was proxied first
90     g.remote_addr = request.environ.get(u'HTTP_X_FORWARDED_FOR', u'')
91     if not g.remote_addr:
92         g.remote_addr = request.environ.get(u'REMOTE_ADDR',
93                                             u'Unknown IP Address')
94 
95     # Authentication plugins get a chance to run here break as soon as a user
96     # is identified.
97     authenticators = p.PluginImplementations(p.IAuthenticator)
98     if authenticators:
99         for item in authenticators:
100             item.identify()
101             if g.user:
102                 break
103 
104     # We haven't identified the user so try the default methods
105     if not getattr(g, u'user', None):
106         _identify_user_default()
107 
108     # If we have a user but not the userobj let's get the userobj. This means
109     # that IAuthenticator extensions do not need to access the user model
110     # directly.
111     if g.user and not getattr(g, u'userobj', None):
112         g.userobj = model.User.by_name(g.user)
113 
114     # general settings
115     if g.user:
116         g.author = g.user
117     else:
118         g.author = g.remote_addr
119     g.author = text_type(g.author)
120 
121 
122 def _identify_user_default():
123     u'''
124     Identifies the user using two methods:
125     a) If they logged into the web interface then repoze.who will
126        set REMOTE_USER.
127     b) For API calls they may set a header with an API key.
128     '''
129 
130     # environ['REMOTE_USER'] is set by repoze.who if it authenticates a
131     # user's cookie. But repoze.who doesn't check the user (still) exists
132     # in our database - we need to do that here. (Another way would be
133     # with an userid_checker, but that would mean another db access.
134     # See: http://docs.repoze.org/who/1.0/narr.html#module-repoze.who\
135     # .plugins.sql )
136     g.user = request.environ.get(u'REMOTE_USER', u'')
137     if g.user:
138         g.user = g.user.decode(u'utf8')
139         g.userobj = model.User.by_name(g.user)
140 
141         if g.userobj is None or not g.userobj.is_active():
142 
143             # This occurs when a user that was still logged in is deleted, or
144             # when you are logged in, clean db and then restart (or when you
145             # change your username). There is no user object, so even though
146             # repoze thinks you are logged in and your cookie has
147             # ckan_display_name, we need to force user to logout and login
148             # again to get the User object.
149 
150             ev = request.environ
151             if u'repoze.who.plugins' in ev:
152                 pth = getattr(ev[u'repoze.who.plugins'][u'friendlyform'],
153                               u'logout_handler_path')
154                 redirect(pth)
155     else:
156         g.userobj = _get_user_for_apikey()
157         if g.userobj is not None:
158             g.user = g.userobj.name
159 
160 
161 def _get_user_for_apikey():
162     apikey_header_name = config.get(APIKEY_HEADER_NAME_KEY,
163                                     APIKEY_HEADER_NAME_DEFAULT)
164     apikey = request.headers.get(apikey_header_name, u'')
165     if not apikey:
166         apikey = request.environ.get(apikey_header_name, u'')
167     if not apikey:
168         # For misunderstanding old documentation (now fixed).
169         apikey = request.environ.get(u'HTTP_AUTHORIZATION', u'')
170     if not apikey:
171         apikey = request.environ.get(u'Authorization', u'')
172         # Forget HTTP Auth credentials (they have spaces).
173         if u' ' in apikey:
174             apikey = u''
175     if not apikey:
176         return None
177     apikey = apikey.decode(u'utf8', u'ignore')
178     log.debug(u'Received API Key: %s' % apikey)
179     query = model.Session.query(model.User)
180     user = query.filter_by(apikey=apikey).first()
181     return user
182
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ckan/views/__init__.py b/ckan/views/__init__.py
--- a/ckan/views/__init__.py
+++ b/ckan/views/__init__.py
@@ -98,8 +98,11 @@
     if authenticators:
         for item in authenticators:
             item.identify()
-            if g.user:
-                break
+            try:
+                if g.user:
+                    break
+            except AttributeError:
+                continue
 
     # We haven't identified the user so try the default methods
     if not getattr(g, u'user', None):

{"golden_diff": "diff --git a/ckan/views/__init__.py b/ckan/views/__init__.py\n--- a/ckan/views/__init__.py\n+++ b/ckan/views/__init__.py\n@@ -98,8 +98,11 @@\n     if authenticators:\n         for item in authenticators:\n             item.identify()\n-            if g.user:\n-                break\n+            try:\n+                if g.user:\n+                    break\n+            except AttributeError:\n+                continue\n \n     # We haven't identified the user so try the default methods\n     if not getattr(g, u'user', None):\n", "issue": "'_Globals' has no attribute 'user' : exception when using an IAuthenticator on CKAN 2.8.0\nI'm putting together a new deployment based on the new CKAN v2.8.0 release. I'm using ckanext-ldap as an authenticator, though it looks like this bug would apply to any authenticator plugin.\r\nThis exact setup worked fine on CKAN v2.7.3.\r\n\r\n### CKAN Version if known (or site URL)\r\nCKAN v 2.8.0\r\nckanext-ldap @ `ckan-upgrade-2.8.0a`\r\n\r\n### Please describe the expected behaviour\r\nIf the IAuthenticator plugin cannot authenticate the user, it does not set `g.user`, and CKAN should run the default authenticator.\r\n\r\n### Please describe the actual behaviour\r\nIf the IAuthenticator plugin cannot authenticate the user, it does not set `g.user`, and CKAN tries to lookup `g.user` and crashes with traceback:\r\n```\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py\", line 1982, in wsgi_app\r\n    response = self.full_dispatch_request()\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py\", line 1614, in full_dispatch_request\r\n    rv = self.handle_user_exception(e)\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py\", line 1517, in handle_user_exception\r\n    reraise(exc_type, exc_value, tb)\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py\", line 1610, in full_dispatch_request\r\n    rv = self.preprocess_request()\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/flask/app.py\", line 1831, in preprocess_request\r\n    rv = func()\r\n  File \"/usr/lib/ckan/venv/src/ckan/ckan/config/middleware/flask_app.py\", line 281, in ckan_before_request\r\n    identify_user()\r\n  File \"/usr/lib/ckan/venv/src/ckan/ckan/views/__init__.py\", line 101, in identify_user\r\n    if g.user:\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/werkzeug/local.py\", line 347, in __getattr__\r\n    return getattr(self._get_current_object(), name)\r\n  File \"/usr/lib/ckan/venv/local/lib/python2.7/site-packages/werkzeug/local.py\", line 347, in __getattr__\r\n    return getattr(self._get_current_object(), name)\r\n  File \"/usr/lib/ckan/venv/src/ckan/ckan/config/middleware/flask_app.py\", line 334, in __getattr__\r\n    return getattr(app_globals.app_globals, name)\r\nAttributeError: '_Globals' object has no attribute 'user'\r\n```\r\n### What steps can be taken to reproduce the issue? \r\n* Install CKAN v2.8.0 as per documented instructions\r\n* Install a plugin that implements IAuthenticator (In this case I am using the ckanext-ldap plugin in the 2.8.0 branch), that may not be able to authenticate the user, so may not set `g.user`.\r\n* Run CKAN normally\r\n* Attempt to load any page. \r\n\r\nWhat is odd is that this section of code at `identify_user` in `ckan/views/__init__.py` has not changed between v2.7.3 and v2.8.0. And the way the authenticator plugin handles/sets `g.user` has not changed either. I'm guessing this is caused by a change in the way the _Globals object behaves when it cannot find an attribute.\n", "before_files": [{"content": "# encoding: utf-8\n\nfrom paste.deploy.converters import asbool\nfrom six import text_type\n\nimport ckan.model as model\nfrom ckan.common import g, request, config, session\nfrom ckan.lib.helpers import redirect_to as redirect\nimport ckan.plugins as p\n\nimport logging\nlog = logging.getLogger(__name__)\n\nAPIKEY_HEADER_NAME_KEY = u'apikey_header_name'\nAPIKEY_HEADER_NAME_DEFAULT = u'X-CKAN-API-Key'\n\n\ndef check_session_cookie(response):\n    u'''\n    The cookies for auth (auth_tkt) and session (ckan) are separate. This\n    checks whether a user is logged in, and determines the validity of the\n    session cookie, removing it if necessary.\n    '''\n    for cookie in request.cookies:\n        # Remove the ckan session cookie if logged out.\n        if cookie == u'ckan' and not getattr(g, u'user', None):\n            # Check session for valid data (including flash messages)\n            is_valid_cookie_data = False\n            for key, value in session.items():\n                if not key.startswith(u'_') and value:\n                    is_valid_cookie_data = True\n                    break\n            if not is_valid_cookie_data:\n                if session.id:\n                    log.debug(u'No valid session data - deleting session')\n                    log.debug(u'Session: %r', session.items())\n                    session.delete()\n                else:\n                    log.debug(u'No session id - deleting session cookie')\n                    response.delete_cookie(cookie)\n        # Remove auth_tkt repoze.who cookie if user not logged in.\n        elif cookie == u'auth_tkt' and not session.id:\n            response.delete_cookie(cookie)\n\n    return response\n\n\ndef set_cors_headers_for_response(response):\n    u'''\n    Set up Access Control Allow headers if either origin_allow_all is True, or\n    the request Origin is in the origin_whitelist.\n    '''\n    if config.get(u'ckan.cors.origin_allow_all') \\\n       and request.headers.get(u'Origin'):\n\n        cors_origin_allowed = None\n        if asbool(config.get(u'ckan.cors.origin_allow_all')):\n            cors_origin_allowed = b'*'\n        elif config.get(u'ckan.cors.origin_whitelist') and \\\n                request.headers.get(u'Origin') \\\n                in config[u'ckan.cors.origin_whitelist'].split(u' '):\n            # set var to the origin to allow it.\n            cors_origin_allowed = request.headers.get(u'Origin')\n\n        if cors_origin_allowed is not None:\n            response.headers[b'Access-Control-Allow-Origin'] = \\\n                cors_origin_allowed\n            response.headers[b'Access-Control-Allow-Methods'] = \\\n                b'POST, PUT, GET, DELETE, OPTIONS'\n            response.headers[b'Access-Control-Allow-Headers'] = \\\n                b'X-CKAN-API-KEY, Authorization, Content-Type'\n\n    return response\n\n\ndef identify_user():\n    u'''Try to identify the user\n    If the user is identified then:\n      g.user = user name (unicode)\n      g.userobj = user object\n      g.author = user name\n    otherwise:\n      g.user = None\n      g.userobj = None\n      g.author = user's IP address (unicode)\n\n    Note: Remember, when running under Pylons, `g` is the Pylons `c` object\n    '''\n    # see if it was proxied first\n    g.remote_addr = request.environ.get(u'HTTP_X_FORWARDED_FOR', u'')\n    if not g.remote_addr:\n        g.remote_addr = request.environ.get(u'REMOTE_ADDR',\n                                            u'Unknown IP Address')\n\n    # Authentication plugins get a chance to run here break as soon as a user\n    # is identified.\n    authenticators = p.PluginImplementations(p.IAuthenticator)\n    if authenticators:\n        for item in authenticators:\n            item.identify()\n            if g.user:\n                break\n\n    # We haven't identified the user so try the default methods\n    if not getattr(g, u'user', None):\n        _identify_user_default()\n\n    # If we have a user but not the userobj let's get the userobj. This means\n    # that IAuthenticator extensions do not need to access the user model\n    # directly.\n    if g.user and not getattr(g, u'userobj', None):\n        g.userobj = model.User.by_name(g.user)\n\n    # general settings\n    if g.user:\n        g.author = g.user\n    else:\n        g.author = g.remote_addr\n    g.author = text_type(g.author)\n\n\ndef _identify_user_default():\n    u'''\n    Identifies the user using two methods:\n    a) If they logged into the web interface then repoze.who will\n       set REMOTE_USER.\n    b) For API calls they may set a header with an API key.\n    '''\n\n    # environ['REMOTE_USER'] is set by repoze.who if it authenticates a\n    # user's cookie. But repoze.who doesn't check the user (still) exists\n    # in our database - we need to do that here. (Another way would be\n    # with an userid_checker, but that would mean another db access.\n    # See: http://docs.repoze.org/who/1.0/narr.html#module-repoze.who\\\n    # .plugins.sql )\n    g.user = request.environ.get(u'REMOTE_USER', u'')\n    if g.user:\n        g.user = g.user.decode(u'utf8')\n        g.userobj = model.User.by_name(g.user)\n\n        if g.userobj is None or not g.userobj.is_active():\n\n            # This occurs when a user that was still logged in is deleted, or\n            # when you are logged in, clean db and then restart (or when you\n            # change your username). There is no user object, so even though\n            # repoze thinks you are logged in and your cookie has\n            # ckan_display_name, we need to force user to logout and login\n            # again to get the User object.\n\n            ev = request.environ\n            if u'repoze.who.plugins' in ev:\n                pth = getattr(ev[u'repoze.who.plugins'][u'friendlyform'],\n                              u'logout_handler_path')\n                redirect(pth)\n    else:\n        g.userobj = _get_user_for_apikey()\n        if g.userobj is not None:\n            g.user = g.userobj.name\n\n\ndef _get_user_for_apikey():\n    apikey_header_name = config.get(APIKEY_HEADER_NAME_KEY,\n                                    APIKEY_HEADER_NAME_DEFAULT)\n    apikey = request.headers.get(apikey_header_name, u'')\n    if not apikey:\n        apikey = request.environ.get(apikey_header_name, u'')\n    if not apikey:\n        # For misunderstanding old documentation (now fixed).\n        apikey = request.environ.get(u'HTTP_AUTHORIZATION', u'')\n    if not apikey:\n        apikey = request.environ.get(u'Authorization', u'')\n        # Forget HTTP Auth credentials (they have spaces).\n        if u' ' in apikey:\n            apikey = u''\n    if not apikey:\n        return None\n    apikey = apikey.decode(u'utf8', u'ignore')\n    log.debug(u'Received API Key: %s' % apikey)\n    query = model.Session.query(model.User)\n    user = query.filter_by(apikey=apikey).first()\n    return user\n", "path": "ckan/views/__init__.py"}], "after_files": [{"content": "# encoding: utf-8\n\nfrom paste.deploy.converters import asbool\nfrom six import text_type\n\nimport ckan.model as model\nfrom ckan.common import g, request, config, session\nfrom ckan.lib.helpers import redirect_to as redirect\nimport ckan.plugins as p\n\nimport logging\nlog = logging.getLogger(__name__)\n\nAPIKEY_HEADER_NAME_KEY = u'apikey_header_name'\nAPIKEY_HEADER_NAME_DEFAULT = u'X-CKAN-API-Key'\n\n\ndef check_session_cookie(response):\n    u'''\n    The cookies for auth (auth_tkt) and session (ckan) are separate. This\n    checks whether a user is logged in, and determines the validity of the\n    session cookie, removing it if necessary.\n    '''\n    for cookie in request.cookies:\n        # Remove the ckan session cookie if logged out.\n        if cookie == u'ckan' and not getattr(g, u'user', None):\n            # Check session for valid data (including flash messages)\n            is_valid_cookie_data = False\n            for key, value in session.items():\n                if not key.startswith(u'_') and value:\n                    is_valid_cookie_data = True\n                    break\n            if not is_valid_cookie_data:\n                if session.id:\n                    log.debug(u'No valid session data - deleting session')\n                    log.debug(u'Session: %r', session.items())\n                    session.delete()\n                else:\n                    log.debug(u'No session id - deleting session cookie')\n                    response.delete_cookie(cookie)\n        # Remove auth_tkt repoze.who cookie if user not logged in.\n        elif cookie == u'auth_tkt' and not session.id:\n            response.delete_cookie(cookie)\n\n    return response\n\n\ndef set_cors_headers_for_response(response):\n    u'''\n    Set up Access Control Allow headers if either origin_allow_all is True, or\n    the request Origin is in the origin_whitelist.\n    '''\n    if config.get(u'ckan.cors.origin_allow_all') \\\n       and request.headers.get(u'Origin'):\n\n        cors_origin_allowed = None\n        if asbool(config.get(u'ckan.cors.origin_allow_all')):\n            cors_origin_allowed = b'*'\n        elif config.get(u'ckan.cors.origin_whitelist') and \\\n                request.headers.get(u'Origin') \\\n                in config[u'ckan.cors.origin_whitelist'].split(u' '):\n            # set var to the origin to allow it.\n            cors_origin_allowed = request.headers.get(u'Origin')\n\n        if cors_origin_allowed is not None:\n            response.headers[b'Access-Control-Allow-Origin'] = \\\n                cors_origin_allowed\n            response.headers[b'Access-Control-Allow-Methods'] = \\\n                b'POST, PUT, GET, DELETE, OPTIONS'\n            response.headers[b'Access-Control-Allow-Headers'] = \\\n                b'X-CKAN-API-KEY, Authorization, Content-Type'\n\n    return response\n\n\ndef identify_user():\n    u'''Try to identify the user\n    If the user is identified then:\n      g.user = user name (unicode)\n      g.userobj = user object\n      g.author = user name\n    otherwise:\n      g.user = None\n      g.userobj = None\n      g.author = user's IP address (unicode)\n\n    Note: Remember, when running under Pylons, `g` is the Pylons `c` object\n    '''\n    # see if it was proxied first\n    g.remote_addr = request.environ.get(u'HTTP_X_FORWARDED_FOR', u'')\n    if not g.remote_addr:\n        g.remote_addr = request.environ.get(u'REMOTE_ADDR',\n                                            u'Unknown IP Address')\n\n    # Authentication plugins get a chance to run here break as soon as a user\n    # is identified.\n    authenticators = p.PluginImplementations(p.IAuthenticator)\n    if authenticators:\n        for item in authenticators:\n            item.identify()\n            try:\n                if g.user:\n                    break\n            except AttributeError:\n                continue\n\n    # We haven't identified the user so try the default methods\n    if not getattr(g, u'user', None):\n        _identify_user_default()\n\n    # If we have a user but not the userobj let's get the userobj. This means\n    # that IAuthenticator extensions do not need to access the user model\n    # directly.\n    if g.user and not getattr(g, u'userobj', None):\n        g.userobj = model.User.by_name(g.user)\n\n    # general settings\n    if g.user:\n        g.author = g.user\n    else:\n        g.author = g.remote_addr\n    g.author = text_type(g.author)\n\n\ndef _identify_user_default():\n    u'''\n    Identifies the user using two methods:\n    a) If they logged into the web interface then repoze.who will\n       set REMOTE_USER.\n    b) For API calls they may set a header with an API key.\n    '''\n\n    # environ['REMOTE_USER'] is set by repoze.who if it authenticates a\n    # user's cookie. But repoze.who doesn't check the user (still) exists\n    # in our database - we need to do that here. (Another way would be\n    # with an userid_checker, but that would mean another db access.\n    # See: http://docs.repoze.org/who/1.0/narr.html#module-repoze.who\\\n    # .plugins.sql )\n    g.user = request.environ.get(u'REMOTE_USER', u'')\n    if g.user:\n        g.user = g.user.decode(u'utf8')\n        g.userobj = model.User.by_name(g.user)\n\n        if g.userobj is None or not g.userobj.is_active():\n\n            # This occurs when a user that was still logged in is deleted, or\n            # when you are logged in, clean db and then restart (or when you\n            # change your username). There is no user object, so even though\n            # repoze thinks you are logged in and your cookie has\n            # ckan_display_name, we need to force user to logout and login\n            # again to get the User object.\n\n            ev = request.environ\n            if u'repoze.who.plugins' in ev:\n                pth = getattr(ev[u'repoze.who.plugins'][u'friendlyform'],\n                              u'logout_handler_path')\n                redirect(pth)\n    else:\n        g.userobj = _get_user_for_apikey()\n        if g.userobj is not None:\n            g.user = g.userobj.name\n\n\ndef _get_user_for_apikey():\n    apikey_header_name = config.get(APIKEY_HEADER_NAME_KEY,\n                                    APIKEY_HEADER_NAME_DEFAULT)\n    apikey = request.headers.get(apikey_header_name, u'')\n    if not apikey:\n        apikey = request.environ.get(apikey_header_name, u'')\n    if not apikey:\n        # For misunderstanding old documentation (now fixed).\n        apikey = request.environ.get(u'HTTP_AUTHORIZATION', u'')\n    if not apikey:\n        apikey = request.environ.get(u'Authorization', u'')\n        # Forget HTTP Auth credentials (they have spaces).\n        if u' ' in apikey:\n            apikey = u''\n    if not apikey:\n        return None\n    apikey = apikey.decode(u'utf8', u'ignore')\n    log.debug(u'Received API Key: %s' % apikey)\n    query = model.Session.query(model.User)\n    user = query.filter_by(apikey=apikey).first()\n    return user\n", "path": "ckan/views/__init__.py"}]}