Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

Commit

Permalink
Handle correctly Unauthorized exception
Browse files Browse the repository at this point in the history
  • Loading branch information
jfroche committed Nov 14, 2008
1 parent 385ccd1 commit b1aef49
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 37 deletions.
9 changes: 7 additions & 2 deletions docs/HISTORY.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
Changelog
=========

0.1 - Unreleased
----------------
0.2 - (2008-11-14)
------------------

* Handle correctly Unauthorized exception

0.1 - (2008-11-13)
------------------

* Initial release

3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages
import os

version = '0.1'
version = '0.2'

setup(name='z3c.soap',
version=version,
Expand Down Expand Up @@ -29,6 +29,7 @@
zip_safe=False,
install_requires=[
'setuptools',
'Products.PluggableAuthService==1.5.3',
'ZSI'],
entry_points="""
# -*- Entry points: -*-
Expand Down
3 changes: 2 additions & 1 deletion z3c/soap/HTTPRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def processInputs(
other=self.other
taintedform=self.taintedform


meth=None
fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1)
if not hasattr(fs,'list') or fs.list is None:
Expand Down Expand Up @@ -721,6 +722,6 @@ def processInputs(
HTTPRequest.processInputs = processInputs
import logging
logger = logging.getLogger('Zope')
logger.info("""SOAPSupport: modified ZPublisher.HTTPRequest.processInputs, Dirk Datzert, 2007-02-06, version for Zope-2.8.x/Zope-2.9.x/Zope-2.10.x\n""")
logger.info("z3c.soap: modified ZPublisher.HTTPRequest.processInputs")

# vi:ts=4
28 changes: 13 additions & 15 deletions z3c/soap/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ when we registered it:
... </SOAP-ENV:Envelope>
... """)
HTTP/1.0 401 Unauthorized
...
Content-Length: ...
Content-Type: text/xml
Www-Authenticate: basic realm="Zope2"
<BLANKLINE>
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Not authorized</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>


Parameters
Expand Down Expand Up @@ -575,16 +579,6 @@ Datetimes appear to work:



Complex Types
-------------

For ZSI to successfully marshal complex values (instances of classes),
you must define a typecode that describes the object (see the ZSI docs
for details on defining typecodes). Once the typecode is defined, it must
be accessible through an instance via the attribute name 'typecode' to
be automatically marshalled.


Faults
------

Expand Down Expand Up @@ -617,16 +611,20 @@ directly. Either case causes a fault response to be returned:
Content-Length: ...
Content-Type: text/xml
<BLANKLINE>
<SOAP-ENV:Envelope ...
Processing Failure
<BLANKLINE>
Unparseable integer
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Processing Failure</faultstring><detail><ZSI:FaultDetail><ZSI:string>
...


Complex Types
-------------

For ZSI to successfully marshal complex values (instances of classes),
you must define a typecode that describes the object (see the ZSI docs
for details on defining typecodes). Once the typecode is defined, it must
be accessible through an instance via the attribute name 'typecode' to
be automatically marshalled.


>>> print http(r"""
... POST /test_folder_1_ HTTP/1.0
... Authorization: Basic %s:%s
Expand Down
51 changes: 51 additions & 0 deletions z3c/soap/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,54 @@ def publish(request, module_name, after_list, debug=0,

import ZPublisher.Publish
ZPublisher.Publish.publish = publish

from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHelper
from urllib import quote


def unauthorized(self):
req = self.REQUEST
resp = req['RESPONSE']

# If we set the auth cookie before, delete it now.
if self.cookie_name in resp.cookies:
del resp.cookies[self.cookie_name]

# Redirect if desired.
url = self.getLoginURL()
if ISOAPRequest.providedBy(req):
#no need to redirect if it's a soap request
return 0

if url is not None:
came_from = req.get('came_from', None)

if came_from is None:
came_from = req.get('URL', '')
query = req.get('QUERY_STRING')
if query:
if not query.startswith('?'):
query = '?' + query
came_from = came_from + query
else:
# If came_from contains a value it means the user
# must be coming through here a second time
# Reasons could be typos when providing credentials
# or a redirect loop (see below)
req_url = req.get('URL', '')

if req_url and req_url == url:
# Oops... The login_form cannot be reached by the user -
# it might be protected itself due to misconfiguration -
# the only sane thing to do is to give up because we are
# in an endless redirect loop.
return 0

url = url + '?came_from=%s' % quote(came_from)
resp.redirect(url, lock=1)
return 1

# Could not challenge.
return 0

CookieAuthHelper.unauthorized = unauthorized
25 changes: 7 additions & 18 deletions z3c/soap/soap.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ def __delattr__(self, name):
def setBody(self, body, title='', is_error=0, bogus_str_search=None):
if isinstance(body, Fault):
# Convert Fault object to SOAP response.
#body = buildSOAP(args=body, config=Config)
body = ZSI.FaultFromException(body, 0)
body = body.AsSOAP()
else:
# Marshall our body as an SOAP response. Strings will be sent
Expand All @@ -101,7 +99,6 @@ def setBody(self, body, title='', is_error=0, bogus_str_search=None):
try:
target = self._method
body = premarshal(body)
#output = StringIO()
result = body
if hasattr(result, 'typecode'):
tc = result.typecode
Expand All @@ -122,35 +119,27 @@ def setBody(self, body, title='', is_error=0, bogus_str_search=None):

def exception(self, fatal=0, info=None,
absuri_match=None, tag_search=None):
# Fetch our exception info. t is type, v is value and tb is the
# traceback object.
if type(info) is type(()) and len(info)==3:
if isinstance(info, tuple) and len(info)==3:
t, v, tb = info
else:
t, v, tb = sys.exc_info()

content = "".join(traceback.format_tb(tb))
logger = logging.getLogger('Zope')
logger.info('SOAPException: %s' % tb)
logger.info('SOAPException: %s' % content)
f=None
if t == 'Unauthorized' or t == Unauthorized or (
isinstance(t, types.ClassType) and issubclass(t, Unauthorized)):
realm=self._real.realm
if realm:
self._real.setHeader('WWW-Authenticate',
'basic realm="%s"' % realm, 1)
self._real.setStatus(401)
return None

# Create an appropriate Fault object. Unfortunately, we throw away
# most of the debugging information. More useful error reporting is
# left as an exercise for the reader.
f=None
if not isinstance(v, Fault):
self._real.setStatus(401)
f = ZSI.Fault(Fault.Server, "Not authorized")
elif not isinstance(v, Fault):
self._real.setStatus(500)
f = ZSI.FaultFromException(u"%s : %s" % (v, content), 0)
# Do the damage.
self.setBody(f)
self._real.setStatus(500)

return tb

def _setHeader(self):
Expand Down

0 comments on commit b1aef49

Please sign in to comment.