Ejemplo n.º 1
0
class EventsBeaconUpdatedRepSchema(BaseRepSchema):
    status = fields.CheckedConstant("ok", required=True)
    event = fields.CheckedConstant("beacon.updated", required=True)
    beacon_id = fields.UUID(required=True)
    index = fields.Integer(required=True)
    src_id = fields.UUID(required=True)
    src_version = fields.Integer(required=True)
Ejemplo n.º 2
0
class EventsRealmVlobsUpdatedRepSchema(BaseRepSchema):
    status = fields.CheckedConstant("ok", required=True)
    event = fields.CheckedConstant("realm.vlobs_updated", required=True)
    realm_id = fields.UUID(required=True)
    checkpoint = fields.Integer(required=True)
    src_id = fields.UUID(required=True)
    src_version = fields.Integer(required=True)
Ejemplo n.º 3
0
class EventsRealmVlobsUpdatedRepSchema(BaseRepSchema):
    event = fields.EnumCheckedConstant(APIEvent.REALM_VLOBS_UPDATED,
                                       required=True)
    realm_id = fields.UUID(required=True)
    checkpoint = fields.Integer(required=True)
    src_id = fields.UUID(required=True)
    src_version = fields.Integer(required=True)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
class VlobReadReqSchema(BaseReqSchema):
    encryption_revision = fields.Integer(required=True)
    vlob_id = VlobIDField(required=True)
    version = fields.Integer(
        required=True,
        allow_none=True,
        validate=lambda n: n is None or _validate_version(n))
    timestamp = fields.DateTime(required=True, allow_none=True)
Ejemplo n.º 7
0
class RealmVlobsUpdatedSchema(BaseSchema):
    __id__ = fields.String(required=True)
    __signal__ = fields.EnumCheckedConstant(BackendEvent.REALM_VLOBS_UPDATED,
                                            required=True)
    organization_id = OrganizationIDField(required=True)
    author = DeviceIDField(required=True)
    realm_id = RealmIDField(required=True)
    checkpoint = fields.Integer(required=True)
    src_id = VlobIDField(required=True)
    src_version = fields.Integer(required=True)
Ejemplo n.º 8
0
    class SCHEMA_CLS(BaseSchema):
        id = BlockIDField(required=True)
        key = fields.SecretKey(required=True)
        offset = fields.Integer(required=True, validate=validate.Range(min=0))
        size = fields.Integer(required=True, validate=validate.Range(min=0))
        digest = fields.HashDigest(required=True)

        @post_load
        def make_obj(self, data: Dict[str, Any]) -> "BlockAccess":
            return BlockAccess(**data)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    class SCHEMA_CLS(BaseSignedDataSchema):
        type = fields.EnumCheckedConstant(ManifestType.WORKSPACE_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)
        children = fields.FrozenMap(
            EntryNameField(validate=validate.Length(min=1, max=256)),
            EntryIDField(required=True),
            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]) -> "WorkspaceManifest":
            data.pop("type")
            return WorkspaceManifest(**data)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
class VlobListVersionsRepSchema(BaseRepSchema):
    versions = fields.Map(
        fields.Integer(required=True),
        fields.Tuple(fields.DateTime(required=True),
                     DeviceIDField(required=True)),
        required=True,
    )
Ejemplo n.º 13
0
class HumanFindReqSchema(BaseReqSchema):
    query = fields.String(required=True, allow_none=True)
    omit_revoked = fields.Boolean(required=True)
    omit_non_human = fields.Boolean(required=True)
    # First page is 1
    page = fields.Int(required=True, validate=lambda n: n > 0)
    per_page = fields.Integer(required=True, validate=lambda n: 0 < n <= 100)
Ejemplo n.º 14
0
class RealmStartReencryptionMaintenanceReqSchema(BaseReqSchema):
    realm_id = fields.UUID(required=True)
    encryption_revision = fields.Integer(required=True)
    timestamp = fields.DateTime(required=True)
    per_participant_message = fields.Map(UserIDField(),
                                         fields.Bytes(required=True),
                                         required=True)
Ejemplo n.º 15
0
class RealmMaintenanceStartedSchema(BaseSchema):
    __id__ = fields.String(required=True)
    __signal__ = fields.EnumCheckedConstant(
        BackendEvent.REALM_MAINTENANCE_STARTED, required=True)
    organization_id = OrganizationIDField(required=True)
    author = DeviceIDField(required=True)
    realm_id = RealmIDField(required=True)
    encryption_revision = fields.Integer(required=True)
Ejemplo n.º 16
0
class MessageReceivedSchema(BaseSchema):
    __id__ = fields.String(required=True)
    __signal__ = fields.EnumCheckedConstant(BackendEvent.MESSAGE_RECEIVED,
                                            required=True)
    organization_id = OrganizationIDField(required=True)
    author = DeviceIDField(required=True)
    recipient = UserIDField(required=True)
    index = fields.Integer(required=True)
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
class OrganizationUpdateReqSchema(BaseSchema):
    # /!\ Missing field and field set to `None` does not mean the same thing:
    # - missing field: don't modify this field
    # - field set to `None`: `None` is a valid value to use for this field
    is_expired = fields.Boolean(required=False)
    user_profile_outsider_allowed = fields.Boolean(required=False)
    # `None` stands for "no limit" here
    active_users_limit = fields.Integer(required=False,
                                        allow_none=True,
                                        validate=lambda x: x >= 0)
Ejemplo n.º 20
0
class OrganizationCreateReqSchema(BaseSchema):
    organization_id = OrganizationIDField(required=True)
    # /!\ Missing field and field set to `None` does not mean the same thing:
    # - missing field: ask the backend to use it default value for this field
    # - field set to `None`: `None` is a valid value to use for this field
    user_profile_outsider_allowed = fields.Boolean(required=False,
                                                   allow_none=False)
    # `None` stands for "no limit" here
    active_users_limit = fields.Integer(required=False,
                                        allow_none=True,
                                        validate=lambda x: x >= 0)
Ejemplo n.º 21
0
class VlobReadRepSchema(BaseRepSchema):
    version = fields.Integer(required=True, validate=_validate_version)
    blob = fields.Bytes(required=True)
    author = DeviceIDField(required=True)
    timestamp = fields.DateTime(required=True)
    # This field is used by the client to figure out if its role certificate cache is up-to-date enough
    # to be able to perform the proper integrity checks on the manifest timestamp.
    # The `missing=None` argument is used to provide compatibilty of new clients with old backends.
    # New in API version 2.3 (Parsec 2.6.0)
    author_last_role_granted_on = fields.DateTime(required=False,
                                                  allow_none=True,
                                                  missing=None)
Ejemplo n.º 22
0
class VlobCreateReqSchema(BaseReqSchema):
    realm_id = fields.UUID(required=True)
    encryption_revision = fields.Integer(required=True)
    vlob_id = fields.UUID(required=True)
    # If blob contains a signed message, it timestamp cannot be directly enforced
    # by the backend (given the message is probably also encrypted).
    # Hence the timestamp is passed in clear so backend can reject the message
    # if it considers the timestamp invalid. On top of that each client asking
    # for the message will receive the declared timestamp to check against
    # the actual timestamp within the message.
    timestamp = fields.DateTime(required=True)
    blob = fields.Bytes(required=True)
Ejemplo n.º 23
0
    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)
Ejemplo n.º 24
0
    class SCHEMA_CLS(OneOfSchema, BaseSignedDataSchema):
        type_field = "type"
        version = fields.Integer(required=True, validate=validate.Range(min=0))

        @property
        def type_schemas(self):
            return {
                ManifestType.FILE_MANIFEST: FileManifest.SCHEMA_CLS,
                ManifestType.FOLDER_MANIFEST: FolderManifest.SCHEMA_CLS,
                ManifestType.WORKSPACE_MANIFEST: WorkspaceManifest.SCHEMA_CLS,
                ManifestType.USER_MANIFEST: UserManifest.SCHEMA_CLS,
            }

        def get_obj_type(self, obj):
            return obj["type"]
Ejemplo n.º 25
0
    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)
Ejemplo n.º 26
0
    class SCHEMA_CLS(BaseSignedDataSchema):
        type = fields.CheckedConstant("sharing.granted", required=True)
        name = fields.String(required=True)
        id = EntryIDField(required=True)
        encryption_revision = fields.Integer(required=True)
        encrypted_on = fields.DateTime(required=True)
        key = fields.SecretKey(required=True)
        # Don't include role given the only reliable way to get this information
        # is to fetch the realm role certificate from the backend.
        # Besides, we will also need the message sender's realm role certificate
        # to make sure he is an owner.

        @post_load
        def make_obj(self, data):
            data.pop("type")
            return SharingGrantedMessageContent(**data)
Ejemplo n.º 27
0
    class SCHEMA_CLS(BaseSignedDataSchema):
        type = fields.CheckedConstant("workspace_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)
        children = fields.FrozenMap(
            EntryNameField(validate=validate.Length(min=1, max=256)),
            EntryIDField(required=True),
            required=True,
        )

        @post_load
        def make_obj(self, data):
            data.pop("type")
            return WorkspaceManifest(**data)
Ejemplo n.º 28
0
    class SCHEMA_CLS(BaseSignedDataSchema):
        type = fields.EnumCheckedConstant(MessageContentType.SHARING_GRANTED,
                                          required=True)
        name = EntryNameField(required=True)
        id = EntryIDField(required=True)
        encryption_revision = fields.Integer(required=True)
        encrypted_on = fields.DateTime(required=True)
        key = fields.SecretKey(required=True)
        # Don't include role given the only reliable way to get this information
        # is to fetch the realm role certificate from the backend.
        # Besides, we will also need the message sender's realm role certificate
        # to make sure he is an owner.

        @post_load
        def make_obj(  # type: ignore[misc]
                self, data: Dict[str, Any]) -> "SharingGrantedMessageContent":
            data.pop("type")
            return SharingGrantedMessageContent(**data)
Ejemplo n.º 29
0
    class SCHEMA_CLS(OneOfSchema, BaseSignedDataSchema):
        type_field = "type"
        version = fields.Integer(required=True, validate=validate.Range(min=0))
        id = EntryIDField(required=True)

        @property
        def type_schemas(
            self
        ) -> Dict[ManifestType, Type[OneOfSchema]]:  # type: ignore[override]
            return {
                ManifestType.FILE_MANIFEST: FileManifest.SCHEMA_CLS,
                ManifestType.FOLDER_MANIFEST: FolderManifest.SCHEMA_CLS,
                ManifestType.WORKSPACE_MANIFEST: WorkspaceManifest.SCHEMA_CLS,
                ManifestType.USER_MANIFEST: UserManifest.SCHEMA_CLS,
            }

        def get_obj_type(self, obj: Dict[str, T]) -> T:
            return obj["type"]
Ejemplo n.º 30
0
    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)