Beispiel #1
0
 def reencrypt(self):
     # Reencrypt files
     for path, entry in self.entries.items():
         if entry:
             file = yield File.load(**entry)
             yield file.reencrypt()
             new_vlob = file.get_vlob()
             self.entries[path] = new_vlob
     for index, entry in enumerate(self.dustbin):
         entry = deepcopy(entry)
         path = entry['path']
         removed_date = entry['removed_date']
         for key in ['path', 'removed_date']:
             del entry[key]
         file = yield File.load(**entry)
         yield file.reencrypt()
         new_vlob = file.get_vlob()
         new_vlob['path'] = path
         new_vlob['removed_date'] = removed_date
         self.dustbin[index] = new_vlob
     # Reencrypt manifest
     blob = yield self.dumps()
     self.encryptor = generate_sym_key()
     encrypted_blob = self.encryptor.encrypt(blob.encode())
     encrypted_blob = to_jsonb64(encrypted_blob)
     new_vlob = yield Effect(EVlobCreate(encrypted_blob))
     self.id = new_vlob['id']
     self.read_trust_seed = new_vlob['read_trust_seed']
     self.write_trust_seed = new_vlob['write_trust_seed']
     self.version = 0
Beispiel #2
0
 def test_load_file(self, file):
     vlob_id = '1234'
     other_vlob_id = '5678'
     read_trust_seed = '42'
     version = 1
     # Load from open files
     file2 = perform_sequence(
         [],
         File.load(vlob_id, to_jsonb64(b'<dummy-key-00000000000000000001>'),
                   read_trust_seed, '43'))
     assert file == file2
     File.files = {}
     # Test reloading commited and not commited file
     for synchronizer_vlob_list in [[vlob_id, other_vlob_id],
                                    [other_vlob_id]]:
         key = to_jsonb64(b'<dummy-key-00000000000000000001>')
         sequence = [
             (EVlobRead(vlob_id, read_trust_seed, None),
              const({
                  'id': vlob_id,
                  'blob': 'foo',
                  'version': version
              })),
             (EVlobList(), const(synchronizer_vlob_list)),
         ]
         file = perform_sequence(
             sequence, File.load(vlob_id, key, read_trust_seed, '43'))
         assert file.dirty is (vlob_id in synchronizer_vlob_list)
         assert file.version == (version - 1 if file.dirty else version)
         File.files = {}
Beispiel #3
0
 def commit(self, recursive=True):
     is_dirty = yield self.is_dirty()
     if self.version != 0 and not is_dirty:
         return
     # Update manifest with new group vlobs
     vlob_list = yield Effect(EVlobList())
     if recursive:
         for group_manifest in self.group_manifests.values():
             new_vlob = yield group_manifest.commit()
             if new_vlob and new_vlob is not True:
                 old_vlob = group_manifest.get_vlob()
                 new_vlob['key'] = old_vlob['key']
                 group_manifest.update_vlob(new_vlob)
     # Update manifest entries with new file vlobs (dustbin entries are already commited)
     for entry in self.entries.values():
         if entry and entry['id'] in vlob_list:
             file = yield File.load(entry['id'],
                                    entry['key'],
                                    entry['read_trust_seed'],
                                    entry['write_trust_seed'])
             new_vlob = yield file.commit()
             if new_vlob and new_vlob is not True:
                 entry['id'] = new_vlob['id']
                 entry['read_trust_seed'] = new_vlob['read_trust_seed']
                 entry['write_trust_seed'] = new_vlob['write_trust_seed']
     # Commit manifest
     blob = yield self.dumps()
     encrypted_blob = self.encryptor.pub_key.encrypt(blob.encode())
     encrypted_blob = to_jsonb64(encrypted_blob)
     yield Effect(EUserVlobUpdate(self.version + 1, encrypted_blob))
     self.original_manifest = ejson_loads(blob)
     synchronized = yield Effect(EUserVlobSynchronize())
     if synchronized:
         self.version += 1
Beispiel #4
0
 def commit(self):
     is_dirty = yield self.is_dirty()
     if self.version != 0 and not is_dirty:
         return
     # Update manifest entries with new file vlobs (dustbin entries are already commited)
     vlob_list = yield Effect(EVlobList())
     for entry in self.entries.values():
         if entry and entry['id'] in vlob_list:
             file = yield File.load(entry['id'],
                                    entry['key'],
                                    entry['read_trust_seed'],
                                    entry['write_trust_seed'])
             new_vlob = yield file.commit()
             if new_vlob and new_vlob is not True:
                 entry['id'] = new_vlob['id']
                 entry['read_trust_seed'] = new_vlob['read_trust_seed']
                 entry['write_trust_seed'] = new_vlob['write_trust_seed']
     # Commit manifest
     blob = yield self.dumps()
     encrypted_blob = self.encryptor.encrypt(blob.encode())
     encrypted_blob = to_jsonb64(encrypted_blob)
     yield Effect(EVlobUpdate(self.id, self.write_trust_seed, self.version + 1, encrypted_blob))
     self.original_manifest = ejson_loads(blob)
     new_vlob = yield Effect(EVlobSynchronize(self.id))
     if new_vlob:
         if new_vlob is not True:
             self.id = new_vlob['id']
             self.read_trust_seed = new_vlob['read_trust_seed']
             self.write_trust_seed = new_vlob['write_trust_seed']
             new_vlob = self.get_vlob()
         self.version += 1
     return new_vlob
Beispiel #5
0
 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()
Beispiel #6
0
 def perform_file_create(self, intent):
     file = yield File.create()
     vlob = file.get_vlob()
     user_manifest = yield self._get_manifest()
     try:
         user_manifest.add_file(intent.path, vlob)
     except (ManifestError, ManifestNotFound) as ex:
         yield file.discard()
         raise ex
Beispiel #7
0
 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
Beispiel #8
0
 def _get_file(self, path, group=None):
     try:
         properties = yield self._get_properties(path=path, group=group)
     except FileNotFound:
         try:
             properties = yield self._get_properties(path=path,
                                                     dustbin=True,
                                                     group=group)
         except FileNotFound:
             raise FileNotFound('Vlob not found.')
     if not properties:
         raise FileNotFound('Vlob not found.')
     file = yield File.load(properties['id'], properties['key'],
                            properties['read_trust_seed'],
                            properties['write_trust_seed'])
     return file
Beispiel #9
0
 def reload(self, reset=False):
     # Subscribe to events
     # yield Effect(EConnectEvent('on_vlob_updated', self.id, self.handler)) # TODO call
     vlob = yield Effect(EVlobRead(self.id, self.read_trust_seed))
     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', 'Group 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.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
Beispiel #10
0
 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()))
         }
Beispiel #11
0
 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.')
Beispiel #12
0
def file(mock_crypto_passthrough):
    block_id = '4567'
    blob = [{
        'blocks': [{
            'block': block_id,
            'digest': digest(b''),
            'size': 0
        }],
        'key': to_jsonb64(b'<dummy-key-00000000000000000001>')
    }]
    blob = ejson_dumps(blob).encode()
    blob = to_jsonb64(blob)
    sequence = [
        (EBlockCreate(''), const(block_id)),
        (EVlobCreate(blob),
         const({
             'id': '1234',
             'read_trust_seed': '42',
             'write_trust_seed': '43'
         })),
    ]
    return perform_sequence(sequence, File.create())