# -*- coding: utf-8 -*- import StringIO import hashlib import sys import os import os.path import fileinput import logging logger = logging.getLogger(__name__) from permission import * from config import config class ObjectError(Exception): pass; class Object: def __init__(self, name, owner, split_name = True): self.hash = name self.owner = owner if split_name: self.object_path = os.path.join(config.root, owner, name[:2], name[2:]) else: self.object_path = os.path.join(config.root, owner, name) def exists(self): return os.path.exists(self.object_path) class ObjectReader(Object): def __init__(self, hash, owner, split_name = True): Object.__init__(self, hash, owner, split_name) if not self.exists(): logger.error("Object {} can't be found for user {}".format(self.hash, self.owner)) raise ObjectError def get_permission(self, user): with open(os.path.join(self.object_path, 'permissions'), 'r') as file: for line in file: name, perm, key = line.split() if name == user: return int(perm) return None def get_key(self, user): with open(os.path.join(self.object_path, 'permissions'), 'r') as file: for line in file: name, perm, key = line.split() if name == user: return key return None def get_permission_key(self, user): with open(os.path.join(self.object_path, 'permissions'), 'r') as file: for line in file: name, perm, key = line.split() if name == user: return (int(perm), key) return (None, None) def get_child_list(self, user): perm = self.get_permission(user) if not perm & LIST: logger.error("User {} doesn't have the list permission for object {}" .format(user, self.hash)) raise PermissionError file = open(os.path.join(self.object_path, 'childs'), 'r') result = [] for line in file: name = line.rstrip('\n') try: child = ObjectReader(name, self.owner) except ObjectError: logger.error('Object {} doesn\'t exist'.format(name)) else: perm, key = child.get_permission_key(user) if perm > 0: result.append((name, perm, key)) file.close() return result def get_content(self, user): """Return object content and the user key to decrypt it.""" perm, key = self.get_permission_key(user) if not perm & READ : logger.error("User {} doesn't have read access to object {}" .format(user, self.hash)) raise PermissionError with open(os.path.join(self.object_path, 'object'), 'r') as file: content = file.read() return content, key class ObjectWriter(ObjectReader): def __init__(self, hash, owner, split_name = True, key = None): Object.__init__(self, hash, owner, split_name) self.files = ('permissions', 'children', 'object') self.__create_skeleton(key) def __create_skeleton(self, key): #new object if not self.exists(): os.makedirs(self.object_path) for filename in self.files: file = open(os.path.join(self.object_path, filename), "w") file.close() #give all the permissions to the owner ALLPERM = READ + MODIFY + APPEND + LIST self.add_user(self.owner, ALLPERM, key) def write(self, user, content): perm = self.get_permission(user) if not perm & MODIFY: logger.error("User {} doesn't have the modify permission for object {}" .format(user, self.hash)) raise PermissionError with open(os.path.join(self.object_path, 'object'), "w") as file: file.write('{}'.format(content)) def append(self, user, content, parent): parent_object = ObjectReader(parent, self.owner) perm = parent_object.get_permission(user) if not perm & APPEND: logger.error("User {} doesn't have the modify permission for object {}" .format(user, parent)) raise PermissionError with open(os.path.join(self.object_path, 'object'), "w") as file: for k, v in content: file.write('{} {}\n'.format(k,v)) #add the child hash to the parent with open(os.path.join(parent_object.object_path, 'children'), "a") as file: file.write('{} {}\n'.format(self.hash)) def add_user(self, user, perm, key = None): with open(os.path.join(self.object_path, 'permissions'), "a") as file: if key: file.write('{} {} {}\n'.format(user, perm, key)) else: file.write('{} {} None\n'.format(user, perm, key)) if __name__ == '__main__': jid = 'thrasibule@alias.im' hash = hashlib.sha1(jid).hexdigest() config.root = '/var/lib/alias' print ObjectReader(hash, jid).get_content(jid)