Revision 3436eeb0 pithos/backends/simple.py
b/pithos/backends/simple.py | ||
---|---|---|
79 | 79 |
sql = '''create table if not exists hashmaps ( |
80 | 80 |
version_id integer, pos integer, block_id text, primary key (version_id, pos))''' |
81 | 81 |
self.con.execute(sql) |
82 |
sql = '''create table if not exists permissions ( |
|
83 |
name text, read text, write text, primary key (name))''' |
|
84 |
self.con.execute(sql) |
|
82 | 85 |
self.con.commit() |
83 | 86 |
|
84 | 87 |
def delete_account(self, user, account): |
... | ... | |
227 | 230 |
path, version_id, mtime, size = self._get_objectinfo(account, container, name) |
228 | 231 |
self._put_metadata(path, meta, replace) |
229 | 232 |
|
233 |
def get_object_permissions(self, user, account, container, name): |
|
234 |
"""Return a dictionary with the object permissions.""" |
|
235 |
|
|
236 |
logger.debug("get_object_permissions: %s %s %s", account, container, name) |
|
237 |
path = self._get_objectinfo(account, container, name)[0] |
|
238 |
return self._get_permissions(path) |
|
239 |
|
|
240 |
def update_object_permissions(self, user, account, container, name, permissions): |
|
241 |
"""Update the permissions associated with the object.""" |
|
242 |
|
|
243 |
logger.debug("update_object_permissions: %s %s %s %s", account, container, name, permissions) |
|
244 |
path = self._get_objectinfo(account, container, name)[0] |
|
245 |
r, w = self._check_permissions(path, permissions) |
|
246 |
self._put_permissions(path, r, w) |
|
247 |
|
|
230 | 248 |
def get_object_hashmap(self, user, account, container, name, version=None): |
231 | 249 |
"""Return the object's size and a list with partial hashes.""" |
232 | 250 |
|
... | ... | |
237 | 255 |
hashmap = [x[0] for x in c.fetchall()] |
238 | 256 |
return size, hashmap |
239 | 257 |
|
240 |
def update_object_hashmap(self, user, account, container, name, size, hashmap, meta={}, replace_meta=False): |
|
258 |
def update_object_hashmap(self, user, account, container, name, size, hashmap, meta={}, replace_meta=False, permissions={}):
|
|
241 | 259 |
"""Create/update an object with the specified size and partial hashes.""" |
242 | 260 |
|
243 | 261 |
logger.debug("update_object_hashmap: %s %s %s %s %s", account, container, name, size, hashmap) |
244 | 262 |
path = self._get_containerinfo(account, container)[0] |
245 | 263 |
path = os.path.join(path, name) |
264 |
if permissions: |
|
265 |
r, w = self._check_permissions(path, permissions) |
|
246 | 266 |
src_version_id, dest_version_id = self._copy_version(path, path, not replace_meta, False) |
247 | 267 |
sql = 'update versions set size = ? where version_id = ?' |
248 | 268 |
self.con.execute(sql, (size, dest_version_id)) |
... | ... | |
253 | 273 |
for k, v in meta.iteritems(): |
254 | 274 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)' |
255 | 275 |
self.con.execute(sql, (dest_version_id, k, v)) |
276 |
if permissions: |
|
277 |
sql = 'insert or replace into permissions (name, read, write) values (?, ?, ?)' |
|
278 |
self.con.execute(sql, (path, r, w)) |
|
256 | 279 |
self.con.commit() |
257 | 280 |
|
258 |
def copy_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, src_version=None): |
|
281 |
def copy_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions={}, src_version=None):
|
|
259 | 282 |
"""Copy an object's data and metadata.""" |
260 | 283 |
|
261 |
logger.debug("copy_object: %s %s %s %s %s %s %s %s", account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, src_version)
|
|
284 |
logger.debug("copy_object: %s %s %s %s %s %s %s %s %s", account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, permissions, src_version)
|
|
262 | 285 |
self._get_containerinfo(account, src_container) |
263 | 286 |
if src_version is None: |
264 | 287 |
src_path = self._get_objectinfo(account, src_container, src_name)[0] |
... | ... | |
266 | 289 |
src_path = os.path.join(account, src_container, src_name) |
267 | 290 |
dest_path = self._get_containerinfo(account, dest_container)[0] |
268 | 291 |
dest_path = os.path.join(dest_path, dest_name) |
292 |
if permissions: |
|
293 |
r, w = self._check_permissions(dest_path, permissions) |
|
269 | 294 |
src_version_id, dest_version_id = self._copy_version(src_path, dest_path, not replace_meta, True, src_version) |
270 | 295 |
for k, v in dest_meta.iteritems(): |
271 | 296 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)' |
272 | 297 |
self.con.execute(sql, (dest_version_id, k, v)) |
298 |
if permissions: |
|
299 |
sql = 'insert or replace into permissions (name, read, write) values (?, ?, ?)' |
|
300 |
self.con.execute(sql, (dest_path, r, w)) |
|
273 | 301 |
self.con.commit() |
274 | 302 |
|
275 |
def move_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False): |
|
303 |
def move_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions={}):
|
|
276 | 304 |
"""Move an object's data and metadata.""" |
277 | 305 |
|
278 |
logger.debug("move_object: %s %s %s %s %s %s %s", account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta)
|
|
279 |
self.copy_object(user, account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, None) |
|
306 |
logger.debug("move_object: %s %s %s %s %s %s %s %s", account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, permissions)
|
|
307 |
self.copy_object(user, account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, permissions, None)
|
|
280 | 308 |
self.delete_object(user, account, src_container, src_name) |
281 | 309 |
|
282 | 310 |
def delete_object(self, user, account, container, name): |
... | ... | |
285 | 313 |
logger.debug("delete_object: %s %s %s", account, container, name) |
286 | 314 |
path, version_id, mtime, size = self._get_objectinfo(account, container, name) |
287 | 315 |
self._put_version(path, 0, 1) |
316 |
sql = 'delete from permissions where name = ?' |
|
317 |
self.con.execute(sql, (path,)) |
|
318 |
self.con.commit() |
|
288 | 319 |
|
289 | 320 |
def list_versions(self, user, account, container, name): |
290 | 321 |
"""Return a list of all (version, version_timestamp) tuples for an object.""" |
... | ... | |
449 | 480 |
self.con.execute(sql, (dest_version_id, k, v)) |
450 | 481 |
self.con.commit() |
451 | 482 |
|
483 |
def _can_read(self, user, path): |
|
484 |
return True |
|
485 |
|
|
486 |
def _can_write(self, user, path): |
|
487 |
return True |
|
488 |
|
|
489 |
def _check_permissions(self, path, permissions): |
|
490 |
# Check for existing permissions. |
|
491 |
sql = '''select name from permissions |
|
492 |
where name != ? and (name like ? or ? like name || ?)''' |
|
493 |
c = self.con.execute(sql, (path, path + '%', path, '%')) |
|
494 |
if c.fetchall() is not None: |
|
495 |
raise AttributeError('Permissions already set') |
|
496 |
|
|
497 |
# Format given permissions set. |
|
498 |
r = permissions.get('read', []) |
|
499 |
w = permissions.get('write', []) |
|
500 |
if True in [False or '*' in x or ',' in x for x in r]: |
|
501 |
raise ValueError('Bad characters in read permissions') |
|
502 |
if True in [False or '*' in x or ',' in x for x in w]: |
|
503 |
raise ValueError('Bad characters in write permissions') |
|
504 |
r = ','.join(r) |
|
505 |
w = ','.join(w) |
|
506 |
if 'public' in permissions: |
|
507 |
r = '*' |
|
508 |
if 'private' in permissions: |
|
509 |
r = '' |
|
510 |
w = '' |
|
511 |
return r, w |
|
512 |
|
|
513 |
def _get_permissions(self, path): |
|
514 |
sql = 'select read, write from permissions where name = ?' |
|
515 |
c = self.con.execute(sql, (path,)) |
|
516 |
row = c.fetchone() |
|
517 |
if not row: |
|
518 |
return {} |
|
519 |
|
|
520 |
r, w = row |
|
521 |
if r == '' and w == '': |
|
522 |
return {'private': True} |
|
523 |
ret = {} |
|
524 |
if w != '': |
|
525 |
ret['write'] = w.split(',') |
|
526 |
if r != '': |
|
527 |
if r == '*': |
|
528 |
ret['public'] = True |
|
529 |
else: |
|
530 |
ret['read'] = r.split(',') |
|
531 |
return ret |
|
532 |
|
|
533 |
def _put_permissions(self, path, r, w): |
|
534 |
sql = 'insert or replace into permissions (name, read, write) values (?, ?, ?)' |
|
535 |
self.con.execute(sql, (path, r, w)) |
|
536 |
self.con.commit() |
|
537 |
|
|
452 | 538 |
def _list_objects(self, path, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None): |
453 | 539 |
cont_prefix = path + '/' |
454 | 540 |
if keys and len(keys) > 0: |
... | ... | |
502 | 588 |
self.con.execute(sql, (path,)) |
503 | 589 |
sql = '''delete from versions where name = ?''' |
504 | 590 |
self.con.execute(sql, (path,)) |
591 |
sql = '''delete from permissions where name like ?''' |
|
592 |
self.con.execute(sql, (path + '%',)) # Redundant. |
|
505 | 593 |
self.con.commit() |
Also available in: Unified diff