Skip to content

Commit

Permalink
[master][#1659][config,lib]: One more fix. This is the redirect when …
Browse files Browse the repository at this point in the history
…you click on a page that you are not allowed to view (e.g. Create Group when not logged in).
  • Loading branch information
David Read committed Jan 16, 2012
1 parent 7eb7ddd commit 75d0bec
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ckan/config/middleware.py
Expand Up @@ -80,6 +80,8 @@ def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
from ckan.lib import repoze_patch
OpenIdIdentificationPlugin.identify = repoze_patch.identify
OpenIdIdentificationPlugin.redirect_to_logged_in = repoze_patch.redirect_to_logged_in
OpenIdIdentificationPlugin._redirect_to_loginform = repoze_patch._redirect_to_loginform
OpenIdIdentificationPlugin.challenge = repoze_patch.challenge

who_parser.identifiers = [i for i in who_parser.identifiers if \
not isinstance(i, OpenIdIdentificationPlugin)]
Expand Down
117 changes: 117 additions & 0 deletions ckan/lib/repoze_patch.py
Expand Up @@ -122,3 +122,120 @@ def redirect_to_logged_in(self, environ):
res.status = 302
res.location = url
environ['repoze.who.application'] = res

def challenge(self, environ, status, app_headers, forget_headers):
"""the challenge method is called when the ``IChallengeDecider``
in ``classifiers.py`` returns ``True``. This is the case for either a
``401`` response from the client or if the key
``repoze.whoplugins.openid.openidrepoze.whoplugins.openid.openid``
is present in the WSGI environment.
The name of this key can be adjusted via the ``openid_field`` configuration
directive.
The latter is the case when we are coming from the login page where the
user entered the openid to use.
``401`` can come back in any case and then we simply redirect to the login
form which is configured in the who configuration as ``login_form_url``.
TODO: make the environment key to check also configurable in the challenge_decider.
For the OpenID flow check `the OpenID library documentation
<http://openidenabled.com/files/python-openid/docs/2.2.1/openid.consumer.consumer-module.html>`_
"""
request = Request(environ)

# check for the field present, if not redirect to login_form
if not request.params.has_key(self.openid_field):
# redirect to login_form
res = Response()
res.status = 302
res.location = get_full_path(self.login_form_url, environ)+"?%s=%s" %(self.came_from_field, request.url)
return res

# now we have an openid from the user in the request
openid_url = request.params[self.openid_field]
if environ['repoze.who.logger'] is not None:
environ['repoze.who.logger'].debug('starting openid request for : %s ' %openid_url)

try:
# we create a new Consumer and start the discovery process for the URL given
# in the library openid_request is called auth_req btw.
openid_request = self.get_consumer(environ).begin(openid_url)

if len(self.ax_require.values()) or len(self.ax_optional.values()):
fetch_request = ax.FetchRequest()
for value in self.ax_require.values():
fetch_request.add(ax.AttrInfo(value, required=True))
for value in self.ax_optional.values():
fetch_request.add(ax.AttrInfo(value, required=False))
openid_request.addExtension(fetch_request)

if len(self.sreg_require) or len(self.sreg_optional):
sreq = sreg.SRegRequest(required=self.sreg_require, optional=self.sreg_optional)
openid_request.addExtension(sreq)


except consumer.DiscoveryFailure, exc:
# eventually no openid server could be found
environ[self.error_field] = 'Error in discovery: %s' %exc[0]
environ['repoze.who.logger'].info('Error in discovery: %s ' %exc[0])
return self._redirect_to_loginform(environ)
except KeyError, exc:
# TODO: when does that happen, why does plone.openid use "pass" here?
environ[self.error_field] = 'Error in discovery: %s' %exc[0]
environ['repoze.who.logger'].info('Error in discovery: %s ' %exc[0])
return self._redirect_to_loginform(environ)
return None

# not sure this can still happen but we are making sure.
# should actually been handled by the DiscoveryFailure exception above
if openid_request is None:
environ[self.error_field] = 'No OpenID services found for %s' %openid_url
environ['repoze.who.logger'].info('No OpenID services found for: %s ' %openid_url)
return self._redirect_to_loginform(environ)

# we have to tell the openid provider where to send the user after login
# so we need to compute this from our path and application URL
# we simply use the URL we are at right now (which is the form)
# this will be captured by the repoze.who identification plugin later on
# it will check if some valid openid response is coming back
# trust_root is the URL (realm) which will be presented to the user
# in the login process and should be your applications url
# TODO: make this configurable?
# return_to is the actual URL to be used for returning to this app
return_to = request.path_url # we return to this URL here
trust_root = request.application_url
if environ['repoze.who.logger'] is not None:
environ['repoze.who.logger'].debug('setting return_to URL to : %s ' %return_to)

# TODO: usually you should check openid_request.shouldSendRedirect()
# but this might say you have to use a form redirect and I don't get why
# so we do the same as plone.openid and ignore it.

# TODO: we might also want to give the application some way of adding
# extensions to this message.
redirect_url = openid_request.redirectURL(trust_root, return_to)
# # , immediate=False)
res = Response()
res.status = 302
res.location = redirect_url
if environ['repoze.who.logger'] is not None:
environ['repoze.who.logger'].debug('redirecting to : %s ' %redirect_url)

# now it's redirecting and might come back via the identify() method
# from the openid provider once the user logged in there.
return res


def _redirect_to_loginform(self, environ={}):
"""redirect the user to the login form"""
res = Response()
res.status = 302
q=''
ef = environ.get(self.error_field, None)
if ef is not None:
q='?%s=%s' %(self.error_field, ef)
res.location = get_full_path(self.login_form_url, environ)+q
return res

0 comments on commit 75d0bec

Please sign in to comment.