Revision 6f4bce7b pithos/backends/modular.py
b/pithos/backends/modular.py | ||
---|---|---|
39 | 39 |
import binascii |
40 | 40 |
|
41 | 41 |
from base import NotAllowedError, BaseBackend |
42 |
from lib.permissions import Permissions |
|
42 |
from lib.permissions import Permissions, READ, WRITE
|
|
43 | 43 |
from lib.hashfiler import Mapper, Blocker |
44 | 44 |
|
45 | 45 |
|
... | ... | |
460 | 460 |
if user != account: |
461 | 461 |
raise NotAllowedError |
462 | 462 |
path = self._get_objectinfo(account, container, name)[0] |
463 |
r, w = self._check_permissions(path, permissions)
|
|
464 |
self._put_permissions(path, r, w)
|
|
463 |
self._check_permissions(path, permissions) |
|
464 |
self._put_permissions(path, permissions)
|
|
465 | 465 |
|
466 | 466 |
@backend_method |
467 | 467 |
def get_object_public(self, user, account, container, name): |
... | ... | |
509 | 509 |
path = self._get_containerinfo(account, container)[0] |
510 | 510 |
path = '/'.join((path, name)) |
511 | 511 |
if permissions is not None: |
512 |
r, w = self._check_permissions(path, permissions)
|
|
512 |
self._check_permissions(path, permissions) |
|
513 | 513 |
src_version_id, dest_version_id = self._copy_version(user, path, path, not replace_meta, False) |
514 | 514 |
sql = 'update versions set size = ? where version_id = ?' |
515 | 515 |
self.con.execute(sql, (size, dest_version_id)) |
... | ... | |
518 | 518 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)' |
519 | 519 |
self.con.execute(sql, (dest_version_id, k, v)) |
520 | 520 |
if permissions is not None: |
521 |
self._put_permissions(path, r, w)
|
|
521 |
self._put_permissions(path, permissions)
|
|
522 | 522 |
|
523 | 523 |
@backend_method |
524 | 524 |
def copy_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None): |
... | ... | |
537 | 537 |
dest_path = self._get_containerinfo(account, dest_container)[0] |
538 | 538 |
dest_path = '/'.join((dest_path, dest_name)) |
539 | 539 |
if permissions is not None: |
540 |
r, w = self._check_permissions(dest_path, permissions)
|
|
540 |
self._check_permissions(dest_path, permissions) |
|
541 | 541 |
src_version_id, dest_version_id = self._copy_version(user, src_path, dest_path, not replace_meta, True, src_version) |
542 | 542 |
for k, v in dest_meta.iteritems(): |
543 | 543 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)' |
544 | 544 |
self.con.execute(sql, (dest_version_id, k, v)) |
545 | 545 |
if permissions is not None: |
546 |
self._put_permissions(dest_path, r, w)
|
|
546 |
self._put_permissions(dest_path, permissions)
|
|
547 | 547 |
|
548 | 548 |
@backend_method |
549 | 549 |
def move_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None): |
... | ... | |
836 | 836 |
pass |
837 | 837 |
|
838 | 838 |
def _get_groups(self, account): |
839 |
groups = {} |
|
840 |
for row in self.permissions.group_list(account): |
|
841 |
if group not in groups: |
|
842 |
groups[group] = [] |
|
843 |
groups[group].append(member) |
|
844 |
return groups |
|
839 |
return self.permissions.group_dict(account) |
|
845 | 840 |
|
846 | 841 |
def _put_groups(self, account, groups, replace=False): |
847 | 842 |
if replace: |
... | ... | |
855 | 850 |
def _del_groups(self, account): |
856 | 851 |
self.permissions.group_destroy(account) |
857 | 852 |
|
858 |
# ---------------- UP TO HERE ---------------- |
|
859 |
|
|
860 | 853 |
def _check_permissions(self, path, permissions): |
861 | 854 |
# Check for existing permissions. |
862 |
sql = '''select name from permissions |
|
863 |
where name != ? and (name like ? or ? like name || ?)''' |
|
864 |
c = self.con.execute(sql, (path, path + '%', path, '%')) |
|
865 |
row = c.fetchone() |
|
866 |
if row: |
|
855 |
paths = self.permissions.access_list(path) |
|
856 |
if paths: |
|
867 | 857 |
ae = AttributeError() |
868 |
ae.data = row[0]
|
|
858 |
ae.data = paths
|
|
869 | 859 |
raise ae |
870 | 860 |
|
871 |
# Format given permissions. |
|
872 |
if len(permissions) == 0: |
|
873 |
return [], [] |
|
874 |
r = permissions.get('read', []) |
|
875 |
w = permissions.get('write', []) |
|
876 | 861 |
# Examples follow. |
877 | 862 |
# if True in [False or ',' in x for x in r]: |
878 | 863 |
# raise ValueError('Bad characters in read permissions') |
879 | 864 |
# if True in [False or ',' in x for x in w]: |
880 | 865 |
# raise ValueError('Bad characters in write permissions') |
881 |
return r, w
|
|
866 |
pass
|
|
882 | 867 |
|
883 | 868 |
def _get_permissions(self, path): |
884 |
# Check for permissions at path or above. |
|
885 |
sql = 'select name, op, user from permissions where ? like name || ?' |
|
886 |
c = self.con.execute(sql, (path, '%')) |
|
887 |
name = path |
|
888 |
perms = {} # Return nothing, if nothing is set. |
|
889 |
for row in c.fetchall(): |
|
890 |
name = row[0] |
|
891 |
if row[1] not in perms: |
|
892 |
perms[row[1]] = [] |
|
893 |
perms[row[1]].append(row[2]) |
|
894 |
return name, perms |
|
895 |
|
|
896 |
def _put_permissions(self, path, r, w): |
|
897 |
sql = 'delete from permissions where name = ?' |
|
898 |
self.con.execute(sql, (path,)) |
|
899 |
sql = 'insert into permissions (name, op, user) values (?, ?, ?)' |
|
869 |
self.permissions.access_inherit(path) |
|
870 |
|
|
871 |
def _put_permissions(self, path, permissions): |
|
872 |
self.permissions.access_revoke_all(path) |
|
873 |
r = permissions.get('read', []) |
|
900 | 874 |
if r: |
901 |
self.con.executemany(sql, [(path, 'read', x) for x in r]) |
|
875 |
self.permissions.access_grant(path, READ, r) |
|
876 |
w = permissions.get('write', []) |
|
902 | 877 |
if w: |
903 |
self.con.executemany(sql, [(path, 'write', x) for x in w])
|
|
878 |
self.permissions.access_grant(path, WRITE, w)
|
|
904 | 879 |
|
905 | 880 |
def _get_public(self, path): |
906 |
sql = 'select name from public where name = ?' |
|
907 |
c = self.con.execute(sql, (path,)) |
|
908 |
row = c.fetchone() |
|
909 |
if not row: |
|
910 |
return False |
|
911 |
return True |
|
881 |
return self.permissions.public_check(path) |
|
912 | 882 |
|
913 | 883 |
def _put_public(self, path, public): |
914 | 884 |
if not public: |
915 |
sql = 'delete from public where name = ?'
|
|
885 |
self.permissions.public_unset(path)
|
|
916 | 886 |
else: |
917 |
sql = 'insert or replace into public (name) values (?)' |
|
918 |
self.con.execute(sql, (path,)) |
|
887 |
self.permissions.public_set(path) |
|
919 | 888 |
|
920 | 889 |
def _del_sharing(self, path): |
921 |
sql = 'delete from permissions where name = ?' |
|
922 |
self.con.execute(sql, (path,)) |
|
923 |
sql = 'delete from public where name = ?' |
|
924 |
self.con.execute(sql, (path,)) |
|
890 |
self.permissions.access_revoke_all(path) |
|
891 |
self.permissions.public_unset(path) |
|
925 | 892 |
|
926 |
def _is_allowed(self, user, account, container, name, op='read'):
|
|
893 |
def _can_read(self, user, account, container, name):
|
|
927 | 894 |
if user == account: |
928 | 895 |
return True |
929 | 896 |
path = '/'.join((account, container, name)) |
930 |
if op == 'read' and self._get_public(path): |
|
931 |
return True |
|
932 |
perm_path, perms = self._get_permissions(path) |
|
933 |
|
|
934 |
# Expand groups. |
|
935 |
for x in ('read', 'write'): |
|
936 |
g_perms = set() |
|
937 |
for y in perms.get(x, []): |
|
938 |
if ':' in y: |
|
939 |
g_account, g_name = y.split(':', 1) |
|
940 |
groups = self._get_groups(g_account) |
|
941 |
if g_name in groups: |
|
942 |
g_perms.update(groups[g_name]) |
|
943 |
else: |
|
944 |
g_perms.add(y) |
|
945 |
perms[x] = g_perms |
|
946 |
|
|
947 |
if op == 'read' and ('*' in perms['read'] or user in perms['read']): |
|
948 |
return True |
|
949 |
if '*' in perms['write'] or user in perms['write']: |
|
950 |
return True |
|
951 |
return False |
|
952 |
|
|
953 |
def _can_read(self, user, account, container, name): |
|
954 |
if not self._is_allowed(user, account, container, name, 'read'): |
|
897 |
if not self.permissions.access_check(path, READ, user) and not self.permissions.access_check(path, WRITE, user): |
|
955 | 898 |
raise NotAllowedError |
956 | 899 |
|
957 | 900 |
def _can_write(self, user, account, container, name): |
958 |
if not self._is_allowed(user, account, container, name, 'write'): |
|
901 |
if user == account: |
|
902 |
return True |
|
903 |
path = '/'.join((account, container, name)) |
|
904 |
if not self.permissions.access_check(path, WRITE, user): |
|
959 | 905 |
raise NotAllowedError |
960 | 906 |
|
961 | 907 |
def _allowed_paths(self, user, prefix=None): |
962 |
sql = '''select distinct name from permissions where (user = ? |
|
963 |
or user in (select account || ':' || gname from groups where user = ?))''' |
|
964 |
param = (user, user) |
|
965 | 908 |
if prefix: |
966 |
sql += ' and name like ?' |
|
967 |
param += (prefix + '/%',) |
|
968 |
c = self.con.execute(sql, param) |
|
969 |
return [x[0] for x in c.fetchall()] |
|
909 |
prefix += '/' |
|
910 |
return self.permissions.access_list_paths(user, prefix) |
|
970 | 911 |
|
971 | 912 |
def _allowed_accounts(self, user): |
972 | 913 |
allow = set() |
... | ... | |
981 | 922 |
return sorted(allow) |
982 | 923 |
|
983 | 924 |
def _shared_paths(self, prefix): |
984 |
sql = 'select distinct name from permissions where name like ?' |
|
985 |
c = self.con.execute(sql, (prefix + '/%',)) |
|
986 |
return [x[0] for x in c.fetchall()] |
|
925 |
prefix += '/' |
|
926 |
return self.permissions.access_list_shared(prefix) |
Also available in: Unified diff