Esempio n. 1
0
    def emit_join_event(activity, user_id, user_name, image) -> None:
        room_id = activity.target.id
        room_name = utils.get_room_name(room_id)

        # if invisible, only sent 'invisible' join to admins in the room
        if utils.get_user_status(user_id) == UserKeys.STATUS_INVISIBLE:
            admins_in_room = environ.env.db.get_admins_in_room(
                room_id, user_id)
            if admins_in_room is None or len(admins_in_room) == 0:
                return

            room_name = utils.get_room_name(room_id)
            activity_json = utils.activity_for_user_joined_invisibly(
                user_id, user_name, room_id, room_name, image)
            for admin_id in admins_in_room:
                environ.env.out_of_scope_emit('gn_user_joined',
                                              activity_json,
                                              room=admin_id,
                                              broadcast=False,
                                              namespace='/ws')
            return

        activity_json = utils.activity_for_user_joined(user_id, user_name,
                                                       room_id, room_name,
                                                       image)
        environ.env.out_of_scope_emit('gn_user_joined',
                                      activity_json,
                                      room=room_id,
                                      broadcast=True,
                                      namespace='/ws')
        environ.env.publish(activity_json, external=True)
Esempio n. 2
0
        def set_user_offline(user_id, current_sid):
            try:
                if not utils.is_valid_id(user_id):
                    logger.warning(
                        'got invalid id on disconnect for act: {}'.format(
                            str(activity.id)))
                    # TODO: sentry
                    return

                environ.env.db.remove_sid_for_user(user_id, current_sid)
                all_sids = utils.get_sids_for_user_id(user_id)

                # if the user still has another session up we don't set the user as offline
                if all_sids is not None and len(all_sids) > 0:
                    logger.debug(
                        'when setting user offline, found other sids: [%s]' %
                        ','.join(all_sids))
                    return

                if utils.get_user_status(user_id) == UserKeys.STATUS_INVISIBLE:
                    environ.env.cache.remove_from_multicast_on_disconnect(
                        user_id)
                else:
                    environ.env.db.set_user_offline(user_id)
            except Exception as e:
                logger.error('could not set user offline: %s' % str(e))
                logger.debug('request for failed set_user_offline(): %s' %
                             str(data))
                logger.exception(traceback.format_exc())
Esempio n. 3
0
    def set_user_online_if_not_previously_invisible(arg: tuple) -> None:
        data, activity = arg
        user_id = activity.actor.id
        user_status = utils.get_user_status(user_id)

        if utils.is_super_user(user_id) or utils.is_global_moderator(user_id):
            try:
                info_message = \
                    'op {} ({}) signed in; ' \
                    'user status is currently set to {}; ' \
                    'if not "3" (invisible), I will now change it to "1" (online)'
                info_message = info_message.format(
                    user_id, utils.get_user_name_for(user_id), user_status)
                logger.info(info_message)
            except NoSuchUserException:
                logger.error(
                    'no username found for op user {}'.format(user_id))
            except Exception as e:
                logger.error(
                    'exception while getting username for op {}: {}'.format(
                        user_id, str(e)))
                logger.exception(e)
                environ.env.capture_exception(sys.exc_info())

        if user_status != UserKeys.STATUS_INVISIBLE:
            logger.info('setting user {} to online'.format(user_id))
            environ.env.db.set_user_online(user_id)
        else:
            # if login after server restart the cache value user:status:<user id> is non-existent, set to invisible
            environ.env.cache.set_user_invisible(user_id)
Esempio n. 4
0
    def publish_activity(arg: tuple) -> None:
        data, activity = arg
        user_id = activity.actor.id
        user_name = environ.env.session.get(SessionKeys.user_name.value)

        user_status = utils.get_user_status(user_id)
        activity_json = utils.activity_for_login(
            user_id, user_name, encode_attachments=False, user_status=user_status)

        environ.env.publish(activity_json, external=True)
Esempio n. 5
0
    def leave_room(arg: tuple) -> None:
        data, activity = arg

        user_id = activity.actor.id
        user_name = activity.actor.display_name
        room_id = activity.target.id

        try:
            room_name = utils.get_room_name(room_id)
        except NoSuchRoomException:
            room_name = '[removed]'

        utils.remove_sid_for_user_in_room(user_id, room_id,
                                          environ.env.request.sid)

        # multi-login, can be in same room as another session
        sids = utils.sids_for_user_in_room(user_id, room_id)
        if sids is not None and len(sids) > 0:
            if len(sids) > 1 or next(iter(sids)) != environ.env.request.sid:
                return

        utils.remove_user_from_room(user_id, user_name, room_id)

        # if invisible, only send 'invisible' leave to admins in the room
        if utils.get_user_status(user_id) == UserKeys.STATUS_INVISIBLE:
            admins_in_room = environ.env.db.get_admins_in_room(
                room_id, user_id)
            if admins_in_room is None or len(admins_in_room) == 0:
                return

            activity_left = utils.activity_for_leave(user_id, user_name,
                                                     room_id, room_name)
            for admin_id in admins_in_room:
                environ.env.out_of_scope_emit('gn_user_left',
                                              activity_left,
                                              room=admin_id,
                                              broadcast=False,
                                              namespace='/ws')
            return

        activity_left = utils.activity_for_leave(user_id, user_name, room_id,
                                                 room_name)
        environ.env.emit('gn_user_left',
                         activity_left,
                         room=room_id,
                         broadcast=True,
                         include_self=False,
                         namespace='/ws')
        utils.check_if_should_remove_room(data, activity)
Esempio n. 6
0
    def set_visible(user_id: str, user_name: str) -> None:
        user_status = utils.get_user_status(user_id, skip_cache=True)
        if user_status in {UserKeys.STATUS_AVAILABLE, UserKeys.STATUS_CHAT}:
            return

        # status is UserKeys.STATUS_VISIBLE, but is in multicast so the user is online
        if environ.env.cache.user_is_in_multicast(user_id):
            OnStatusHooks.logger.info(
                'setting user {} ({}) to visible (online), was invisible (online)'
                .format(user_id, user_name))
            OnStatusHooks.set_online(user_id, user_name)

        # otherwise status is UserKeys.STATUS_INVISIBLE, but if not in multicast the user is offline
        else:
            OnStatusHooks.logger.info(
                'setting user {} ({}) to visible (offline), was invisible (offline)'
                .format(user_id, user_name))
            OnStatusHooks.set_offline(user_id, user_name)
Esempio n. 7
0
 def log_admin_activity(user_id, user_name, status):
     try:
         info_message = \
             'op {} ({}) requested to change status to {}; user status is currently set to {}'.format(
                 user_id,
                 user_name,
                 status,
                 utils.get_user_status(user_id)
             )
         OnStatusHooks.logger.info(info_message)
     except NoSuchUserException:
         OnStatusHooks.logger.error(
             'no username found for op user {}'.format(user_id))
     except Exception as e:
         OnStatusHooks.logger.error(
             'exception while getting username for op {}: {}'.format(
                 user_id, str(e)))
         OnStatusHooks.logger.exception(e)
         environ.env.capture_exception(sys.exc_info())
Esempio n. 8
0
    def set_visible(user_id: str, user_name: str) -> None:
        user_status = utils.get_user_status(user_id, skip_cache=True)
        if user_status in {UserKeys.STATUS_AVAILABLE, UserKeys.STATUS_CHAT}:
            return

        # status is UserKeys.STATUS_VISIBLE, but is in multicast so the user is online
        if environ.env.cache.user_is_in_multicast(user_id):
            OnStatusHooks.logger.info(
                'setting user {} ({}) to visible (online), was invisible (online)'
                .format(user_id, user_name))
            OnStatusHooks.set_online(user_id, user_name)

        # otherwise status is UserKeys.STATUS_INVISIBLE, but if not in multicast the user is offline
        # TODO: when choosing to login invisibly, this is called before the user connects to dino, so should NOT do set_offline()
        # TODO: should visible login call set_status with 'online' or 'visible'?
        else:
            OnStatusHooks.logger.info(
                'setting user {} ({}) to visible (offline), was invisible (offline)'
                .format(user_id, user_name))
            OnStatusHooks.set_offline(user_id, user_name)
Esempio n. 9
0
    def leave_room(arg: tuple) -> None:
        data, activity = arg

        #  todo: should handle invisibility here? don't broadcast leaving a room if invisible
        user_id = activity.actor.id
        user_name = activity.actor.display_name
        room_id = activity.target.id

        try:
            room_name = utils.get_room_name(room_id)
        except NoSuchRoomException:
            room_name = '[removed]'

        utils.remove_user_from_room(user_id, user_name, room_id)

        # if invisible, only send 'invisible' leave to admins in the room
        if utils.get_user_status(user_id) == UserKeys.STATUS_INVISIBLE:
            admins_in_room = environ.env.db.get_admins_in_room(
                room_id, user_id)
            if admins_in_room is None or len(admins_in_room) == 0:
                return

            activity_left = utils.activity_for_leave(user_id, user_name,
                                                     room_id, room_name)
            for admin_id in admins_in_room:
                environ.env.out_of_scope_emit('gn_user_left',
                                              activity_left,
                                              room=admin_id,
                                              broadcast=False,
                                              namespace='/ws')
            return

        activity_left = utils.activity_for_leave(user_id, user_name, room_id,
                                                 room_name)
        environ.env.emit('gn_user_left',
                         activity_left,
                         room=room_id,
                         broadcast=True,
                         include_self=False,
                         namespace='/ws')
        utils.check_if_should_remove_room(data, activity)
Esempio n. 10
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())