class SCHEMA_CLS(BaseSchema): type = fields.CheckedConstant("local_pending_enrollment", required=True) x509_certificate = fields.Nested(X509Certificate.SCHEMA_CLS, required=True) addr = BackendPkiEnrollmentAddrField(required=True) submitted_on = fields.DateTime(required=True) enrollment_id = fields.UUID(required=True) submit_payload = fields.Nested(PkiEnrollmentSubmitPayload.SCHEMA_CLS, required=True) encrypted_key = fields.Bytes(required=True) ciphertext = fields.Bytes(required=True) # An encrypted PendingDeviceKeys @post_load def make_obj(self, data): data.pop("type", None) return LocalPendingEnrollment(**data)
class SCHEMA_CLS(BaseSignedDataSchema): type = fields.EnumCheckedConstant(ManifestType.FILE_MANIFEST, required=True) id = EntryIDField(required=True) parent = EntryIDField(required=True) # Version 0 means the data is not synchronized version = fields.Integer(required=True, validate=validate.Range(min=0)) created = fields.DateTime(required=True) updated = fields.DateTime(required=True) size = fields.Integer(required=True, validate=validate.Range(min=0)) blocksize = fields.Integer(required=True, validate=validate.Range(min=8)) blocks = fields.FrozenList(fields.Nested(BlockAccess.SCHEMA_CLS), required=True) @pre_load def fix_legacy(self, data: Dict[str, T]) -> Dict[str, T]: # Compatibility with versions <= 1.14 if data["author"] is None: data["author"] = LOCAL_AUTHOR_LEGACY_PLACEHOLDER return data @post_load def make_obj(self, data: Dict[str, Any]) -> "FileManifest": data.pop("type") return FileManifest(**data)
class UserGetRepSchema(BaseRepSchema): user_certificate = fields.Bytes(required=True) revoked_user_certificate = fields.Bytes(required=True, allow_none=True) device_certificates = fields.List(fields.Bytes(required=True), required=True) trustchain = fields.Nested(TrustchainSchema, required=True)
class SCHEMA_CLS(BaseSchema): type = fields.EnumCheckedConstant( LocalManifestType.LOCAL_WORKSPACE_MANIFEST, required=True) base = fields.Nested(RemoteWorkspaceManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) children = fields.FrozenMap(EntryNameField(), EntryIDField(required=True), required=True) # Confined entries are entries that are meant to stay locally and not be added # to the uploaded remote manifest when synchronizing. The criteria for being # confined is to have a filename that matched the "prevent sync" pattern at the time of # the last change (or when a new filter was successfully applied) local_confinement_points = fields.FrozenSet( EntryIDField(required=True)) # Filtered entries are entries present in the base manifest that are not exposed # locally. We keep track of them to remember that those entries have not been # deleted locally and hence should be restored when crafting the remote manifest # to upload. remote_confinement_points = fields.FrozenSet( EntryIDField(required=True)) @post_load def make_obj(self, data): data.pop("type") data.setdefault("local_confinement_points", frozenset()) data.setdefault("remote_confinement_points", frozenset()) return LocalWorkspaceManifest(**data)
class SCHEMA_CLS(BaseSchema): type = fields.EnumCheckedConstant( LocalManifestType.LOCAL_USER_MANIFEST, required=True) base = fields.Nested(RemoteUserManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) last_processed_message = fields.Integer(required=True, validate=validate.Range(min=0)) workspaces = fields.FrozenList(fields.Nested( WorkspaceEntry.SCHEMA_CLS), required=True) @post_load def make_obj(self, data): data.pop("type") return LocalUserManifest(**data)
class SCHEMA_CLS(BaseSchema): type = fields.EnumCheckedConstant( LocalManifestType.LOCAL_FILE_MANIFEST, required=True) base = fields.Nested(RemoteFileManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) size = fields.Integer(required=True, validate=validate.Range(min=0)) blocksize = fields.Integer(required=True, validate=validate.Range(min=8)) blocks = fields.FrozenList(fields.FrozenList( fields.Nested(Chunk.SCHEMA_CLS)), required=True) @post_load def make_obj(self, data): data.pop("type") return LocalFileManifest(**data)
class OrganizationStatsRepSchema(BaseSchema): data_size = fields.Integer(required=True) metadata_size = fields.Integer(required=True) realms = fields.Integer(required=True) users = fields.Integer(required=True) active_users = fields.Integer(required=True) users_per_profile_detail = fields.List( fields.Nested(UsersPerProfileDetailItemSchema), required=True)
class UserSchema(UnknownCheckedSchema): user_id = fields.String(required=True) is_admin = fields.Boolean(required=True) created_on = fields.DateTime(required=True) certified_user = fields.Bytes(required=True) user_certifier = fields.DeviceID(allow_none=True) devices = fields.Map(fields.DeviceName(), fields.Nested(DeviceSchema), required=True)
class ApiReleaseSchema(BaseSchema): draft = fields.Boolean(missing=False) prerelease = fields.Boolean(missing=False) tag_name = fields.String(required=True) assets = fields.List(fields.Nested(ApiReleaseAssetSchema), missing=[]) @post_load def add_version_field(self, data): try: data["version"] = Version(data["tag_name"]) except ValueError: data["version"] = None return data
class SCHEMA_CLS(BaseSchema): type = fields.EnumCheckedConstant( LocalManifestType.LOCAL_WORKSPACE_MANIFEST, required=True) base = fields.Nested(_PyWorkspaceManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) children = fields.FrozenMap(EntryNameField(), EntryIDField(), required=True) # Added in Parsec v1.15 # Confined entries are entries that are meant to stay locally and not be added # to the uploaded remote manifest when synchronizing. The criteria for being # confined is to have a filename that matched the "prevent sync" pattern at the time of # the last change (or when a new filter was successfully applied) local_confinement_points = fields.FrozenSet(EntryIDField(), allow_none=False, required=False, missing=frozenset()) # Added in Parsec v1.15 # Filtered entries are entries present in the base manifest that are not exposed # locally. We keep track of them to remember that those entries have not been # deleted locally and hence should be restored when crafting the remote manifest # to upload. remote_confinement_points = fields.FrozenSet(EntryIDField(), allow_none=False, required=False, missing=frozenset()) # Added in Parsec v1.15 # Speculative placeholders are created when we want to access a workspace # but didn't retrieve manifest data from backend yet. This implies: # - non-placeholders cannot be speculative # - the only non-speculative placeholder is the placeholder initialized # during the initial workspace creation # This speculative information is useful during merge to understand if # a data is not present in the placeholder compared with a remote because: # a) the data is not locally known (speculative is True) # b) the data is known, but has been locally removed (speculative is False) # Prevented to be `required=True` by backward compatibility speculative = fields.Boolean(allow_none=False, required=False, missing=False) @post_load def make_obj(self, data): # TODO: Ensure non-placeholder cannot be marked speculative assert data["speculative"] is False or data["base"].version == 0 # TODO: Should this assert be in remote workspace manifest definition instead ? # TODO: but in theory remote workspace manifest should assert version > 0 ! assert data["base"].version != 0 or not data["base"].children data.pop("type") return LocalWorkspaceManifest(**data)
class SCHEMA_CLS(BaseSchema): type = fields.EnumCheckedConstant( LocalManifestType.LOCAL_USER_MANIFEST, required=True) base = fields.Nested(_PyUserManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) last_processed_message = fields.Integer(required=True, validate=validate.Range(min=0)) workspaces = fields.FrozenList(fields.Nested( _PyWorkspaceEntry.SCHEMA_CLS), required=True) # Added in Parsec v1.15 # Speculative placeholders are created when we want to access the # user manifest but didn't retrieve it from backend yet. This implies: # - non-placeholders cannot be speculative # - the only non-speculative placeholder is the placeholder initialized # during the initial user claim (by opposition of subsequent device # claims on the same user) # This speculative information is useful during merge to understand if # a data is not present in the placeholder compared with a remote because: # a) the data is not locally known (speculative is True) # b) the data is known, but has been locally removed (speculative is False) # Prevented to be `required=True` by backward compatibility speculative = fields.Boolean(allow_none=False, required=False, missing=False) @post_load def make_obj(self, data): data.pop("type") # TODO: Ensure non-placeholder cannot be marked speculative assert data["speculative"] is False or data["base"].version == 0 # TODO: Should this assert be in remote workspace manifest definition instead ? # TODO: but in theory remote workspace manifest should assert version > 0 ! assert data["base"].version != 0 or not data["base"].workspaces return LocalUserManifest(**data)
class SCHEMA_CLS(BaseSchema): id = ChunkIDField(required=True) start = fields.Integer(required=True, validate=validate.Range(min=0)) stop = fields.Integer(required=True, validate=validate.Range(min=1)) raw_offset = fields.Integer(required=True, validate=validate.Range(min=0)) raw_size = fields.Integer(required=True, validate=validate.Range(min=1)) access = fields.Nested(BlockAccess.SCHEMA_CLS, required=True, allow_none=True) @post_load def make_obj(self, data): return Chunk(**data)
class SCHEMA_CLS(BaseSignedDataSchema): type = fields.CheckedConstant("user_manifest", required=True) id = EntryIDField(required=True) # Version 0 means the data is not synchronized (hence author sould be None) version = fields.Integer(required=True, validate=validate.Range(min=0)) created = fields.DateTime(required=True) updated = fields.DateTime(required=True) last_processed_message = fields.Integer(required=True, validate=validate.Range(min=0)) workspaces = fields.List(fields.Nested(WorkspaceEntry.SCHEMA_CLS), required=True) @post_load def make_obj(self, data): data.pop("type") return UserManifest(**data)
class SCHEMA_CLS(BaseSignedDataSchema): type = fields.CheckedConstant("file_manifest", required=True) id = EntryIDField(required=True) parent = EntryIDField(required=True) # Version 0 means the data is not synchronized (hence author sould be None) version = fields.Integer(required=True, validate=validate.Range(min=0)) created = fields.DateTime(required=True) updated = fields.DateTime(required=True) size = fields.Integer(required=True, validate=validate.Range(min=0)) blocksize = fields.Integer(required=True, validate=validate.Range(min=8)) blocks = fields.FrozenList(fields.Nested(BlockAccess.SCHEMA_CLS), required=True) @post_load def make_obj(self, data): data.pop("type") return FileManifest(**data)
class SCHEMA_CLS(OneOfSchema, BaseSchema): type_field = "type" base = fields.Nested(BaseRemoteManifest.SCHEMA_CLS, required=True) need_sync = fields.Boolean(required=True) updated = fields.DateTime(required=True) @property def type_schemas(self): return { LocalManifestType.LOCAL_FILE_MANIFEST: LocalFileManifest.SCHEMA_CLS, LocalManifestType.LOCAL_FOLDER_MANIFEST: LocalFolderManifest.SCHEMA_CLS, LocalManifestType.LOCAL_WORKSPACE_MANIFEST: LocalWorkspaceManifest.SCHEMA_CLS, LocalManifestType.LOCAL_USER_MANIFEST: LocalUserManifest.SCHEMA_CLS, } def get_obj_type(self, obj): return obj["type"]
class SCHEMA_CLS(BaseSignedDataSchema): type = fields.EnumCheckedConstant(ManifestType.USER_MANIFEST, required=True) id = EntryIDField(required=True) # Version 0 means the data is not synchronized version = fields.Integer(required=True, validate=validate.Range(min=0)) created = fields.DateTime(required=True) updated = fields.DateTime(required=True) last_processed_message = fields.Integer(required=True, validate=validate.Range(min=0)) workspaces = fields.List(fields.Nested(WorkspaceEntry.SCHEMA_CLS), required=True) @pre_load def fix_legacy(self, data: Dict[str, T]) -> Dict[str, T]: # Compatibility with versions <= 1.14 if data["author"] is None: data["author"] = LOCAL_AUTHOR_LEGACY_PLACEHOLDER return data @post_load def make_obj(self, data: Dict[str, Any]) -> "UserManifest": data.pop("type") return UserManifest(**data)
class DeviceClaimAnswerSchema(UnknownCheckedSchema): type = fields.CheckedConstant("device_claim_answer", required=True) private_key = fields.PrivateKey(required=True) user_manifest_access = fields.Nested(ManifestAccessSchema, required=True)
class MessageGetRepSchema(BaseRepSchema): messages = fields.List(fields.Nested(MessageSchema), required=True)
class SharingMessageContentSchema(UnknownCheckedSchema): type = fields.CheckedConstant("share", required=True) author = fields.String(required=True) access = fields.Nested(ManifestAccessSchema, required=True) name = fields.String(required=True)
class VlobGroupCheckReqSchema(BaseReqSchema): to_check = fields.List(fields.Nested(CheckEntrySchema), required=True)
class VlobGroupCheckRepSchema(BaseRepSchema): changed = fields.List(fields.Nested(ChangedEntrySchema), required=True)
class UserGetRepSchema(BaseRepSchema, UserSchema): trustchain = fields.Map(fields.DeviceID(), fields.Nested(DeviceSchema), required=True)
class BeaconReadRepSchema(BaseRepSchema): items = fields.List(fields.Nested(BeaconItemSchema), required=True)
class PkiEnrollmentListRepSchema(BaseRepSchema): enrollments = fields.List(fields.Nested(PkiEnrollmentListItemSchema), required=True)
class APIV1_UserGetInvitationCreatorRepSchema(BaseRepSchema): device_certificate = fields.Bytes(required=True) user_certificate = fields.Bytes(required=True) trustchain = fields.Nested(TrustchainSchema, required=True)
class VlobMaintenanceGetReencryptionBatchRepSchema(BaseRepSchema): batch = fields.List(fields.Nested(ReencryptionBatchEntrySchema), required=True)
class HumanFindRepSchema(BaseRepSchema): results = fields.List( fields.Nested(HumanFindResultItemSchema, required=True)) page = fields.Int(validate=lambda n: n > 0) per_page = fields.Integer(validate=lambda n: 0 < n <= 100) total = fields.Int(validate=lambda n: n >= 0)
class VlobMaintenanceSaveReencryptionBatchReqSchema(BaseReqSchema): realm_id = fields.UUID(required=True) encryption_revision = fields.Integer(required=True) batch = fields.List(fields.Nested(ReencryptionBatchEntrySchema), required=True)
class InviteListRepSchema(BaseRepSchema): invitations = fields.List(fields.Nested(InviteListItemSchema), required=True)
class ApiReleasesSchema(BaseSchema): releases = fields.List(fields.Nested(ApiReleaseSchema), missing=[])