Esempio n. 1
0
def media_post_comment(request, media):
    """
    recieves POST from a MediaEntry() comment form, saves the comment.
    """
    if not request.method == 'POST':
        raise MethodNotAllowed()

    comment = request.db.TextComment()
    comment.actor = request.user.id
    comment.content = six.text_type(request.form['comment_content'])

    # Show error message if commenting is disabled.
    if not mg_globals.app_config['allow_comments']:
        messages.add_message(request, messages.ERROR,
                             _("Sorry, comments are disabled."))
    elif not comment.content.strip():
        messages.add_message(request, messages.ERROR,
                             _("Oops, your comment was empty."))
    else:
        create_activity("post", comment, comment.actor, target=media)
        add_comment_subscription(request.user, media)
        comment.save()

        link = request.db.Comment()
        link.target = media
        link.comment = comment
        link.save()

        messages.add_message(request, messages.SUCCESS,
                             _('Your comment has been posted!'))
        trigger_notification(link, media, request)

    return redirect_obj(request, media)
def media_post_comment(request, media):
    """
    recieves POST from a MediaEntry() comment form, saves the comment.
    """
    if not request.method == 'POST':
        raise MethodNotAllowed()

    comment = request.db.MediaComment()
    comment.media_entry = media.id
    comment.author = request.user.id
    comment.content = six.text_type(request.form['comment_content'])

    # Show error message if commenting is disabled.
    if not mg_globals.app_config['allow_comments']:
        messages.add_message(
            request,
            messages.ERROR,
            _("Sorry, comments are disabled."))
    elif not comment.content.strip():
        messages.add_message(
            request,
            messages.ERROR,
            _("Oops, your comment was empty."))
    else:
        create_activity("post", comment, comment.author, target=media)
        add_comment_subscription(request.user, media)
        comment.save()

        messages.add_message(
            request, messages.SUCCESS,
            _('Your comment has been posted!'))
        trigger_notification(comment, media, request)

    return redirect_obj(request, media)
def api_add_to_feed(request, entry):
    """ Add media to Feed """
    feed_url = request.urlgen(
        'mediagoblin.user_pages.atom_feed',
        qualified=True, user=request.user.username
    )

    add_comment_subscription(request.user, entry)

    # Create activity
    create_activity("post", entry, entry.uploader)
    entry.save()
    run_process_media(entry, feed_url)

    return json_response(entry.serialize(request))
Esempio n. 4
0
def api_add_to_feed(request, entry):
    """ Add media to Feed """
    feed_url = request.urlgen('mediagoblin.user_pages.atom_feed',
                              qualified=True,
                              user=request.user.username)

    add_comment_subscription(request.user, entry)

    # Create activity
    activity = create_activity(verb="post",
                               obj=entry,
                               actor=entry.actor,
                               generator=create_generator(request))
    entry.save()
    run_process_media(entry, feed_url)

    return activity
Esempio n. 5
0
def api_add_to_feed(request, entry):
    """ Add media to Feed """
    feed_url = request.urlgen(
        'mediagoblin.user_pages.atom_feed',
        qualified=True, user=request.user.username
    )

    add_comment_subscription(request.user, entry)

    # Create activity
    activity = create_activity(
        verb="post",
        obj=entry,
        actor=entry.uploader,
        generator=create_generator(request)
    )
    entry.save()
    run_process_media(entry, feed_url)

    return activity
Esempio n. 6
0
def submit_start(request):
    """
    First view for submitting a file.
    """
    upload_limit, max_file_size = get_upload_file_limits(request.user)

    submit_form = submit_forms.get_submit_start_form(
        request.form,
        license=request.user.license_preference,
        max_file_size=max_file_size,
        upload_limit=upload_limit,
        uploaded=request.user.uploaded)
    users_collections = Collection.query.filter_by(
        actor=request.user.id,
        type=Collection.USER_DEFINED_TYPE
    ).order_by(Collection.title)

    # Only show the Collections dropdown if the user has some
    # collections set up
    if users_collections.count() > 0:
        submit_form.collection.query = users_collections
    else:
        del submit_form.collection

    if request.method == 'POST' and submit_form.validate():
        if not check_file_field(request, 'file'):
            submit_form.file.errors.append(
                _(u'You must provide a file.'))
        else:
            try:
                media = submit_media(
                    mg_app=request.app, user=request.user,
                    submitted_file=request.files['file'],
                    filename=request.files['file'].filename,
                    title=six.text_type(submit_form.title.data),
                    description=six.text_type(submit_form.description.data),
                    license=six.text_type(submit_form.license.data) or None,
                    tags_string=submit_form.tags.data,
                    upload_limit=upload_limit, max_file_size=max_file_size,
                    urlgen=request.urlgen)

                if submit_form.collection and submit_form.collection.data:
                    add_media_to_collection(
                        submit_form.collection.data, media)
                    create_activity(
                        "add", media, request.user,
                        target=submit_form.collection.data)

                messages.add_message(
                    request,
                    messages.SUCCESS,
                    _('Woohoo! Submitted!'))

                return redirect(request, "mediagoblin.user_pages.user_home",
                            user=request.user.username)


            # Handle upload limit issues
            except FileUploadLimit:
                submit_form.file.errors.append(
                    _(u'Sorry, the file size is too big.'))
            except UserUploadLimit:
                submit_form.file.errors.append(
                    _('Sorry, uploading this file will put you over your'
                      ' upload limit.'))
            except UserPastUploadLimit:
                messages.add_message(
                    request,
                    messages.WARNING,
                    _('Sorry, you have reached your upload limit.'))
                return redirect(request, "mediagoblin.user_pages.user_home",
                                user=request.user.username)
            except FileTypeNotSupported as e:
                submit_form.file.errors.append(e)
            except Exception as e:
                raise

    return render_to_response(
        request,
        'mediagoblin/submit/start.html',
        {'submit_form': submit_form,
         'app_config': mg_globals.app_config})
Esempio n. 7
0
def submit_media(mg_app, user, submitted_file, filename,
                 title=None, description=None,
                 license=None, metadata=None, tags_string=u"",
                 upload_limit=None, max_file_size=None,
                 callback_url=None,
                 # If provided we'll do the feed_url update, otherwise ignore
                 urlgen=None,):
    """
    Args:
     - mg_app: The MediaGoblinApp instantiated for this process
     - user: the user object this media entry should be associated with
     - submitted_file: the file-like object that has the
       being-submitted file data in it (this object should really have
       a .name attribute which is the filename on disk!)
     - filename: the *original* filename of this.  Not necessarily the
       one on disk being referenced by submitted_file.
     - title: title for this media entry
     - description: description for this media entry
     - license: license for this media entry
     - tags_string: comma separated string of tags to be associated
       with this entry
     - upload_limit: size in megabytes that's the per-user upload limit
     - max_file_size: maximum size each file can be that's uploaded
     - callback_url: possible post-hook to call after submission
     - urlgen: if provided, used to do the feed_url update
    """
    if upload_limit and user.uploaded >= upload_limit:
        raise UserPastUploadLimit()

    # If the filename contains non ascii generate a unique name
    if not all(ord(c) < 128 for c in filename):
        filename = six.text_type(uuid.uuid4()) + splitext(filename)[-1]

    # Sniff the submitted media to determine which
    # media plugin should handle processing
    media_type, media_manager = sniff_media(submitted_file, filename)

    # create entry and save in database
    entry = new_upload_entry(user)
    entry.media_type = media_type
    entry.title = (title or six.text_type(splitext(filename)[0]))

    entry.description = description or u""

    entry.license = license or None

    entry.media_metadata = metadata or {}

    # Process the user's folksonomy "tags"
    entry.tags = convert_to_tag_list_of_dicts(tags_string)

    # Generate a slug from the title
    entry.generate_slug()

    queue_file = prepare_queue_task(mg_app, entry, filename)

    with queue_file:
        queue_file.write(submitted_file)

    # Get file size and round to 2 decimal places
    file_size = mg_app.queue_store.get_file_size(
        entry.queued_media_file) / (1024.0 * 1024)
    file_size = float('{0:.2f}'.format(file_size))

    # Check if file size is over the limit
    if max_file_size and file_size >= max_file_size:
        raise FileUploadLimit()

    # Check if user is over upload limit
    if upload_limit and (user.uploaded + file_size) >= upload_limit:
        raise UserUploadLimit()

    user.uploaded = user.uploaded + file_size
    user.save()

    entry.file_size = file_size

    # Save now so we have this data before kicking off processing
    entry.save()

    # Various "submit to stuff" things, callbackurl and this silly urlgen
    # thing
    if callback_url:
        metadata = ProcessingMetaData()
        metadata.media_entry = entry
        metadata.callback_url = callback_url
        metadata.save()

    if urlgen:
        feed_url = urlgen(
            'mediagoblin.user_pages.atom_feed',
            qualified=True, user=user.username)
    else:
        feed_url = None

    add_comment_subscription(user, entry)

    # Create activity
    create_activity("post", entry, entry.uploader)
    entry.save()

    # Pass off to processing
    #
    # (... don't change entry after this point to avoid race
    # conditions with changes to the document via processing code)
    run_process_media(entry, feed_url)

    return entry
Esempio n. 8
0
def submit_media(
    mg_app,
    user,
    submitted_file,
    filename,
    title=None,
    description=None,
    collection_slug=None,
    license=None,
    metadata=None,
    tags_string=u"",
    callback_url=None,
    urlgen=None,
):
    """
    Args:
     - mg_app: The MediaGoblinApp instantiated for this process
     - user: the user object this media entry should be associated with
     - submitted_file: the file-like object that has the
       being-submitted file data in it (this object should really have
       a .name attribute which is the filename on disk!)
     - filename: the *original* filename of this.  Not necessarily the
       one on disk being referenced by submitted_file.
     - title: title for this media entry
     - description: description for this media entry
     - collection_slug: collection for this media entry
     - license: license for this media entry
     - tags_string: comma separated string of tags to be associated
       with this entry
     - callback_url: possible post-hook to call after submission
     - urlgen: if provided, used to do the feed_url update and assign a public
               ID used in the API (very important).
    """
    upload_limit, max_file_size = get_upload_file_limits(user)
    if upload_limit and user.uploaded >= upload_limit:
        raise UserPastUploadLimit()

    # If the filename contains non ascii generate a unique name
    if not all(ord(c) < 128 for c in filename):
        filename = six.text_type(uuid.uuid4()) + splitext(filename)[-1]

    # Sniff the submitted media to determine which
    # media plugin should handle processing
    media_type, media_manager = sniff_media(submitted_file, filename)

    # create entry and save in database
    entry = new_upload_entry(user)
    entry.media_type = media_type
    entry.title = (title or six.text_type(splitext(filename)[0]))

    entry.description = description or u""

    entry.license = license or None

    entry.media_metadata = metadata or {}

    # Process the user's folksonomy "tags"
    entry.tags = convert_to_tag_list_of_dicts(tags_string)

    # Generate a slug from the title
    entry.generate_slug()

    queue_file = prepare_queue_task(mg_app, entry, filename)

    with queue_file:
        queue_file.write(submitted_file)

    # Get file size and round to 2 decimal places
    file_size = mg_app.queue_store.get_file_size(
        entry.queued_media_file) / (1024.0 * 1024)
    file_size = float('{0:.2f}'.format(file_size))

    # Check if file size is over the limit
    if max_file_size and file_size >= max_file_size:
        raise FileUploadLimit()

    # Check if user is over upload limit
    if upload_limit and (user.uploaded + file_size) >= upload_limit:
        raise UserUploadLimit()

    user.uploaded = user.uploaded + file_size
    user.save()

    entry.file_size = file_size

    # Save now so we have this data before kicking off processing
    entry.save()

    # Various "submit to stuff" things, callbackurl and this silly urlgen
    # thing
    if callback_url:
        metadata = ProcessingMetaData()
        metadata.media_entry = entry
        metadata.callback_url = callback_url
        metadata.save()

    if urlgen:
        # Generate the public_id, this is very importent, especially relating
        # to deletion, it allows the shell to be accessable post-delete!
        entry.get_public_id(urlgen)

        # Generate the feed URL
        feed_url = urlgen('mediagoblin.user_pages.atom_feed',
                          qualified=True,
                          user=user.username)
    else:
        feed_url = None

    add_comment_subscription(user, entry)

    # Create activity
    create_activity("post", entry, entry.actor)
    entry.save()

    # add to collection
    if collection_slug:
        collection = Collection.query.filter_by(slug=collection_slug,
                                                actor=user.id).first()
        if collection:
            add_media_to_collection(collection, entry)

    # Pass off to processing
    #
    # (... don't change entry after this point to avoid race
    # conditions with changes to the document via processing code)
    run_process_media(entry, feed_url)

    return entry
def multi_submit_start(request):
    """
  First view for submitting a file.
  """
    submit_form = submit_forms.get_submit_start_form(
        request.form, license=request.user.license_preference)
    users_collections = Collection.query.filter_by(
        actor=request.user.id,
        type=Collection.USER_DEFINED_TYPE).order_by(Collection.title)

    if users_collections.count() > 0:
        submit_form.collection.query = users_collections
    else:
        del submit_form.collection


#  Below is what was used for mediagoblin 0.5.0-dev. Above is the new way.
#  submit_form = submit_forms.SubmitStartForm(request.form, license=request.user.license_preference)
    filecount = 0
    if request.method == 'POST' and submit_form.validate():
        if not check_file_field(request, 'file'):
            submit_form.file.errors.append(
                _(u'You must provide at least one file.'))
        else:
            for submitted_file in request.files.getlist('file'):
                try:
                    if not submitted_file.filename:
                        # MOST likely an invalid file
                        continue  # Skip the rest of the loop for this file
                    else:
                        filename = submitted_file.filename
                        _log.info("html5-multi-upload: Got filename: %s" %
                                  filename)

                        # If the filename contains non ascii generate a unique name
                        if not all(ord(c) < 128 for c in filename):
                            filename = str(
                                uuid.uuid4()) + splitext(filename)[-1]

                        # Sniff the submitted media to determine which
                        # media plugin should handle processing
                        media_type, media_manager = sniff_media(
                            submitted_file, filename)

                        # create entry and save in database
                        entry = new_upload_entry(request.user)
                        entry.media_type = str(media_type)
                        entry.title = (str(submit_form.title.data) or str(
                            splitext(submitted_file.filename)[0]))

                        entry.description = str(submit_form.description.data)

                        entry.license = str(submit_form.license.data) or None

                        # Process the user's folksonomy "tags"
                        entry.tags = convert_to_tag_list_of_dicts(
                            submit_form.tags.data)

                        # Generate a slug from the title
                        entry.generate_slug()

                        queue_file = prepare_queue_task(
                            request.app, entry, filename)

                        with queue_file:
                            queue_file.write(submitted_file.stream.read())

                        # Save now so we have this data before kicking off processing
                        entry.save()

                        # Pass off to async processing
                        #
                        # (... don't change entry after this point to avoid race
                        # conditions with changes to the document via processing code)
                        feed_url = request.urlgen(
                            'mediagoblin.user_pages.atom_feed',
                            qualified=True,
                            user=request.user.username)
                        run_process_media(entry, feed_url)
                        if submit_form.collection and submit_form.collection.data:
                            add_media_to_collection(
                                submit_form.collection.data, entry)
                            create_activity("add",
                                            entry,
                                            request.user,
                                            target=submit_form.collection.data)

                        add_comment_subscription(request.user, entry)
                        filecount = filecount + 1

                except Exception as e:
                    '''
          This section is intended to catch exceptions raised in
          mediagoblin.media_types
          '''
                    if isinstance(e, TypeNotFound) or isinstance(
                            e, FileTypeNotSupported):
                        submit_form.file.errors.append(e)
                    else:
                        raise

            add_message(request, SUCCESS,
                        _('Woohoo! Submitted %d Files!' % filecount))
            return redirect(request,
                            "mediagoblin.user_pages.user_home",
                            user=request.user.username)

    return render_to_response(request, 'start.html',
                              {'multi_submit_form': submit_form})
Esempio n. 10
0
def feed_endpoint(request, outbox=None):
    """ Handles the user's outbox - /api/user/<username>/feed """
    username = request.matchdict["username"]
    requested_user = LocalUser.query.filter(
        LocalUser.username == username).first()

    # check if the user exists
    if requested_user is None:
        return json_error("No such 'user' with id '{0}'".format(username), 404)

    if request.data:
        data = json.loads(request.data.decode())
    else:
        data = {"verb": None, "object": {}}

    if request.method in ["POST", "PUT"]:
        # Validate that the activity is valid
        if "verb" not in data or "object" not in data:
            return json_error("Invalid activity provided.")

        # Check that the verb is valid
        if data["verb"] not in ["post", "update", "delete"]:
            return json_error("Verb not yet implemented", 501)

        # We need to check that the user they're posting to is
        # the person that they are.
        if requested_user.id != request.user.id:
            return json_error("Not able to post to another users feed.",
                              status=403)

        # Handle new posts
        if data["verb"] == "post":
            obj = data.get("object", None)
            if obj is None:
                return json_error("Could not find 'object' element.")

            if obj.get("objectType", None) == "comment":
                # post a comment
                if not request.user.has_privilege(u'commenter'):
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403)

                comment = TextComment(actor=request.user.id)
                comment.unserialize(data["object"], request)
                comment.save()

                # Create activity for comment
                generator = create_generator(request)
                activity = create_activity(verb="post",
                                           actor=request.user,
                                           obj=comment,
                                           target=comment.get_reply_to(),
                                           generator=generator)

                return json_response(activity.serialize(request))

            elif obj.get("objectType", None) == "image":
                # Posting an image to the feed
                media_id = extract_url_arguments(
                    url=data["object"]["id"], urlmap=request.app.url_map)["id"]

                # Build public_id
                public_id = request.urlgen("mediagoblin.api.object",
                                           object_type=obj["objectType"],
                                           id=media_id,
                                           qualified=True)

                media = MediaEntry.query.filter_by(public_id=public_id).first()

                if media is None:
                    return json_response(
                        "No such 'image' with id '{0}'".format(media_id),
                        status=404)

                if media.actor != request.user.id:
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403)

                if not media.unserialize(data["object"]):
                    return json_error(
                        "Invalid 'image' with id '{0}'".format(media_id))

                # Add location if one exists
                if "location" in data:
                    Location.create(data["location"], self)

                media.save()
                activity = api_add_to_feed(request, media)

                return json_response(activity.serialize(request))

            elif obj.get("objectType", None) is None:
                # They need to tell us what type of object they're giving us.
                return json_error("No objectType specified.")
            else:
                # Oh no! We don't know about this type of object (yet)
                object_type = obj.get("objectType", None)
                return json_error(
                    "Unknown object type '{0}'.".format(object_type))

        # Updating existing objects
        if data["verb"] == "update":
            # Check we've got a valid object
            obj = data.get("object", None)

            if obj is None:
                return json_error("Could not find 'object' element.")

            if "objectType" not in obj:
                return json_error("No objectType specified.")

            if "id" not in obj:
                return json_error("Object ID has not been specified.")

            obj_id = extract_url_arguments(url=obj["id"],
                                           urlmap=request.app.url_map)["id"]

            public_id = request.urlgen("mediagoblin.api.object",
                                       object_type=obj["objectType"],
                                       id=obj_id,
                                       qualified=True)

            # Now try and find object
            if obj["objectType"] == "comment":
                if not request.user.has_privilege(u'commenter'):
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403)

                comment = TextComment.query.filter_by(
                    public_id=public_id).first()
                if comment is None:
                    return json_error(
                        "No such 'comment' with id '{0}'.".format(obj_id))

                # Check that the person trying to update the comment is
                # the author of the comment.
                if comment.actor != request.user.id:
                    return json_error(
                        "Only author of comment is able to update comment.",
                        status=403)

                if not comment.unserialize(data["object"], request):
                    return json_error("Invalid 'comment' with id '{0}'".format(
                        obj["id"]))

                comment.save()

                # Create an update activity
                generator = create_generator(request)
                activity = create_activity(verb="update",
                                           actor=request.user,
                                           obj=comment,
                                           generator=generator)

                return json_response(activity.serialize(request))

            elif obj["objectType"] == "image":
                image = MediaEntry.query.filter_by(public_id=public_id).first()
                if image is None:
                    return json_error(
                        "No such 'image' with the id '{0}'.".format(obj["id"]))

                # Check that the person trying to update the comment is
                # the author of the comment.
                if image.actor != request.user.id:
                    return json_error(
                        "Only uploader of image is able to update image.",
                        status=403)

                if not image.unserialize(obj):
                    return json_error(
                        "Invalid 'image' with id '{0}'".format(obj_id))
                image.generate_slug()
                image.save()

                # Create an update activity
                generator = create_generator(request)
                activity = create_activity(verb="update",
                                           actor=request.user,
                                           obj=image,
                                           generator=generator)

                return json_response(activity.serialize(request))
            elif obj["objectType"] == "person":
                # check this is the same user
                if "id" not in obj or obj["id"] != requested_user.id:
                    return json_error("Incorrect user id, unable to update")

                requested_user.unserialize(obj)
                requested_user.save()

                generator = create_generator(request)
                activity = create_activity(verb="update",
                                           actor=request.user,
                                           obj=requested_user,
                                           generator=generator)

                return json_response(activity.serialize(request))

        elif data["verb"] == "delete":
            obj = data.get("object", None)
            if obj is None:
                return json_error("Could not find 'object' element.")

            if "objectType" not in obj:
                return json_error("No objectType specified.")

            if "id" not in obj:
                return json_error("Object ID has not been specified.")

            # Parse out the object ID
            obj_id = extract_url_arguments(url=obj["id"],
                                           urlmap=request.app.url_map)["id"]

            public_id = request.urlgen("mediagoblin.api.object",
                                       object_type=obj["objectType"],
                                       id=obj_id,
                                       qualified=True)

            if obj.get("objectType", None) == "comment":
                # Find the comment asked for
                comment = TextComment.query.filter_by(
                    public_id=public_id, actor=request.user.id).first()

                if comment is None:
                    return json_error(
                        "No such 'comment' with id '{0}'.".format(obj_id))

                # Make a delete activity
                generator = create_generator(request)
                activity = create_activity(verb="delete",
                                           actor=request.user,
                                           obj=comment,
                                           generator=generator)

                # Unfortunately this has to be done while hard deletion exists
                context = activity.serialize(request)

                # now we can delete the comment
                comment.delete()

                return json_response(context)

            if obj.get("objectType", None) == "image":
                # Find the image
                entry = MediaEntry.query.filter_by(
                    public_id=public_id, actor=request.user.id).first()

                if entry is None:
                    return json_error(
                        "No such 'image' with id '{0}'.".format(obj_id))

                # Make the delete activity
                generator = create_generator(request)
                activity = create_activity(verb="delete",
                                           actor=request.user,
                                           obj=entry,
                                           generator=generator)

                # This is because we have hard deletion
                context = activity.serialize(request)

                # Now we can delete the image
                entry.delete()

                return json_response(context)

    elif request.method != "GET":
        return json_error("Unsupported HTTP method {0}".format(request.method),
                          status=501)

    feed = {
        "displayName":
        "Activities by {user}@{host}".format(user=request.user.username,
                                             host=request.host),
        "objectTypes": ["activity"],
        "url":
        request.base_url,
        "links": {
            "self": {
                "href": request.url
            }
        },
        "author":
        request.user.serialize(request),
        "items": [],
    }

    # Create outbox
    if outbox is None:
        outbox = Activity.query.filter_by(actor=requested_user.id)
    else:
        outbox = outbox.filter_by(actor=requested_user.id)

    # We want the newest things at the top (issue: #1055)
    outbox = outbox.order_by(Activity.published.desc())

    # Limit by the "count" (default: 20)
    limit = request.args.get("count", 20)

    try:
        limit = int(limit)
    except ValueError:
        limit = 20

    # The upper most limit should be 200
    limit = limit if limit < 200 else 200

    # apply the limit
    outbox = outbox.limit(limit)

    # Offset (default: no offset - first <count>  result)
    offset = request.args.get("offset", 0)
    try:
        offset = int(offset)
    except ValueError:
        offset = 0
    outbox = outbox.offset(offset)

    # Build feed.
    for activity in outbox:
        try:
            feed["items"].append(activity.serialize(request))
        except AttributeError:
            # This occurs because of how we hard-deletion and the object
            # no longer existing anymore. We want to keep the Activity
            # in case someone wishes to look it up but we shouldn't display
            # it in the feed.
            pass
    feed["totalItems"] = len(feed["items"])

    return json_response(feed)
def media_collect(request, media):
    """Add media to collection submission"""

    form = user_forms.MediaCollectForm(request.form)
    # A user's own collections:
    form.collection.query = Collection.query.filter_by(
        creator = request.user.id).order_by(Collection.title)

    if request.method != 'POST' or not form.validate():
        # No POST submission, or invalid form
        if not form.validate():
            messages.add_message(request, messages.ERROR,
                _('Please check your entries and try again.'))

        return render_to_response(
            request,
            'mediagoblin/user_pages/media_collect.html',
            {'media': media,
             'form': form})

    # If we are here, method=POST and the form is valid, submit things.
    # If the user is adding a new collection, use that:
    if form.collection_title.data:
        # Make sure this user isn't duplicating an existing collection
        existing_collection = Collection.query.filter_by(
                                creator=request.user.id,
                                title=form.collection_title.data).first()
        if existing_collection:
            messages.add_message(request, messages.ERROR,
                _('You already have a collection called "%s"!')
                % existing_collection.title)
            return redirect(request, "mediagoblin.user_pages.media_home",
                            user=media.get_uploader.username,
                            media=media.slug_or_id)

        collection = Collection()
        collection.title = form.collection_title.data
        collection.description = form.collection_description.data
        collection.creator = request.user.id
        collection.generate_slug()
        create_activity("create", collection, collection.creator)
        collection.save()

    # Otherwise, use the collection selected from the drop-down
    else:
        collection = form.collection.data
        if collection and collection.creator != request.user.id:
            collection = None

    # Make sure the user actually selected a collection
    if not collection:
        messages.add_message(
            request, messages.ERROR,
            _('You have to select or add a collection'))
        return redirect(request, "mediagoblin.user_pages.media_collect",
                    user=media.get_uploader.username,
                    media_id=media.id)


    # Check whether media already exists in collection
    elif CollectionItem.query.filter_by(
        media_entry=media.id,
        collection=collection.id).first():
        messages.add_message(request, messages.ERROR,
                             _('"%s" already in collection "%s"')
                             % (media.title, collection.title))
    else: # Add item to collection
        add_media_to_collection(collection, media, form.note.data)
        create_activity("add", media, request.user, target=collection)
        messages.add_message(request, messages.SUCCESS,
                             _('"%s" added to collection "%s"')
                             % (media.title, collection.title))

    return redirect_obj(request, media)
Esempio n. 12
0
def media_collect(request, media):
    """Add media to collection submission"""

    # If media is not processed, return NotFound.
    if not media.state == 'processed':
        return render_404(request)

    form = user_forms.MediaCollectForm(request.form)
    # A user's own collections:
    form.collection.query = Collection.query.filter_by(
        actor=request.user.id,
        type=Collection.USER_DEFINED_TYPE).order_by(Collection.title)

    if request.method != 'POST' or not form.validate():
        # No POST submission, or invalid form
        if not form.validate():
            messages.add_message(request, messages.ERROR,
                                 _('Please check your entries and try again.'))

        return render_to_response(request,
                                  'mediagoblin/user_pages/media_collect.html',
                                  {
                                      'media': media,
                                      'form': form
                                  })

    # If we are here, method=POST and the form is valid, submit things.
    # If the user is adding a new collection, use that:
    if form.collection_title.data:
        # Make sure this user isn't duplicating an existing collection
        existing_collection = Collection.query.filter_by(
            actor=request.user.id,
            title=form.collection_title.data,
            type=Collection.USER_DEFINED_TYPE).first()
        if existing_collection:
            messages.add_message(
                request, messages.ERROR,
                _('You already have a collection called "%s"!') %
                existing_collection.title)
            return redirect(request,
                            "mediagoblin.user_pages.media_home",
                            user=media.get_actor.username,
                            media=media.slug_or_id)

        collection = Collection()
        collection.title = form.collection_title.data
        collection.description = form.collection_description.data
        collection.actor = request.user.id
        collection.type = Collection.USER_DEFINED_TYPE
        collection.generate_slug()
        collection.get_public_id(request.urlgen)
        create_activity("create", collection, collection.actor)
        collection.save()

    # Otherwise, use the collection selected from the drop-down
    else:
        collection = form.collection.data
        if collection and collection.actor != request.user.id:
            collection = None

    # Make sure the user actually selected a collection
    if not collection:
        messages.add_message(request, messages.ERROR,
                             _('You have to select or add a collection'))
        return redirect(request,
                        "mediagoblin.user_pages.media_collect",
                        user=media.get_actor.username,
                        media_id=media.id)

    item = CollectionItem.query.filter_by(collection=collection.id)
    item = item.join(CollectionItem.object_helper).filter_by(
        model_type=media.__tablename__, obj_pk=media.id).first()

    # Check whether media already exists in collection
    if item is not None:
        messages.add_message(
            request, messages.ERROR,
            _('"%s" already in collection "%s"') %
            (media.title, collection.title))
    else:  # Add item to collection
        add_media_to_collection(collection, media, form.note.data)
        create_activity("add", media, request.user, target=collection)
        messages.add_message(
            request, messages.SUCCESS,
            _('"%s" added to collection "%s"') %
            (media.title, collection.title))

    return redirect_obj(request, media)
def multi_submit_start(request):
  """
  First view for submitting a file.
  """
  submit_form = submit_forms.get_submit_start_form(request.form, license=request.user.license_preference)
  users_collections = Collection.query.filter_by(
    actor=request.user.id,
    type=Collection.USER_DEFINED_TYPE
  ).order_by(Collection.title)

  if users_collections.count() > 0:
    submit_form.collection.query = users_collections
  else:
    del submit_form.collection

#  Below is what was used for mediagoblin 0.5.0-dev. Above is the new way.
#  submit_form = submit_forms.SubmitStartForm(request.form, license=request.user.license_preference)
  filecount = 0
  if request.method == 'POST' and submit_form.validate():
    if not check_file_field(request, 'file'):
      submit_form.file.errors.append(_(u'You must provide at least one file.'))
    else:
      for submitted_file in request.files.getlist('file'):
        try:
          if not submitted_file.filename:
            # MOST likely an invalid file
            continue # Skip the rest of the loop for this file
          else:
            filename = submitted_file.filename
            _log.info("html5-multi-upload: Got filename: %s" % filename)

            # If the filename contains non ascii generate a unique name
            if not all(ord(c) < 128 for c in filename):
              filename = unicode(uuid.uuid4()) + splitext(filename)[-1]

            # Sniff the submitted media to determine which
            # media plugin should handle processing
            media_type, media_manager = sniff_media(
              submitted_file, filename)

            # create entry and save in database
            entry = new_upload_entry(request.user)
            entry.media_type = unicode(media_type)
            entry.title = (
              unicode(submit_form.title.data)
              or unicode(splitext(submitted_file.filename)[0]))

            entry.description = unicode(submit_form.description.data)

            entry.license = unicode(submit_form.license.data) or None

            # Process the user's folksonomy "tags"
            entry.tags = convert_to_tag_list_of_dicts(
              submit_form.tags.data)

            # Generate a slug from the title
            entry.generate_slug()

            queue_file = prepare_queue_task(request.app, entry, filename)

            with queue_file:
              queue_file.write(submitted_file.stream.read())

            # Save now so we have this data before kicking off processing
            entry.save()

            # Pass off to async processing
            #
            # (... don't change entry after this point to avoid race
            # conditions with changes to the document via processing code)
            feed_url = request.urlgen(
              'mediagoblin.user_pages.atom_feed',
              qualified=True, user=request.user.username)
            run_process_media(entry, feed_url)
            if submit_form.collection and submit_form.collection.data:
              add_media_to_collection(
                submit_form.collection.data, entry)
              create_activity(
                "add", entry, request.user,
                target=submit_form.collection.data)

            add_comment_subscription(request.user, entry)
            filecount = filecount + 1

        except Exception as e:
          '''
          This section is intended to catch exceptions raised in
          mediagoblin.media_types
          '''
          if isinstance(e, TypeNotFound) or isinstance(e, FileTypeNotSupported):
            submit_form.file.errors.append(e)
          else:
            raise

      add_message(request, SUCCESS, _('Woohoo! Submitted %d Files!' % filecount))
      return redirect(request, "mediagoblin.user_pages.user_home",
              user=request.user.username)

  return render_to_response(
    request,
    'start.html',
    {'multi_submit_form': submit_form})
Esempio n. 14
0
def feed_endpoint(request, outbox=None):
    """ Handles the user's outbox - /api/user/<username>/feed """
    username = request.matchdict["username"]
    requested_user = LocalUser.query.filter(LocalUser.username==username).first()

    # check if the user exists
    if requested_user is None:
        return json_error("No such 'user' with id '{0}'".format(username), 404)

    if request.data:
        data = json.loads(request.data.decode())
    else:
        data = {"verb": None, "object": {}}


    if request.method in ["POST", "PUT"]:
        # Validate that the activity is valid
        if "verb" not in data or "object" not in data:
            return json_error("Invalid activity provided.")

        # Check that the verb is valid
        if data["verb"] not in ["post", "update", "delete"]:
            return json_error("Verb not yet implemented", 501)

        # We need to check that the user they're posting to is
        # the person that they are.
        if requested_user.id != request.user.id:
            return json_error(
                "Not able to post to another users feed.",
                status=403
            )

        # Handle new posts
        if data["verb"] == "post":
            obj = data.get("object", None)
            if obj is None:
                return json_error("Could not find 'object' element.")

            if obj.get("objectType", None) == "comment":
                # post a comment
                if not request.user.has_privilege(u'commenter'):
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403
                    )

                comment = TextComment(actor=request.user.id)
                comment.unserialize(data["object"], request)
                comment.save()

                # Create activity for comment
                generator = create_generator(request)
                activity = create_activity(
                    verb="post",
                    actor=request.user,
                    obj=comment,
                    target=comment.get_reply_to(),
                    generator=generator
                )

                return json_response(activity.serialize(request))

            elif obj.get("objectType", None) == "image":
                # Posting an image to the feed
                media_id = extract_url_arguments(
                    url=data["object"]["id"],
                    urlmap=request.app.url_map
                )["id"]

                # Build public_id
                public_id = request.urlgen(
                    "mediagoblin.api.object",
                    object_type=obj["objectType"],
                    id=media_id,
                    qualified=True
                )

                media = MediaEntry.query.filter_by(
                    public_id=public_id
                ).first()

                if media is None:
                    return json_response(
                        "No such 'image' with id '{0}'".format(media_id),
                        status=404
                    )

                if media.actor != request.user.id:
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403
                    )


                if not media.unserialize(data["object"]):
                    return json_error(
                        "Invalid 'image' with id '{0}'".format(media_id)
                    )


                # Add location if one exists
                if "location" in data:
                    Location.create(data["location"], self)

                media.save()
                activity = api_add_to_feed(request, media)

                return json_response(activity.serialize(request))

            elif obj.get("objectType", None) is None:
                # They need to tell us what type of object they're giving us.
                return json_error("No objectType specified.")
            else:
                # Oh no! We don't know about this type of object (yet)
                object_type = obj.get("objectType", None)
                return json_error(
                    "Unknown object type '{0}'.".format(object_type)
                )

        # Updating existing objects
        if data["verb"] == "update":
            # Check we've got a valid object
            obj = data.get("object", None)

            if obj is None:
                return json_error("Could not find 'object' element.")

            if "objectType" not in obj:
                return json_error("No objectType specified.")

            if "id" not in obj:
                return json_error("Object ID has not been specified.")

            obj_id = extract_url_arguments(
                url=obj["id"],
                urlmap=request.app.url_map
            )["id"]

            public_id = request.urlgen(
                "mediagoblin.api.object",
                object_type=obj["objectType"],
                id=obj_id,
                qualified=True
            )

            # Now try and find object
            if obj["objectType"] == "comment":
                if not request.user.has_privilege(u'commenter'):
                    return json_error(
                        "Privilege 'commenter' required to comment.",
                        status=403
                    )

                comment = TextComment.query.filter_by(
                    public_id=public_id
                ).first()
                if comment is None:
                    return json_error(
                        "No such 'comment' with id '{0}'.".format(obj_id)
                    )

                # Check that the person trying to update the comment is
                # the author of the comment.
                if comment.actor != request.user.id:
                    return json_error(
                        "Only author of comment is able to update comment.",
                        status=403
                    )

                if not comment.unserialize(data["object"], request):
                    return json_error(
                        "Invalid 'comment' with id '{0}'".format(obj["id"])
                    )

                comment.save()

                # Create an update activity
                generator = create_generator(request)
                activity = create_activity(
                    verb="update",
                    actor=request.user,
                    obj=comment,
                    generator=generator
                )

                return json_response(activity.serialize(request))

            elif obj["objectType"] == "image":
                image = MediaEntry.query.filter_by(
                    public_id=public_id
                ).first()
                if image is None:
                    return json_error(
                        "No such 'image' with the id '{0}'.".format(obj["id"])
                    )

                # Check that the person trying to update the comment is
                # the author of the comment.
                if image.actor != request.user.id:
                    return json_error(
                        "Only uploader of image is able to update image.",
                        status=403
                    )

                if not image.unserialize(obj):
                    return json_error(
                        "Invalid 'image' with id '{0}'".format(obj_id)
                    )
                image.generate_slug()
                image.save()

                # Create an update activity
                generator = create_generator(request)
                activity = create_activity(
                    verb="update",
                    actor=request.user,
                    obj=image,
                    generator=generator
                )

                return json_response(activity.serialize(request))
            elif obj["objectType"] == "person":
                # check this is the same user
                if "id" not in obj or obj["id"] != requested_user.id:
                    return json_error(
                        "Incorrect user id, unable to update"
                    )

                requested_user.unserialize(obj)
                requested_user.save()

                generator = create_generator(request)
                activity = create_activity(
                    verb="update",
                    actor=request.user,
                    obj=requested_user,
                    generator=generator
                )

                return json_response(activity.serialize(request))

        elif data["verb"] == "delete":
            obj = data.get("object", None)
            if obj is None:
                return json_error("Could not find 'object' element.")

            if "objectType" not in obj:
                return json_error("No objectType specified.")

            if "id" not in obj:
                return json_error("Object ID has not been specified.")

            # Parse out the object ID
            obj_id = extract_url_arguments(
                url=obj["id"],
                urlmap=request.app.url_map
            )["id"]

            public_id = request.urlgen(
                "mediagoblin.api.object",
                object_type=obj["objectType"],
                id=obj_id,
                qualified=True
            )

            if obj.get("objectType", None) == "comment":
                # Find the comment asked for
                comment = TextComment.query.filter_by(
                    public_id=public_id,
                    actor=request.user.id
                ).first()

                if comment is None:
                    return json_error(
                        "No such 'comment' with id '{0}'.".format(obj_id)
                    )

                # Make a delete activity
                generator = create_generator(request)
                activity = create_activity(
                    verb="delete",
                    actor=request.user,
                    obj=comment,
                    generator=generator
                )

                # Unfortunately this has to be done while hard deletion exists
                context = activity.serialize(request)

                # now we can delete the comment
                comment.delete()

                return json_response(context)

            if obj.get("objectType", None) == "image":
                # Find the image
                entry = MediaEntry.query.filter_by(
                    public_id=public_id,
                    actor=request.user.id
                ).first()

                if entry is None:
                    return json_error(
                        "No such 'image' with id '{0}'.".format(obj_id)
                    )

                # Make the delete activity
                generator = create_generator(request)
                activity = create_activity(
                    verb="delete",
                    actor=request.user,
                    obj=entry,
                    generator=generator
                )

                # This is because we have hard deletion
                context = activity.serialize(request)

                # Now we can delete the image
                entry.delete()

                return json_response(context)

    elif request.method != "GET":
        return json_error(
            "Unsupported HTTP method {0}".format(request.method),
            status=501
        )

    feed = {
        "displayName": "Activities by {user}@{host}".format(
            user=request.user.username,
            host=request.host
        ),
        "objectTypes": ["activity"],
        "url": request.base_url,
        "links": {"self": {"href": request.url}},
        "author": request.user.serialize(request),
        "items": [],
    }

    # Create outbox
    if outbox is None:
        outbox = Activity.query.filter_by(actor=request.user.id)
    else:
        outbox = outbox.filter_by(actor=request.user.id)

    # We want the newest things at the top (issue: #1055)
    outbox = outbox.order_by(Activity.published.desc())

    # Limit by the "count" (default: 20)
    limit = request.args.get("count", 20)

    try:
        limit = int(limit)
    except ValueError:
        limit = 20

    # The upper most limit should be 200
    limit = limit if limit < 200 else 200

    # apply the limit
    outbox = outbox.limit(limit)

    # Offset (default: no offset - first <count>  result)
    outbox = outbox.offset(request.args.get("offset", 0))

    # Build feed.
    for activity in outbox:
        try:
            feed["items"].append(activity.serialize(request))
        except AttributeError:
            # This occurs because of how we hard-deletion and the object
            # no longer existing anymore. We want to keep the Activity
            # in case someone wishes to look it up but we shouldn't display
            # it in the feed.
            pass
    feed["totalItems"] = len(feed["items"])

    return json_response(feed)
Esempio n. 15
0
def submit_start(request):
    """
    First view for submitting a file.
    """
    upload_limit, max_file_size = get_upload_file_limits(request.user)

    submit_form = submit_forms.get_submit_start_form(
        request.form,
        license=request.user.license_preference,
        max_file_size=max_file_size,
        upload_limit=upload_limit,
        uploaded=request.user.uploaded)
    users_collections = Collection.query.filter_by(
        actor=request.user.id,
        type=Collection.USER_DEFINED_TYPE
    ).order_by(Collection.title)

    # Only show the Collections dropdown if the user has some
    # collections set up
    if users_collections.count() > 0:
        submit_form.collection.query = users_collections
    else:
        del submit_form.collection

    if request.method == 'POST' and submit_form.validate():
        if not check_file_field(request, 'file'):
            submit_form.file.errors.append(
                _('You must provide a file.'))
        else:
            try:
                media = submit_media(
                    mg_app=request.app, user=request.user,
                    submitted_file=request.files['file'],
                    filename=request.files['file'].filename,
                    title=str(submit_form.title.data),
                    description=str(submit_form.description.data),
                    license=str(submit_form.license.data) or None,
                    tags_string=submit_form.tags.data,
                    urlgen=request.urlgen)

                if submit_form.collection and submit_form.collection.data:
                    add_media_to_collection(
                        submit_form.collection.data, media)
                    create_activity(
                        "add", media, request.user,
                        target=submit_form.collection.data)

                messages.add_message(
                    request,
                    messages.SUCCESS,
                    _('Woohoo! Submitted!'))

                return redirect(request, "mediagoblin.user_pages.user_home",
                            user=request.user.username)


            # Handle upload limit issues
            except FileUploadLimit:
                submit_form.file.errors.append(
                    _('Sorry, the file size is too big.'))
            except UserUploadLimit:
                submit_form.file.errors.append(
                    _('Sorry, uploading this file will put you over your'
                      ' upload limit.'))
            except UserPastUploadLimit:
                messages.add_message(
                    request,
                    messages.WARNING,
                    _('Sorry, you have reached your upload limit.'))
                return redirect(request, "mediagoblin.user_pages.user_home",
                                user=request.user.username)
            except FileTypeNotSupported as e:
                submit_form.file.errors.append(e)
            except Exception as e:
                raise

    return render_to_response(
        request,
        'mediagoblin/submit/start.html',
        {'submit_form': submit_form,
         'app_config': mg_globals.app_config})