Ejemplo n.º 1
0
class FakeEvent:
    event_id = attr.ib()
    room_id = attr.ib()
    auth_events = attr.ib()

    type = "foo"
    state_key = "foo"

    internal_metadata = _EventInternalMetadata({})

    def auth_event_ids(self):
        return self.auth_events

    def is_state(self):
        return True
Ejemplo n.º 2
0
class EventBuilder:
    """A format independent event builder used to build up the event content
    before signing the event.

    (Note that while objects of this class are frozen, the
    content/unsigned/internal_metadata fields are still mutable)

    Attributes:
        room_version: Version of the target room
        room_id
        type
        sender
        content
        unsigned
        internal_metadata

        _state
        _auth
        _store
        _clock
        _hostname: The hostname of the server creating the event
        _signing_key: The signing key to use to sign the event as the server
    """

    _state = attr.ib(type=StateHandler)
    _auth = attr.ib(type=Auth)
    _store = attr.ib(type=DataStore)
    _clock = attr.ib(type=Clock)
    _hostname = attr.ib(type=str)
    _signing_key = attr.ib(type=SigningKey)

    room_version = attr.ib(type=RoomVersion)

    room_id = attr.ib(type=str)
    type = attr.ib(type=str)
    sender = attr.ib(type=str)

    content = attr.ib(default=attr.Factory(dict), type=JsonDict)
    unsigned = attr.ib(default=attr.Factory(dict), type=JsonDict)

    # These only exist on a subset of events, so they raise AttributeError if
    # someone tries to get them when they don't exist.
    _state_key = attr.ib(default=None, type=Optional[str])
    _redacts = attr.ib(default=None, type=Optional[str])
    _origin_server_ts = attr.ib(default=None, type=Optional[int])

    internal_metadata = attr.ib(
        default=attr.Factory(lambda: _EventInternalMetadata({})),
        type=_EventInternalMetadata,
    )

    @property
    def state_key(self):
        if self._state_key is not None:
            return self._state_key

        raise AttributeError("state_key")

    def is_state(self):
        return self._state_key is not None

    async def build(
        self,
        prev_event_ids: List[str],
        auth_event_ids: Optional[List[str]],
    ) -> EventBase:
        """Transform into a fully signed and hashed event

        Args:
            prev_event_ids: The event IDs to use as the prev events
            auth_event_ids: The event IDs to use as the auth events.
                Should normally be set to None, which will cause them to be calculated
                based on the room state at the prev_events.

        Returns:
            The signed and hashed event.
        """
        if auth_event_ids is None:
            state_ids = await self._state.get_current_state_ids(
                self.room_id, prev_event_ids
            )
            auth_event_ids = self._auth.compute_auth_events(self, state_ids)

        format_version = self.room_version.event_format
        if format_version == EventFormatVersions.V1:
            # The types of auth/prev events changes between event versions.
            auth_events = await self._store.add_event_hashes(
                auth_event_ids
            )  # type: Union[List[str], List[Tuple[str, Dict[str, str]]]]
            prev_events = await self._store.add_event_hashes(
                prev_event_ids
            )  # type: Union[List[str], List[Tuple[str, Dict[str, str]]]]
        else:
            auth_events = auth_event_ids
            prev_events = prev_event_ids

        old_depth = await self._store.get_max_depth_of(prev_event_ids)
        depth = old_depth + 1

        # we cap depth of generated events, to ensure that they are not
        # rejected by other servers (and so that they can be persisted in
        # the db)
        depth = min(depth, MAX_DEPTH)

        event_dict = {
            "auth_events": auth_events,
            "prev_events": prev_events,
            "type": self.type,
            "room_id": self.room_id,
            "sender": self.sender,
            "content": self.content,
            "unsigned": self.unsigned,
            "depth": depth,
            "prev_state": [],
        }  # type: Dict[str, Any]

        if self.is_state():
            event_dict["state_key"] = self._state_key

        if self._redacts is not None:
            event_dict["redacts"] = self._redacts

        if self._origin_server_ts is not None:
            event_dict["origin_server_ts"] = self._origin_server_ts

        return create_local_event_from_event_dict(
            clock=self._clock,
            hostname=self._hostname,
            signing_key=self._signing_key,
            room_version=self.room_version,
            event_dict=event_dict,
            internal_metadata_dict=self.internal_metadata.get_dict(),
        )
Ejemplo n.º 3
0
class EventBuilder(object):
    """A format independent event builder used to build up the event content
    before signing the event.

    (Note that while objects of this class are frozen, the
    content/unsigned/internal_metadata fields are still mutable)

    Attributes:
        room_version: Version of the target room
        room_id (str)
        type (str)
        sender (str)
        content (dict)
        unsigned (dict)
        internal_metadata (_EventInternalMetadata)

        _state (StateHandler)
        _auth (synapse.api.Auth)
        _store (DataStore)
        _clock (Clock)
        _hostname (str): The hostname of the server creating the event
        _signing_key: The signing key to use to sign the event as the server
    """

    _state = attr.ib()
    _auth = attr.ib()
    _store = attr.ib()
    _clock = attr.ib()
    _hostname = attr.ib()
    _signing_key = attr.ib()

    room_version = attr.ib(type=RoomVersion)

    room_id = attr.ib()
    type = attr.ib()
    sender = attr.ib()

    content = attr.ib(default=attr.Factory(dict))
    unsigned = attr.ib(default=attr.Factory(dict))

    # These only exist on a subset of events, so they raise AttributeError if
    # someone tries to get them when they don't exist.
    _state_key = attr.ib(default=None)
    _redacts = attr.ib(default=None)
    _origin_server_ts = attr.ib(default=None)

    internal_metadata = attr.ib(
        default=attr.Factory(lambda: _EventInternalMetadata({})))

    @property
    def state_key(self):
        if self._state_key is not None:
            return self._state_key

        raise AttributeError("state_key")

    def is_state(self):
        return self._state_key is not None

    @defer.inlineCallbacks
    def build(self, prev_event_ids):
        """Transform into a fully signed and hashed event

        Args:
            prev_event_ids (list[str]): The event IDs to use as the prev events

        Returns:
            Deferred[FrozenEvent]
        """

        state_ids = yield self._state.get_current_state_ids(
            self.room_id, prev_event_ids)
        auth_ids = yield self._auth.compute_auth_events(self, state_ids)

        format_version = self.room_version.event_format
        if format_version == EventFormatVersions.V1:
            auth_events = yield self._store.add_event_hashes(auth_ids)
            prev_events = yield self._store.add_event_hashes(prev_event_ids)
        else:
            auth_events = auth_ids
            prev_events = prev_event_ids

        old_depth = yield self._store.get_max_depth_of(prev_event_ids)
        depth = old_depth + 1

        # we cap depth of generated events, to ensure that they are not
        # rejected by other servers (and so that they can be persisted in
        # the db)
        depth = min(depth, MAX_DEPTH)

        event_dict = {
            "auth_events": auth_events,
            "prev_events": prev_events,
            "type": self.type,
            "room_id": self.room_id,
            "sender": self.sender,
            "content": self.content,
            "unsigned": self.unsigned,
            "depth": depth,
            "prev_state": [],
        }

        if self.is_state():
            event_dict["state_key"] = self._state_key

        if self._redacts is not None:
            event_dict["redacts"] = self._redacts

        if self._origin_server_ts is not None:
            event_dict["origin_server_ts"] = self._origin_server_ts

        return create_local_event_from_event_dict(
            clock=self._clock,
            hostname=self._hostname,
            signing_key=self._signing_key,
            room_version=self.room_version,
            event_dict=event_dict,
            internal_metadata_dict=self.internal_metadata.get_dict(),
        )
Ejemplo n.º 4
0
class EventBuilder:
    """A format independent event builder used to build up the event content
    before signing the event.

    (Note that while objects of this class are frozen, the
    content/unsigned/internal_metadata fields are still mutable)

    Attributes:
        room_version: Version of the target room
        room_id
        type
        sender
        content
        unsigned
        internal_metadata

        _state
        _auth
        _store
        _clock
        _hostname: The hostname of the server creating the event
        _signing_key: The signing key to use to sign the event as the server
    """

    _state: StateHandler
    _event_auth_handler: "EventAuthHandler"
    _store: DataStore
    _clock: Clock
    _hostname: str
    _signing_key: SigningKey

    room_version: RoomVersion

    room_id: str
    type: str
    sender: str

    content: JsonDict = attr.Factory(dict)
    unsigned: JsonDict = attr.Factory(dict)

    # These only exist on a subset of events, so they raise AttributeError if
    # someone tries to get them when they don't exist.
    _state_key: Optional[str] = None
    _redacts: Optional[str] = None
    _origin_server_ts: Optional[int] = None

    internal_metadata: _EventInternalMetadata = attr.Factory(
        lambda: _EventInternalMetadata({}))

    @property
    def state_key(self) -> str:
        if self._state_key is not None:
            return self._state_key

        raise AttributeError("state_key")

    def is_state(self) -> bool:
        return self._state_key is not None

    async def build(
        self,
        prev_event_ids: List[str],
        auth_event_ids: Optional[List[str]],
        depth: Optional[int] = None,
    ) -> EventBase:
        """Transform into a fully signed and hashed event

        Args:
            prev_event_ids: The event IDs to use as the prev events
            auth_event_ids: The event IDs to use as the auth events.
                Should normally be set to None, which will cause them to be calculated
                based on the room state at the prev_events.
            depth: Override the depth used to order the event in the DAG.
                Should normally be set to None, which will cause the depth to be calculated
                based on the prev_events.

        Returns:
            The signed and hashed event.
        """
        if auth_event_ids is None:
            state_ids = await self._state.get_current_state_ids(
                self.room_id, prev_event_ids)
            auth_event_ids = self._event_auth_handler.compute_auth_events(
                self, state_ids)

        format_version = self.room_version.event_format
        # The types of auth/prev events changes between event versions.
        prev_events: Union[List[str], List[Tuple[str, Dict[str, str]]]]
        auth_events: Union[List[str], List[Tuple[str, Dict[str, str]]]]
        if format_version == EventFormatVersions.V1:
            auth_events = await self._store.add_event_hashes(auth_event_ids)
            prev_events = await self._store.add_event_hashes(prev_event_ids)
        else:
            auth_events = auth_event_ids
            prev_events = prev_event_ids

        # Otherwise, progress the depth as normal
        if depth is None:
            (
                _,
                most_recent_prev_event_depth,
            ) = await self._store.get_max_depth_of(prev_event_ids)

            depth = most_recent_prev_event_depth + 1

        # we cap depth of generated events, to ensure that they are not
        # rejected by other servers (and so that they can be persisted in
        # the db)
        depth = min(depth, MAX_DEPTH)

        event_dict: Dict[str, Any] = {
            "auth_events": auth_events,
            "prev_events": prev_events,
            "type": self.type,
            "room_id": self.room_id,
            "sender": self.sender,
            "content": self.content,
            "unsigned": self.unsigned,
            "depth": depth,
            "prev_state": [],
        }

        if self.is_state():
            event_dict["state_key"] = self._state_key

        if self._redacts is not None:
            event_dict["redacts"] = self._redacts

        if self._origin_server_ts is not None:
            event_dict["origin_server_ts"] = self._origin_server_ts

        return create_local_event_from_event_dict(
            clock=self._clock,
            hostname=self._hostname,
            signing_key=self._signing_key,
            room_version=self.room_version,
            event_dict=event_dict,
            internal_metadata_dict=self.internal_metadata.get_dict(),
        )