Revision 65bbcd43
b/snf-cyclades-app/synnefo/plankton/utils.py | ||
---|---|---|
35 | 35 |
from synnefo.plankton.backend import ImageBackend |
36 | 36 |
from contextlib import contextmanager |
37 | 37 |
|
38 |
|
|
39 | 38 |
def plankton_method(func): |
40 | 39 |
"""Decorator function for API methods using ImageBackend. |
41 | 40 |
|
b/snf-pithos-app/pithos/api/functions.py | ||
---|---|---|
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 | 34 |
from xml.dom import minidom |
35 |
from urllib import unquote |
|
36 | 35 |
|
37 |
from django.conf import settings |
|
38 | 36 |
from django.http import HttpResponse |
39 | 37 |
from django.template.loader import render_to_string |
40 | 38 |
from django.utils import simplejson as json |
... | ... | |
44 | 42 |
|
45 | 43 |
from synnefo.lib.astakos import get_user, get_uuids as _get_uuids |
46 | 44 |
|
45 |
from snf_django.lib import api |
|
47 | 46 |
from snf_django.lib.api import faults |
48 | 47 |
|
49 | 48 |
from pithos.api.util import ( |
... | ... | |
57 | 56 |
get_content_range, socket_read_iterator, SaveToBackendHandler, |
58 | 57 |
object_data_response, put_object_block, hashmap_md5, simple_list_response, |
59 | 58 |
api_method, is_uuid, |
60 |
retrieve_uuid, retrieve_displayname, retrieve_uuids, retrieve_displaynames |
|
59 |
retrieve_uuid, retrieve_displayname, retrieve_uuids, retrieve_displaynames, |
|
60 |
get_pithos_usage |
|
61 | 61 |
) |
62 | 62 |
|
63 | 63 |
from pithos.api.settings import (UPDATE_MD5, TRANSLATE_UUIDS, |
... | ... | |
70 | 70 |
|
71 | 71 |
from pithos.backends.filter import parse_filters |
72 | 72 |
|
73 |
import logging |
|
74 | 73 |
import hashlib |
75 | 74 |
|
75 |
import logging |
|
76 | 76 |
logger = logging.getLogger(__name__) |
77 | 77 |
|
78 | 78 |
|
... | ... | |
102 | 102 |
return authenticate(request) |
103 | 103 |
return account_list(request) |
104 | 104 |
else: |
105 |
return method_not_allowed(request) |
|
105 |
return api.method_not_allowed(request)
|
|
106 | 106 |
|
107 | 107 |
|
108 | 108 |
@csrf_exempt |
... | ... | |
121 | 121 |
elif request.method == 'GET': |
122 | 122 |
return container_list(request, v_account) |
123 | 123 |
else: |
124 |
return method_not_allowed(request) |
|
124 |
return api.method_not_allowed(request)
|
|
125 | 125 |
|
126 | 126 |
|
127 | 127 |
@csrf_exempt |
... | ... | |
144 | 144 |
elif request.method == 'GET': |
145 | 145 |
return object_list(request, v_account, v_container) |
146 | 146 |
else: |
147 |
return method_not_allowed(request) |
|
147 |
return api.method_not_allowed(request)
|
|
148 | 148 |
|
149 | 149 |
|
150 | 150 |
@csrf_exempt |
... | ... | |
174 | 174 |
elif request.method == 'DELETE': |
175 | 175 |
return object_delete(request, v_account, v_container, v_object) |
176 | 176 |
else: |
177 |
return method_not_allowed(request) |
|
177 |
return api.method_not_allowed(request)
|
|
178 | 178 |
|
179 | 179 |
|
180 |
@api_method('GET', user_required=False) |
|
180 |
@api_method('GET', user_required=False, logger=logger)
|
|
181 | 181 |
def authenticate(request): |
182 | 182 |
# Normal Response Codes: 204 |
183 | 183 |
# Error Response Codes: internalServerError (500), |
... | ... | |
200 | 200 |
return response |
201 | 201 |
|
202 | 202 |
|
203 |
@api_method('GET', format_allowed=True, request_usage=True)
|
|
203 |
@api_method('GET', format_allowed=True, user_required=True, logger=logger)
|
|
204 | 204 |
def account_list(request): |
205 | 205 |
# Normal Response Codes: 200, 204 |
206 | 206 |
# Error Response Codes: internalServerError (500), |
... | ... | |
230 | 230 |
for x in accounts: |
231 | 231 |
if x == request.user_uniq: |
232 | 232 |
continue |
233 |
usage = get_pithos_usage(request.x_auth_token) |
|
233 | 234 |
try: |
234 | 235 |
meta = request.backend.get_account_meta( |
235 | 236 |
request.user_uniq, x, 'pithos', include_user_defined=False, |
236 |
external_quota=request.user_usage)
|
|
237 |
external_quota=usage) |
|
237 | 238 |
groups = request.backend.get_account_groups(request.user_uniq, x) |
238 | 239 |
except NotAllowedError: |
239 | 240 |
raise faults.Forbidden('Not allowed') |
... | ... | |
262 | 263 |
return response |
263 | 264 |
|
264 | 265 |
|
265 |
@api_method('HEAD', request_usage=True)
|
|
266 |
@api_method('HEAD', user_required=True, logger=logger)
|
|
266 | 267 |
def account_meta(request, v_account): |
267 | 268 |
# Normal Response Codes: 204 |
268 | 269 |
# Error Response Codes: internalServerError (500), |
... | ... | |
270 | 271 |
# badRequest (400) |
271 | 272 |
|
272 | 273 |
until = get_int_parameter(request.GET.get('until')) |
274 |
usage = get_pithos_usage(request.x_auth_token) |
|
273 | 275 |
try: |
274 | 276 |
meta = request.backend.get_account_meta( |
275 | 277 |
request.user_uniq, v_account, 'pithos', until, |
276 |
external_quota=request.user_usage)
|
|
278 |
external_quota=usage) |
|
277 | 279 |
groups = request.backend.get_account_groups( |
278 | 280 |
request.user_uniq, v_account) |
279 | 281 |
|
... | ... | |
282 | 284 |
groups[k] = retrieve_displaynames( |
283 | 285 |
getattr(request, 'token', None), groups[k]) |
284 | 286 |
policy = request.backend.get_account_policy( |
285 |
request.user_uniq, v_account, external_quota=request.user_usage)
|
|
287 |
request.user_uniq, v_account, external_quota=usage) |
|
286 | 288 |
except NotAllowedError: |
287 | 289 |
raise faults.Forbidden('Not allowed') |
288 | 290 |
|
... | ... | |
293 | 295 |
return response |
294 | 296 |
|
295 | 297 |
|
296 |
@api_method('POST') |
|
298 |
@api_method('POST', user_required=True, logger=logger)
|
|
297 | 299 |
def account_update(request, v_account): |
298 | 300 |
# Normal Response Codes: 202 |
299 | 301 |
# Error Response Codes: internalServerError (500), |
... | ... | |
340 | 342 |
return HttpResponse(status=202) |
341 | 343 |
|
342 | 344 |
|
343 |
@api_method('GET', format_allowed=True, request_usage=True)
|
|
345 |
@api_method('GET', format_allowed=True, user_required=True, logger=logger)
|
|
344 | 346 |
def container_list(request, v_account): |
345 | 347 |
# Normal Response Codes: 200, 204 |
346 | 348 |
# Error Response Codes: internalServerError (500), |
... | ... | |
349 | 351 |
# badRequest (400) |
350 | 352 |
|
351 | 353 |
until = get_int_parameter(request.GET.get('until')) |
354 |
usage = get_pithos_usage(request.x_auth_token) |
|
352 | 355 |
try: |
353 | 356 |
meta = request.backend.get_account_meta( |
354 | 357 |
request.user_uniq, v_account, 'pithos', until, |
355 |
external_quota=request.user_usage)
|
|
358 |
external_quota=usage) |
|
356 | 359 |
groups = request.backend.get_account_groups( |
357 | 360 |
request.user_uniq, v_account) |
358 | 361 |
policy = request.backend.get_account_policy( |
359 |
request.user_uniq, v_account, external_quota=request.user_usage)
|
|
362 |
request.user_uniq, v_account, external_quota=usage) |
|
360 | 363 |
except NotAllowedError: |
361 | 364 |
raise faults.Forbidden('Not allowed') |
362 | 365 |
|
... | ... | |
425 | 428 |
return response |
426 | 429 |
|
427 | 430 |
|
428 |
@api_method('HEAD') |
|
431 |
@api_method('HEAD', user_required=True, logger=logger)
|
|
429 | 432 |
def container_meta(request, v_account, v_container): |
430 | 433 |
# Normal Response Codes: 204 |
431 | 434 |
# Error Response Codes: internalServerError (500), |
... | ... | |
454 | 457 |
return response |
455 | 458 |
|
456 | 459 |
|
457 |
@api_method('PUT') |
|
460 |
@api_method('PUT', user_required=True, logger=logger)
|
|
458 | 461 |
def container_create(request, v_account, v_container): |
459 | 462 |
# Normal Response Codes: 201, 202 |
460 | 463 |
# Error Response Codes: internalServerError (500), |
... | ... | |
498 | 501 |
return HttpResponse(status=ret) |
499 | 502 |
|
500 | 503 |
|
501 |
@api_method('POST', format_allowed=True) |
|
504 |
@api_method('POST', format_allowed=True, user_required=True, logger=logger)
|
|
502 | 505 |
def container_update(request, v_account, v_container): |
503 | 506 |
# Normal Response Codes: 202 |
504 | 507 |
# Error Response Codes: internalServerError (500), |
... | ... | |
549 | 552 |
return response |
550 | 553 |
|
551 | 554 |
|
552 |
@api_method('DELETE') |
|
555 |
@api_method('DELETE', user_required=True, logger=logger)
|
|
553 | 556 |
def container_delete(request, v_account, v_container): |
554 | 557 |
# Normal Response Codes: 204 |
555 | 558 |
# Error Response Codes: internalServerError (500), |
... | ... | |
578 | 581 |
return HttpResponse(status=204) |
579 | 582 |
|
580 | 583 |
|
581 |
@api_method('GET', format_allowed=True) |
|
584 |
@api_method('GET', format_allowed=True, user_required=True, logger=logger)
|
|
582 | 585 |
def object_list(request, v_account, v_container): |
583 | 586 |
# Normal Response Codes: 200, 204 |
584 | 587 |
# Error Response Codes: internalServerError (500), |
... | ... | |
746 | 749 |
return response |
747 | 750 |
|
748 | 751 |
|
749 |
@api_method('HEAD') |
|
752 |
@api_method('HEAD', user_required=True, logger=logger)
|
|
750 | 753 |
def object_meta(request, v_account, v_container, v_object): |
751 | 754 |
# Normal Response Codes: 204 |
752 | 755 |
# Error Response Codes: internalServerError (500), |
... | ... | |
795 | 798 |
return response |
796 | 799 |
|
797 | 800 |
|
798 |
@api_method('GET', format_allowed=True) |
|
801 |
@api_method('GET', format_allowed=True, user_required=True, logger=logger)
|
|
799 | 802 |
def object_read(request, v_account, v_container, v_object): |
800 | 803 |
# Normal Response Codes: 200, 206 |
801 | 804 |
# Error Response Codes: internalServerError (500), |
... | ... | |
937 | 940 |
return object_data_response(request, sizes, hashmaps, meta) |
938 | 941 |
|
939 | 942 |
|
940 |
@api_method('PUT', format_allowed=True) |
|
943 |
@api_method('PUT', format_allowed=True, user_required=True, logger=logger)
|
|
941 | 944 |
def object_write(request, v_account, v_container, v_object): |
942 | 945 |
# Normal Response Codes: 201 |
943 | 946 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1096 | 1099 |
return response |
1097 | 1100 |
|
1098 | 1101 |
|
1099 |
@api_method('POST') |
|
1102 |
@api_method('POST', user_required=True, logger=logger)
|
|
1100 | 1103 |
def object_write_form(request, v_account, v_container, v_object): |
1101 | 1104 |
# Normal Response Codes: 201 |
1102 | 1105 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1129 | 1132 |
return response |
1130 | 1133 |
|
1131 | 1134 |
|
1132 |
@api_method('COPY', format_allowed=True) |
|
1135 |
@api_method('COPY', format_allowed=True, user_required=True, logger=logger)
|
|
1133 | 1136 |
def object_copy(request, v_account, v_container, v_object): |
1134 | 1137 |
# Normal Response Codes: 201 |
1135 | 1138 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1171 | 1174 |
return response |
1172 | 1175 |
|
1173 | 1176 |
|
1174 |
@api_method('MOVE', format_allowed=True) |
|
1177 |
@api_method('MOVE', format_allowed=True, user_required=True, logger=logger)
|
|
1175 | 1178 |
def object_move(request, v_account, v_container, v_object): |
1176 | 1179 |
# Normal Response Codes: 201 |
1177 | 1180 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1212 | 1215 |
return response |
1213 | 1216 |
|
1214 | 1217 |
|
1215 |
@api_method('POST', format_allowed=True) |
|
1218 |
@api_method('POST', format_allowed=True, user_required=True, logger=logger)
|
|
1216 | 1219 |
def object_update(request, v_account, v_container, v_object): |
1217 | 1220 |
# Normal Response Codes: 202, 204 |
1218 | 1221 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1423 | 1426 |
return response |
1424 | 1427 |
|
1425 | 1428 |
|
1426 |
@api_method('DELETE') |
|
1429 |
@api_method('DELETE', user_required=True, logger=logger)
|
|
1427 | 1430 |
def object_delete(request, v_account, v_container, v_object): |
1428 | 1431 |
# Normal Response Codes: 204 |
1429 | 1432 |
# Error Response Codes: internalServerError (500), |
... | ... | |
1446 | 1449 |
except QuotaError, e: |
1447 | 1450 |
raise faults.RequestEntityTooLarge('Quota error: %s' % e) |
1448 | 1451 |
return HttpResponse(status=204) |
1449 |
|
|
1450 |
|
|
1451 |
@api_method() |
|
1452 |
def method_not_allowed(request): |
|
1453 |
raise faults.BadRequest('Method not allowed') |
b/snf-pithos-app/pithos/api/public.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved.
|
|
1 |
# Copyright 2011-2013 GRNET S.A. All rights reserved.
|
|
2 | 2 |
# |
3 | 3 |
# Redistribution and use in source and binary forms, with or |
4 | 4 |
# without modification, are permitted provided that the following |
... | ... | |
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
import logging |
|
35 |
|
|
36 | 34 |
from django.http import HttpResponse |
37 | 35 |
from django.views.decorators.csrf import csrf_exempt |
38 | 36 |
|
39 |
from synnefo.lib.astakos import get_user
|
|
37 |
from snf_django.lib import api
|
|
40 | 38 |
from snf_django.lib.api import faults |
41 | 39 |
|
42 | 40 |
from pithos.api.util import (put_object_headers, update_manifest_meta, |
... | ... | |
44 | 42 |
validate_matching_preconditions, |
45 | 43 |
object_data_response, api_method, |
46 | 44 |
split_container_object_string) |
47 |
from pithos.api.settings import AUTHENTICATION_URL, AUTHENTICATION_USERS |
|
48 |
|
|
49 | 45 |
|
46 |
import logging |
|
50 | 47 |
logger = logging.getLogger(__name__) |
51 | 48 |
|
52 | 49 |
|
53 | 50 |
@csrf_exempt |
54 | 51 |
def public_demux(request, v_public): |
55 |
get_user(request, AUTHENTICATION_URL, AUTHENTICATION_USERS) |
|
56 | 52 |
if request.method == 'HEAD': |
57 | 53 |
return public_meta(request, v_public) |
58 | 54 |
elif request.method == 'GET': |
59 | 55 |
return public_read(request, v_public) |
60 | 56 |
else: |
61 |
return method_not_allowed(request) |
|
57 |
return api.method_not_allowed(request)
|
|
62 | 58 |
|
63 | 59 |
|
64 |
@api_method('HEAD', user_required=False)
|
|
60 |
@api_method(http_method="HEAD", user_required=False, logger=logger)
|
|
65 | 61 |
def public_meta(request, v_public): |
66 | 62 |
# Normal Response Codes: 204 |
67 | 63 |
# Error Response Codes: internalServerError (500), |
... | ... | |
89 | 85 |
return response |
90 | 86 |
|
91 | 87 |
|
92 |
@api_method('GET', user_required=False)
|
|
88 |
@api_method(http_method="GET", user_required=False, logger=logger)
|
|
93 | 89 |
def public_read(request, v_public): |
94 | 90 |
# Normal Response Codes: 200, 206 |
95 | 91 |
# Error Response Codes: internalServerError (500), |
... | ... | |
139 | 135 |
try: |
140 | 136 |
for x in objects: |
141 | 137 |
s, h = request.backend.get_object_hashmap(request.user_uniq, |
142 |
v_account, src_container, x[0], x[1]) |
|
138 |
v_account, |
|
139 |
src_container, |
|
140 |
x[0], x[1]) |
|
143 | 141 |
sizes.append(s) |
144 | 142 |
hashmaps.append(h) |
145 | 143 |
except: |
... | ... | |
161 | 159 |
meta['Content-Disposition'] = 'attachment; filename=%s' % (name,) |
162 | 160 |
|
163 | 161 |
return object_data_response(request, sizes, hashmaps, meta, True) |
164 |
|
|
165 |
|
|
166 |
@api_method(user_required=False) |
|
167 |
def method_not_allowed(request, **v_args): |
|
168 |
raise faults.ItemNotFound('Object does not exist') |
b/snf-pithos-app/pithos/api/util.py | ||
---|---|---|
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 | 34 |
from functools import wraps |
35 |
from time import time |
|
36 | 35 |
from traceback import format_exc |
37 |
from wsgiref.handlers import format_date_time |
|
38 |
from binascii import hexlify, unhexlify |
|
39 |
from datetime import datetime, tzinfo, timedelta |
|
36 |
from datetime import datetime |
|
40 | 37 |
from urllib import quote, unquote |
41 | 38 |
|
42 | 39 |
from django.conf import settings |
... | ... | |
49 | 46 |
from django.core.files.uploadedfile import UploadedFile |
50 | 47 |
|
51 | 48 |
from synnefo.lib.parsedate import parse_http_date_safe, parse_http_date |
52 |
from synnefo.lib.astakos import get_user |
|
53 |
from snf_django.lib.api import faults |
|
49 |
from synnefo.lib.astakos import user_for_token |
|
50 |
from snf_django.lib import api |
|
51 |
from snf_django.lib.api import faults, utils |
|
54 | 52 |
|
55 | 53 |
from pithos.api.settings import (BACKEND_DB_MODULE, BACKEND_DB_CONNECTION, |
56 | 54 |
BACKEND_BLOCK_MODULE, BACKEND_BLOCK_PATH, |
... | ... | |
67 | 65 |
RADOS_POOL_MAPS, TRANSLATE_UUIDS, |
68 | 66 |
PUBLIC_URL_SECURITY, |
69 | 67 |
PUBLIC_URL_ALPHABET) |
70 |
from pithos.backends import connect_backend |
|
71 | 68 |
from pithos.backends.base import (NotAllowedError, QuotaError, ItemNotExists, |
72 | 69 |
VersionNotExists) |
73 | 70 |
from synnefo.lib.astakos import (get_user_uuid, get_displayname, |
... | ... | |
82 | 79 |
logger = logging.getLogger(__name__) |
83 | 80 |
|
84 | 81 |
|
85 |
class UTC(tzinfo): |
|
86 |
def utcoffset(self, dt): |
|
87 |
return timedelta(0) |
|
88 |
|
|
89 |
def tzname(self, dt): |
|
90 |
return 'UTC' |
|
91 |
|
|
92 |
def dst(self, dt): |
|
93 |
return timedelta(0) |
|
94 |
|
|
95 |
|
|
96 | 82 |
def json_encode_decimal(obj): |
97 | 83 |
if isinstance(obj, decimal.Decimal): |
98 | 84 |
return str(obj) |
99 | 85 |
raise TypeError(repr(obj) + " is not JSON serializable") |
100 | 86 |
|
101 | 87 |
|
102 |
def isoformat(d): |
|
103 |
"""Return an ISO8601 date string that includes a timezone.""" |
|
104 |
|
|
105 |
return d.replace(tzinfo=UTC()).isoformat() |
|
106 |
|
|
107 |
|
|
108 | 88 |
def rename_meta_key(d, old, new): |
109 | 89 |
if old not in d: |
110 | 90 |
return |
... | ... | |
120 | 100 |
""" |
121 | 101 |
|
122 | 102 |
if 'last_modified' in d and d['last_modified']: |
123 |
d['last_modified'] = isoformat( |
|
103 |
d['last_modified'] = utils.isoformat(
|
|
124 | 104 |
datetime.fromtimestamp(d['last_modified'])) |
125 | 105 |
return dict([(k.lower().replace('-', '_'), v) for k, v in d.iteritems()]) |
126 | 106 |
|
... | ... | |
985 | 965 |
public_url_security=PUBLIC_URL_SECURITY, |
986 | 966 |
public_url_alphabet=PUBLIC_URL_ALPHABET) |
987 | 967 |
|
968 |
|
|
988 | 969 |
def get_backend(): |
989 | 970 |
backend = _pithos_backend_pool.pool_get() |
990 | 971 |
backend.default_policy['quota'] = BACKEND_QUOTA |
... | ... | |
1010 | 991 |
|
1011 | 992 |
|
1012 | 993 |
def update_response_headers(request, response): |
1013 |
if request.serialization == 'xml': |
|
1014 |
response['Content-Type'] = 'application/xml; charset=UTF-8' |
|
1015 |
elif request.serialization == 'json': |
|
1016 |
response['Content-Type'] = 'application/json; charset=UTF-8' |
|
1017 |
elif not response['Content-Type']: |
|
1018 |
response['Content-Type'] = 'text/plain; charset=UTF-8' |
|
1019 |
|
|
1020 | 994 |
if (not response.has_header('Content-Length') and |
1021 | 995 |
not (response.has_header('Content-Type') and |
1022 | 996 |
response['Content-Type'].startswith('multipart/byteranges'))): |
... | ... | |
1031 | 1005 |
response[quote(k)] = quote(v, safe='/=,:@; ') |
1032 | 1006 |
|
1033 | 1007 |
|
1034 |
def render_fault(request, fault): |
|
1035 |
if isinstance(fault, faults.InternalServerError) and settings.DEBUG: |
|
1036 |
fault.details = format_exc(fault) |
|
1037 |
|
|
1038 |
request.serialization = 'text' |
|
1039 |
data = fault.message + '\n' |
|
1040 |
if fault.details: |
|
1041 |
data += '\n' + fault.details |
|
1042 |
response = HttpResponse(data, status=fault.code) |
|
1043 |
update_response_headers(request, response) |
|
1044 |
return response |
|
1045 |
|
|
1046 |
|
|
1047 |
def request_serialization(request, format_allowed=False): |
|
1048 |
"""Return the serialization format requested. |
|
1049 |
|
|
1050 |
Valid formats are 'text' and 'json', 'xml' if 'format_allowed' is True. |
|
1051 |
""" |
|
1052 |
|
|
1053 |
if not format_allowed: |
|
1054 |
return 'text' |
|
1055 |
|
|
1056 |
format = request.GET.get('format') |
|
1057 |
if format == 'json': |
|
1058 |
return 'json' |
|
1059 |
elif format == 'xml': |
|
1060 |
return 'xml' |
|
1061 |
|
|
1062 |
for item in request.META.get('HTTP_ACCEPT', '').split(','): |
|
1063 |
accept, sep, rest = item.strip().partition(';') |
|
1064 |
if accept == 'application/json': |
|
1065 |
return 'json' |
|
1066 |
elif accept == 'application/xml' or accept == 'text/xml': |
|
1067 |
return 'xml' |
|
1068 |
|
|
1069 |
return 'text' |
|
1070 |
|
|
1071 |
def get_pithos_usage(usage): |
|
1008 |
def get_pithos_usage(token): |
|
1009 |
"""Get Pithos Usage from astakos.""" |
|
1010 |
user_info = user_for_token(token, AUTHENTICATION_URL, AUTHENTICATION_USERS, |
|
1011 |
usage=True) |
|
1012 |
usage = user_info.get("usage", []) |
|
1072 | 1013 |
for u in usage: |
1073 | 1014 |
if u.get('name') == 'pithos+.diskspace': |
1074 | 1015 |
return u |
1075 | 1016 |
|
1076 |
def api_method(http_method=None, format_allowed=False, user_required=True, |
|
1077 |
request_usage=False): |
|
1078 |
"""Decorator function for views that implement an API method.""" |
|
1079 | 1017 |
|
1018 |
def api_method(http_method=None, user_required=True, logger=None, |
|
1019 |
format_allowed=False): |
|
1080 | 1020 |
def decorator(func): |
1021 |
@api.api_method(http_method=http_method, user_required=user_required, |
|
1022 |
logger=logger, format_allowed=format_allowed) |
|
1081 | 1023 |
@wraps(func) |
1082 | 1024 |
def wrapper(request, *args, **kwargs): |
1083 |
try: |
|
1084 |
if http_method and request.method != http_method: |
|
1085 |
raise faults.BadRequest('Method not allowed.') |
|
1086 |
|
|
1087 |
if user_required: |
|
1088 |
token = None |
|
1089 |
if request.method in ('HEAD', 'GET') and COOKIE_NAME in request.COOKIES: |
|
1090 |
cookie_value = unquote( |
|
1091 |
request.COOKIES.get(COOKIE_NAME, '')) |
|
1092 |
account, sep, token = cookie_value.partition('|') |
|
1093 |
get_user(request, |
|
1094 |
AUTHENTICATION_URL, |
|
1095 |
AUTHENTICATION_USERS, |
|
1096 |
token, |
|
1097 |
request_usage) |
|
1098 |
if getattr(request, 'user', None) is None: |
|
1099 |
raise faults.Unauthorized('Access denied') |
|
1100 |
assert getattr(request, 'user_uniq', None) != None |
|
1101 |
request.user_usage = get_pithos_usage(request.user.get('usage', [])) |
|
1102 |
request.token = request.GET.get('X-Auth-Token', request.META.get('HTTP_X_AUTH_TOKEN', token)) |
|
1103 |
|
|
1104 |
# The args variable may contain up to (account, container, object). |
|
1105 |
if len(args) > 1 and len(args[1]) > 256: |
|
1106 |
raise faults.BadRequest('Container name too large.') |
|
1107 |
if len(args) > 2 and len(args[2]) > 1024: |
|
1108 |
raise faults.BadRequest('Object name too large.') |
|
1109 |
|
|
1110 |
# Format and check headers. |
|
1111 |
update_request_headers(request) |
|
1025 |
# The args variable may contain up to (account, container, object). |
|
1026 |
if len(args) > 1 and len(args[1]) > 256: |
|
1027 |
raise faults.BadRequest("Container name too large") |
|
1028 |
if len(args) > 2 and len(args[2]) > 1024: |
|
1029 |
raise faults.BadRequest('Object name too large.') |
|
1112 | 1030 |
|
1113 |
# Fill in custom request variables. |
|
1114 |
request.serialization = request_serialization( |
|
1115 |
request, format_allowed) |
|
1031 |
try: |
|
1032 |
# Add a PithosBackend as attribute of the request object |
|
1116 | 1033 |
request.backend = get_backend() |
1117 |
|
|
1034 |
# Many API method expect thet X-Auth-Token in request,token |
|
1035 |
request.token = request.x_auth_token |
|
1036 |
update_request_headers(request) |
|
1118 | 1037 |
response = func(request, *args, **kwargs) |
1119 | 1038 |
update_response_headers(request, response) |
1120 | 1039 |
return response |
1121 |
except faults.Fault, fault: |
|
1122 |
if fault.code >= 500: |
|
1123 |
logger.exception("API Fault") |
|
1124 |
return render_fault(request, fault) |
|
1125 |
except BaseException, e: |
|
1126 |
logger.exception('Unexpected error: %s' % e) |
|
1127 |
fault = faults.InternalServerError('Unexpected error') |
|
1128 |
return render_fault(request, fault) |
|
1129 | 1040 |
finally: |
1130 |
if getattr(request, 'backend', None) is not None: |
|
1041 |
# Always close PithosBackend connection |
|
1042 |
if getattr(request, "backend", None) is not None: |
|
1131 | 1043 |
request.backend.close() |
1132 | 1044 |
return wrapper |
1133 | 1045 |
return decorator |
Also available in: Unified diff