Esempio n. 1
0
def addActivityComment(context, request):
    """
    POST /activities/{activity}/comments
    """
    #XXX TODO ara només es tracta la primera activitat,
    # s'ha de iterar si es vol que el comentari sigui de N activitats
    activityid = request.matchdict['activity']

    mmdb = MADMaxDB(context.db)
    refering_activity = mmdb.activity[activityid]

    # Prepare rest parameters to be merged with post data
    rest_params = {'verb': 'comment',
                   'object': {'inReplyTo': [{'_id':ObjectId(activityid),
                                              'objectType':refering_activity.object['objectType']}]}}

    # Initialize a Activity object from the request
    newactivity = Activity()
    newactivity.fromRequest(request, rest_params=rest_params)

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    comment = dict(newactivity.object)
    comment['published'] = newactivity.published
    comment['author'] = request.actor
    comment['id'] = newactivity._id
    del comment['inReplyTo']

    refering_activity.addComment(comment)

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 2
0
File: social.py Progetto: UPCnet/max
def like(activity, request):
    """
        Like activity
    """
    if activity.has_like_from(request.actor):
        code = 200

        activities = MADMaxCollection(request, 'activity')
        query = {'verb': 'like', 'object._id': activity['_id'], 'actor.username': request.actor['username']}
        newactivity = activities.last(query)  # Pick the last one, so we get the last time user liked this activity

    else:
        code = 201
        # Prepare rest parameters to be merged with post data
        rest_params = {
            'verb': 'like',
            'object': {
                '_id': ObjectId(activity['_id']),
                'objectType': activity['objectType'],
            }
        }

        # Initialize a Activity object from the request
        newactivity = Activity.from_request(request, rest_params=rest_params)

        newactivity_oid = newactivity.insert()
        newactivity['_id'] = newactivity_oid

        activity.add_like_from(request.actor)

    newactivity['object']['likes'] = activity['likes']  # Return the current likes of the activity
    newactivity['object']['likesCount'] = activity['likesCount']  # Return the current likes of the activity
    newactivity['object']['liked'] = activity.has_like_from(request.actor)
    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 3
0
def subscribe(context, request):
    """
        Subscribe user to context
    """
    actor = request.actor
    rest_params = {'object': context,
                   'verb': 'subscribe'}

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    # Check if user is already subscribed
    subscribed_contexts_hashes = [a['hash'] for a in actor['subscribedTo']]
    if newactivity['object'].getHash() in subscribed_contexts_hashes:
        # If user already subscribed, send a 200 code and retrieve the original subscribe activity
        # post when user was subscribed. This way in th return data we'll have the date of subscription
        code = 200
        activities = MADMaxCollection(request, 'activity')
        query = {'verb': 'subscribe', 'object.url': newactivity['object']['url'], 'actor.username': actor['username']}
        newactivity = activities.last(query)  # Pick the last one, so we get the last time user subscribed (in cas a unsbuscription occured sometime...)

    else:
        actor.addSubscription(context)

        # If user wasn't created, 201 will show that the subscription has just been added
        code = 201
        newactivity_oid = newactivity.insert()  # Insert a subscribe activity
        newactivity['_id'] = newactivity_oid
    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 4
0
def follow(context, request):
    """
        /people/{username}/follows/{followedUsername}'
    """
    #XXX TODO ara nomes es tracta un sol follow
    # s'ha de iterar si es vol que el comentari sigui de N follows
    rest_params = {
        'actor': request.actor,
        'verb': 'follow',
        'object': {
            'username': request.matchdict['followedUsername'],
            'objectType': 'person'
        }
    }

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    request.actor.addFollower(newactivity['object'])

    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 5
0
def unfavorite(activity, request):
    """
        Unfavorite activity
    """
    # Prepare rest parameters to be merged with post data
    rest_params = {
        'verb': 'unfavorite',
        'object': {
            '_id': ObjectId(activity['_id']),
            'objectType': activity['objectType'],
        }
    }

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    activity.delete_favorite_from(request.actor)

    newactivity['object']['favorites'] = activity['favorites']
    newactivity['object']['favoritesCount'] = activity['favoritesCount']
    newactivity['object']['favorited'] = activity.has_favorite_from(request.actor)
    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=200)
    return handler.buildResponse()
Esempio n. 6
0
def addAdminUserActivity(context, request):
    """
         /admin/people|contexts/{username|urlHash}/activities

         Add activity impersonated as a valid MAX user or context
    """
    rest_params = {'actor': request.actor,
                   'verb': 'post'}

    # Initialize a Activity object from the request
    newactivity = Activity()
    newactivity.fromRequest(request, rest_params=rest_params)

    # If we have the _id setted, then the object already existed in the DB,
    # otherwise, proceed to insert it into the DB
    # In both cases, respond with the JSON of the object and the appropiate
    # HTTP Status Code

    if newactivity.get('_id'):
        # Already Exists
        code = 200
    else:
        # New User
        code = 201
        activity_oid = newactivity.insert()
        newactivity['_id'] = activity_oid

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 7
0
def addContextActivity(context, request):
    """
         Add a context activity

         If an actor is found on the request body it will be taken as the ownership of the activity, either
         the actor being a Person or a Context. If no actor specified on json payload, the current authenticated
         user will be taken as request.actor.
    """
    rest_params = {
        'verb': 'post',
        'contexts': [
            context
        ]
    }
    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    # Search if there's any activity from the same user with
    # the same actor in the last minute

    actor_id_key = 'actor.{}'.format(request.actor.unique)
    actor_id_value = request.actor.get(request.actor.unique)

    query = {
        actor_id_key: actor_id_value,
        'published': {'$gt': newactivity['published'] - timedelta(minutes=1)},
        'contexts.hash': context['hash'],
        'verb': 'post'
    }

    possible_duplicates = request.db.activity.search(query)
    duplicated = False
    for candidate in possible_duplicates:
        if candidate['object']['content'] == newactivity['object'].get('content', ''):
            duplicated = candidate
            break

    if duplicated:
        code = 200
        newactivity = duplicated
    else:
        # New activity
        code = 201
        if newactivity['object']['objectType'] == u'image' or \
           newactivity['object']['objectType'] == u'file':
            # Extract the file before saving object
            activity_file = newactivity.extract_file_from_activity()
            activity_oid = newactivity.insert()
            newactivity['_id'] = ObjectId(activity_oid)
            newactivity.process_file(request, activity_file)
            newactivity.save()
        else:
            activity_oid = newactivity.insert()
            newactivity['_id'] = ObjectId(activity_oid)

    handler = JSONResourceEntity(request, newactivity.flatten(squash=['keywords']), status_code=code)
    return handler.buildResponse()
Esempio n. 8
0
def follow(context, request):
    """
        /people/{username}/follows/{followedDN}'
    """
    #XXX TODO ara nomes es tracta un sol follow
    # s'ha de iterar si es vol que el comentari sigui de N follows
    actor = request.actor
    rest_params = {'actor': request.actor}

    # Initialize a Activity object from the request
    newactivity = Activity(request, rest_params=rest_params)

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    actor.addFollower(newactivity['object'])

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 9
0
def follow(context, request):
    """
        /people/{username}/follows/{followedDN}'
    """
    #XXX TODO ara nomes es tracta un sol follow
    # s'ha de iterar si es vol que el comentari sigui de N follows
    actor = request.actor
    rest_params = {'actor': request.actor}

    # Initialize a Activity object from the request
    newactivity = Activity(request, rest_params=rest_params)

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    actor.addFollower(newactivity['object'])

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 10
0
def addUserActivity(context, request):
    """
         /users/{username}/activities

         Afegeix una activitat
    """
    rest_params = {'actor': request.actor,
                   'verb': 'post'}

    # Initialize a Activity object from the request
    newactivity = Activity()
    newactivity.fromRequest(request, rest_params=rest_params)

    # If we have the _id setted, then the object already existed in the DB,
    # otherwise, proceed to insert it into the DB
    # In both cases, respond with the JSON of the object and the appropiate
    # HTTP Status Code

    if newactivity.get('_id'):
        # Already Exists
        code = 200
    else:
        # New User
        code = 201
        activity_oid = newactivity.insert()
        newactivity['_id'] = activity_oid

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 11
0
def addUserActivity(user, request):
    """
         Add a timeline activity

         Add activity posted as {username}. User in url will be taken as the actor that will own
         the activity. When url {username} and authenticated user don't match, user must have special
         permissions to be able to impersoate the activity.

    """
    rest_params = {'actor': request.actor,
                   'verb': 'post'}

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    # Search if there's any activity from the same user with
    # the same actor and without context
    query = {
        'actor.username': request.actor['username'],
        'published': {'$gt': newactivity['published'] - timedelta(minutes=1)},
        'contexts': {'$exists': False},
        'verb': 'post'
    }

    possible_duplicates = request.db.activity.search(query)
    duplicated = None
    for candidate in possible_duplicates:
        if candidate['object']['content'] == newactivity['object'].get('content', ''):
            duplicated = candidate
            break

    if duplicated:
        code = 200
        newactivity = duplicated
    else:
        # New activity
        code = 201
        if newactivity['object']['objectType'] == u'image' or \
           newactivity['object']['objectType'] == u'file':
            # Extract the file before saving object
            activity_file = newactivity.extract_file_from_activity()
            activity_oid = newactivity.insert()
            newactivity['_id'] = ObjectId(activity_oid)
            newactivity.process_file(request, activity_file)
            newactivity.save()
        else:
            activity_oid = newactivity.insert()
            newactivity['_id'] = activity_oid

    handler = JSONResourceEntity(request, newactivity.flatten(squash=['keywords']), status_code=code)
    return handler.buildResponse()
Esempio n. 12
0
def joinConversation(conversation, request):
    """
        Join conversation
    """
    actor = request.actor
    cid = request.matchdict['id']

    # Check if user is already subscribed
    if conversation.subscription:
        # If user already subscribed, send a 200 code and retrieve the original subscribe activity
        # post when user was subscribed. This way in th return data we'll have the date of subscription
        code = 200
        activities = MADMaxCollection(request, 'activity')
        query = {'verb': 'subscribe', 'object.id': cid, 'actor.username': actor['username']}
        newactivity = activities.last(query)  # Pick the last one, so we get the last time user subscribed (in cas a unsbuscription occured sometime...)

    else:
        if len(conversation['participants']) == CONVERSATION_PARTICIPANTS_LIMIT:
            raise Forbidden('This conversation is full, no more of {} participants allowed'.format(CONVERSATION_PARTICIPANTS_LIMIT))

        if 'group' not in conversation.get('tags', []):
            raise Forbidden('This is not a group conversation, so no one else is allowed'.format(CONVERSATION_PARTICIPANTS_LIMIT))

        if not request.creator.is_allowed_to_see(actor):
            raise Forbidden('User {} is not allowed to have a conversation with {}'.format(request.creator['username'], actor['username']))

        conversation['participants'].append(actor.flatten(preserve=['displayName', 'objectType', 'username']))
        actor.addSubscription(conversation)

        # If we add anyone to a conversation,  we remove the archive tag, no matter how many participants have
        if 'archive' in conversation.get('tags', []):
            conversation['tags'].remove('archive')

        conversation.save()

        # If user wasn't created, 201 will show that the subscription has just been added
        code = 201

        # Initialize a Activity object from the request
        rest_params = {'actor': actor,
                       'verb': 'subscribe',
                       'object': {'objectType': 'conversation',
                                  'id': cid,
                                  'participants': conversation['participants']}
                       }

        newactivity = Activity.from_request(request, rest_params=rest_params)
        newactivity_oid = newactivity.insert()  # Insert a subscribe activity
        newactivity['_id'] = newactivity_oid
    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 13
0
def addActivityComment(activity, request):
    """
        Add a comment to an activity
    """

    # Prepare rest parameters to be merged with post data
    rest_params = {
        'verb': 'comment',
        'object': {
            'inReplyTo': [{
                '_id': activity['_id'],
                'objectType': activity['object']['objectType'],
                'contexts': []
            }]
        }
    }

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    refering_activity_contexts = activity.get('contexts', [])
    if len(refering_activity_contexts) > 0:
        context_hashes = [ctxt['hash'] for ctxt in refering_activity_contexts]
        newactivity['object']['inReplyTo'][0]['contexts'] = context_hashes

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    comment = dict(newactivity['object'])
    comment['published'] = newactivity['published']
    comment['actor'] = request.actor
    comment['id'] = newactivity['_id']
    del comment['inReplyTo']
    activity.addComment(comment)

    handler = JSONResourceEntity(request, newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 14
0
File: social.py Progetto: UPCnet/max
def unlike(activity, request):
    """
        Unlike activity
    """

    # Prepare rest parameters to be merged with post data
    rest_params = {
        'verb': 'unlike',
        'object': {
            '_id': ObjectId(activity['_id']),
            'objectType': activity['objectType'],
        }
    }

    # Initialize a Activity object from the request
    newactivity = Activity.from_request(request, rest_params=rest_params)

    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    activity.delete_like_from(request.actor)

    return HTTPNoContent()
Esempio n. 15
0
def addActivityComment(context, request):
    """
    POST /activities/{activity}/comments
    """
    #XXX TODO ara només es tracta la primera activitat,
    # s'ha de iterar si es vol que el comentari sigui de N activitats
    activityid = request.matchdict['activity']

    mmdb = MADMaxDB(context.db)
    refering_activity = mmdb.activity[activityid]

    # Prepare rest parameters to be merged with post data
    rest_params = {
        'verb': 'comment',
        'object': {
            'inReplyTo': [{
                '_id': ObjectId(activityid),
                'objectType': refering_activity.object['objectType']
            }]
        }
    }

    # Initialize a Activity object from the request
    newactivity = Activity()
    newactivity.fromRequest(request, rest_params=rest_params)

    code = 201
    newactivity_oid = newactivity.insert()
    newactivity['_id'] = newactivity_oid

    comment = dict(newactivity.object)
    comment['published'] = newactivity.published
    comment['author'] = request.actor
    comment['id'] = newactivity._id
    del comment['inReplyTo']

    refering_activity.addComment(comment)

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 16
0
def subscribe(context, request):
    """
        /people/{username}/subscriptions
    """
    # XXX For now only one context can be subscribed at a time
    actor = request.actor
    rest_params = {'actor': actor,
                   'verb': 'subscribe'}

    # Initialize a Activity object from the request
    newactivity = Activity()
    newactivity.fromRequest(request, rest_params=rest_params)

    #Check if user is already subscribed
    subscribed_contexts_hashes = [a['urlHash'] for a in actor.subscribedTo['items']]
    if sha1(newactivity.object['url']).hexdigest() in subscribed_contexts_hashes:
        # If user already subscribed, send a 200 code and retrieve the original subscribe activity
        # post when user was susbcribed. This way in th return data we'll have the date of subscription
        code = 200
        activities = MADMaxCollection(context.db.activity)
        query = {'verb': 'subscribe', 'object.url': newactivity.object['url'], 'actor.username': actor.username}
        newactivity = activities.search(query)[-1]  # Pick the last one, so we get the last time user subscribed (in case a unsbuscription occured sometime...)

    else:
        # If user wasn't created, 201 indicates that the subscription has just been added
        code = 201
        newactivity_oid = newactivity.insert()  # Insert a subscribe activity
        newactivity['_id'] = newactivity_oid

        #Register subscription to the actor
        contexts = MADMaxCollection(context.db.contexts, query_key='urlHash')
        scontext = contexts[sha1(newactivity['object']['url']).hexdigest()]
        actor.addSubscription(scontext)

    handler = JSONResourceEntity(newactivity.flatten(), status_code=code)
    return handler.buildResponse()
Esempio n. 17
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()