def move(self, old_path, new_path): old_path = '/' + old_path.strip('/') new_path = '/' + new_path.strip('/') new_parent_folder = os.path.dirname(new_path) if old_path not in self.entries: raise ManifestNotFound('File not found.') if new_parent_folder not in self.entries: raise ManifestNotFound('Destination Folder not found.') if new_path in self.entries: raise ManifestError('already_exists', 'File already exists.') for entry, vlob in self.entries.items(): if entry.startswith(old_path): new_entry = new_path + entry[len(old_path):] self.entries[new_entry] = vlob del self.entries[entry]
def add_file(self, path, vlob): path = '/' + path.strip('/') parent_folder = os.path.dirname(path) if parent_folder not in self.entries: raise ManifestNotFound('Destination Folder not found.') if path in self.entries: raise ManifestError('already_exists', 'File already exists.') self.entries[path] = vlob
def show_dustbin(self, path=None): if not path: return self.dustbin else: path = '/' + path.strip('/') results = [entry for entry in self.dustbin if entry['path'] == path] if not results: raise ManifestNotFound('Path not found.') return results
def reencrypt_file(self, path): path = '/' + path.strip('/') try: entry = self.entries[path] except KeyError: raise ManifestNotFound('File not found.') file = yield File.load(**entry) yield file.reencrypt() self.entries[path] = file.get_vlob()
def get_group_vlobs(self, group=None): if group: groups = [group] else: groups = self.group_manifests.keys() results = {} try: for group in groups: results[group] = self.group_manifests[group].get_vlob() except KeyError: raise ManifestNotFound('Group not found.') return results
def undelete_file(self, vlob): for entry in self.dustbin: if entry['id'] == vlob: path = entry['path'] if path in self.entries: raise ManifestError('already_exists', 'Restore path already used.') del entry['path'] del entry['removed_date'] self.dustbin[:] = [item for item in self.dustbin if item['id'] != vlob] self.entries[path] = entry folder = os.path.dirname(path) self.create_folder(folder, parents=True) return raise ManifestNotFound('Vlob not found.')
def create_folder(self, path, parents=False): path = '/' + path.strip('/') if path in self.entries: if parents: return self.entries[path] else: raise ManifestError('already_exists', 'Folder already exists.') parent_folder = os.path.dirname(path) if parent_folder not in self.entries: if parents: self.create_folder(parent_folder, parents=True) else: raise ManifestNotFound("Parent folder doesn't exists.") self.entries[path] = None return self.entries[path]
def reload(self, reset=False): vlob = yield Effect(EUserVlobRead()) if not vlob['blob']: raise ManifestNotFound('User manifest not found.') blob = from_jsonb64(vlob['blob']) content = self.encryptor.decrypt(blob) if not reset and vlob['version'] <= self.version: return new_manifest = ejson_loads(content.decode()) backup_new_manifest = deepcopy(new_manifest) consistency = yield self.check_consistency(new_manifest) if not consistency: raise ManifestError('not_consistent', 'User manifest not consistent.') if not reset: diff = yield self.diff_versions() new_manifest = self.patch(new_manifest, diff) self.entries = new_manifest['entries'] self.dustbin = new_manifest['dustbin'] self.version = vlob['version'] self.group_manifests = {} for group, group_vlob in new_manifest['groups'].items(): self.import_group_vlob(group, group_vlob) self.original_manifest = backup_new_manifest versions = new_manifest['versions'] file_vlob = None for vlob_id, version in sorted(versions.items()): for entry in self.entries.values(): if entry and entry['id'] == vlob_id: file_vlob = entry break if not file_vlob: for entry in self.dustbin: if entry['id'] == vlob_id: file_vlob = {'id': entry['id'], 'read_trust_seed': entry['read_trust_seed'], 'write_trust_seed': entry['write_trust_seed'], 'key': entry['key']} break if file_vlob: file_vlob = None file = yield File.load(entry['id'], entry['key'], entry['read_trust_seed'], entry['write_trust_seed']) try: yield file.restore(version) except FileError: pass
def stat(self, path): path = '/' + path.strip('/') if path != '/' and path not in self.entries: raise ManifestNotFound('Folder or file not found.') entry = self.entries[path] if entry: file = yield File.load(**entry) stat = yield file.stat() return stat else: # Skip mtime and size given that they are too complicated to provide for folder # TODO time except mtime children = {} for entry in self.entries: if (entry != path and entry.startswith(path) and entry.count('/', len(path) + 1) == 0): children[os.path.basename(entry)] = deepcopy(self.entries[entry]) return { 'type': 'folder', 'children': sorted(list(children.keys())) }
def delete(self, path): path = '/' + path.strip('/') deleted_paths = [] for entry in self.entries: if entry == path or entry.startswith(path + '/') or path == '/': deleted_paths.append(entry) for path in deleted_paths: entry = self.entries[path] if entry: file = yield File.load(entry['id'], entry['key'], entry['read_trust_seed'], entry['write_trust_seed']) discarded = yield file.discard() # TODO discard or not? if not discarded: dustbin_entry = {'removed_date': datetime.utcnow().isoformat(), 'path': path} dustbin_entry.update(entry) self.dustbin.append(dustbin_entry) if path != '/': del self.entries[path] if not deleted_paths: raise ManifestNotFound('File or directory not found.')
def remove_group(self, group): # TODO deleted group is not moved in dusbin, but hackers could continue to read/write files try: del self.group_manifests[group] except KeyError: raise ManifestNotFound('Group not found.')
def reencrypt_group_manifest(self, group): try: group_manifest = self.group_manifests[group] except KeyError: raise ManifestNotFound('Group not found.') yield group_manifest.reencrypt()
def get_group_manifest(self, group): try: return self.group_manifests[group] except KeyError: raise ManifestNotFound('Group not found.')