Exemplo n.º 1
0
    def on_invite(self, activity: Activity) -> (bool, int, str):
        if not hasattr(activity.actor, 'url'):
            return False, ECodes.MISSING_ACTOR_URL, 'need invite room uuid in actor.url'
        invite_room = activity.actor.url

        if not hasattr(activity, 'target') or not hasattr(
                activity.target, 'id'):
            return False, ECodes.MISSING_TARGET_ID, 'no target.id (uuid of user to invite)'

        try:
            activity.target.display_name = utils.get_user_name_for(
                activity.target.id)
        except NoSuchUserException:
            return False, ECodes.NO_SUCH_USER, 'no such user for target.id (uuid of user to invite)'

        try:
            channel_id = utils.get_channel_for_room(invite_room)
        except (NoSuchRoomException, NoChannelFoundException):
            return False, ECodes.NO_SUCH_ROOM, 'no room/channel found for actor.url room uuid'

        if not utils.room_exists(channel_id, invite_room):
            return False, ECodes.NO_SUCH_ROOM, 'room actor.url does not exist'

        if not hasattr(activity, 'object'):
            activity.object = DefObject(dict())

        activity.object.url = channel_id
        activity.object.display_name = utils.get_channel_name(channel_id)

        return True, None, None
Exemplo n.º 2
0
    def on_create(self, activity: Activity) -> (bool, int, str):
        if not hasattr(activity, 'object') or not hasattr(
                activity.object, 'url'):
            return False, ECodes.MISSING_OBJECT_URL, 'no channel id set'
        if not hasattr(activity.target, 'display_name'):
            return False, ECodes.MISSING_TARGET_DISPLAY_NAME, 'no room name set'

        room_name = activity.target.display_name
        channel_id = activity.object.url

        if not hasattr(activity, 'actor') or not hasattr(activity.actor, 'id'):
            return False, ECodes.MISSING_ACTOR_ID, 'need actor.id (user uuid)'

        try:
            activity.object.display_name = utils.get_channel_name(channel_id)
        except NoSuchChannelException:
            return False, ECodes.NO_SUCH_CHANNEL, 'channel does not exist'

        if room_name is None or room_name.strip() == '':
            return False, ECodes.MISSING_TARGET_DISPLAY_NAME, 'got blank room name, can not create'

        if not utils.is_base64(room_name):
            return False, ECodes.NOT_BASE64, 'invalid room name, not base64 encoded'
        room_name = utils.b64d(room_name)

        if not environ.env.db.channel_exists(channel_id):
            return False, ECodes.NO_SUCH_CHANNEL, 'channel does not exist'

        if utils.room_name_restricted(room_name):
            return False, ECodes.ROOM_NAME_RESTRICTED, 'restricted room name'

        if environ.env.db.room_name_exists(channel_id, room_name):
            return False, ECodes.ROOM_ALREADY_EXISTS, 'a room with that name already exists'

        if not hasattr(activity.target, 'object_type') or \
                activity.target.object_type is None or \
                len(str(activity.target.object_type).strip()) == 0:
            # for acl validation to know we're trying to create a room
            activity.target.object_type = 'room'

        channel_acls = utils.get_acls_in_channel_for_action(
            channel_id, ApiActions.CREATE)
        is_valid, msg = validation.acl.validate_acl_for_action(
            activity, ApiTargets.CHANNEL, ApiActions.CREATE, channel_acls)

        if not is_valid:
            return False, ECodes.NOT_ALLOWED, msg

        return True, None, None
Exemplo n.º 3
0
    def remove_ban(self, user_id: str, target_id: str,
                   target_type: str) -> None:
        ban_activity = {
            'actor': {
                'id': '0',
                'displayName': utils.b64e('admin')
            },
            'verb': 'unban',
            'object': {
                'id': user_id,
                'displayName': utils.b64e(utils.get_user_name_for(user_id))
            },
            'target': {
                'objectType': target_type
            },
            'id': str(uuid()),
            'published':
            datetime.utcnow().strftime(ConfigKeys.DEFAULT_DATE_FORMAT)
        }

        if target_type == 'global':
            self.env.db.remove_global_ban(user_id)

        elif target_type == 'channel':
            self.env.db.remove_channel_ban(target_id, user_id)
            ban_activity['target']['id'] = target_id
            ban_activity['target']['displayName'] = utils.b64e(
                utils.get_channel_name(target_id))

        elif target_type == 'room':
            self.env.db.remove_room_ban(target_id, user_id)
            ban_activity['target']['id'] = target_id
            ban_activity['target']['displayName'] = utils.b64e(
                utils.get_room_name(target_id))

        else:
            raise UnknownBanTypeException(target_type)

        self.env.publish(ban_activity)
Exemplo n.º 4
0
    def on_whisper(self, activity: Activity) -> (bool, int, str):
        if not hasattr(activity, 'target') or not hasattr(
                activity.target, 'id'):
            return False, ECodes.MISSING_TARGET_ID, 'no target.id (user uuid to whisper to)'
        if not hasattr(activity, 'actor') or not hasattr(activity.actor, 'id'):
            return False, ECodes.MISSING_ACTOR_ID, 'no actor.id (id of user who is whispering)'
        if not hasattr(activity, 'actor') or not hasattr(
                activity.actor, 'url'):
            return False, ECodes.MISSING_ACTOR_URL, 'no actor.url (room uuid to whisper in)'
        if not hasattr(activity, 'object') or not hasattr(
                activity.object, 'content'):
            return False, ECodes.MISSING_OBJECT_CONTENT, 'no object.content (message to whisper)'

        if not utils.is_base64(activity.object.content):
            return False, ECodes.NOT_BASE64, 'object.content needs to be base64 encoded'

        try:
            activity.object.url = utils.get_channel_for_room(
                activity.actor.url)
        except (NoSuchChannelException, NoChannelFoundException):
            return False, ECodes.NO_SUCH_ROOM, 'no room found for actor.url (room uuid to whisper in)'

        try:
            activity.object.display_name = utils.get_channel_name(
                activity.object.url)
        except (NoSuchChannelException, NoChannelFoundException):
            return False, ECodes.NO_SUCH_CHANNEL, 'no channel found for actor.url (room uuid to whisper in)'

        channel_acls = utils.get_acls_in_channel_for_action(
            activity.object.url, ApiActions.WHISPER)
        is_valid, msg = validation.acl.validate_acl_for_action(
            activity, ApiTargets.CHANNEL, ApiActions.WHISPER, channel_acls)

        if not is_valid:
            return False, ECodes.NOT_ALLOWED, msg

        return True, None, None
Exemplo n.º 5
0
    def handle_ban(self, activity: Activity):
        banner_id = activity.actor.id
        if banner_id == '0' or banner_id is None:
            banner_id = '0'
            banner_name = 'admin'
        else:
            try:
                banner_name = utils.get_user_name_for(banner_id)
            except NoSuchUserException:
                # if banning from rest api the user might not exist
                logger.error('no such user when banning: %s' % banner_id)
                return

        banned_id = activity.object.id
        if not utils.is_valid_id(banned_id):
            logger.warning('got invalid id on ban activity: {}'.format(
                str(activity.id)))
            # TODO: sentry
            return

        banned_name = utils.get_user_name_for(banned_id)
        banned_sids = utils.get_sids_for_user_id(banned_id)
        namespace = activity.target.url or '/ws'
        target_type = activity.target.object_type

        if target_type == 'room':
            target_id = activity.target.id
            target_name = utils.get_room_name(target_id)
        elif target_type == 'channel':
            target_id = activity.target.id
            target_name = utils.get_channel_name(target_id)
        else:
            target_id = ''
            target_name = ''

        if len(banned_sids) == 0 or banned_sids == [None
                                                    ] or banned_sids[0] == '':
            logger.warning('no sid(s) found for user id %s' % banned_id)
            return

        reason = None
        if hasattr(activity.object, 'content'):
            reason = activity.object.content

        activity_json = utils.activity_for_user_banned(banner_id, banner_name,
                                                       banned_id, banned_name,
                                                       target_id, target_name,
                                                       reason)

        try:
            ban_activity = self.get_ban_activity(activity, target_type)
            self.env.out_of_scope_emit('gn_banned',
                                       ban_activity,
                                       json=True,
                                       namespace=namespace,
                                       room=banned_id)

            if target_id is None or target_id == '':
                rooms_for_user = self.env.db.rooms_for_user(banned_id)
                logger.info(
                    'user %s is in these rooms (will ban from all): %s' %
                    (banned_id, str(rooms_for_user)))
                self.ban_globally(activity_json, activity, rooms_for_user,
                                  banned_id, banned_sids, namespace)

                if utils.get_user_status(
                        banned_id) == UserKeys.STATUS_INVISIBLE:
                    environ.env.cache.remove_from_multicast_on_disconnect(
                        banned_id)
                else:
                    environ.env.db.set_user_offline(banned_id)

                disconnect_activity = utils.activity_for_disconnect(
                    banned_id, banned_name)
                self.env.publish(disconnect_activity, external=True)

            elif target_type == 'channel':
                rooms_in_channel = self.env.db.rooms_for_channel(target_id)
                self.ban_channel(activity_json, activity, rooms_in_channel,
                                 target_id, banned_id, banned_sids, namespace)
            else:
                self.ban_room(activity_json, activity, target_id, banned_id,
                              banned_sids, namespace)

        except KeyError as ke:
            logger.error('could not ban: %s' % str(ke))
            logger.exception(traceback.format_exc())
            self.env.capture_exception(sys.exc_info())
Exemplo n.º 6
0
 def test_get_channel_name(self):
     self.assertEqual(BaseWithDb.CHANNEL_NAME, utils.get_channel_name(BaseWithDb.CHANNEL_ID))
Exemplo n.º 7
0
    def on_join(self, activity: Activity) -> (bool, int, str):
        room_id = activity.target.id
        room_name = activity.target.display_name
        user_id = environ.env.session.get(SessionKeys.user_id.value, None)

        if user_id is None or len(user_id.strip()) == 0:
            user_id = activity.actor.id

        if room_id is not None and len(room_id.strip()) > 0:
            try:
                room_name = utils.get_room_name(room_id)
            except NoSuchRoomException:
                return False, ECodes.NO_SUCH_ROOM, 'room does not exist'
        else:
            if room_name is None or len(room_name.strip()) == 0:
                return False, ECodes.MISSING_TARGET_DISPLAY_NAME, 'neither room id nor name supplied'

            try:
                room_id = utils.get_room_id(room_name)
            except NoSuchRoomException:
                return False, ECodes.NO_SUCH_ROOM, 'room does not exists with given name'
            except MultipleRoomsFoundForNameException:
                return False, ECodes.MULTIPLE_ROOMS_WITH_NAME, 'found multiple rooms with name "%s"' % room_name

        if not hasattr(activity, 'object'):
            activity.object = DefObject(dict())

        if not utils.user_is_online(user_id):
            user_name = '<unknown>'
            try:
                user_name = utils.get_user_name_for(user_id)
            except NoSuchUserException:
                logger.error('could not get username for user id %s' % user_id)

            logger.warning(
                'user "%s" (%s) is not online, not joining room "%s" (%s)!' %
                (user_name, user_id, room_name, room_id))
            return False, ECodes.NOT_ONLINE, 'user is not online'

        if utils.is_super_user(user_id) or utils.is_global_moderator(user_id):
            return True, None, None
        if utils.is_owner(room_id, user_id):
            return True, None, None

        channel_id = utils.get_channel_for_room(room_id)

        if utils.is_owner_channel(channel_id, user_id):
            return True, None, None

        activity.object.url = channel_id
        activity.object.display_name = utils.get_channel_name(channel_id)
        activity.target.object_type = 'room'

        try:
            acls = utils.get_acls_in_room_for_action(room_id, ApiActions.JOIN)
        except NoSuchRoomException:
            return False, ECodes.NO_SUCH_ROOM, 'no such room'

        is_valid, error_msg = validation.acl.validate_acl_for_action(
            activity, ApiTargets.ROOM, ApiActions.JOIN, acls)
        if not is_valid:
            return False, ECodes.NOT_ALLOWED, error_msg

        is_banned, info_dict = utils.is_banned(user_id, room_id)
        if is_banned:
            scope = info_dict['scope']
            seconds_left = info_dict['seconds']
            target_id = info_dict['id']
            target_name = ''
            if scope == 'room':
                target_name = utils.get_room_name(target_id)
            elif scope == 'channel':
                target_name = utils.get_channel_name(target_id)
            reason = utils.reason_for_ban(user_id, scope, target_id)

            json_act = utils.activity_for_already_banned(
                seconds_left, reason, scope, target_id, target_name)
            return False, ECodes.USER_IS_BANNED, json_act

        return True, None, None
Exemplo n.º 8
0
    def on_message(self, activity: Activity) -> (bool, int, str):
        room_id = activity.target.id
        user_id = activity.actor.id
        object_type = activity.target.object_type
        message = activity.object.content

        from_room_id = None
        if hasattr(activity.actor, 'url'):
            from_room_id = activity.actor.url

        if message is None or len(message.strip()) == 0:
            return False, ECodes.EMPTY_MESSAGE, 'empty message body'

        if not utils.is_base64(message):
            return False, ECodes.NOT_BASE64, 'invalid message content, not base64 encoded'

        if room_id is None or room_id == '':
            return False, ECodes.MISSING_TARGET_ID, 'no room id specified when sending message'

        if object_type not in ['room', 'private']:
            return False, ECodes.INVALID_TARGET_TYPE, \
                   'invalid object_type "%s", must be one of [room, private]' % object_type

        if object_type == 'room':
            channel_id = None
            if hasattr(activity, 'object') and hasattr(activity.object, 'url'):
                channel_id = activity.object.url
            if channel_id is None or len(channel_id.strip()) == 0:
                channel_id = utils.get_channel_for_room(room_id)

            if channel_id is None or channel_id == '':
                return False, ECodes.MISSING_OBJECT_URL, 'no channel id specified when sending message'

            activity.object.url = channel_id
            activity.object.display_name = utils.get_channel_name(channel_id)

            if not utils.channel_exists(channel_id):
                return False, ECodes.NO_SUCH_CHANNEL, 'channel %s does not exists' % channel_id

            if not utils.room_exists(channel_id, room_id):
                return False, ECodes.NO_SUCH_ROOM, 'target room %s does not exist' % room_id

            if from_room_id is not None:
                if from_room_id != room_id and not utils.room_exists(
                        channel_id, from_room_id):
                    return False, ECodes.NO_SUCH_ROOM, 'origin room %s does not exist' % from_room_id

            if not utils.is_user_in_room(user_id, room_id):
                logger.warning('user "%s" is not in room "%s' %
                               (user_id, room_id))
                if from_room_id is None:
                    return False, ECodes.USER_NOT_IN_ROOM, 'user is not in target room'
                if not utils.is_user_in_room(user_id, from_room_id):
                    return False, ECodes.USER_NOT_IN_ROOM, 'user is not in origin room, cannot send message from there'
                if not utils.can_send_cross_room(activity, from_room_id,
                                                 room_id):
                    return False, ECodes.NOT_ALLOWED, \
                           'user not allowed to send cross-room msg from %s to %s' % (from_room_id, room_id)

        elif object_type == 'private':
            channel_id = None
            if hasattr(activity, 'object') and hasattr(activity.object, 'url'):
                channel_id = activity.object.url

            if channel_id is None or len(channel_id.strip()) == 0:
                try:
                    channel_id = utils.get_channel_for_room(room_id)
                except NoSuchRoomException:
                    # TODO: ignore for now, but capture so we can track; a user room won't exist, try to emit anyway
                    environ.env.capture_exception(sys.exc_info())
                    return True, False, False

            if not utils.channel_exists(channel_id):
                return False, ECodes.NO_SUCH_CHANNEL, 'channel %s does not exists' % channel_id
            if not utils.room_exists(channel_id, room_id):
                return False, ECodes.NO_SUCH_ROOM, 'target room %s does not exist' % room_id

        return True, None, None