diff options
-rw-r--r-- | mediagoblin/config_spec.ini | 7 | ||||
-rw-r--r-- | mediagoblin/edit/forms.py | 8 | ||||
-rw-r--r-- | mediagoblin/edit/views.py | 101 | ||||
-rw-r--r-- | mediagoblin/submit/views.py | 5 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/edit/attachments.html | 55 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media.html | 52 | ||||
-rw-r--r-- | mediagoblin/user_pages/routing.py | 5 | ||||
-rw-r--r-- | mediagoblin/user_pages/views.py | 5 |
8 files changed, 201 insertions, 37 deletions
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 6e0d52b4..11badc1f 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -32,6 +32,12 @@ local_templates = string() # itself) celery_setup_elsewhere = boolean(default=False) +# Whether or not users are able to upload files of any filetype with +# their media entries -- This is useful if you want to provide the +# source files for a media file but can also be a HUGE security risk. +allow_attachments = boolean(default=False) + + [storage:publicstore] base_dir = string(default="%(here)s/user_dev/media/public") base_url = string(default="/mgoblin_media/") @@ -39,6 +45,7 @@ base_url = string(default="/mgoblin_media/") [storage:queuestore] base_dir = string(default="%(here)s/user_dev/media/queue") + [celery] # known booleans celery_result_persistent = boolean() diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 2f3ed203..c5ab9fd9 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -40,4 +40,10 @@ class EditProfileForm(wtforms.Form): url = wtforms.TextField( _('Website'), [wtforms.validators.Optional(), - wtforms.validators.URL(message=_('Improperly formed URL'))]) + wtforms.validators.URL(message='Improperly formed URL')]) + +class EditAttachmentsForm(wtforms.Form): + attachment_name = wtforms.TextField( + 'Title') + attachment_file = wtforms.FileField( + 'File') diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 0b1a98f1..b0145a04 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -17,6 +17,10 @@ from webob import exc from string import split +from cgi import FieldStorage +from datetime import datetime + +from werkzeug.utils import secure_filename from mediagoblin import messages from mediagoblin import mg_globals @@ -35,11 +39,18 @@ def edit_media(request, media): if not may_edit_media(request, media): return exc.HTTPForbidden() - form = forms.EditForm(request.POST, - title = media['title'], - slug = media['slug'], - description = media['description'], - tags = media_tags_as_string(media['tags'])) + defaults = dict( + title=media['title'], + slug=media['slug'], + description=media['description'], + tags=media_tags_as_string(media['tags'])) + + if len(media['attachment_files']): + defaults['attachment_name'] = media['attachment_files'][0]['name'] + + form = forms.EditForm( + request.POST, + **defaults) if request.method == 'POST' and form.validate(): # Make sure there isn't already a MediaEntry with such a slug @@ -48,7 +59,7 @@ def edit_media(request, media): {'slug': request.POST['slug'], 'uploader': media['uploader'], '_id': {'$ne': media['_id']}}).count() - + if existing_user_slug_entries: form.slug.errors.append( _(u'An entry with that slug already exists for this user.')) @@ -57,10 +68,18 @@ def edit_media(request, media): media['description'] = request.POST.get('description') media['tags'] = convert_to_tag_list_of_dicts( request.POST.get('tags')) - + media['description_html'] = cleaned_markdown_conversion( media['description']) + if 'attachment_name' in request.POST: + media['attachment_files'][0]['name'] = \ + request.POST['attachment_name'] + + if 'attachment_delete' in request.POST \ + and 'y' == request.POST['attachment_delete']: + del media['attachment_files'][0] + media['slug'] = request.POST['slug'] media.save() @@ -73,18 +92,68 @@ def edit_media(request, media): messages.add_message( request, messages.WARNING, _("You are editing another user's media. Proceed with caution.")) - return render_to_response( request, 'mediagoblin/edit/edit.html', {'media': media, 'form': form}) - + +@get_user_media_entry @require_active_login -def edit_profile(request): +def edit_attachments(request, media): + if mg_globals.app_config['allow_attachments']: + form = forms.EditAttachmentsForm() + + # Add any attachements + if ('attachment_file' in request.POST + and isinstance(request.POST['attachment_file'], FieldStorage) + and request.POST['attachment_file'].file): + + attachment_public_filepath \ + = mg_globals.public_store.get_unique_filepath( + ['media_entries', unicode(media['_id']), 'attachment', + secure_filename(request.POST['attachment_file'].filename)]) + + attachment_public_file = mg_globals.public_store.get_file( + attachment_public_filepath, 'wb') + + try: + attachment_public_file.write( + request.POST['attachment_file'].file.read()) + finally: + request.POST['attachment_file'].file.close() + + media['attachment_files'].append(dict( + name=request.POST['attachment_name'] \ + or request.POST['attachment_file'].filename, + filepath=attachment_public_filepath, + created=datetime.utcnow() + )) + media.save() + + messages.add_message( + request, messages.SUCCESS, + "You added the attachment %s!" \ + % (request.POST['attachment_name'] + or request.POST['attachment_file'].filename)) + + return redirect(request, 'mediagoblin.user_pages.media_home', + user=media.uploader()['username'], + media=media['slug']) + return render_to_response( + request, + 'mediagoblin/edit/attachments.html', + {'media': media, + 'form': form}) + else: + return exc.HTTPForbidden() + + +@require_active_login +def edit_profile(request): # admins may edit any user profile given a username in the querystring edit_username = request.GET.get('username') if request.user['is_admin'] and request.user['username'] != edit_username: @@ -98,8 +167,8 @@ def edit_profile(request): user = request.user form = forms.EditProfileForm(request.POST, - url = user.get('url'), - bio = user.get('bio')) + url=user.get('url'), + bio=user.get('bio')) if request.method == 'POST' and form.validate(): user['url'] = request.POST['url'] @@ -109,12 +178,12 @@ def edit_profile(request): user.save() - messages.add_message(request, - messages.SUCCESS, - 'Profile edited!') + messages.add_message(request, + messages.SUCCESS, + 'Profile edited!') return redirect(request, 'mediagoblin.user_pages.user_home', - user=edit_username) + user=edit_username) return render_to_response( request, diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 1ba17954..4481adeb 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -14,8 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import mediagoblin.mg_globals as mg_globals import uuid - from os.path import splitext from cgi import FieldStorage @@ -127,4 +127,5 @@ def submit_start(request): return render_to_response( request, 'mediagoblin/submit/start.html', - {'submit_form': submit_form}) + {'submit_form': submit_form, + 'app_config': mg_globals.app_config}) diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html new file mode 100644 index 00000000..2f319dbb --- /dev/null +++ b/mediagoblin/templates/mediagoblin/edit/attachments.html @@ -0,0 +1,55 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.edit.attachments', + user= media.uploader().username, + media= media._id) }}" + method="POST" enctype="multipart/form-data"> + <div class="grid_8 prefix_1 suffix_1 edit_box form_box"> + <h1>Editing attachments for {{ media.title }}</h1> + <div style="text-align: center;" > + <img src="{{ request.app.public_store.file_url( + media['media_files']['thumb']) }}" /> + </div> + + {% if media.attachment_files|count %} + <h2>Attachments</h2> + <ul> + {% for attachment in media.attachment_files %} + <li> + <a target="_blank" href="{{ request.app.public_store.file_url( + attachment['filepath']) }}"> + {{ attachment.name -}} + </a><br /> + </li> + {% endfor %} + </ul> + {% endif %} + + <h2>Add attachment</h2> + {{ wtforms_util.render_divs(form) }} + <div class="form_submit_buttons"> + <a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a> + <input type="submit" value="Save changes" class="button" /> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 6747fddc..08d5dbe9 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -116,21 +116,43 @@ <div class="grid_5 omega"> {% include "mediagoblin/utils/prev_next.html" %} - {% if media['uploader'] == request.user['_id'] or - request.user['is_admin'] %} - <h3>Temporary button holder</h3> - <p> - <a href="{{ request.urlgen('mediagoblin.edit.edit_media', - user= media.uploader().username, - media= media._id) }}" - ><img src="{{ request.staticdirect('/images/icon_edit.png') }}" - class="media_icon" />edit</a> - </p> - <p> - <img src="{{ request.staticdirect('/images/icon_delete.png') }}" - class="media_icon" />{% trans %}delete{% endtrans %} - </p> - {% endif %} + + {% if media['uploader'] == request.user['_id'] or + request.user['is_admin'] %} + <h3>Temporary button holder</h3> + <p> + <a href="{{ request.urlgen('mediagoblin.edit.edit_media', + user= media.uploader().username, + media= media._id) }}" + ><img src="{{ request.staticdirect('/images/icon_edit.png') }}" + class="media_icon" />edit</a> + </p> + <p> + <img src="{{ request.staticdirect('/images/icon_delete.png') }}" + class="media_icon" />{% trans %}delete{% endtrans %} + </p> + {% endif %} + + {% if media.attachment_files|count %} + <h3>Attachments</h3> + <ul> + {% for attachment in media.attachment_files %} + <li> + <a href="{{ request.app.public_store.file_url(attachment.filepath) }}"> + {{ attachment.name }} + </a> + </li> + {% endfor %} + </ul> + {% endif %} + + {% if app_config['allow_attachments'] + and (media['uploader'] == request.user['_id'] + or request.user['is_admin']) %} + <a href="{{ request.urlgen('mediagoblin.edit.attachments', + user=media.uploader().username, + media=media._id) }}">Add attachment</a> + {% endif %} {% if media.tags %} {% include "mediagoblin/utils/tags.html" %} diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py index bf9f12ab..65c0fa64 100644 --- a/mediagoblin/user_pages/routing.py +++ b/mediagoblin/user_pages/routing.py @@ -28,7 +28,10 @@ user_routes = [ '/{user}/m/{media}/c/{comment}/', controller="mediagoblin.user_pages.views:media_home"), Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/", - controller="mediagoblin.edit.views:edit_media"), + controller="mediagoblin.edit.views:edit_media"), + Route('mediagoblin.edit.attachments', + '/{user}/m/{media}/attachments/', + controller="mediagoblin.edit.views:edit_attachments"), Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/', controller="mediagoblin.user_pages.views:atom_feed"), Route('mediagoblin.user_pages.media_post_comment', diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 3677c134..2d9bcd21 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -16,7 +16,7 @@ from webob import exc -from mediagoblin import messages +from mediagoblin import messages, mg_globals from mediagoblin.db.util import DESCENDING, ObjectId from mediagoblin.util import ( Pagination, render_to_response, redirect, cleaned_markdown_conversion, @@ -118,7 +118,8 @@ def media_home(request, media, page, **kwargs): {'media': media, 'comments': comments, 'pagination': pagination, - 'comment_form': comment_form}) + 'comment_form': comment_form, + 'app_config': mg_globals.app_config}) @require_active_login |