Beispiel #1
0
def activity_for_going_visible(user_id: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id
        },
        'verb': 'visible'
    })
Beispiel #2
0
def activity_for_list_channels(activity: Activity, channels: dict) -> dict:
    response = ActivityBuilder.enrich({
        'object': {
            'objectType': 'channels'
        },
        'verb': 'list'
    })

    response['object']['attachments'] = list()
    for channel_id, (channel_name, sort_order) in channels.items():
        object_type = is_channel_static_or_temporary_or_mix(channel_id)

        response['object']['attachments'].append({
            'id':
            channel_id,
            'url':
            sort_order,
            'displayName':
            b64e(channel_name),
            'objectType':
            object_type
        })
        response['object']['attachments'] = sorted(
            response['object']['attachments'], key=lambda k: k['url'])

    return response
Beispiel #3
0
def activity_for_list_rooms(activity: Activity, rooms: dict) -> dict:
    response = ActivityBuilder.enrich({
        'object': {
            'url': activity.object.url,
            'objectType': 'rooms'
        },
        'verb': 'list'
    })

    response['object']['attachments'] = list()
    for room_id, room_details in rooms.items():
        room_name = room_details['name']
        nr_users_in_room = room_details['users']

        object_type = 'static'
        if 'ephemeral' in room_details and room_details['ephemeral']:
            object_type = 'temporary'

        response['object']['attachments'].append({
            'id':
            room_id,
            'url':
            room_details['sort_order'],
            'displayName':
            b64e(room_name),
            'summary':
            nr_users_in_room,
            'objectType':
            object_type,
            'content':
            room_details['roles']
        })

    return response
Beispiel #4
0
def activity_for_user_kicked(kicker_id: str,
                             kicker_name: str,
                             kicked_id: str,
                             kicked_name: str,
                             room_id: str,
                             room_name: str,
                             reason=None) -> dict:
    activity = ActivityBuilder.enrich({
        'actor': {
            'id': kicker_id,
            'displayName': b64e(kicker_name)
        },
        'object': {
            'id': kicked_id
        },
        'target': {
            'id': room_id,
            'displayName': b64e(room_name)
        },
        'verb': 'kick'
    })

    if not is_base64(kicked_name):
        kicked_name = b64e(kicked_name)

    activity['object']['displayName'] = kicked_name

    if reason is not None:
        if is_base64(reason):
            activity['object']['content'] = reason
        else:
            logger.warning('ignoring reason for kick activity, not base64')
            logger.debug('request with non-base64 reason: %s' % activity)

    return activity
Beispiel #5
0
    def do_post(self):
        is_valid, msg, json = self.validate_json()
        if not is_valid:
            logger.error('invalid json: %s' % msg)
            raise RuntimeError('invalid json')

        if json is None:
            raise RuntimeError('no json in request')
        if not isinstance(json, dict):
            raise RuntimeError('need a dict')
        logger.debug('POST request: %s' % str(json))

        if 'id' not in json:
            raise RuntimeError('no id parameter in request')
        if 'status' not in json:
            raise RuntimeError('no status parameter in request')

        user_id = json.get('id')
        status = json.get('status')
        all_statuses = {'online', 'offline', 'invisible', 'visible'}
        if status not in all_statuses:
            raise RuntimeError('unknown status [{}], need one of [{}]'.format(
                status, ','.join(all_statuses)))

        try:
            environ.env.db.create_user(user_id, str(user_id))
        except UserExistsException:
            pass

        activity_base = {'actor': {'id': user_id}, 'verb': status}
        data = ActivityBuilder.enrich(activity_base)
        activity = parse(data)
        environ.env.observer.emit('on_status', (data, activity))
Beispiel #6
0
def activity_for_disconnect(user_id: str, user_name: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name)
        },
        'verb': 'disconnect'
    })
Beispiel #7
0
def activity_for_broadcast(body: str, verb: str = 'broadcast') -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'displayName': ADMIN_B64,  # 'Admin' in base64
            'id': '0'
        },
        'content': body,
        'verb': verb
    })
Beispiel #8
0
def activity_for_sid_disconnect(user_id: str, user_name: str,
                                current_sid: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name),
            'content': current_sid,
        },
        'verb': 'ended'
    })
Beispiel #9
0
def activity_for_connect(user_id: str, user_name: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id':
            user_id,
            'displayName':
            b64e(user_name),
            'attachments':
            get_user_info_attachments_for(user_id, include_user_agent=True)
        },
        'verb': 'connect'
    })
Beispiel #10
0
def activity_for_login(user_id: str,
                       user_name: str,
                       include_unread_history: bool = False,
                       encode_attachments: bool = True,
                       heartbeat_sid=False,
                       user_status=UserKeys.STATUS_AVAILABLE) -> dict:
    if heartbeat_sid:
        sid = 'hb-{}'.format(user_id)
    else:
        try:
            sid = environ.env.request.sid
        except Exception as e:
            logger.error('could not get sid for user "{}": {}'.format(
                user_id, str(e)))
            logger.exception(traceback.format_exc())
            environ.env.capture_exception(sys.exc_info())
            sid = ''

    include_user_agent = True
    if heartbeat_sid:
        include_user_agent = False

    response = ActivityBuilder.enrich({
        'actor': {
            'id':
            user_id,
            'summary':
            _user_status_int_to_str(str(user_status)),
            'displayName':
            b64e(user_name),
            'content':
            sid,
            'attachments':
            get_user_info_attachments_for(
                user_id,
                encode_attachments,
                include_user_agent=include_user_agent)
        },
        'verb': 'login'
    })

    if include_unread_history:
        messages = get_unacked_messages(user_id)
        if len(messages) > 0:
            history_activity = activity_for_history(as_parser(response),
                                                    messages)
            response['object'] = {
                'objectType': 'history',
                'attachments': history_activity['object']['attachments']
            }

    return response
Beispiel #11
0
def activity_for_users_in_room(activity: Activity, users_orig: dict) -> dict:
    users = users_orig.copy()
    response = ActivityBuilder.enrich({
        'target': {
            'id': activity.target.id,
            'displayName': b64e(activity.target.display_name)
        },
        'object': {
            'objectType': 'users'
        },
        'verb': 'list'
    })

    response['object']['attachments'] = list()
    this_user_id = environ.env.session.get(SessionKeys.user_id.value)
    this_user_is_super_user = is_super_user(
        this_user_id) or is_global_moderator(this_user_id)

    for user_id, user_name in users.items():
        user_info = get_user_info_attachments_for(user_id)
        if this_user_is_super_user:
            user_ip = ''
            try:
                user_ip = environ.env.request.remote_addr
            except Exception as e:
                logger.error('could not get remote address of user %s: %s' %
                             (user_info, str(e)))
                logger.exception(traceback.format_exc())
                environ.env.capture_exception(sys.exc_info())

            user_info.append({'objectType': 'ip', 'content': b64e(user_ip)})

        # temporary fix for avoiding dead users
        if len(user_info) == 0:
            environ.env.db.leave_room(user_id, activity.target.id)
            continue

        user_roles = environ.env.db.get_user_roles_in_room(
            user_id, activity.target.id)
        user_attachment = {
            'id': user_id,
            'displayName': b64e(user_name),
            'attachments': user_info,
            'content': ','.join(user_roles),
            'objectType': 'user'
        }
        if this_user_is_super_user and user_is_invisible(user_id):
            user_attachment['objectType'] = 'invisible'

        response['object']['attachments'].append(user_attachment)

    return response
Beispiel #12
0
def activity_for_message(user_id: str, user_name: str) -> dict:
    """
    user for sending event to other system to do statistics for how active a user is
    :param user_id: the id of the user
    :param user_name: the name of the user
    :return: an activity streams dict
    """
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name)
        },
        'verb': 'send'
    })
Beispiel #13
0
def activity_for_leave(user_id: str, user_name: str, room_id: str,
                       room_name: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName':
            user_name if is_base64(user_name) else b64e(user_name)
        },
        'target': {
            'id': room_id,
            'displayName':
            room_name if is_base64(room_name) else b64e(room_name)
        },
        'verb': 'leave'
    })
Beispiel #14
0
def activity_for_msg_status(activity: Activity, statuses: dict) -> dict:
    act = ActivityBuilder.enrich({
        'object': {
            'objectType': 'statuses',
            'attachments': list()
        },
        'target': {
            'id': activity.target.id,
        },
        'verb': 'check'
    })

    for msg_id, status in statuses.items():
        act['object']['attachments'].append({'id': msg_id, 'content': status})

    return act
Beispiel #15
0
def activity_for_room_removed(activity: Activity,
                              room_name: str,
                              reason: str = None) -> dict:
    act = ActivityBuilder.enrich({
        'target': {
            'id': activity.target.id,
            'displayName': b64e(room_name),
            'objectType': 'room'
        },
        'verb': 'removed'
    })

    if reason is not None and len(reason.strip()) > 0:
        act['object'] = {'content': b64e(reason)}

    return act
Beispiel #16
0
def check_if_remove_room_owner(activity: Activity):
    user_id = activity.actor.id
    user_name = environ.env.session.get(SessionKeys.user_name.value)
    room_id = activity.target.id
    room_name = get_room_name(room_id)
    channel_id = get_channel_for_room(room_id)

    if not environ.env.db.is_room_ephemeral(room_id):
        logger.info('room %s (%s) is not ephemeral, not considering removal' %
                    (room_name, room_id))
        return

    owners = get_owners_for_room(room_id)
    users_in_room = get_users_in_room(room_id)

    if user_id in users_in_room:
        del users_in_room[user_id]

    for owner_id, owner_name in owners.items():
        if owner_id in users_in_room:
            logger.info(
                'owner %s (%s) is still in room %s (%s), not considering removal'
                % (owner_name, owner_id, room_name, room_id))
            return

    for user_id_still_in_room, user_name_still_in_room in users_in_room.items(
    ):
        kick_activity = ActivityBuilder.enrich({
            'actor': {
                'id': user_id,
                'displayName': b64e(user_name)
            },
            'verb': 'kick',
            'object': {
                'id': user_id_still_in_room,
                'displayName': b64e(user_name_still_in_room),
                'content': b64e('All owners have left the room')
            },
            'target': {
                'url': environ.env.request.namespace,
                'id': room_id,
                'displayName': b64e(room_name)
            }
        })
        environ.env.publish(kick_activity)

    remove_room(channel_id, room_id, user_id, user_name, room_name)
Beispiel #17
0
def activity_for_join(activity: Activity, acls: dict, messages: list,
                      owners: dict, users: dict) -> dict:
    response = ActivityBuilder.enrich({
        'object': {
            'objectType': 'room',
            'attachments': list()
        },
        'verb': 'join',
        'target': {
            'id': activity.target.id,
            'displayName': b64e(get_room_name(activity.target.id))
        }
    })

    acl_activity = activity_for_get_acl(activity, acls)
    response['object']['attachments'].append({
        'objectType':
        'acl',
        'attachments':
        acl_activity['object']['attachments']
    })

    history_activity = activity_for_history(activity, messages)
    response['object']['attachments'].append({
        'objectType':
        'history',
        'attachments':
        history_activity['object']['attachments']
    })

    owners_activity = activity_for_owners(activity, owners)
    response['object']['attachments'].append({
        'objectType':
        'owner',
        'attachments':
        owners_activity['object']['attachments']
    })

    users_in_room_activity = activity_for_users_in_room(activity, users)
    response['object']['attachments'].append({
        'objectType':
        'user',
        'attachments':
        users_in_room_activity['object']['attachments']
    })

    return response
Beispiel #18
0
    def autojoin_rooms(arg: tuple) -> None:
        data, activity = arg

        if not str(environ.env.config.get(ConfigKeys.AUTOJOIN_ENABLED, 'false')).lower() in {'true', 'yes', '1', 'y'}:
            return

        try:
            room_acls = environ.env.db.get_room_acls_for_action(ApiActions.AUTOJOIN)
        except Exception as e:
            logger.error('could not get autojoin acls: {}'.format(str(e)))
            return

        for room_id, acls in room_acls.items():
            # sometimes room_id is None, if no autojoin rooms exist
            if room_id is None or len(room_id.strip()) == 0:
                continue

            # needed for validation
            join_data = data.copy()
            join_data['target'] = {
                'id': room_id,
                'objectType': 'room'
            }

            is_valid, error_msg = validation.acl.validate_acl_for_action(
                activitystreams.parse(join_data),
                ApiTargets.ROOM,
                ApiActions.JOIN,
                acls
            )

            if not is_valid:
                continue

            join_data = ActivityBuilder.enrich({
                'verb': 'join',
                'actor': {
                    'id': activity.actor.id
                },
                'target': {
                    'id': room_id
                }
            })
            environ.env.observer.emit('on_join', (join_data, activitystreams.parse(join_data)))
Beispiel #19
0
def activity_for_whisper(message: str, whisperer_id: str, whisperer_name: str,
                         room_id: str, room_name: str, channel_id: str,
                         channel_name: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': whisperer_id,
            'displayName': b64e(whisperer_name)
        },
        'verb': 'whisper',
        'object': {
            'content': message,
            'url': channel_id,
            'displayName': b64e(channel_name)
        },
        'target': {
            'id': room_id,
            'displayName': b64e(room_name)
        }
    })
Beispiel #20
0
def activity_for_invite(inviter_id: str, inviter_name: str, room_id: str,
                        room_name: str, channel_id: str,
                        channel_name: str) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': inviter_id,
            'displayName': b64e(inviter_name),
            'attachments': get_user_info_attachments_for(inviter_id)
        },
        'verb': 'invite',
        'object': {
            'url': channel_id,
            'displayName': b64e(channel_name)
        },
        'target': {
            'id': room_id,
            'displayName': b64e(room_name)
        }
    })
Beispiel #21
0
def activity_for_report(activity: Activity) -> dict:
    return ActivityBuilder.enrich({
        'actor': {
            'id': activity.actor.id,  # user id of the one reporting
            'displayName': b64e(activity.actor.display_name)
        },
        'object': {
            'summary':
            activity.object.summary,  # free-text reason for reporting
            'content': activity.object.content,  # the reported message
            'id': activity.object.id  # id of the reported message
        },
        'target': {
            'id':
            activity.target.id,  # user id of user who sent to reported message
            'displayName': activity.target.display_name
        },
        'verb': 'report'
    })
Beispiel #22
0
def activity_for_user_joined(user_id: str, user_name: str, room_id: str,
                             room_name: str, image_url: str) -> dict:
    user_roles = environ.env.db.get_user_roles_in_room(user_id, room_id)
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name),
            'image': {
                'url': image_url
            },
            'attachments': get_user_info_attachments_for(user_id),
            'content': ','.join(user_roles)
        },
        'target': {
            'id': room_id,
            'displayName': b64e(room_name)
        },
        'verb': 'join'
    })
Beispiel #23
0
    def publish_startup_done_event() -> None:
        if len(environ.env.config) == 0 or environ.env.config.get(
                ConfigKeys.TESTING, False):
            # assume we're testing
            return

        if environ.env.node != 'web':
            # avoid publishing duplicate events by only letting the web node publish external events
            return

        json_event = ActivityBuilder.enrich({
            'verb':
            'restart',
            'content':
            environ.env.config.get(ConfigKeys.ENVIRONMENT),
        })

        logger.debug('publishing restart-done event to external queue: %s' %
                     str(json_event))
        environ.env.publish(json_event, external=True)
Beispiel #24
0
def activity_for_blacklisted_word(activity: Activity,
                                  blacklisted_word: str = None) -> dict:
    if blacklisted_word is not None:
        blacklisted_word = b64e(blacklisted_word)

    return ActivityBuilder.enrich({
        'actor': {
            'id': activity.actor.id,
            'displayName': activity.actor.display_name
        },
        'object': {
            'content': activity.object.content,
            'summary': blacklisted_word
        },
        'target': {
            'id': activity.target.id,
            'displayName': b64e(activity.target.display_name)
        },
        'verb': 'blacklisted'
    })
Beispiel #25
0
def activity_for_owners(activity: Activity, owners: dict) -> dict:
    response = ActivityBuilder.enrich({
        'object': {
            'objectType': 'owner'
        },
        'target': {
            'id': activity.target.id,
            'displayName': b64e(activity.target.display_name)
        },
        'verb': 'list'
    })

    response['object']['attachments'] = list()
    for user_id, user_name in owners.items():
        response['object']['attachments'].append({
            'id': user_id,
            'displayName': b64e(user_name)
        })

    return response
Beispiel #26
0
def activity_for_message(user_id: str,
                         user_name: str,
                         message_id: str = None) -> dict:
    """
    user for sending event to other system to do statistics for how active a user is
    :param user_id: the id of the user
    :param user_name: the name of the user
    :param message_id: the id of the message stored in db, is None if using REST to send, not stored
    :return: an activity streams dict
    """
    data = {
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name)
        },
        'verb': 'send'
    }
    if message_id is not None:
        data['object'] = {'id': message_id}

    return ActivityBuilder.enrich(data)
Beispiel #27
0
def activity_for_remove_room(user_id: str,
                             user_name: str,
                             room_id: str,
                             room_name: str,
                             reason: str = None) -> dict:
    act = ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name)
        },
        'target': {
            'id': room_id,
            'displayName': b64e(room_name)
        },
        'verb': 'remove'
    })

    if reason is not None and len(reason.strip()) > 0:
        act['object'] = {'content': b64e(reason)}

    return act
Beispiel #28
0
def activity_for_get_acl(activity: Activity, acl_values: dict) -> dict:
    response = ActivityBuilder.enrich({
        'object': {
            'objectType': 'acl'
        },
        'verb': 'get'
    })

    if hasattr(activity, 'target') and hasattr(activity.target, 'id'):
        response['target'] = {'id': activity.target.id}

    response['object']['attachments'] = list()
    for api_action, acls in acl_values.items():
        for acl_type, acl_value in acls.items():
            response['object']['attachments'].append({
                'objectType': acl_type,
                'content': acl_value,
                'summary': api_action
            })

    return response
Beispiel #29
0
def activity_for_request_admin(user_id: str, user_name: str, room_id: str,
                               room_name: str, message: str,
                               admin_room_id: str):
    return ActivityBuilder.enrich({
        'actor': {
            'id': user_id,
            'displayName': b64e(user_name),
            'attachments': get_user_info_attachments_for(user_id)
        },
        'verb': 'request',
        'object': {
            'content': message
        },
        'target': {
            'id': admin_room_id,
            'displayName': b64e('Admins')
        },
        'generator': {
            'id': room_id,
            'displayName': b64e(room_name)
        }
    })
Beispiel #30
0
def activity_for_create_room(data: dict, activity: Activity) -> dict:
    response = ActivityBuilder.enrich({
        'actor': {
            'id': activity.actor.id,
            'displayName': b64e(activity.actor.display_name),
            'attachments': get_user_info_attachments_for(activity.actor.id)
        },
        'object': {
            'url': activity.object.url
        },
        'target': {
            'id': activity.target.id,
            'displayName': activity.target.display_name,
            'objectType':
            'temporary'  # all rooms created using the api are temporary
        },
        'verb': 'create'
    })

    if 'object' in data and 'attachments' in data['object']:
        response['object']['attachments'] = data['object']['attachments']

    return response