示例#1
0
        if isinstance(raw, UUID):
            super().__init__(bytes=raw.bytes)
        elif isinstance(raw, bytes):
            super().__init__(bytes=raw)
        else:
            super().__init__(hex=raw)

    def __repr__(self) -> str:
        return f"<EntryID {self.hex}>"

    @classmethod
    def new(cls: Type[EntryIDTypeVar]) -> EntryIDTypeVar:
        return cls(uuid4())


EntryIDField = fields.uuid_based_field_factory(EntryID)


class EntryName(str):
    __slots__ = ()

    def __new__(cls, raw: str) -> "EntryName":
        raw = normalize("NFC", raw)
        # Stick to UNIX filesystem philosophy:
        # - no `.` or `..` name
        # - no `/` or null byte in the name
        # - max 255 bytes long name
        if (not 0 < len(raw.encode("utf8")) < 256 or raw == "." or raw == ".."
                or "/" in raw or "\x00" in raw):
            raise ValueError("Invalid entry name")
        return super(EntryName, cls).__new__(cls, raw)
示例#2
0
    "BlockAccess",  # noqa: Republishing
    "BlockID",  # noqa: Republishing
    "WorkspaceRole",
)

DEFAULT_BLOCK_SIZE = 512 * 1024  # 512 KB

# Cheap rename
WorkspaceRole = RealmRole


class ChunkID(UUID4):
    pass


ChunkIDField = fields.uuid_based_field_factory(ChunkID)


@functools.total_ordering
@attr.s(slots=True, frozen=True, auto_attribs=True, kw_only=True, eq=False)
class Chunk(BaseData):
    """Represents a chunk of a data in file manifest.

    The raw data is identified by its `id` attribute and is aligned using the
    `raw_offset` attribute with respect to the file addressing. The raw data
    size is stored as `raw_size`.

    The `start` and `stop` attributes then describes the span of the actual data
    still with respect to the file addressing.

    This means the following rule applies:
示例#3
0
    BaseAPISignedData,
    BaseSignedDataSchema,
    DataValidationError,
)
from parsec.api.data.entry import EntryID, EntryIDField, EntryName, EntryNameField
from enum import Enum

LOCAL_AUTHOR_LEGACY_PLACEHOLDER = DeviceID(
    "LOCAL_AUTHOR_LEGACY_PLACEHOLDER@LOCAL_AUTHOR_LEGACY_PLACEHOLDER")


class BlockID(UUID4):
    pass


BlockIDField = fields.uuid_based_field_factory(BlockID)


class ManifestType(Enum):
    FILE_MANIFEST = "file_manifest"
    FOLDER_MANIFEST = "folder_manifest"
    WORKSPACE_MANIFEST = "workspace_manifest"
    USER_MANIFEST = "user_manifest"


@attr.s(slots=True, frozen=True, auto_attribs=True, kw_only=True, eq=False)
class BlockAccess(BaseData):
    class SCHEMA_CLS(BaseSchema):
        id = BlockIDField(required=True)
        key = fields.SecretKey(required=True)
        offset = fields.Integer(required=True, validate=validate.Range(min=0))
示例#4
0

class VlobID(UUID4):
    __slots__ = ()


_PyVlobID = VlobID
if not TYPE_CHECKING:
    try:
        from libparsec.types import VlobID as _RsVlobID
    except:
        pass
    else:
        VlobID = _RsVlobID

VlobIDField = fields.uuid_based_field_factory(VlobID)

_validate_version = validate.Range(min=1)


class VlobCreateReqSchema(BaseReqSchema):
    realm_id = RealmIDField(required=True)
    encryption_revision = fields.Integer(required=True)
    vlob_id = VlobIDField(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)
示例#5
0
_PyInvitationToken = InvitationToken
if not TYPE_CHECKING:
    try:
        from libparsec.types import InvitationToken as _RsInvitationToken
    except:
        pass
    else:
        InvitationToken = _RsInvitationToken


class InvitationType(Enum):
    USER = "******"
    DEVICE = "DEVICE"


InvitationTokenField = fields.uuid_based_field_factory(InvitationToken)
InvitationTypeField = fields.enum_field_factory(InvitationType)


class InviteNewUserReqSchema(BaseReqSchema):
    type = fields.EnumCheckedConstant(InvitationType.USER, required=True)
    claimer_email = fields.String(required=True)
    send_email = fields.Boolean(required=True)


class InviteNewDeviceReqSchema(BaseReqSchema):
    type = fields.EnumCheckedConstant(InvitationType.DEVICE, required=True)
    send_email = fields.Boolean(required=True)


class InviteNewReqSchema(OneOfSchema):
示例#6
0
class MaintenanceType(Enum):
    GARBAGE_COLLECTION = "GARBAGE_COLLECTION"
    REENCRYPTION = "REENCRYPTION"


class RealmRole(Enum):
    OWNER = "OWNER"
    MANAGER = "MANAGER"
    CONTRIBUTOR = "CONTRIBUTOR"
    READER = "READER"


RealmRoleField = fields.enum_field_factory(RealmRole)
MaintenanceTypeField = fields.enum_field_factory(MaintenanceType)
RealmIDField = fields.uuid_based_field_factory(RealmID)


class RealmCreateReqSchema(BaseReqSchema):
    role_certificate = fields.Bytes(required=True)


class RealmCreateRepSchema(BaseRepSchema):
    pass


realm_create_serializer = CmdSerializer(RealmCreateReqSchema,
                                        RealmCreateRepSchema)


class RealmStatusReqSchema(BaseReqSchema):