<commit_before># -*- coding: utf-8 -*-
# Copyright 2014 - 2016 OpenMarket Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from twisted.internet import defer

from synapse.api.errors import LimitExceededError, SynapseError, AuthError
from synapse.crypto.event_signing import add_hashes_and_signatures
from synapse.api.constants import Membership, EventTypes
from synapse.types import UserID, RoomAlias, Requester
from synapse.push.action_generator import ActionGenerator

from synapse.util.logcontext import PreserveLoggingContext

import logging


logger = logging.getLogger(__name__)


class BaseHandler(object):
    """
    Common base class for the event handlers.

    :type store: synapse.storage.events.StateStore
    :type state_handler: synapse.state.StateHandler
    """

    def __init__(self, hs):
        self.store = hs.get_datastore()
        self.auth = hs.get_auth()
        self.notifier = hs.get_notifier()
        self.state_handler = hs.get_state_handler()
        self.distributor = hs.get_distributor()
        self.ratelimiter = hs.get_ratelimiter()
        self.clock = hs.get_clock()
        self.hs = hs

        self.signing_key = hs.config.signing_key[0]
        self.server_name = hs.hostname

        self.event_builder_factory = hs.get_event_builder_factory()

    @defer.inlineCallbacks
    def filter_events_for_clients(self, user_tuples, events, event_id_to_state):
        """ Returns dict of user_id -> list of events that user is allowed to
        see.

        :param (str, bool) user_tuples: (user id, is_peeking) for each
            user to be checked. is_peeking should be true if:
              * the user is not currently a member of the room, and:
              * the user has not been a member of the room since the given
                events
        """
        forgotten = yield defer.gatherResults([
            self.store.who_forgot_in_room(
                room_id,
            )
            for room_id in frozenset(e.room_id for e in events)
        ], consumeErrors=True)

        # Set of membership event_ids that have been forgotten
        event_id_forgotten = frozenset(
            row["event_id"] for rows in forgotten for row in rows
        )

        def allowed(event, user_id, is_peeking):
            state = event_id_to_state[event.event_id]

            # get the room_visibility at the time of the event.
            visibility_event = state.get((EventTypes.RoomHistoryVisibility, ""), None)
            if visibility_event:
                visibility = visibility_event.content.get("history_visibility", "shared")
            else:
                visibility = "shared"

            # if it was world_readable, it's easy: everyone can read it
            if visibility == "world_readable":
                return True

            # get the user's membership at the time of the event. (or rather,
            # just *after* the event. Which means that people can see their
            # own join events, but not (currently) their own leave events.)
            membership_event = state.get((EventTypes.Member, user_id), None)
            if membership_event:
                if membership_event.event_id in event_id_forgotten:
                    membership = None
                else:
                    membership = membership_event.membership
            else:
                membership = None

            # if the user was a member of the room at the time of the event,
            # they can see it.
            if membership == Membership.JOIN:
                return True

            if visibility == "joined":
                # we weren't a member at the time of the event, so we can't
                # see this event.
                return False

            elif visibility == "invited":
                # user can also see the event if they were *invited* at the time
                # of the event.
                return membership == Membership.INVITE

            else:
                # visibility is shared: user can also see the event if they have
                # become a member since the event<commit_msg>Send history visibility on boundary changes<commit_after># -*- coding: utf-8 -*-
# Copyright 2014 - 2016 OpenMarket Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from twisted.internet import defer

from synapse.api.errors import LimitExceededError, SynapseError, AuthError
from synapse.crypto.event_signing import add_hashes_and_signatures
from synapse.api.constants import Membership, EventTypes
from synapse.types import UserID, RoomAlias, Requester
from synapse.push.action_generator import ActionGenerator

from synapse.util.logcontext import PreserveLoggingContext

import logging


logger = logging.getLogger(__name__)


VISIBILITY_PRIORITY = (
    "world_readable",
    "shared",
    "invited",
    "joined",
)


class BaseHandler(object):
    """
    Common base class for the event handlers.

    :type store: synapse.storage.events.StateStore
    :type state_handler: synapse.state.StateHandler
    """

    def __init__(self, hs):
        self.store = hs.get_datastore()
        self.auth = hs.get_auth()
        self.notifier = hs.get_notifier()
        self.state_handler = hs.get_state_handler()
        self.distributor = hs.get_distributor()
        self.ratelimiter = hs.get_ratelimiter()
        self.clock = hs.get_clock()
        self.hs = hs

        self.signing_key = hs.config.signing_key[0]
        self.server_name = hs.hostname

        self.event_builder_factory = hs.get_event_builder_factory()

    @defer.inlineCallbacks
    def filter_events_for_clients(self, user_tuples, events, event_id_to_state):
        """ Returns dict of user_id -> list of events that user is allowed to
        see.

        :param (str, bool) user_tuples: (user id, is_peeking) for each
            user to be checked. is_peeking should be true if:
              * the user is not currently a member of the room, and:
              * the user has not been a member of the room since the given
                events
        """
        forgotten = yield defer.gatherResults([
            self.store.who_forgot_in_room(
                room_id,
            )
            for room_id in frozenset(e.room_id for e in events)
        ], consumeErrors=True)

        # Set of membership event_ids that have been forgotten
        event_id_forgotten = frozenset(
            row["event_id"] for rows in forgotten for row in rows
        )

        def allowed(event, user_id, is_peeking):
            state = event_id_to_state[event.event_id]

            # get the room_visibility at the time of the event.
            visibility_event = state.get((EventTypes.RoomHistoryVisibility, ""), None)
            if visibility_event:
                visibility = visibility_event.content.get("history_visibility", "shared")
            else:
                visibility = "shared"

            if visibility not in VISIBILITY_PRIORITY:
                visibility = "shared"

            # if it was world_readable, it's easy: everyone can read it
            if visibility == "world_readable":
                return True

            # Always allow history visibility events on boundaries. This is done
            # by setting the effective visibility to the least restrictive
            # of the old vs new.
            if event.type == EventTypes.RoomHistoryVisibility:
                prev_content = event.unsigned.get("prev_content", {})
                prev_visibility = prev_content.get("history_visibility", None)

                if prev_visibility not in VISIBILITY_PRIORITY:
                    prev_visibility = "shared"

                new_priority = VISIBILITY_PRIORITY.index(visibility)
                old_priority = VISIBILITY_PRIORITY.index(prev_visibility)
                if old_priority < new_priority:
                    visibility = prev_visibility

            # get the user's membership at the time of the event. (or rather,
            # just *after* the event. Which means that people can see their
            # own join events, but not (currently) their own leave events.)
            membership_event = state.get((EventTypes.Member, user_id), None)
            if membership_event:
                if membership_event.event_id in event_id_forgotten:
                    membership = None
                else:
                    membership = membership_event.membership
            else:
                membership = None

            # if the user was a member of the room at the time of the event,
            # they can see it.
            if membership == Membership.JOIN:
                return True

            if visibility == "joined":
                # we weren't a member at the time of the event, so we can't
                # see this event.
                return False

            elif visibility == "invited":
                # user can also see the event if they were *invited* at the time
                # of the event.
                return membership == Membership.INVITE

            else:
                # visibility is shared: user can also see the event if they have
                # become a member since the event
{'fraction_non_alphanumeric': 0.067798273155416, 'fraction_numerical': 0.0027472527472527475, 'mean_word_length': 2.174400498287138, 'pattern_counts': {'":': 6, '<': 4, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2068899', 'n_tokens_mistral': 2744, 'n_tokens_neox': 2592, 'n_words': 936}