Commit 4fb2ab61 authored by Sofia Papagiannaki's avatar Sofia Papagiannaki
Browse files

Change pithos sharing to work with account uuids

parent 42c9eb23
......@@ -53,7 +53,8 @@ from pithos.api.util import (
put_object_headers, update_manifest_meta, update_sharing_meta, update_public_meta,
validate_modification_preconditions, validate_matching_preconditions, split_container_object_string,
copy_or_move_object, get_int_parameter, get_content_length, get_content_range, socket_read_iterator,
SaveToBackendHandler, object_data_response, put_object_block, hashmap_md5, simple_list_response, api_method)
SaveToBackendHandler, object_data_response, put_object_block, hashmap_md5, simple_list_response, api_method,
retrieve_username, retrieve_uuid)
from pithos.api.settings import UPDATE_MD5
from pithos.backends.base import NotAllowedError, QuotaError, ContainerNotEmpty, ItemNotExists, VersionNotExists, ContainerExists
......@@ -175,6 +176,8 @@ def account_list(request):
# The cloudfiles python bindings expect 200 if json/xml.
response.status_code = 204
return response
if 'translate' in request.GET:
accounts = [retrieve_username(x) for x in accounts]
response.status_code = 200
response.content = '\n'.join(accounts) + '\n'
return response
......@@ -190,6 +193,8 @@ def account_list(request):
except NotAllowedError:
raise Forbidden('Not allowed')
else:
if 'translate' in request.GET:
meta['name'] = retrieve_username(x)
rename_meta_key(meta, 'modified', 'last_modified')
rename_meta_key(
meta, 'until_timestamp', 'x_account_until_timestamp')
......@@ -219,6 +224,8 @@ def account_meta(request, v_account):
request.user_uniq, v_account, 'pithos', until)
groups = request.backend.get_account_groups(
request.user_uniq, v_account)
for k in groups:
groups[k] = [retrieve_username(x) for x in groups[k]]
policy = request.backend.get_account_policy(
request.user_uniq, v_account)
except NotAllowedError:
......@@ -239,6 +246,12 @@ def account_update(request, v_account):
# badRequest (400)
meta, groups = get_account_headers(request)
for k in groups:
try:
groups[k] = [retrieve_uuid(x) for x in groups[k]]
except ItemNotExists, e:
raise BadRequest(
'Bad X-Account-Group header value: unknown account: %s' % e)
replace = True
if 'update' in request.GET:
replace = False
......
......@@ -65,9 +65,11 @@ from pithos.api.settings import (BACKEND_DB_MODULE, BACKEND_DB_CONNECTION,
BACKEND_QUOTA, BACKEND_VERSIONING,
BACKEND_FREE_VERSIONING,
AUTHENTICATION_URL, AUTHENTICATION_USERS,
SERVICE_TOKEN, COOKIE_NAME)
SERVICE_TOKEN, COOKIE_NAME, USER_INFO_URL)
from pithos.backends import connect_backend
from pithos.backends.base import NotAllowedError, QuotaError, ItemNotExists, VersionNotExists
from pithos.backends.base import (NotAllowedError, QuotaError, ItemNotExists,
VersionNotExists)
from synnefo.lib.astakos import get_user_uuid, get_username
import logging
import re
......@@ -275,13 +277,56 @@ def update_manifest_meta(request, v_account, meta):
meta['checksum'] = md5.hexdigest().lower()
def retrieve_username(uuid):
try:
return get_username(
SERVICE_TOKEN, uuid, USER_INFO_URL, AUTHENTICATION_USERS)
except:
# if it fails just leave the metadata intact
return uuid
def retrieve_uuid(username):
try:
return get_user_uuid(
SERVICE_TOKEN, username, USER_INFO_URL, AUTHENTICATION_USERS)
except Exception, e:
if e.args:
status = e.args[-1]
if status == 404:
raise ItemNotExists(username)
raise
def replace_permissions_username(holder):
try:
# check first for a group permission
account, group = holder.split(':')
except ValueError:
return retrieve_uuid(holder)
else:
return ':'.join([retrieve_uuid(account), group])
def replace_permissions_uuid(holder):
try:
# check first for a group permission
account, group = holder.split(':')
except ValueError:
return retrieve_username(holder)
else:
return ':'.join([retrieve_username(account), group])
def update_sharing_meta(request, permissions, v_account, v_container, v_object, meta):
if permissions is None:
return
allowed, perm_path, perms = permissions
if len(perms) == 0:
return
perms['read'] = [replace_permissions_uuid(x) for x in perms.get('read', [])]
perms['write'] = \
[replace_permissions_uuid(x) for x in perms.get('write', [])]
ret = []
r = ','.join(perms.get('read', []))
if r:
ret.append('read=' + r)
......@@ -514,7 +559,8 @@ def get_sharing(request):
if '*' in ret['read']:
ret['read'] = ['*']
if len(ret['read']) == 0:
raise BadRequest('Bad X-Object-Sharing header value')
raise BadRequest(
'Bad X-Object-Sharing header value: invalid length')
elif perm.startswith('write='):
ret['write'] = list(set(
[v.replace(' ', '').lower() for v in perm[6:].split(',')]))
......@@ -523,9 +569,21 @@ def get_sharing(request):
if '*' in ret['write']:
ret['write'] = ['*']
if len(ret['write']) == 0:
raise BadRequest('Bad X-Object-Sharing header value')
raise BadRequest(
'Bad X-Object-Sharing header value: invalid length')
else:
raise BadRequest('Bad X-Object-Sharing header value')
raise BadRequest(
'Bad X-Object-Sharing header value: missing prefix')
# replace username with uuid
try:
ret['read'] = \
[replace_permissions_username(x) for x in ret.get('read', [])]
ret['write'] = \
[replace_permissions_username(x) for x in ret.get('write', [])]
except ItemNotFound, e:
raise BadRequest(
'Bad X-Object-Sharing header value: unknown account: %s' % e)
# Keep duplicates only in write list.
dups = [x for x in ret.get(
......
......@@ -78,6 +78,12 @@ xvals = table(
column('value', sa.String(256))
)
g = table(
'groups',
column('owner', sa.String(256)),
column('name', sa.String(256)),
column('member', sa.String(256))
)
def upgrade():
connection = op.get_bind()
......@@ -132,6 +138,24 @@ def upgrade():
u = u.values({'value':new_value})
connection.execute(u)
s = sa.select([g.c.owner, g.c.name, g.c.member])
groups = connection.execute(s).fetchall()
for owner, name, member in groups:
owner_uuid = get_uuid(owner)
member_uuid = get_uuid(member)
if owner_uuid or member_uuid:
u = g.update()
u = u.where(and_(
g.c.owner == owner,
g.c.name == name,
g.c.member == member))
values = {}
if owner_uuid:
values['owner'] = owner_uuid
if member_uuid:
values['member'] = member_uuid
u = u.values(values)
connection.execute(u)
def downgrade():
connection = op.get_bind()
......@@ -185,3 +209,22 @@ def downgrade():
xvals.c.value ==value))
u = u.values({'value':new_value})
connection.execute(u)
s = sa.select([g.c.owner, g.c.name, g.c.member])
groups = connection.execute(s).fetchall()
for owner, name, member in groups:
owner_username = get_username(owner)
member_username = get_username(member)
if owner_username or member_username:
u = g.update()
u = u.where(and_(
g.c.owner == owner,
g.c.name == name,
g.c.member == member))
values = {}
if owner_username:
values['owner'] = owner_username
if member_username:
values['member'] = member_username
u = u.values(values)
connection.execute(u)
......@@ -959,12 +959,15 @@ class Pithos_Client(OOS_Client):
delimiter=delimiter,
**headers)
def list_shared_by_others(self, limit=None, marker=None, format='text'):
def list_shared_with_me(self, limit=None, marker=None, format='text',
translate=None):
"""lists other accounts that share objects to the user"""
l = ['limit', 'marker']
params = {}
for elem in [elem for elem in l if eval(elem)]:
params[elem] = eval(elem)
if translate is not None:
params['translate'] = ''
return self._list('', format, params)
def share_object(self, container, object, l, read=True):
......
......@@ -39,6 +39,8 @@ from os import environ
from sys import argv, exit, stdin, stdout
from datetime import datetime
from django.core.validators import email_re
from pithos.tools.lib.client import Pithos_Client, Fault
from pithos.tools.lib.util import get_user, get_auth, get_url
from pithos.tools.lib.transfer import upload, download
......@@ -52,7 +54,6 @@ import os
_cli_commands = {}
def cli_command(*args):
def decorator(cls):
cls.commands = args
......@@ -93,6 +94,13 @@ class Command(object):
val = getattr(options, key)
setattr(self, key, val)
if email_re.match(self.user):
try:
from synnefo.lib.astakos import get_user_uuid
from pithos.api.settings import SERVICE_TOKEN
self.user = get_user_uuid(SERVICE_TOKEN, self.user)
except ImportError:
pass
self.client = Pithos_Client(
self.url, self.token, self.user, self.verbose,
self.debug)
......@@ -763,8 +771,9 @@ class SharingObject(Command):
attrs = ['limit', 'marker']
args = self._build_args(attrs)
args['format'] = 'json' if self.detail else 'text'
args['translate'] = ''
print_list(self.client.list_shared_by_others(**args))
print_list(self.client.list_shared_with_me(**args))
@cli_command('send')
......
......@@ -1864,14 +1864,11 @@ class ListSharing(BaseTestCase):
self.client.share_object('c1', 'o1', (account,), read=True)
break
def tearDown(self):
pass
def test_list_other_shared(self):
self.other = Pithos_Client(get_url(),
self.o1_sharing[0],
self.o1_sharing[1])
self.assertTrue(get_user() in self.other.list_shared_by_others())
self.assertTrue(get_user() in self.other.list_shared_with_me())
def test_list_my_shared(self):
my_shared_containers = self.client.list_containers(shared=True)
......@@ -2337,7 +2334,7 @@ class TestPermissions(BaseTestCase):
for token, account in OTHER_ACCOUNTS.items():
if account in self.authorized:
self.other = Pithos_Client(get_url(), token, account)
self.assertTrue(get_user() in self.other.list_shared_by_others())
self.assertTrue(get_user() in self.other.list_shared_with_me())
class TestPublish(BaseTestCase):
def test_publish(self):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment