Revision 02c0c3fa pithos/backends/simple.py
b/pithos/backends/simple.py | ||
---|---|---|
80 | 80 |
sql = '''create table if not exists hashmaps ( |
81 | 81 |
version_id integer, pos integer, block_id text, primary key (version_id, pos))''' |
82 | 82 |
self.con.execute(sql) |
83 |
sql = '''create table if not exists groups ( |
|
84 |
account text, name text, users text, primary key (account, name))''' |
|
85 |
self.con.execute(sql) |
|
83 | 86 |
sql = '''create table if not exists permissions ( |
84 | 87 |
name text, read text, write text, primary key (name))''' |
85 | 88 |
self.con.execute(sql) |
89 |
sql = '''create table if not exists policy ( |
|
90 |
name text, key text, value text, primary key (name, key))''' |
|
91 |
self.con.execute(sql) |
|
86 | 92 |
self.con.commit() |
87 | 93 |
|
88 |
def delete_account(self, user, account): |
|
89 |
"""Delete the account with the given name.""" |
|
90 |
|
|
91 |
logger.debug("delete_account: %s", account) |
|
92 |
if user != account: |
|
93 |
raise NotAllowedError |
|
94 |
count, bytes, tstamp = self._get_pathstats(account) |
|
95 |
if count > 0: |
|
96 |
raise IndexError('Account is not empty') |
|
97 |
self._del_path(account) # Point of no return. |
|
98 |
|
|
99 | 94 |
def get_account_meta(self, user, account, until=None): |
100 | 95 |
"""Return a dictionary with the account metadata.""" |
101 | 96 |
|
... | ... | |
140 | 135 |
raise NotAllowedError |
141 | 136 |
self._put_metadata(user, account, meta, replace) |
142 | 137 |
|
143 |
def list_containers(self, user, account, marker=None, limit=10000, until=None):
|
|
144 |
"""Return a list of containers existing under an account."""
|
|
138 |
def get_account_groups(self, user, account):
|
|
139 |
"""Return a dictionary with the user groups defined for this account."""
|
|
145 | 140 |
|
146 |
logger.debug("list_containers: %s %s %s %s", account, marker, limit, until)
|
|
141 |
logger.debug("get_account_groups: %s", account)
|
|
147 | 142 |
if user != account: |
148 | 143 |
raise NotAllowedError |
149 |
return self._list_objects(account, '', '/', marker, limit, False, [], until)
|
|
144 |
return self._get_groups(account)
|
|
150 | 145 |
|
151 |
def put_container(self, user, account, container):
|
|
152 |
"""Create a new container with the given name."""
|
|
146 |
def update_account_groups(self, user, account, groups, replace=False):
|
|
147 |
"""Update the groups associated with the account."""
|
|
153 | 148 |
|
154 |
logger.debug("put_container: %s %s", account, container)
|
|
149 |
logger.debug("update_account_groups: %s %s %s", account, groups, replace)
|
|
155 | 150 |
if user != account: |
156 | 151 |
raise NotAllowedError |
157 |
try: |
|
158 |
path, version_id, mtime = self._get_containerinfo(account, container) |
|
159 |
except NameError: |
|
160 |
path = os.path.join(account, container) |
|
161 |
version_id = self._put_version(path, user) |
|
162 |
else: |
|
163 |
raise NameError('Container already exists') |
|
152 |
for k, v in groups.iteritems(): |
|
153 |
if True in [False or ',' in x for x in v]: |
|
154 |
raise ValueError('Bad characters in groups') |
|
155 |
if replace: |
|
156 |
sql = 'delete from groups where account = ?' |
|
157 |
self.con.execute(sql, (account,)) |
|
158 |
for k, v in groups.iteritems(): |
|
159 |
if len(v) == 0: |
|
160 |
if not replace: |
|
161 |
sql = 'delete from groups where account = ? and name = ?' |
|
162 |
self.con.execute(sql, (account, k)) |
|
163 |
else: |
|
164 |
sql = 'insert or replace into groups (account, name, users) values (?, ?, ?)' |
|
165 |
self.con.execute(sql, (account, k, ','.join(v))) |
|
166 |
self.con.commit() |
|
164 | 167 |
|
165 |
def delete_container(self, user, account, container):
|
|
166 |
"""Delete the container with the given name."""
|
|
168 |
def delete_account(self, user, account):
|
|
169 |
"""Delete the account with the given name."""
|
|
167 | 170 |
|
168 |
logger.debug("delete_container: %s %s", account, container)
|
|
171 |
logger.debug("delete_account: %s", account)
|
|
169 | 172 |
if user != account: |
170 | 173 |
raise NotAllowedError |
171 |
path, version_id, mtime = self._get_containerinfo(account, container) |
|
172 |
count, bytes, tstamp = self._get_pathstats(path) |
|
174 |
count, bytes, tstamp = self._get_pathstats(account) |
|
173 | 175 |
if count > 0: |
174 |
raise IndexError('Container is not empty') |
|
175 |
self._del_path(path) # Point of no return. |
|
176 |
self._copy_version(user, account, account, True, True) # New account version. |
|
176 |
raise IndexError('Account is not empty') |
|
177 |
self._del_path(account) # Point of no return. |
|
178 |
|
|
179 |
def list_containers(self, user, account, marker=None, limit=10000, until=None): |
|
180 |
"""Return a list of containers existing under an account.""" |
|
181 |
|
|
182 |
logger.debug("list_containers: %s %s %s %s", account, marker, limit, until) |
|
183 |
if user != account: |
|
184 |
raise NotAllowedError |
|
185 |
return self._list_objects(account, '', '/', marker, limit, False, [], until) |
|
177 | 186 |
|
178 | 187 |
def get_container_meta(self, user, account, container, until=None): |
179 | 188 |
"""Return a dictionary with the container metadata.""" |
... | ... | |
207 | 216 |
path, version_id, mtime = self._get_containerinfo(account, container) |
208 | 217 |
self._put_metadata(user, path, meta, replace) |
209 | 218 |
|
219 |
def get_container_policy(self, user, account, container): |
|
220 |
"""Return a dictionary with the container policy.""" |
|
221 |
|
|
222 |
logger.debug("get_container_policy: %s %s", account, container) |
|
223 |
return {} |
|
224 |
|
|
225 |
def update_container_policy(self, user, account, container, policy, replace=False): |
|
226 |
"""Update the policy associated with the account.""" |
|
227 |
|
|
228 |
logger.debug("update_container_policy: %s %s %s %s", account, container, policy, replace) |
|
229 |
return |
|
230 |
|
|
231 |
def put_container(self, user, account, container, policy=None): |
|
232 |
"""Create a new container with the given name.""" |
|
233 |
|
|
234 |
logger.debug("put_container: %s %s %s", account, container, policy) |
|
235 |
if user != account: |
|
236 |
raise NotAllowedError |
|
237 |
try: |
|
238 |
path, version_id, mtime = self._get_containerinfo(account, container) |
|
239 |
except NameError: |
|
240 |
path = os.path.join(account, container) |
|
241 |
version_id = self._put_version(path, user) |
|
242 |
else: |
|
243 |
raise NameError('Container already exists') |
|
244 |
|
|
245 |
def delete_container(self, user, account, container): |
|
246 |
"""Delete the container with the given name.""" |
|
247 |
|
|
248 |
logger.debug("delete_container: %s %s", account, container) |
|
249 |
if user != account: |
|
250 |
raise NotAllowedError |
|
251 |
path, version_id, mtime = self._get_containerinfo(account, container) |
|
252 |
count, bytes, tstamp = self._get_pathstats(path) |
|
253 |
if count > 0: |
|
254 |
raise IndexError('Container is not empty') |
|
255 |
self._del_path(path) # Point of no return. |
|
256 |
self._copy_version(user, account, account, True, True) # New account version. |
|
257 |
|
|
210 | 258 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None): |
211 | 259 |
"""Return a list of objects existing under a container.""" |
212 | 260 |
|
... | ... | |
273 | 321 |
r, w = self._check_permissions(path, permissions) |
274 | 322 |
self._put_permissions(path, r, w) |
275 | 323 |
|
324 |
def get_object_public(self, user, account, container, name): |
|
325 |
"""Return the public URL of the object if applicable.""" |
|
326 |
|
|
327 |
logger.debug("get_object_public: %s %s %s", account, container, name) |
|
328 |
return None |
|
329 |
|
|
330 |
def update_object_public(self, user, account, container, name, public): |
|
331 |
"""Update the public status of the object.""" |
|
332 |
|
|
333 |
logger.debug("update_object_public: %s %s %s %s", account, container, name, public) |
|
334 |
return |
|
335 |
|
|
276 | 336 |
def get_object_hashmap(self, user, account, container, name, version=None): |
277 | 337 |
"""Return the object's size and a list with partial hashes.""" |
278 | 338 |
|
... | ... | |
524 | 584 |
self.con.execute(sql, (dest_version_id, k, v)) |
525 | 585 |
self.con.commit() |
526 | 586 |
|
587 |
def _get_groups(self, account): |
|
588 |
sql = 'select name, users from groups where account = ?' |
|
589 |
c = self.con.execute(sql, (account,)) |
|
590 |
return dict([(x[0], x[1].split(',')) for x in c.fetchall()]) |
|
591 |
|
|
527 | 592 |
def _is_allowed(self, user, account, container, name, op='read'): |
528 | 593 |
if user == account: |
529 | 594 |
return True |
530 | 595 |
path = os.path.join(account, container, name) |
531 | 596 |
perm_path, perms = self._get_permissions(path) |
597 |
|
|
598 |
# Expand groups. |
|
599 |
for x in ('read', 'write'): |
|
600 |
g_perms = [] |
|
601 |
for y in perms.get(x, []): |
|
602 |
if ':' in y: |
|
603 |
g_account, g_name = y.split(':', 1) |
|
604 |
groups = self._get_groups(g_account) |
|
605 |
if g_name in groups: |
|
606 |
g_perms += groups[g_name] |
|
607 |
else: |
|
608 |
g_perms.append(y) |
|
609 |
perms[x] = g_perms |
|
610 |
|
|
532 | 611 |
if op == 'read' and user in perms.get('read', []): |
533 | 612 |
return True |
534 | 613 |
if user in perms.get('write', []): |
Also available in: Unified diff