Пример #1
0
def add_message(conversation, request):
    """
        Adds a message to a conversation

        The request.actor is the one "talking", either if it was the authenticated user,
        the rest username or the post body actor, in this order.
    """

    try:
        mobile = request.decoded_payload['object']['mobile']
    except:
        mobile = False

    message_params = {'actor': request.actor,
                      'verb': 'post',
                      'contexts': [conversation]
                      }

    if 'single' in message_params['contexts'][0]['tags']:
        users = MADMaxCollection(request, 'users', query_key='username')
        for participant in message_params['contexts'][0]['participants']:
            user = users[participant['username']]
            if user.getSubscription(conversation) is None:
                user.addSubscription(conversation)
                conversation['tags'].remove('single')
                conversation.save()
                notifier = RabbitNotifications(request)
                notifier.add_conversation(conversation)


    # Initialize a Message (Activity) object from the request
    newmessage = Message.from_request(request, rest_params=message_params)

    if newmessage['object']['objectType'] == u'image' or \
       newmessage['object']['objectType'] == u'file':
        # Extract the file before saving object
        message_file = newmessage.extract_file_from_activity()
        message_oid = newmessage.insert()
        newmessage['_id'] = ObjectId(message_oid)
        newmessage.process_file(request, message_file)
        newmessage.save()
        if mobile:
            notifier = RabbitNotifications(request)
            notifier.add_conversation_message(conversation, newmessage)
    else:
        message_oid = newmessage.insert()
        newmessage['_id'] = message_oid
        if mobile:
            notifier = RabbitNotifications(request)
            notifier.add_conversation_message(conversation, newmessage)

    handler = JSONResourceEntity(request, newmessage.flatten(), status_code=201)
    return handler.buildResponse()
Пример #2
0
def postMessage2Conversation(conversations, request):
    """
        Add a new conversation
    """
    # We are forced the check and extract the context of the conversation here,
    # We can't initialize the activity first, because it would fail (chiken-egg stuff)
    data = request.decoded_payload
    ctxts = data.get('contexts', [])
    if len(ctxts) == 0:
        raise ValidationError('Empty contexts parameter')

    request_participants = ctxts[0].get('participants', [])
    if len(request_participants) == 0:
        raise ValidationError('Empty participants parameter')
    if len(request_participants) != len(list(set(request_participants))):
        raise ValidationError('One or more users duplicated in participants list')
    if len(request_participants) == 1 and request_participants[0] == request.actor['username']:
        raise ValidationError('Cannot start a conversation with oneself')

    if request.actor['username'] not in request_participants and not request.has_permission(add_conversation_for_others):
        raise ValidationError('Actor must be part of the participants list.')

    # Loop trough all participants, if there's one that doesn't exists, an exception will raise
    # This check is to avoid any conversation creation if there's any invalid participant
    # Also store the definitive list that will be saved in participants field

    participants = {}
    users = MADMaxCollection(request, 'users', query_key='username')
    for participant in request_participants:
        user = users[participant]
        if request.actor['username'] != user['username'] and not request.actor.is_allowed_to_see(user):
            raise Forbidden('User {} is not allowed to have a conversation with {}'.format(request.actor['username'], user['username']))
        participants[participant] = user

    # If there are only two participants in the conversation, try to get an existing conversation
    # Otherwise, assume is a group conversation and create a new one
    current_conversation = None
    if len(request_participants) == 2:
        current_conversation = conversations.first({
            'objectType': 'conversation',
            'participants': {
                '$size': 2},
            'tags': {'$not': {'$in': ['group']}},
            'participants.username': {
                '$all': request_participants}
        })

        if current_conversation and 'single' in current_conversation['tags']:
                for participant in participants:
                    if participants[participant].getSubscription(current_conversation) is None:
                        participants[participant].addSubscription(current_conversation)
                        current_conversation['tags'].remove('single')
                        current_conversation.save()

    if current_conversation is None:
        # Initialize a conversation (context) object from the request, overriding the object using the context
        conversation_params = dict(actor=request.actor,
                                   tags=['group'] if len(participants) > 2 else [],
                                   participants=[participant.flatten(preserve=['displayName', 'objectType', 'username']) for participant in participants.values()],
                                   permissions={'read': 'subscribed',
                                                'write': 'subscribed',
                                                'subscribe': 'restricted',
                                                'unsubscribe': 'subscribed'})
        if ctxts[0].get('displayName', False):
            conversation_params['displayName'] = ctxts[0]['displayName']

        newconversation = Conversation.from_request(request, rest_params=conversation_params)

        # New conversation
        contextid = newconversation.insert()
        newconversation['_id'] = contextid

        # Subscribe everyone,
        for user in newconversation['participants']:
            db_user = participants[user['username']]
            db_user.addSubscription(newconversation)
            # Initialize a Subscription Activity
            rest_params = {'actor': db_user,
                           'verb': 'subscribe',
                           'object': {'objectType': 'conversation',
                                      'id': newconversation['_id'],
                                      'participants': newconversation['participants']},
                           'contexts': []  # Override contexts from request

                           }
            newactivity = Activity.from_request(request, rest_params=rest_params)
            newactivity_oid = newactivity.insert()  # Insert a subscribe activity
            newactivity['_id'] = newactivity_oid

        current_conversation = newconversation

    # We need to reload the actor, in order to have the subscription updated
    # We need to reload reified acl's, so then new actor subscription will be visible by __acl__
    request.actor.reload()
    current_conversation.reload__acl__()

    message_params = {'actor': request.actor,
                      'contexts': [current_conversation],
                      'verb': 'post'}

    try:
        # Initialize a Message (Activity) object from the request
        newmessage = Message.from_request(request, rest_params=message_params)
    except Exception as catched:
        # In case we coulnd't post the message, rollback conversation creation
        current_conversation.delete()
        raise catched

    # Grant subscribe permission to the user creating the conversation, only if the conversation
    # is bigger than 2 people. Conversations that are created with only 2 people from the beggining
    # Will not be able to grow

    if len(current_conversation['participants']) > 2:
        subscription = request.actor.getSubscription(current_conversation)
        request.actor.grantPermission(subscription, 'invite', permanent=False)
        request.actor.grantPermission(subscription, 'kick', permanent=False)
        request.actor.revokePermission(subscription, 'unsubscribe', permanent=False)

    message_oid = newmessage.insert()
    newmessage['_id'] = message_oid

    output_message = newmessage.flatten()
    output_message['contexts'][0]['displayName'] = current_conversation.realDisplayName(request.actor)
    output_message['contexts'][0]['tags'] = current_conversation.get('tags', [])

    # Notification is done here because we don't want to do it right after insertion
    # as a possible rollback would cause a  notification of a inexistent conversation
    notifier = RabbitNotifications(request)
    notifier.add_conversation(current_conversation)

    handler = JSONResourceEntity(request, output_message, status_code=201)
    return handler.buildResponse()