diff options
-rw-r--r-- | mediagoblin/decorators.py | 8 | ||||
-rw-r--r-- | mediagoblin/edit/views.py | 3 | ||||
-rw-r--r-- | mediagoblin/media_types/audio/processing.py | 10 | ||||
-rw-r--r-- | mediagoblin/media_types/video/processing.py | 11 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/edit/edit.html | 2 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/root.html | 7 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/collection_list.html | 56 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media.html | 6 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html | 2 | ||||
-rw-r--r-- | mediagoblin/tests/test_submission.py | 10 | ||||
-rw-r--r-- | mediagoblin/user_pages/routing.py | 10 | ||||
-rw-r--r-- | mediagoblin/user_pages/views.py | 18 |
12 files changed, 117 insertions, 26 deletions
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index 5533e81d..a40f1d5a 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -69,7 +69,7 @@ def user_may_delete_media(controller): """ @wraps(controller) def wrapper(request, *args, **kwargs): - uploader_id = MediaEntry.query.get(request.matchdict['media']).uploader + uploader_id = kwargs['media'].uploader if not (request.user.is_admin or request.user.id == uploader_id): raise Forbidden() @@ -209,12 +209,16 @@ def get_media_entry_by_id(controller): @wraps(controller) def wrapper(request, *args, **kwargs): media = MediaEntry.query.filter_by( - id=request.matchdict['media'], + id=request.matchdict['media_id'], state=u'processed').first() # Still no media? Okay, 404. if not media: return render_404(request) + given_username = request.matchdict.get('user') + if given_username and (given_username != media.get_uploader.username): + return render_404(request) + return controller(request, media=media, *args, **kwargs) return wrapper diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index ece11df5..9b7cab46 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -27,6 +27,7 @@ from mediagoblin.auth import lib as auth_lib from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media from mediagoblin.decorators import (require_active_login, active_user_from_url, + get_media_entry_by_id, get_user_media_entry, user_may_alter_collection, get_user_collection) from mediagoblin.tools.response import render_to_response, redirect from mediagoblin.tools.translate import pass_to_ugettext as _ @@ -37,7 +38,7 @@ from mediagoblin.db.util import check_media_slug_used, check_collection_slug_use import mimetypes -@get_user_media_entry +@get_media_entry_by_id @require_active_login def edit_media(request, media): if not may_edit_media(request, media): diff --git a/mediagoblin/media_types/audio/processing.py b/mediagoblin/media_types/audio/processing.py index aee843d5..c4ccad49 100644 --- a/mediagoblin/media_types/audio/processing.py +++ b/mediagoblin/media_types/audio/processing.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -import tempfile +from tempfile import NamedTemporaryFile import os from mediagoblin import mg_globals as mgg @@ -73,7 +73,7 @@ def process_audio(entry): transcoder = AudioTranscoder() - with tempfile.NamedTemporaryFile() as webm_audio_tmp: + with NamedTemporaryFile(dir=workbench.dir) as webm_audio_tmp: progress_callback = ProgressCallback(entry) transcoder.transcode( @@ -99,7 +99,7 @@ def process_audio(entry): original=os.path.splitext( queued_filepath[-1])[0])) - with tempfile.NamedTemporaryFile(suffix='.ogg') as wav_tmp: + with NamedTemporaryFile(dir=workbench.dir, suffix='.ogg') as wav_tmp: _log.info('Creating OGG source for spectrogram') transcoder.transcode( queued_filename, @@ -109,7 +109,7 @@ def process_audio(entry): thumbnailer = AudioThumbnailer() - with tempfile.NamedTemporaryFile(suffix='.jpg') as spectrogram_tmp: + with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as spectrogram_tmp: thumbnailer.spectrogram( wav_tmp.name, spectrogram_tmp.name, @@ -122,7 +122,7 @@ def process_audio(entry): entry.media_files['spectrogram'] = spectrogram_filepath - with tempfile.NamedTemporaryFile(suffix='.jpg') as thumb_tmp: + with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as thumb_tmp: thumbnailer.thumbnail_spectrogram( spectrogram_tmp.name, thumb_tmp.name, diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py index aa6a25df..703c4681 100644 --- a/mediagoblin/media_types/video/processing.py +++ b/mediagoblin/media_types/video/processing.py @@ -14,7 +14,7 @@ # 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 tempfile +from tempfile import NamedTemporaryFile import logging from mediagoblin import mg_globals as mgg @@ -74,7 +74,7 @@ def process_video(entry): entry, name_builder.fill('{basename}.thumbnail.jpg')) # Create a temporary file for the video destination - tmp_dst = tempfile.NamedTemporaryFile() + tmp_dst = NamedTemporaryFile(dir=workbench.dir) with tmp_dst: # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square @@ -88,6 +88,7 @@ def process_video(entry): # Push transcoded video to public storage _log.debug('Saving medium...') + # TODO (#419, we read everything in RAM here!) mgg.public_store.get_file(medium_filepath, 'wb').write( tmp_dst.read()) _log.debug('Saved medium') @@ -100,7 +101,7 @@ def process_video(entry): height=transcoder.dst_data.videoheight) # Create a temporary file for the video thumbnail - tmp_thumb = tempfile.NamedTemporaryFile(suffix='.jpg') + tmp_thumb = NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') with tmp_thumb: # Create a thumbnail.jpg that fits in a 180x180 square @@ -129,9 +130,13 @@ def process_video(entry): with mgg.public_store.get_file(original_filepath, 'wb') as \ original_file: _log.debug('Saving original...') + # TODO (#419, we read everything in RAM here!) original_file.write(queued_file.read()) _log.debug('Saved original') entry.media_files['original'] = original_filepath mgg.queue_store.delete_file(queued_filepath) + + # clean up workbench + workbench.destroy_self() diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html index 1f5b91f7..9a040095 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit.html +++ b/mediagoblin/templates/mediagoblin/edit/edit.html @@ -29,7 +29,7 @@ <form action="{{ request.urlgen('mediagoblin.edit.edit_media', user= media.get_uploader.username, - media= media.id) }}" + media_id=media.id) }}" method="POST" enctype="multipart/form-data"> <div class="form_box_xl edit_box"> <h1>{% trans media_title=media.title %}Editing {{ media_title }}{% endtrans %}</h1> diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html index 047dd2bb..11e8f2ac 100644 --- a/mediagoblin/templates/mediagoblin/root.html +++ b/mediagoblin/templates/mediagoblin/root.html @@ -27,9 +27,10 @@ <li><a href="{{ request.urlgen('mediagoblin.submit.start') }}"> {%- trans %}Add media{% endtrans -%} </a></li> - <li><a href="{{ request.urlgen('mediagoblin.submit.collection') }}"> - {%- trans %}Create new collection{% endtrans -%} - </a></li> + <li><a href="{{ request.urlgen('mediagoblin.user_pages.collection_list', + user=request.user.username) }}"> + {%- trans %}Browse collections{% endtrans -%} + </a></li> <li><a href="{{ request.urlgen('mediagoblin.edit.account') }}"> {%- trans %}Change account settings{% endtrans -%} </a></li> diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html new file mode 100644 index 00000000..abf22623 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html @@ -0,0 +1,56 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# 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" %} + +{% block title %} + {%- trans username=user.username -%} + {{ username }}'s collections + {%- endtrans %} — {{ super() }} +{% endblock %} + +{% block mediagoblin_content -%} + <h1> + {%- trans username=user.username, + user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=user.username) -%} + <a href="{{ user_url }}">{{ username }}</a>'s collections + {%- endtrans %} + </h1> + + {% if request.user %} + {% if request.user.status == 'active' %} + <p> + <a href="{{ request.urlgen('mediagoblin.submit.collection', + user=user.username) }}"> + {%- trans %}Create new collection{% endtrans -%} + </p> + {% endif %} + {% endif %} + + <ul> + {% for coll in collections %} + {% set coll_url = request.urlgen( + 'mediagoblin.user_pages.user_collection', + user=user.username, + collection=coll.slug) %} + <li><a href="{{ coll_url }}">{{ coll.title }}</li> + {% endfor %} + </ul> + +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 11f2a2a1..10b48296 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -83,11 +83,11 @@ request.user.is_admin) %} {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', user= media.get_uploader.username, - media= media.id) %} + media_id=media.id) %} <a class="button_action" href="{{ edit_url }}">{% trans %}Edit{% endtrans %}</a> {% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', user= media.get_uploader.username, - media= media.id) %} + media_id=media.id) %} <a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a> {% endif %} {% autoescape False %} @@ -104,7 +104,7 @@ {% if request.user %} <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', user= media.get_uploader.username, - media=media.id) }}" method="POST" id="form_comment"> + media_id=media.id) }}" method="POST" id="form_comment"> <p> {% trans %}You can use <a href="http://daringfireball.net/projects/markdown/basics">Markdown</a> for formatting.{% endtrans %} </p> diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html index 833f500d..d2a5655e 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html @@ -23,7 +23,7 @@ <form action="{{ request.urlgen('mediagoblin.user_pages.media_confirm_delete', user=media.get_uploader.username, - media=media.id) }}" + media_id=media.id) }}" method="POST" enctype="multipart/form-data"> <div class="form_box"> <h1> diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index faf4e744..53330c48 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -161,11 +161,17 @@ class TestSubmission: media = self.check_media(request, {'title': u'Balanced Goblin'}, 1) media_id = media.id + # At least render the edit page + edit_url = request.urlgen( + 'mediagoblin.edit.edit_media', + user=self.test_user.username, media_id=media_id) + self.test_app.get(edit_url) + # Add a comment, so we can test for its deletion later. self.check_comments(request, media_id, 0) comment_url = request.urlgen( 'mediagoblin.user_pages.media_post_comment', - user=self.test_user.username, media=media_id) + user=self.test_user.username, media_id=media_id) response = self.do_post({'comment_content': 'i love this test'}, url=comment_url, do_follow=True)[0] self.check_comments(request, media_id, 1) @@ -174,7 +180,7 @@ class TestSubmission: # --------------------------------------------------- delete_url = request.urlgen( 'mediagoblin.user_pages.media_confirm_delete', - user=self.test_user.username, media=media_id) + user=self.test_user.username, media_id=media_id) # Empty data means don't confirm response = self.do_post({}, do_follow=True, url=delete_url)[0] media = self.check_media(request, {'title': u'Balanced Goblin'}, 1) diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py index 63bf5c2a..a9431405 100644 --- a/mediagoblin/user_pages/routing.py +++ b/mediagoblin/user_pages/routing.py @@ -24,12 +24,12 @@ add_route('mediagoblin.user_pages.media_home', 'mediagoblin.user_pages.views:media_home') add_route('mediagoblin.user_pages.media_confirm_delete', - '/u/<string:user>/m/<string:media>/confirm-delete/', + '/u/<string:user>/m/<int:media_id>/confirm-delete/', 'mediagoblin.user_pages.views:media_confirm_delete') # Submission handling of new comments. TODO: only allow for POST methods add_route('mediagoblin.user_pages.media_post_comment', - '/u/<string:user>/m/<string:media>/comment/add/', + '/u/<string:user>/m/<int:media_id>/comment/add/', 'mediagoblin.user_pages.views:media_post_comment') add_route('mediagoblin.user_pages.user_gallery', @@ -48,6 +48,10 @@ add_route('mediagoblin.user_pages.media_collect', '/u/<string:user>/m/<string:media>/collect/', 'mediagoblin.user_pages.views:media_collect') +add_route('mediagoblin.user_pages.collection_list', + '/u/<string:user>/collections/', + 'mediagoblin.user_pages.views:collection_list') + add_route('mediagoblin.user_pages.user_collection', '/u/<string:user>/collection/<string:collection>/', 'mediagoblin.user_pages.views:user_collection') @@ -74,7 +78,7 @@ add_route('mediagoblin.user_pages.processing_panel', # Stray edit routes add_route('mediagoblin.edit.edit_media', - '/u/<string:user>/m/<string:media>/edit/', + '/u/<string:user>/m/<int:media_id>/edit/', 'mediagoblin.edit.views:edit_media') add_route('mediagoblin.edit.attachments', diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 1af04e7f..30c78a38 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -27,6 +27,7 @@ from mediagoblin.user_pages import forms as user_forms from mediagoblin.user_pages.lib import send_comment_email from mediagoblin.decorators import (uses_pagination, get_user_media_entry, + get_media_entry_by_id, require_active_login, user_may_delete_media, user_may_alter_collection, get_user_collection, get_user_collection_item, active_user_from_url) @@ -137,7 +138,7 @@ def media_home(request, media, page, **kwargs): 'app_config': mg_globals.app_config}) -@get_user_media_entry +@get_media_entry_by_id @require_active_login def media_post_comment(request, media): """ @@ -257,7 +258,7 @@ def media_collect(request, media): #TODO: Why does @user_may_delete_media not implicate @require_active_login? -@get_user_media_entry +@get_media_entry_by_id @require_active_login @user_may_delete_media def media_confirm_delete(request, media): @@ -322,6 +323,19 @@ def user_collection(request, page, url_user=None): 'pagination': pagination}) +@active_user_from_url +def collection_list(request, url_user=None): + """A User-defined Collection""" + collections = Collection.query.filter_by( + get_creator=url_user) + + return render_to_response( + request, + 'mediagoblin/user_pages/collection_list.html', + {'user': url_user, + 'collections': collections}) + + @get_user_collection_item @require_active_login @user_may_alter_collection |