Use 401 error when missing token and 403 when forbidden.
authorAntony Chazapis <chazapis@gmail.com>
Fri, 21 Oct 2011 13:16:34 +0000 (16:16 +0300)
committerAntony Chazapis <chazapis@gmail.com>
Fri, 21 Oct 2011 13:16:34 +0000 (16:16 +0300)
Fixes #1369

docs/source/devguide.rst
pithos/api/functions.py
pithos/api/util.py
pithos/public/functions.py
tools/test

index baa25dc..a4f70eb 100644 (file)
@@ -25,7 +25,7 @@ Document Revisions
 =========================  ================================
 Revision                   Description
 =========================  ================================
 =========================  ================================
 Revision                   Description
 =========================  ================================
-0.7 (Oct 17, 2011)         Suggest upload/download methods using hashmaps.
+0.7 (Oct 21, 2011)         Suggest upload/download methods using hashmaps.
 \                          Propose syncing algorithm.
 \                          Support cross-account object copy and move.
 \                          Pass token as a request parameter when using ``POST`` via an HTML form.
 \                          Propose syncing algorithm.
 \                          Support cross-account object copy and move.
 \                          Pass token as a request parameter when using ``POST`` via an HTML form.
@@ -108,7 +108,8 @@ The allowable request operations and respective return codes per level are prese
 Return Code                Description
 =========================  ================================
 400 (Bad Request)          The request is invalid
 Return Code                Description
 =========================  ================================
 400 (Bad Request)          The request is invalid
-401 (Unauthorized)         Request not allowed
+401 (Unauthorized)         Missing or invalid token
+403 (Forbidden)            Request not allowed
 404 (Not Found)            The requested resource was not found
 503 (Service Unavailable)  The request cannot be completed because of an internal error
 =========================  ================================
 404 (Not Found)            The requested resource was not found
 503 (Service Unavailable)  The request cannot be completed because of an internal error
 =========================  ================================
index 2d21ed9..7c7005e 100644 (file)
@@ -42,7 +42,7 @@ from django.utils.http import parse_etags
 from django.utils.encoding import smart_unicode, smart_str
 from xml.dom import minidom
 
 from django.utils.encoding import smart_unicode, smart_str
 from xml.dom import minidom
 
-from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, ItemNotFound, Conflict,
+from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, Forbidden, ItemNotFound, Conflict,
     LengthRequired, PreconditionFailed, RequestEntityTooLarge, RangeNotSatisfiable, UnprocessableEntity)
 from pithos.api.util import (rename_meta_key, format_header_key, printable_header_dict, get_account_headers,
     put_account_headers, get_container_headers, put_container_headers, get_object_headers, put_object_headers,
     LengthRequired, PreconditionFailed, RequestEntityTooLarge, RangeNotSatisfiable, UnprocessableEntity)
 from pithos.api.util import (rename_meta_key, format_header_key, printable_header_dict, get_account_headers,
     put_account_headers, get_container_headers, put_container_headers, get_object_headers, put_object_headers,
@@ -113,7 +113,7 @@ def object_demux(request, v_account, v_container, v_object):
 def authenticate(request):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
 def authenticate(request):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     x_auth_user = request.META.get('HTTP_X_AUTH_USER')
     #                       badRequest (400)
     
     x_auth_user = request.META.get('HTTP_X_AUTH_USER')
@@ -160,7 +160,7 @@ def account_list(request):
             meta = request.backend.get_account_meta(request.user, x)
             groups = request.backend.get_account_groups(request.user, x)
         except NotAllowedError:
             meta = request.backend.get_account_meta(request.user, x)
             groups = request.backend.get_account_groups(request.user, x)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         else:
             rename_meta_key(meta, 'modified', 'last_modified')
             rename_meta_key(meta, 'until_timestamp', 'x_account_until_timestamp')
         else:
             rename_meta_key(meta, 'modified', 'last_modified')
             rename_meta_key(meta, 'until_timestamp', 'x_account_until_timestamp')
@@ -179,7 +179,7 @@ def account_list(request):
 def account_meta(request, v_account):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
 def account_meta(request, v_account):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -188,7 +188,7 @@ def account_meta(request, v_account):
         groups = request.backend.get_account_groups(request.user, v_account)
         policy = request.backend.get_account_policy(request.user, v_account)
     except NotAllowedError:
         groups = request.backend.get_account_groups(request.user, v_account)
         policy = request.backend.get_account_policy(request.user, v_account)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     
     validate_modification_preconditions(request, meta)
     
     
     validate_modification_preconditions(request, meta)
     
@@ -200,7 +200,7 @@ def account_meta(request, v_account):
 def account_update(request, v_account):
     # Normal Response Codes: 202
     # Error Response Codes: serviceUnavailable (503),
 def account_update(request, v_account):
     # Normal Response Codes: 202
     # Error Response Codes: serviceUnavailable (503),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     meta, groups = get_account_headers(request)
     #                       badRequest (400)
     
     meta, groups = get_account_headers(request)
@@ -212,7 +212,7 @@ def account_update(request, v_account):
             request.backend.update_account_groups(request.user, v_account,
                                                     groups, replace)
         except NotAllowedError:
             request.backend.update_account_groups(request.user, v_account,
                                                     groups, replace)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except ValueError:
             raise BadRequest('Invalid groups header')
     if meta or replace:
         except ValueError:
             raise BadRequest('Invalid groups header')
     if meta or replace:
@@ -220,7 +220,7 @@ def account_update(request, v_account):
             request.backend.update_account_meta(request.user, v_account, meta,
                                                 replace)
         except NotAllowedError:
             request.backend.update_account_meta(request.user, v_account, meta,
                                                 replace)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
     return HttpResponse(status=202)
 
 @api_method('GET', format_allowed=True)
     return HttpResponse(status=202)
 
 @api_method('GET', format_allowed=True)
@@ -228,7 +228,7 @@ def container_list(request, v_account):
     # Normal Response Codes: 200, 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 200, 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -237,7 +237,7 @@ def container_list(request, v_account):
         groups = request.backend.get_account_groups(request.user, v_account)
         policy = request.backend.get_account_policy(request.user, v_account)
     except NotAllowedError:
         groups = request.backend.get_account_groups(request.user, v_account)
         policy = request.backend.get_account_policy(request.user, v_account)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     
     validate_modification_preconditions(request, meta)
     
     
     validate_modification_preconditions(request, meta)
     
@@ -257,7 +257,7 @@ def container_list(request, v_account):
         containers = request.backend.list_containers(request.user, v_account,
                                                 marker, limit, shared, until)
     except NotAllowedError:
         containers = request.backend.list_containers(request.user, v_account,
                                                 marker, limit, shared, until)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         containers = []
     
     except NameError:
         containers = []
     
@@ -278,7 +278,7 @@ def container_list(request, v_account):
             policy = request.backend.get_container_policy(request.user,
                                                             v_account, x)
         except NotAllowedError:
             policy = request.backend.get_container_policy(request.user,
                                                             v_account, x)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             pass
         else:
         except NameError:
             pass
         else:
@@ -300,7 +300,7 @@ def container_meta(request, v_account, v_container):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -312,7 +312,7 @@ def container_meta(request, v_account, v_container):
         policy = request.backend.get_container_policy(request.user, v_account,
                                                         v_container)
     except NotAllowedError:
         policy = request.backend.get_container_policy(request.user, v_account,
                                                         v_container)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     
     except NameError:
         raise ItemNotFound('Container does not exist')
     
@@ -327,7 +327,7 @@ def container_create(request, v_account, v_container):
     # Normal Response Codes: 201, 202
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 201, 202
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     meta, policy = get_container_headers(request)
     #                       badRequest (400)
     
     meta, policy = get_container_headers(request)
@@ -336,7 +336,7 @@ def container_create(request, v_account, v_container):
         request.backend.put_container(request.user, v_account, v_container, policy)
         ret = 201
     except NotAllowedError:
         request.backend.put_container(request.user, v_account, v_container, policy)
         ret = 201
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except ValueError:
         raise BadRequest('Invalid policy header')
     except NameError:
     except ValueError:
         raise BadRequest('Invalid policy header')
     except NameError:
@@ -347,7 +347,7 @@ def container_create(request, v_account, v_container):
             request.backend.update_container_policy(request.user, v_account,
                                             v_container, policy, replace=False)
         except NotAllowedError:
             request.backend.update_container_policy(request.user, v_account,
                                             v_container, policy, replace=False)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Container does not exist')
         except ValueError:
         except NameError:
             raise ItemNotFound('Container does not exist')
         except ValueError:
@@ -357,7 +357,7 @@ def container_create(request, v_account, v_container):
             request.backend.update_container_meta(request.user, v_account,
                                             v_container, meta, replace=False)
         except NotAllowedError:
             request.backend.update_container_meta(request.user, v_account,
                                             v_container, meta, replace=False)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Container does not exist')
     
         except NameError:
             raise ItemNotFound('Container does not exist')
     
@@ -368,7 +368,7 @@ def container_update(request, v_account, v_container):
     # Normal Response Codes: 202
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 202
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     meta, policy = get_container_headers(request)
     #                       badRequest (400)
     
     meta, policy = get_container_headers(request)
@@ -380,7 +380,7 @@ def container_update(request, v_account, v_container):
             request.backend.update_container_policy(request.user, v_account,
                                                 v_container, policy, replace)
         except NotAllowedError:
             request.backend.update_container_policy(request.user, v_account,
                                                 v_container, policy, replace)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Container does not exist')
         except ValueError:
         except NameError:
             raise ItemNotFound('Container does not exist')
         except ValueError:
@@ -390,7 +390,7 @@ def container_update(request, v_account, v_container):
             request.backend.update_container_meta(request.user, v_account,
                                                     v_container, meta, replace)
         except NotAllowedError:
             request.backend.update_container_meta(request.user, v_account,
                                                     v_container, meta, replace)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Container does not exist')
     
         except NameError:
             raise ItemNotFound('Container does not exist')
     
@@ -417,7 +417,7 @@ def container_delete(request, v_account, v_container):
     # Error Response Codes: serviceUnavailable (503),
     #                       conflict (409),
     #                       itemNotFound (404),
     # Error Response Codes: serviceUnavailable (503),
     #                       conflict (409),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -425,7 +425,7 @@ def container_delete(request, v_account, v_container):
         request.backend.delete_container(request.user, v_account, v_container,
                                             until)
     except NotAllowedError:
         request.backend.delete_container(request.user, v_account, v_container,
                                             until)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     except IndexError:
     except NameError:
         raise ItemNotFound('Container does not exist')
     except IndexError:
@@ -437,7 +437,7 @@ def object_list(request, v_account, v_container):
     # Normal Response Codes: 200, 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 200, 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -449,7 +449,7 @@ def object_list(request, v_account, v_container):
         policy = request.backend.get_container_policy(request.user, v_account,
                                                         v_container)
     except NotAllowedError:
         policy = request.backend.get_container_policy(request.user, v_account,
                                                         v_container)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     
     except NameError:
         raise ItemNotFound('Container does not exist')
     
@@ -498,7 +498,7 @@ def object_list(request, v_account, v_container):
                                     v_container, prefix, delimiter, marker,
                                     limit, virtual, keys, shared, until)
     except NotAllowedError:
                                     v_container, prefix, delimiter, marker,
                                     limit, virtual, keys, shared, until)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     
     except NameError:
         raise ItemNotFound('Container does not exist')
     
@@ -529,7 +529,7 @@ def object_list(request, v_account, v_container):
                     permissions = None
                     public = None
             except NotAllowedError:
                     permissions = None
                     public = None
             except NotAllowedError:
-                raise Unauthorized('Access denied')
+                raise Forbidden('Not allowed')
             except NameError:
                 pass
             else:
             except NameError:
                 pass
             else:
@@ -553,7 +553,7 @@ def object_meta(request, v_account, v_container, v_object):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     version = request.GET.get('version')
     #                       badRequest (400)
     
     version = request.GET.get('version')
@@ -569,7 +569,7 @@ def object_meta(request, v_account, v_container, v_object):
             permissions = None
             public = None
     except NotAllowedError:
             permissions = None
             public = None
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Object does not exist')
     except IndexError:
     except NameError:
         raise ItemNotFound('Object does not exist')
     except IndexError:
@@ -599,7 +599,7 @@ def object_read(request, v_account, v_container, v_object):
     #                       rangeNotSatisfiable (416),
     #                       preconditionFailed (412),
     #                       itemNotFound (404),
     #                       rangeNotSatisfiable (416),
     #                       preconditionFailed (412),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400),
     #                       notModified (304)
     
     #                       badRequest (400),
     #                       notModified (304)
     
@@ -614,7 +614,7 @@ def object_read(request, v_account, v_container, v_object):
             v = request.backend.list_versions(request.user, v_account,
                                                 v_container, v_object)
         except NotAllowedError:
             v = request.backend.list_versions(request.user, v_account,
                                                 v_container, v_object)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         d = {'versions': v}
         if request.serialization == 'xml':
             d['object'] = v_object
         d = {'versions': v}
         if request.serialization == 'xml':
             d['object'] = v_object
@@ -638,7 +638,7 @@ def object_read(request, v_account, v_container, v_object):
             permissions = None
             public = None
     except NotAllowedError:
             permissions = None
             public = None
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Object does not exist')
     except IndexError:
     except NameError:
         raise ItemNotFound('Object does not exist')
     except IndexError:
@@ -665,7 +665,7 @@ def object_read(request, v_account, v_container, v_object):
             objects = request.backend.list_objects(request.user, v_account,
                                 src_container, prefix=src_name, virtual=False)
         except NotAllowedError:
             objects = request.backend.list_objects(request.user, v_account,
                                 src_container, prefix=src_name, virtual=False)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except ValueError:
             raise BadRequest('Invalid X-Object-Manifest header')
         except NameError:
         except ValueError:
             raise BadRequest('Invalid X-Object-Manifest header')
         except NameError:
@@ -678,7 +678,7 @@ def object_read(request, v_account, v_container, v_object):
                 sizes.append(s)
                 hashmaps.append(h)
         except NotAllowedError:
                 sizes.append(s)
                 hashmaps.append(h)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Object does not exist')
         except IndexError:
         except NameError:
             raise ItemNotFound('Object does not exist')
         except IndexError:
@@ -690,7 +690,7 @@ def object_read(request, v_account, v_container, v_object):
             sizes.append(s)
             hashmaps.append(h)
         except NotAllowedError:
             sizes.append(s)
             hashmaps.append(h)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Object does not exist')
         except IndexError:
         except NameError:
             raise ItemNotFound('Object does not exist')
         except IndexError:
@@ -727,7 +727,7 @@ def object_write(request, v_account, v_container, v_object):
     #                       lengthRequired (411),
     #                       conflict (409),
     #                       itemNotFound (404),
     #                       lengthRequired (411),
     #                       conflict (409),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     # Evaluate conditions.
     #                       badRequest (400)
     
     # Evaluate conditions.
@@ -736,7 +736,7 @@ def object_write(request, v_account, v_container, v_object):
             meta = request.backend.get_object_meta(request.user, v_account,
                                                         v_container, v_object)
         except NotAllowedError:
             meta = request.backend.get_object_meta(request.user, v_account,
                                                         v_container, v_object)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             meta = {}
         validate_matching_preconditions(request, meta)
         except NameError:
             meta = {}
         validate_matching_preconditions(request, meta)
@@ -829,7 +829,7 @@ def object_write(request, v_account, v_container, v_object):
                         v_account, v_container, v_object, size, hashmap, meta,
                         True, permissions)
     except NotAllowedError:
                         v_account, v_container, v_object, size, hashmap, meta,
                         True, permissions)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except IndexError, e:
         raise Conflict('\n'.join(e.data) + '\n')
     except NameError:
     except IndexError, e:
         raise Conflict('\n'.join(e.data) + '\n')
     except NameError:
@@ -845,7 +845,7 @@ def object_write(request, v_account, v_container, v_object):
             request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
         except NotAllowedError:
             request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Object does not exist')
     
         except NameError:
             raise ItemNotFound('Object does not exist')
     
@@ -859,7 +859,7 @@ def object_write_form(request, v_account, v_container, v_object):
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     if not request.FILES.has_key('X-Object-Data'):
     #                       badRequest (400)
     
     if not request.FILES.has_key('X-Object-Data'):
@@ -883,7 +883,7 @@ def object_write_form(request, v_account, v_container, v_object):
         version_id = request.backend.update_object_hashmap(request.user,
                     v_account, v_container, v_object, size, hashmap, meta, True)
     except NotAllowedError:
         version_id = request.backend.update_object_hashmap(request.user,
                     v_account, v_container, v_object, size, hashmap, meta, True)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     except QuotaError:
     except NameError:
         raise ItemNotFound('Container does not exist')
     except QuotaError:
@@ -899,7 +899,7 @@ def object_copy(request, v_account, v_container, v_object):
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True)
     #                       badRequest (400)
     
     dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True)
@@ -920,7 +920,7 @@ def object_copy(request, v_account, v_container, v_object):
             meta = request.backend.get_object_meta(request.user, v_account,
                                             v_container, v_object, src_version)
         except NotAllowedError:
             meta = request.backend.get_object_meta(request.user, v_account,
                                             v_container, v_object, src_version)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except (NameError, IndexError):
             raise ItemNotFound('Container or object does not exist')
         validate_matching_preconditions(request, meta)
         except (NameError, IndexError):
             raise ItemNotFound('Container or object does not exist')
         validate_matching_preconditions(request, meta)
@@ -936,7 +936,7 @@ def object_move(request, v_account, v_container, v_object):
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 201
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True)
     #                       badRequest (400)
     
     dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True)
@@ -956,7 +956,7 @@ def object_move(request, v_account, v_container, v_object):
             meta = request.backend.get_object_meta(request.user, v_account,
                                                     v_container, v_object)
         except NotAllowedError:
             meta = request.backend.get_object_meta(request.user, v_account,
                                                     v_container, v_object)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Container or object does not exist')
         validate_matching_preconditions(request, meta)
         except NameError:
             raise ItemNotFound('Container or object does not exist')
         validate_matching_preconditions(request, meta)
@@ -973,7 +973,7 @@ def object_update(request, v_account, v_container, v_object):
     # Error Response Codes: serviceUnavailable (503),
     #                       conflict (409),
     #                       itemNotFound (404),
     # Error Response Codes: serviceUnavailable (503),
     #                       conflict (409),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     meta, permissions, public = get_object_headers(request)
     content_type = meta.get('Content-Type')
     #                       badRequest (400)
     meta, permissions, public = get_object_headers(request)
     content_type = meta.get('Content-Type')
@@ -984,7 +984,7 @@ def object_update(request, v_account, v_container, v_object):
         prev_meta = request.backend.get_object_meta(request.user, v_account,
                                                     v_container, v_object)
     except NotAllowedError:
         prev_meta = request.backend.get_object_meta(request.user, v_account,
                                                     v_container, v_object)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Object does not exist')
     
     except NameError:
         raise ItemNotFound('Object does not exist')
     
@@ -1012,7 +1012,7 @@ def object_update(request, v_account, v_container, v_object):
                 request.backend.update_object_permissions(request.user,
                                 v_account, v_container, v_object, permissions)
             except NotAllowedError:
                 request.backend.update_object_permissions(request.user,
                                 v_account, v_container, v_object, permissions)
             except NotAllowedError:
-                raise Unauthorized('Access denied')
+                raise Forbidden('Not allowed')
             except NameError:
                 raise ItemNotFound('Object does not exist')
             except ValueError:
             except NameError:
                 raise ItemNotFound('Object does not exist')
             except ValueError:
@@ -1024,7 +1024,7 @@ def object_update(request, v_account, v_container, v_object):
                 request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
             except NotAllowedError:
                 request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
             except NotAllowedError:
-                raise Unauthorized('Access denied')
+                raise Forbidden('Not allowed')
             except NameError:
                 raise ItemNotFound('Object does not exist')
         if meta or replace:
             except NameError:
                 raise ItemNotFound('Object does not exist')
         if meta or replace:
@@ -1032,7 +1032,7 @@ def object_update(request, v_account, v_container, v_object):
                 version_id = request.backend.update_object_meta(request.user,
                                 v_account, v_container, v_object, meta, replace)
             except NotAllowedError:
                 version_id = request.backend.update_object_meta(request.user,
                                 v_account, v_container, v_object, meta, replace)
             except NotAllowedError:
-                raise Unauthorized('Access denied')
+                raise Forbidden('Not allowed')
             except NameError:
                 raise ItemNotFound('Object does not exist')        
             response['X-Object-Version'] = version_id
             except NameError:
                 raise ItemNotFound('Object does not exist')        
             response['X-Object-Version'] = version_id
@@ -1053,7 +1053,7 @@ def object_update(request, v_account, v_container, v_object):
         size, hashmap = request.backend.get_object_hashmap(request.user,
                                             v_account, v_container, v_object)
     except NotAllowedError:
         size, hashmap = request.backend.get_object_hashmap(request.user,
                                             v_account, v_container, v_object)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Object does not exist')
     
     except NameError:
         raise ItemNotFound('Object does not exist')
     
@@ -1074,7 +1074,7 @@ def object_update(request, v_account, v_container, v_object):
             src_size, src_hashmap = request.backend.get_object_hashmap(request.user,
                                         src_account, src_container, src_name, src_version)
         except NotAllowedError:
             src_size, src_hashmap = request.backend.get_object_hashmap(request.user,
                                         src_account, src_container, src_name, src_version)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Source object does not exist')
         
         except NameError:
             raise ItemNotFound('Source object does not exist')
         
@@ -1160,7 +1160,7 @@ def object_update(request, v_account, v_container, v_object):
                         v_account, v_container, v_object, size, hashmap, meta,
                         replace, permissions)
     except NotAllowedError:
                         v_account, v_container, v_object, size, hashmap, meta,
                         replace, permissions)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Container does not exist')
     except ValueError:
     except NameError:
         raise ItemNotFound('Container does not exist')
     except ValueError:
@@ -1174,7 +1174,7 @@ def object_update(request, v_account, v_container, v_object):
             request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
         except NotAllowedError:
             request.backend.update_object_public(request.user, v_account,
                                                 v_container, v_object, public)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Object does not exist')
     
         except NameError:
             raise ItemNotFound('Object does not exist')
     
@@ -1188,7 +1188,7 @@ def object_delete(request, v_account, v_container, v_object):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
+    #                       forbidden (403),
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
     #                       badRequest (400)
     
     until = get_int_parameter(request.GET.get('until'))
@@ -1196,7 +1196,7 @@ def object_delete(request, v_account, v_container, v_object):
         request.backend.delete_object(request.user, v_account, v_container,
                                         v_object, until)
     except NotAllowedError:
         request.backend.delete_object(request.user, v_account, v_container,
                                         v_object, until)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except NameError:
         raise ItemNotFound('Object does not exist')
     return HttpResponse(status=204)
     except NameError:
         raise ItemNotFound('Object does not exist')
     return HttpResponse(status=204)
index d21e237..296be84 100644 (file)
@@ -45,7 +45,7 @@ from django.utils.http import http_date, parse_etags
 from django.utils.encoding import smart_str
 
 from pithos.api.compat import parse_http_date_safe, parse_http_date
 from django.utils.encoding import smart_str
 
 from pithos.api.compat import parse_http_date_safe, parse_http_date
-from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, ItemNotFound,
+from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, Forbidden, ItemNotFound,
                                 Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge,
                                 RangeNotSatisfiable, ServiceUnavailable)
 from pithos.backends import connect_backend
                                 Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge,
                                 RangeNotSatisfiable, ServiceUnavailable)
 from pithos.backends import connect_backend
@@ -303,7 +303,7 @@ def copy_or_move_object(request, src_account, src_container, src_name, dest_acco
                                                         dest_account, dest_container, dest_name,
                                                         meta, False, permissions, src_version)
     except NotAllowedError:
                                                         dest_account, dest_container, dest_name,
                                                         meta, False, permissions, src_version)
     except NotAllowedError:
-        raise Unauthorized('Access denied')
+        raise Forbidden('Not allowed')
     except (NameError, IndexError):
         raise ItemNotFound('Container or object does not exist')
     except ValueError:
     except (NameError, IndexError):
         raise ItemNotFound('Container or object does not exist')
     except ValueError:
@@ -316,7 +316,7 @@ def copy_or_move_object(request, src_account, src_container, src_name, dest_acco
         try:
             request.backend.update_object_public(request.user, dest_account, dest_container, dest_name, public)
         except NotAllowedError:
         try:
             request.backend.update_object_public(request.user, dest_account, dest_container, dest_name, public)
         except NotAllowedError:
-            raise Unauthorized('Access denied')
+            raise Forbidden('Not allowed')
         except NameError:
             raise ItemNotFound('Object does not exist')
     return version_id
         except NameError:
             raise ItemNotFound('Object does not exist')
     return version_id
@@ -767,7 +767,7 @@ def request_serialization(request, format_allowed=False):
     
     return 'text'
 
     
     return 'text'
 
-def api_method(http_method=None, format_allowed=False):
+def api_method(http_method=None, format_allowed=False, user_required=True):
     """Decorator function for views that implement an API method."""
     
     def decorator(func):
     """Decorator function for views that implement an API method."""
     
     def decorator(func):
@@ -776,6 +776,8 @@ def api_method(http_method=None, format_allowed=False):
             try:
                 if http_method and request.method != http_method:
                     raise BadRequest('Method not allowed.')
             try:
                 if http_method and request.method != http_method:
                     raise BadRequest('Method not allowed.')
+                if user_required and getattr(request, 'user', None) is None:
+                    raise Unauthorized('Access denied')
                 
                 # The args variable may contain up to (account, container, object).
                 if len(args) > 1 and len(args[1]) > 256:
                 
                 # The args variable may contain up to (account, container, object).
                 if len(args) > 1 and len(args[1]) > 256:
@@ -797,6 +799,7 @@ def api_method(http_method=None, format_allowed=False):
                 fault = ServiceUnavailable('Unexpected error')
                 return render_fault(request, fault)
             finally:
                 fault = ServiceUnavailable('Unexpected error')
                 return render_fault(request, fault)
             finally:
-                request.backend.wrapper.conn.close()
+                if getattr(request, 'backend', None) is not None:
+                    request.backend.wrapper.conn.close()
         return wrapper
     return decorator
         return wrapper
     return decorator
index 0eeb950..91fda1c 100644 (file)
@@ -52,14 +52,11 @@ def object_demux(request, v_account, v_container, v_object):
     else:
         return method_not_allowed(request)
 
     else:
         return method_not_allowed(request)
 
-# TODO: Use a version of api_method that does not check for a token.
-
-@api_method('HEAD')
+@api_method('HEAD', user_required=False)
 def object_meta(request, v_account, v_container, v_object):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
 def object_meta(request, v_account, v_container, v_object):
     # Normal Response Codes: 204
     # Error Response Codes: serviceUnavailable (503),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
     #                       badRequest (400)
     
     try:
     #                       badRequest (400)
     
     try:
@@ -78,14 +75,13 @@ def object_meta(request, v_account, v_container, v_object):
     put_object_meta(response, meta, True)
     return response
 
     put_object_meta(response, meta, True)
     return response
 
-@api_method('GET')
+@api_method('GET', user_required=False)
 def object_read(request, v_account, v_container, v_object):
     # Normal Response Codes: 200, 206
     # Error Response Codes: serviceUnavailable (503),
     #                       rangeNotSatisfiable (416),
     #                       preconditionFailed (412),
     #                       itemNotFound (404),
 def object_read(request, v_account, v_container, v_object):
     # Normal Response Codes: 200, 206
     # Error Response Codes: serviceUnavailable (503),
     #                       rangeNotSatisfiable (416),
     #                       preconditionFailed (412),
     #                       itemNotFound (404),
-    #                       unauthorized (401),
     #                       badRequest (400),
     #                       notModified (304)
     
     #                       badRequest (400),
     #                       notModified (304)
     
@@ -139,6 +135,6 @@ def object_read(request, v_account, v_container, v_object):
     
     return object_data_response(request, sizes, hashmaps, meta, True)
 
     
     return object_data_response(request, sizes, hashmaps, meta, True)
 
-@api_method()
+@api_method(user_required=False)
 def method_not_allowed(request, **v_args):
     raise ItemNotFound('Object does not exist')
 def method_not_allowed(request, **v_args):
     raise ItemNotFound('Object does not exist')
index 6d611cb..fa26fc6 100755 (executable)
@@ -125,7 +125,7 @@ class BaseTestCase(unittest.TestCase):
                 'content_type',
                 'content_encoding',
                 'last_modified',)}
                 'content_type',
                 'content_encoding',
                 'last_modified',)}
-        self.return_codes = (400, 401, 404, 503,)
+        self.return_codes = (400, 401, 403, 404, 503,)
     
     def tearDown(self):
         self._clean_account()
     
     def tearDown(self):
         self._clean_account()
@@ -333,8 +333,8 @@ class AccountHead(BaseTestCase):
             size = size + int(m['x-container-bytes-used'])
         self.assertEqual(meta['x-account-bytes-used'], str(size))
     
             size = size + int(m['x-container-bytes-used'])
         self.assertEqual(meta['x-account-bytes-used'], str(size))
     
-    def test_get_account_401(self):
-        self.assert_raises_fault(401,
+    def test_get_account_403(self):
+        self.assert_raises_fault(403,
                                  self.invalid_client.retrieve_account_metadata)
     
     def test_get_account_meta_until(self):
                                  self.invalid_client.retrieve_account_metadata)
     
     def test_get_account_meta_until(self):
@@ -371,8 +371,8 @@ class AccountGet(BaseTestCase):
         containers = self.client.list_containers()
         self.assertEquals(self.containers, containers)
     
         containers = self.client.list_containers()
         self.assertEquals(self.containers, containers)
     
-    def test_list_401(self):
-        self.assert_raises_fault(401, self.invalid_client.list_containers)
+    def test_list_403(self):
+        self.assert_raises_fault(403, self.invalid_client.list_containers)
     
     def test_list_with_limit(self):
         limit = 2
     
     def test_list_with_limit(self):
         limit = 2
@@ -509,7 +509,7 @@ class AccountPost(BaseTestCase):
         
     def test_invalid_account_update_meta(self):
         meta = {'test':'test', 'tost':'tost'}
         
     def test_invalid_account_update_meta(self):
         meta = {'test':'test', 'tost':'tost'}
-        self.assert_raises_fault(401,
+        self.assert_raises_fault(403,
                                  self.invalid_client.update_account_metadata,
                                  **meta)
     
                                  self.invalid_client.update_account_metadata,
                                  **meta)
     
@@ -1889,13 +1889,13 @@ class TestGreek(BaseTestCase):
                             '0009',
                             'διογένης',
                             get_api())
                             '0009',
                             'διογένης',
                             get_api())
-        self.assert_not_raises_fault(401, chef.retrieve_object_metadata,
+        self.assert_not_raises_fault(403, chef.retrieve_object_metadata,
                                      'φάκελος', 'ο1', account=get_user())
         
         #check write access
         self.client.share_object('φάκελος', 'ο1', ['διογένης'], read=False)
         new_data = get_random_data()
                                      'φάκελος', 'ο1', account=get_user())
         
         #check write access
         self.client.share_object('φάκελος', 'ο1', ['διογένης'], read=False)
         new_data = get_random_data()
-        self.assert_not_raises_fault(401, chef.update_object,
+        self.assert_not_raises_fault(403, chef.update_object,
                                      'φάκελος', 'ο1', StringIO(new_data),
                                      account=get_user())
         
                                      'φάκελος', 'ο1', StringIO(new_data),
                                      account=get_user())
         
@@ -1969,10 +1969,10 @@ class TestPermissions(BaseTestCase):
         for token, account in OTHER_ACCOUNTS.items():
             cl = Pithos_Client(get_server(), token, account, get_api()) 
             if account in authorized or any:
         for token, account in OTHER_ACCOUNTS.items():
             cl = Pithos_Client(get_server(), token, account, get_api()) 
             if account in authorized or any:
-                self.assert_not_raises_fault(401, cl.retrieve_object_metadata,
+                self.assert_not_raises_fault(403, cl.retrieve_object_metadata,
                                              'c', 'o', account=get_user())
             else:
                                              'c', 'o', account=get_user())
             else:
-                self.assert_raises_fault(401, cl.retrieve_object_metadata,
+                self.assert_raises_fault(403, cl.retrieve_object_metadata,
                                          'c', 'o', account=get_user())
         
         #check inheritance
                                          'c', 'o', account=get_user())
         
         #check inheritance
@@ -1980,10 +1980,10 @@ class TestPermissions(BaseTestCase):
         for token, account in OTHER_ACCOUNTS.items():
             cl = Pithos_Client(get_server(), token, account, get_api()) 
             if account in authorized or any:
         for token, account in OTHER_ACCOUNTS.items():
             cl = Pithos_Client(get_server(), token, account, get_api()) 
             if account in authorized or any:
-                self.assert_not_raises_fault(401, cl.retrieve_object_metadata,
+                self.assert_not_raises_fault(403, cl.retrieve_object_metadata,
                                              'c', 'o/also-shared', account=get_user())
             else:
                                              'c', 'o/also-shared', account=get_user())
             else:
-                self.assert_raises_fault(401, cl.retrieve_object_metadata,
+                self.assert_raises_fault(403, cl.retrieve_object_metadata,
                                          'c', 'o/also-shared', account=get_user())
     
     def assert_write(self, o_data, authorized=[], any=False):
                                          'c', 'o/also-shared', account=get_user())
     
     def assert_write(self, o_data, authorized=[], any=False):
@@ -1992,7 +1992,7 @@ class TestPermissions(BaseTestCase):
             new_data = get_random_data()
             if account in authorized or any:
                 # test write access
             new_data = get_random_data()
             if account in authorized or any:
                 # test write access
-                self.assert_not_raises_fault(401, cl.update_object,
+                self.assert_not_raises_fault(403, cl.update_object,
                                              'c', 'o', StringIO(new_data),
                                              account=get_user())
                 try:
                                              'c', 'o', StringIO(new_data),
                                              account=get_user())
                 try:
@@ -2002,9 +2002,9 @@ class TestPermissions(BaseTestCase):
                     self.assertEqual(new_data, server_data[len(o_data):])
                     o_data = server_data
                 except Fault, f:
                     self.assertEqual(new_data, server_data[len(o_data):])
                     o_data = server_data
                 except Fault, f:
-                    self.failIf(f.status == 401)
+                    self.failIf(f.status == 403)
             else:
             else:
-                self.assert_raises_fault(401, cl.update_object,
+                self.assert_raises_fault(403, cl.update_object,
                                              'c', 'o', StringIO(new_data),
                                              account=get_user())
         
                                              'c', 'o', StringIO(new_data),
                                              account=get_user())
         
@@ -2016,7 +2016,7 @@ class TestPermissions(BaseTestCase):
             new_data = get_random_data()
             if account in authorized or any:
                 # test write access
             new_data = get_random_data()
             if account in authorized or any:
                 # test write access
-                self.assert_not_raises_fault(401, cl.update_object,
+                self.assert_not_raises_fault(403, cl.update_object,
                                              'c', o['name'],
                                              StringIO(new_data),
                                              account=get_user())
                                              'c', o['name'],
                                              StringIO(new_data),
                                              account=get_user())
@@ -2026,9 +2026,9 @@ class TestPermissions(BaseTestCase):
                     self.assertEqual(new_data, server_data[len(o_data):])
                     o_data = server_data
                 except Fault, f:
                     self.assertEqual(new_data, server_data[len(o_data):])
                     o_data = server_data
                 except Fault, f:
-                    self.failIf(f.status == 401)
+                    self.failIf(f.status == 403)
             else:
             else:
-                self.assert_raises_fault(401, cl.update_object,
+                self.assert_raises_fault(403, cl.update_object,
                                              'c', o['name'],
                                              StringIO(new_data),
                                              account=get_user())
                                              'c', o['name'],
                                              StringIO(new_data),
                                              account=get_user())