Ejemplo n.º 1
0
def add_hashes_and_signatures(
    room_version: RoomVersion,
    event_dict: JsonDict,
    signature_name: str,
    signing_key: SigningKey,
) -> None:
    """Add content hash and sign the event

    Args:
        room_version: the version of the room this event is in

        event_dict: The event to add hashes to and sign
        signature_name: The name of the entity signing the event
            (typically the server's hostname).
        signing_key: The key to sign with
    """

    name, digest = compute_content_hash(event_dict,
                                        hash_algorithm=hashlib.sha256)

    event_dict.setdefault("hashes", {})[name] = encode_base64(digest)

    event_dict["signatures"] = compute_event_signature(
        room_version,
        event_dict,
        signature_name=signature_name,
        signing_key=signing_key)
Ejemplo n.º 2
0
def create_local_event_from_event_dict(
    clock: Clock,
    hostname: str,
    signing_key: SigningKey,
    room_version: RoomVersion,
    event_dict: JsonDict,
    internal_metadata_dict: Optional[JsonDict] = None,
) -> EventBase:
    """Takes a fully formed event dict, ensuring that fields like `origin`
    and `origin_server_ts` have correct values for a locally produced event,
    then signs and hashes it.
    """

    format_version = room_version.event_format
    if format_version not in KNOWN_EVENT_FORMAT_VERSIONS:
        raise Exception("No event format defined for version %r" %
                        (format_version, ))

    if internal_metadata_dict is None:
        internal_metadata_dict = {}

    time_now = int(clock.time_msec())

    if format_version == EventFormatVersions.V1:
        event_dict["event_id"] = _create_event_id(clock, hostname)

    event_dict["origin"] = hostname
    event_dict.setdefault("origin_server_ts", time_now)

    event_dict.setdefault("unsigned", {})
    age = event_dict["unsigned"].pop("age", 0)
    event_dict["unsigned"].setdefault("age_ts", time_now - age)

    event_dict.setdefault("signatures", {})

    add_hashes_and_signatures(room_version, event_dict, hostname, signing_key)
    return make_event_from_dict(event_dict,
                                room_version,
                                internal_metadata_dict=internal_metadata_dict)
Ejemplo n.º 3
0
    def _inject_bundled_aggregations(
        self,
        event: EventBase,
        time_now: int,
        config: SerializeEventConfig,
        bundled_aggregations: Dict[str, "BundledAggregations"],
        serialized_event: JsonDict,
        apply_edits: bool,
    ) -> None:
        """Potentially injects bundled aggregations into the unsigned portion of the serialized event.

        Args:
            event: The event being serialized.
            time_now: The current time in milliseconds
            config: Event serialization config
            bundled_aggregations: Bundled aggregations to be injected.
                A map from event_id to aggregation data. Must contain at least an
                entry for `event`.

                While serializing the bundled aggregations this map may be searched
                again for additional events in a recursive manner.
            serialized_event: The serialized event which may be modified.
            apply_edits: Whether the content of the event should be modified to reflect
               any replacement in `aggregations.replace`.
        """

        # We have already checked that aggregations exist for this event.
        event_aggregations = bundled_aggregations[event.event_id]

        # The JSON dictionary to be added under the unsigned property of the event
        # being serialized.
        serialized_aggregations = {}

        if event_aggregations.annotations:
            serialized_aggregations[
                RelationTypes.ANNOTATION] = event_aggregations.annotations

        if event_aggregations.references:
            serialized_aggregations[
                RelationTypes.REFERENCE] = event_aggregations.references

        if event_aggregations.replace:
            # If there is an edit, optionally apply it to the event.
            edit = event_aggregations.replace
            if apply_edits:
                self._apply_edit(event, serialized_event, edit)

            # Include information about it in the relations dict.
            serialized_aggregations[RelationTypes.REPLACE] = {
                "event_id": edit.event_id,
                "origin_server_ts": edit.origin_server_ts,
                "sender": edit.sender,
            }

        # Include any threaded replies to this event.
        if event_aggregations.thread:
            thread = event_aggregations.thread

            serialized_latest_event = self.serialize_event(
                thread.latest_event,
                time_now,
                config=config,
                bundle_aggregations=bundled_aggregations,
            )

            thread_summary = {
                "latest_event": serialized_latest_event,
                "count": thread.count,
                "current_user_participated": thread.current_user_participated,
            }
            serialized_aggregations[RelationTypes.THREAD] = thread_summary

        # Include the bundled aggregations in the event.
        if serialized_aggregations:
            # There is likely already an "unsigned" field, but a filter might
            # have stripped it off (via the event_fields option). The server is
            # allowed to return additional fields, so add it back.
            serialized_event.setdefault("unsigned", {}).setdefault(
                "m.relations", {}).update(serialized_aggregations)