Revision 27932481
b/snf-pithos-app/Changelog | ||
---|---|---|
1 | 1 |
Changelog |
2 | 2 |
========= |
3 | 3 |
|
4 |
v0.13.0 |
|
5 |
------ |
|
6 |
* setting *PITHOS_SERVICE_TOKEN* is no longer required for feedback to work |
|
7 |
* settings *PITHOS_PROXY_USER_SERVICES*, *PITHOS_USER_CATALOG_URL*, *PITHOS_USER_FEEDBACK_URL*, |
|
8 |
*PITHOS_USER_LOGIN_URL* should be set |
|
9 |
|
|
4 | 10 |
v0.10.0 |
5 | 11 |
------ |
6 | 12 |
* improve sql queries |
... | ... | |
12 | 18 |
v0.9.7 |
13 | 19 |
------ |
14 | 20 |
* Delegate feedback post request to Identity Provider (astakos) |
15 |
New setting *PITHOS_SERVICE_TOKEN* is required to be set for feedback to
|
|
21 |
New setting *PITHOS_SERVICE_TOKEN* is required to be set for feedback to |
|
16 | 22 |
work. |
17 | 23 |
* Change API calls to include public objects in shared by me |
18 | 24 |
|
... | ... | |
22 | 28 |
|
23 | 29 |
v0.9.5 |
24 | 30 |
------ |
25 |
* Calculate the length of the last block properly.
|
|
31 |
* Calculate the length of the last block properly. |
|
26 | 32 |
|
27 | 33 |
v0.9.4 |
28 | 34 |
------ |
b/snf-pithos-app/README | ||
---|---|---|
30 | 30 |
=============================== ==================================================== ============================================================ |
31 | 31 |
Name Default value Description |
32 | 32 |
=============================== ==================================================== ============================================================ |
33 |
PROXY_USER_SERVICES True Whether to proxy user feedback and catalog services
|
|
33 |
PITHOS_PROXY_USER_SERVICES True Whether to proxy user feedback and catalog services
|
|
34 | 34 |
PITHOS_USER_CATALOG_URL \http://127.0.0.1:8000/im/service/api/v2.0/users/ Astakos User Catalog URL |
35 | 35 |
PITHOS_USER_FEEDBACK_URL \http://127.0.0.1:8000/im/service/api/v2.0/feedback/ Astakos User Feedback URL |
36 | 36 |
PITHOS_USER_LOGIN_URL \http://127.0.0.1:8000/login/ Astakos User Login URL |
... | ... | |
48 | 48 |
PITHOS_BACKEND_VERSIONING auto Default versioning policy for containers |
49 | 49 |
PITHOS_BACKEND_FREE_VERSIONING True Default versioning debit policy (default free) |
50 | 50 |
PITHOS_UPDATE_MD5 True Update object checksums when using hashmaps |
51 |
PITHOS_SERVICE_TOKEN '' Service token acquired by the identity provider (astakos) |
|
52 | 51 |
=============================== ==================================================== ============================================================ |
53 | 52 |
|
54 | 53 |
To update checksums asynchronously, enable the queue, install snf-pithos-tools and use ``pithos-dispatcher``:: |
b/snf-pithos-app/conf/20-snf-pithos-app-settings.conf | ||
---|---|---|
42 | 42 |
|
43 | 43 |
# Disable if checksums are not required or are computed asynchronously by an external process. |
44 | 44 |
#PITHOS_UPDATE_MD5 = True |
45 |
|
|
46 |
# Service Token acquired by identity provider. |
|
47 |
#PITHOS_SERVICE_TOKEN = '' |
b/snf-pithos-app/pithos/api/delegate.py | ||
---|---|---|
44 | 44 |
from django.views.decorators.csrf import csrf_exempt |
45 | 45 |
|
46 | 46 |
from pithos.api.settings import ( |
47 |
AUTHENTICATION_USERS, USER_LOGIN_URL, USER_FEEDBACK_URL, USER_CATALOG_URL, |
|
48 |
SERVICE_TOKEN) |
|
47 |
AUTHENTICATION_USERS, USER_LOGIN_URL, USER_FEEDBACK_URL, USER_CATALOG_URL) |
|
49 | 48 |
|
50 | 49 |
from synnefo.lib.pool.http import get_http_connection |
51 | 50 |
|
b/snf-pithos-app/pithos/api/functions.py | ||
---|---|---|
58 | 58 |
copy_or_move_object, get_int_parameter, get_content_length, |
59 | 59 |
get_content_range, socket_read_iterator, SaveToBackendHandler, |
60 | 60 |
object_data_response, put_object_block, hashmap_md5, simple_list_response, |
61 |
api_method, retrieve_displayname, retrieve_uuid, retrieve_displaynames, |
|
62 |
retrieve_uuids) |
|
61 |
api_method, |
|
62 |
# retrieve_uuid |
|
63 |
) |
|
63 | 64 |
|
64 | 65 |
from pithos.api.settings import UPDATE_MD5 |
65 | 66 |
|
... | ... | |
185 | 186 |
response.status_code = 204 |
186 | 187 |
return response |
187 | 188 |
response.status_code = 200 |
188 |
put_account_translation_headers(response, accounts) |
|
189 | 189 |
response.content = '\n'.join(accounts) + '\n' |
190 | 190 |
return response |
191 | 191 |
|
... | ... | |
201 | 201 |
except NotAllowedError: |
202 | 202 |
raise Forbidden('Not allowed') |
203 | 203 |
else: |
204 |
meta['account_presentation'] = retrieve_username(x) |
|
205 | 204 |
rename_meta_key(meta, 'modified', 'last_modified') |
206 | 205 |
rename_meta_key( |
207 | 206 |
meta, 'until_timestamp', 'x_account_until_timestamp') |
... | ... | |
232 | 231 |
external_quota=request.user_usage) |
233 | 232 |
groups = request.backend.get_account_groups( |
234 | 233 |
request.user_uniq, v_account) |
235 |
for k in groups: |
|
236 |
groups[k] = [retrieve_username(x) for x in groups[k]] |
|
237 | 234 |
policy = request.backend.get_account_policy( |
238 | 235 |
request.user_uniq, v_account, external_quota=request.user_usage) |
239 | 236 |
except NotAllowedError: |
... | ... | |
254 | 251 |
# badRequest (400) |
255 | 252 |
|
256 | 253 |
meta, groups = get_account_headers(request) |
257 |
for k in groups: |
|
258 |
try: |
|
259 |
groups[k] = [retrieve_uuid(x) for x in groups[k]]
|
|
260 |
except ItemNotExists, e: |
|
261 |
raise BadRequest( |
|
262 |
'Bad X-Account-Group header value: unknown account: %s' % e) |
|
254 |
# for k in groups:
|
|
255 |
# try:
|
|
256 |
# groups[k] = [retrieve_uuid(request.token, x) for x in groups[k]]
|
|
257 |
# except ItemNotExists, e:
|
|
258 |
# raise BadRequest(
|
|
259 |
# 'Bad X-Account-Group header value: unknown account: %s' % e)
|
|
263 | 260 |
replace = True |
264 | 261 |
if 'update' in request.GET: |
265 | 262 |
replace = False |
... | ... | |
636 | 633 |
|
637 | 634 |
object_meta = [] |
638 | 635 |
for meta in objects: |
639 |
modified_by = meta.get('modified_by') |
|
640 |
if modified_by: |
|
641 |
meta['modified_by'] = retrieve_username(modified_by) |
|
642 | 636 |
if len(meta) == 1: |
643 | 637 |
# Virtual objects/directories. |
644 | 638 |
object_meta.append(meta) |
b/snf-pithos-app/pithos/api/settings.py | ||
---|---|---|
62 | 62 |
# Update object checksums when using hashmaps. |
63 | 63 |
UPDATE_MD5 = getattr(settings, 'PITHOS_UPDATE_MD5', True) |
64 | 64 |
|
65 |
# Service Token acquired by identity provider. |
|
66 |
SERVICE_TOKEN = getattr(settings, 'PITHOS_SERVICE_TOKEN', '') |
|
67 |
|
|
68 | 65 |
RADOS_STORAGE = getattr(settings, 'PITHOS_RADOS_STORAGE', False) |
69 | 66 |
RADOS_POOL_BLOCKS= getattr(settings, 'PITHOS_RADOS_POOL_BLOCKS', 'blocks') |
70 | 67 |
RADOS_POOL_MAPS = getattr(settings, 'PITHOS_RADOS_POOL_MAPS', 'maps') |
b/snf-pithos-app/pithos/api/util.py | ||
---|---|---|
65 | 65 |
BACKEND_QUOTA, BACKEND_VERSIONING, |
66 | 66 |
BACKEND_FREE_VERSIONING, |
67 | 67 |
AUTHENTICATION_URL, AUTHENTICATION_USERS, |
68 |
SERVICE_TOKEN, COOKIE_NAME, USER_CATALOG_URL,
|
|
68 |
COOKIE_NAME, USER_CATALOG_URL, |
|
69 | 69 |
RADOS_STORAGE, RADOS_POOL_BLOCKS, |
70 | 70 |
RADOS_POOL_MAPS) |
71 | 71 |
from pithos.backends import connect_backend |
... | ... | |
164 | 164 |
return meta, groups |
165 | 165 |
|
166 | 166 |
|
167 |
def put_account_translation_headers(response, accounts): |
|
168 |
for x in accounts: |
|
169 |
k = smart_str('X-Account-Presentation-%s' % x, strings_only=True) |
|
170 |
v = smart_str(retrieve_username(x), strings_only=True) |
|
171 |
response[k] = v |
|
172 |
|
|
173 |
|
|
174 | 167 |
def put_account_headers(response, meta, groups, policy): |
175 | 168 |
if 'count' in meta: |
176 | 169 |
response['X-Account-Container-Count'] = meta['count'] |
... | ... | |
241 | 234 |
if not restricted: |
242 | 235 |
response['X-Object-Hash'] = meta['hash'] |
243 | 236 |
response['X-Object-UUID'] = meta['uuid'] |
244 |
modified_by = retrieve_displayname(meta['modified_by']) |
|
245 | 237 |
response['X-Object-Modified-By'] = smart_str( |
246 |
modified_by, strings_only=True)
|
|
238 |
meta['modified_by'], strings_only=True)
|
|
247 | 239 |
response['X-Object-Version'] = meta['version'] |
248 | 240 |
response['X-Object-Version-Timestamp'] = http_date( |
249 | 241 |
int(meta['version_timestamp'])) |
... | ... | |
295 | 287 |
else: |
296 | 288 |
return True |
297 | 289 |
|
298 |
def retrieve_displayname(uuid): |
|
290 |
########################## |
|
291 |
# USER CATALOG utilities # |
|
292 |
########################## |
|
293 |
|
|
294 |
def retrieve_displayname(token, uuid): |
|
299 | 295 |
try: |
300 | 296 |
return get_displayname( |
301 |
SERVICE_TOKEN, uuid, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
297 |
token, uuid, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
302 | 298 |
except: |
303 | 299 |
# if it fails just leave the input intact |
304 | 300 |
return uuid |
305 | 301 |
|
306 |
def retrieve_displaynames(uuids): |
|
302 |
def retrieve_displaynames(token, uuids):
|
|
307 | 303 |
return get_displaynames( |
308 |
SERVICE_TOKEN, uuids, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
304 |
token, uuids, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
309 | 305 |
|
310 |
def retrieve_uuid(displayname): |
|
306 |
def retrieve_uuid(token, displayname):
|
|
311 | 307 |
if is_uuid(displayname): |
312 | 308 |
return displayname |
313 | 309 |
|
314 | 310 |
uuid = get_user_uuid( |
315 |
SERVICE_TOKEN, displayname, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
311 |
token, displayname, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
316 | 312 |
if not uuid: |
317 | 313 |
raise ItemNotExists(displayname) |
318 | 314 |
return uuid |
319 | 315 |
|
320 |
def retrieve_uuids(displaynames): |
|
316 |
def retrieve_uuids(token, displaynames):
|
|
321 | 317 |
return get_uuids( |
322 |
SERVICE_TOKEN, displaynames, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
318 |
token, displaynames, USER_CATALOG_URL, AUTHENTICATION_USERS)
|
|
323 | 319 |
|
324 |
def replace_permissions_displayname(holder): |
|
320 |
def replace_permissions_displayname(token, holder):
|
|
325 | 321 |
try: |
326 | 322 |
# check first for a group permission |
327 | 323 |
account, group = holder.split(':') |
... | ... | |
330 | 326 |
else: |
331 | 327 |
return ':'.join([retrieve_uuid(account), group]) |
332 | 328 |
|
333 |
def replace_permissions_uuid(holder): |
|
329 |
def replace_permissions_uuid(token, holder):
|
|
334 | 330 |
try: |
335 | 331 |
# check first for a group permission |
336 | 332 |
account, group = holder.split(':') |
... | ... | |
346 | 342 |
if len(perms) == 0: |
347 | 343 |
return |
348 | 344 |
|
349 |
perms['read'] = [replace_permissions_uuid(x) for x in perms.get('read', [])] |
|
350 |
perms['write'] = \ |
|
351 |
[replace_permissions_uuid(x) for x in perms.get('write', [])] |
|
345 |
# replace uuid with displayname |
|
346 |
# perms['read'] = [replace_permissions_uuid(request.token, x) for x in perms.get('read', [])] |
|
347 |
# perms['write'] = \ |
|
348 |
# [replace_permissions_uuid(request.token, x) for x in perms.get('write', [])] |
|
352 | 349 |
|
353 | 350 |
ret = [] |
354 | 351 |
|
... | ... | |
601 | 598 |
'Bad X-Object-Sharing header value: missing prefix') |
602 | 599 |
|
603 | 600 |
# replace displayname with uuid |
604 |
try: |
|
605 |
ret['read'] = \ |
|
606 |
[replace_permissions_displayname(x) for x in ret.get('read', [])]
|
|
607 |
ret['write'] = \ |
|
608 |
[replace_permissions_displayname(x) for x in ret.get('write', [])]
|
|
609 |
except ItemNotExists, e: |
|
610 |
raise BadRequest( |
|
611 |
'Bad X-Object-Sharing header value: unknown account: %s' % e) |
|
601 |
# try:
|
|
602 |
# ret['read'] = \
|
|
603 |
# [replace_permissions_displayname(request.token, x) for x in ret.get('read', [])]
|
|
604 |
# ret['write'] = \
|
|
605 |
# [replace_permissions_displayname(request.token, x) for x in ret.get('write', [])]
|
|
606 |
# except ItemNotExists, e:
|
|
607 |
# raise BadRequest(
|
|
608 |
# 'Bad X-Object-Sharing header value: unknown account: %s' % e)
|
|
612 | 609 |
|
613 | 610 |
# Keep duplicates only in write list. |
614 | 611 |
dups = [x for x in ret.get( |
... | ... | |
1072 | 1069 |
if getattr(request, 'user', None) is None: |
1073 | 1070 |
raise Unauthorized('Access denied') |
1074 | 1071 |
assert getattr(request, 'user_uniq', None) != None |
1075 |
request.user_usage = get_pithos_usage( |
|
1076 |
request.user.get('usage', []))
|
|
1077 |
|
|
1072 |
request.user_usage = get_pithos_usage(request.user.get('usage', []))
|
|
1073 |
request.token = request.GET.get('X-Auth-Token', request.META.get('HTTP_X_AUTH_TOKEN', token))
|
|
1074 |
|
|
1078 | 1075 |
# The args variable may contain up to (account, container, object). |
1079 | 1076 |
if len(args) > 1 and len(args[1]) > 256: |
1080 | 1077 |
raise BadRequest('Container name too large.') |
Also available in: Unified diff