Revision b18ef3ad
b/docs/source/devguide.rst | ||
---|---|---|
30 | 30 |
\ Create object using a standard HTML form. |
31 | 31 |
\ Purge container/object history. |
32 | 32 |
\ List other accounts that share objects with a user. |
33 |
\ List shared containers/objects. |
|
33 | 34 |
0.4 (July 01, 2011) Object permissions and account groups. |
34 | 35 |
\ Control versioning behavior and container quotas with container policy directives. |
35 | 36 |
\ Support updating/deleting individual metadata with ``POST``. |
... | ... | |
206 | 207 |
limit The amount of results requested (default is 10000) |
207 | 208 |
marker Return containers with name lexicographically after marker |
208 | 209 |
format Optional extended reply type (can be ``json`` or ``xml``) |
210 |
shared Show only shared containers (no value parameter) |
|
209 | 211 |
until Optional timestamp |
210 | 212 |
====================== ========================= |
211 | 213 |
|
... | ... | |
343 | 345 |
path Assume ``prefix=path`` and ``delimiter=/`` |
344 | 346 |
format Optional extended reply type (can be ``json`` or ``xml``) |
345 | 347 |
meta Return objects having the specified meta keys (can be a comma separated list) |
348 |
shared Show only shared objects (no value parameter) |
|
346 | 349 |
until Optional timestamp |
347 | 350 |
====================== =================================== |
348 | 351 |
|
... | ... | |
883 | 886 |
* Headers ``X-Container-Block-*`` at the container level, exposing the underlying storage characteristics. |
884 | 887 |
* All metadata replies, at all levels, include latest modification information. |
885 | 888 |
* At all levels, a ``GET`` request may use ``If-Modified-Since`` and ``If-Unmodified-Since`` headers. |
886 |
* Container/object lists include all associated metadata if the reply is of type json/xml. Some names are kept to their OOS API equivalents for compatibility. |
|
889 |
* Container/object lists include all associated metadata if the reply is of type json/xml. Some names are kept to their OOS API equivalents for compatibility. |
|
890 |
* Option to include only shared containers/objects in listings. |
|
887 | 891 |
* Object metadata allowed, in addition to ``X-Object-Meta-*``: ``Content-Encoding``, ``Content-Disposition``, ``X-Object-Manifest``. These are all replaced with every update operation, except if using the ``update`` parameter (in which case individual keys can also be deleted). Deleting meta by providing empty values also works when copying/moving an object. |
888 | 892 |
* Multi-range object ``GET`` support as outlined in RFC2616. |
889 | 893 |
* Object hashmap retrieval through ``GET`` and the ``format`` parameter. |
b/pithos/api/functions.py | ||
---|---|---|
198 | 198 |
meta, groups = get_account_headers(request) |
199 | 199 |
replace = True |
200 | 200 |
if 'update' in request.GET: |
201 |
replace = False
|
|
201 |
replace = False |
|
202 | 202 |
if groups: |
203 | 203 |
try: |
204 | 204 |
backend.update_account_groups(request.user, v_account, groups, replace) |
... | ... | |
237 | 237 |
if not limit: |
238 | 238 |
limit = 10000 |
239 | 239 |
|
240 |
shared = False |
|
241 |
if 'shared' in request.GET: |
|
242 |
shared = True |
|
243 |
|
|
240 | 244 |
try: |
241 |
containers = backend.list_containers(request.user, v_account, marker, limit, until) |
|
245 |
containers = backend.list_containers(request.user, v_account, marker, limit, shared, until)
|
|
242 | 246 |
except NotAllowedError: |
243 | 247 |
raise Unauthorized('Access denied') |
244 | 248 |
except NameError: |
... | ... | |
426 | 430 |
else: |
427 | 431 |
keys = [] |
428 | 432 |
|
433 |
shared = False |
|
434 |
if 'shared' in request.GET: |
|
435 |
shared = True |
|
436 |
|
|
429 | 437 |
try: |
430 |
objects = backend.list_objects(request.user, v_account, v_container, prefix, delimiter, marker, limit, virtual, keys, until) |
|
438 |
objects = backend.list_objects(request.user, v_account, v_container, prefix, delimiter, marker, limit, virtual, keys, shared, until)
|
|
431 | 439 |
except NotAllowedError: |
432 | 440 |
raise Unauthorized('Access denied') |
433 | 441 |
except NameError: |
... | ... | |
901 | 909 |
content_length = -1 |
902 | 910 |
if request.META.get('HTTP_TRANSFER_ENCODING') != 'chunked': |
903 | 911 |
content_length = get_content_length(request) |
904 |
|
|
912 |
|
|
905 | 913 |
if length is None: |
906 | 914 |
length = content_length |
907 | 915 |
else: |
b/pithos/backends/base.py | ||
---|---|---|
111 | 111 |
""" |
112 | 112 |
return |
113 | 113 |
|
114 |
def list_containers(self, user, account, marker=None, limit=10000, until=None): |
|
114 |
def list_containers(self, user, account, marker=None, limit=10000, shared=False, until=None):
|
|
115 | 115 |
"""Return a list of container names existing under an account. |
116 | 116 |
|
117 | 117 |
Parameters: |
118 | 118 |
'marker': Start list from the next item after 'marker' |
119 | 119 |
'limit': Number of containers to return |
120 |
'shared': Only list containers with permissions set |
|
120 | 121 |
|
121 | 122 |
Raises: |
122 | 123 |
NotAllowedError: Operation not permitted |
... | ... | |
195 | 196 |
""" |
196 | 197 |
return |
197 | 198 |
|
198 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None): |
|
199 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], shared=False, until=None):
|
|
199 | 200 |
"""Return a list of object (name, version_id) tuples existing under a container. |
200 | 201 |
|
201 | 202 |
Parameters: |
... | ... | |
209 | 210 |
If set, the result will include all names after 'prefix',\ |
210 | 211 |
up to and including the 'delimiter' if it is found |
211 | 212 |
'keys': Include objects that have meta with the keys in the list |
213 |
'shared': Only list objects with permissions set |
|
212 | 214 |
|
213 | 215 |
Raises: |
214 | 216 |
NotAllowedError: Operation not permitted |
b/pithos/backends/simple.py | ||
---|---|---|
238 | 238 |
self._del_groups(account) |
239 | 239 |
|
240 | 240 |
@backend_method |
241 |
def list_containers(self, user, account, marker=None, limit=10000, until=None): |
|
241 |
def list_containers(self, user, account, marker=None, limit=10000, shared=False, until=None):
|
|
242 | 242 |
"""Return a list of containers existing under an account.""" |
243 | 243 |
|
244 | 244 |
logger.debug("list_containers: %s %s %s %s", account, marker, limit, until) |
... | ... | |
248 | 248 |
allowed = self._allowed_containers(user, account) |
249 | 249 |
start, limit = self._list_limits(allowed, marker, limit) |
250 | 250 |
return allowed[start:start + limit] |
251 |
else: |
|
252 |
if shared: |
|
253 |
allowed = [x.split('/', 2)[1] for x in self._shared_paths(account)] |
|
254 |
start, limit = self._list_limits(allowed, marker, limit) |
|
255 |
return allowed[start:start + limit] |
|
251 | 256 |
return [x[0] for x in self._list_objects(account, '', '/', marker, limit, False, [], until)] |
252 | 257 |
|
253 | 258 |
@backend_method |
... | ... | |
369 | 374 |
self._copy_version(user, account, account, True, False) # New account version (for timestamp update). |
370 | 375 |
|
371 | 376 |
@backend_method |
372 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None): |
|
377 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], shared=False, until=None):
|
|
373 | 378 |
"""Return a list of objects existing under a container.""" |
374 | 379 |
|
375 |
logger.debug("list_objects: %s %s %s %s %s %s %s %s %s", account, container, prefix, delimiter, marker, limit, virtual, keys, until)
|
|
380 |
logger.debug("list_objects: %s %s %s %s %s %s %s %s %s %s", account, container, prefix, delimiter, marker, limit, virtual, keys, shared, until)
|
|
376 | 381 |
allowed = [] |
377 | 382 |
if user != account: |
378 | 383 |
if until: |
... | ... | |
380 | 385 |
allowed = self._allowed_paths(user, os.path.join(account, container)) |
381 | 386 |
if not allowed: |
382 | 387 |
raise NotAllowedError |
388 |
else: |
|
389 |
if shared: |
|
390 |
allowed = self._shared_paths(os.path.join(account, container)) |
|
383 | 391 |
path, version_id, mtime = self._get_containerinfo(account, container, until) |
384 | 392 |
return self._list_objects(path, prefix, delimiter, marker, limit, virtual, keys, until, allowed) |
385 | 393 |
|
... | ... | |
970 | 978 |
for path in self._allowed_paths(user, account): |
971 | 979 |
allow.add(path.split('/', 2)[1]) |
972 | 980 |
return sorted(allow) |
981 |
|
|
982 |
def _shared_paths(self, prefix): |
|
983 |
sql = 'select distinct name from permissions where name like ?' |
|
984 |
c = self.con.execute(sql, (prefix + '/%',)) |
|
985 |
return [x[0] for x in c.fetchall()] |
Also available in: Unified diff