diff options
Diffstat (limited to 'mediagoblin')
23 files changed, 316 insertions, 95 deletions
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index b7c6f29a..6c00aa58 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -34,6 +34,9 @@ allow_registration = boolean(default=True) # tag parsing tags_max_length = integer(default=255) +# Enable/disable comments +allow_comments = boolean(default=True) + # Whether comments are ascending or descending comments_ascending = boolean(default=True) diff --git a/mediagoblin/init/config.py b/mediagoblin/init/config.py index ac4ab9bf..11a91cff 100644 --- a/mediagoblin/init/config.py +++ b/mediagoblin/init/config.py @@ -14,6 +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 logging import os import pkg_resources @@ -21,6 +22,9 @@ from configobj import ConfigObj, flatten_errors from validate import Validator +_log = logging.getLogger(__name__) + + CONFIG_SPEC_PATH = pkg_resources.resource_filename( 'mediagoblin', 'config_spec.ini') @@ -42,6 +46,9 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): Also provides %(__file__)s and %(here)s values of this file and its directory respectively similar to paste deploy. + Also reads for [plugins] section, appends all config_spec.ini + files from said plugins into the general config_spec specification. + This function doesn't itself raise any exceptions if validation fails, you'll have to do something @@ -57,10 +64,45 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): """ config_path = os.path.abspath(config_path) + # PRE-READ of config file. This allows us to fetch the plugins so + # we can add their plugin specs to the general config_spec. + config = ConfigObj( + config_path, + interpolation='ConfigParser') + + plugins = config.get("plugins", {}).keys() + plugin_configs = {} + + for plugin in plugins: + try: + plugin_config_spec_path = pkg_resources.resource_filename( + plugin, "config_spec.ini") + if not os.path.exists(plugin_config_spec_path): + continue + + plugin_config_spec = ConfigObj( + plugin_config_spec_path, + encoding='UTF8', list_values=False, _inspec=True) + _setup_defaults(plugin_config_spec, config_path) + + if not "plugin_spec" in plugin_config_spec: + continue + + plugin_configs[plugin] = plugin_config_spec["plugin_spec"] + + except ImportError: + _log.warning( + "When setting up config section, could not import '%s'" % + plugin) + + # Now load the main config spec config_spec = ConfigObj( config_spec, encoding='UTF8', list_values=False, _inspec=True) + # append the plugin specific sections of the config spec + config_spec['plugins'] = plugin_configs + _setup_defaults(config_spec, config_path) config = ConfigObj( diff --git a/mediagoblin/media_types/ascii/__init__.py b/mediagoblin/media_types/ascii/__init__.py index 856d1d7b..0931e83a 100644 --- a/mediagoblin/media_types/ascii/__init__.py +++ b/mediagoblin/media_types/ascii/__init__.py @@ -14,16 +14,18 @@ # 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/>. +from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.ascii.processing import process_ascii, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "ASCII", - "processor": process_ascii, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/ascii.html", - "default_thumb": "images/media_thumbs/ascii.jpg", - "accepted_extensions": [ - "txt", "asc", "nfo"]} +class ASCIIMediaManager(MediaManagerBase): + human_readable = "ASCII" + processor = staticmethod(process_ascii) + sniff_handler = staticmethod(sniff_handler) + display_template = "mediagoblin/media_displays/ascii.html" + default_thumb = "images/media_thumbs/ascii.jpg" + accepted_extensions = ["txt", "asc", "nfo"] + + +MEDIA_MANAGER = ASCIIMediaManager diff --git a/mediagoblin/media_types/audio/__init__.py b/mediagoblin/media_types/audio/__init__.py index 4f3ead60..2eb7300e 100644 --- a/mediagoblin/media_types/audio/__init__.py +++ b/mediagoblin/media_types/audio/__init__.py @@ -14,12 +14,17 @@ # 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/>. +from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.audio.processing import process_audio, \ sniff_handler -MEDIA_MANAGER = { - 'human_readable': 'Audio', - 'processor': process_audio, - 'sniff_handler': sniff_handler, - 'display_template': 'mediagoblin/media_displays/audio.html', - 'accepted_extensions': ['mp3', 'flac', 'wav', 'm4a']} + +class AudioMediaManager(MediaManagerBase): + human_readable = "Audio" + processor = staticmethod(process_audio) + sniff_handler = staticmethod(sniff_handler) + display_template = "mediagoblin/media_displays/audio.html" + accepted_extensions = ["mp3", "flac", "wav", "m4a"] + + +MEDIA_MANAGER = AudioMediaManager diff --git a/mediagoblin/media_types/pdf/__init__.py b/mediagoblin/media_types/pdf/__init__.py index a6d23c93..f0ba7867 100644 --- a/mediagoblin/media_types/pdf/__init__.py +++ b/mediagoblin/media_types/pdf/__init__.py @@ -14,16 +14,18 @@ # 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/>. +from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.pdf.processing import process_pdf, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "PDF", - "processor": process_pdf, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/pdf.html", - "default_thumb": "images/media_thumbs/pdf.jpg", - "accepted_extensions": [ - "pdf"]} +class PDFMediaManager(MediaManagerBase): + human_readable = "PDF" + processor = staticmethod(process_pdf) + sniff_handler = staticmethod(sniff_handler) + display_template = "mediagoblin/media_displays/pdf.html" + default_thumb = "images/media_thumbs/pdf.jpg" + accepted_extensions = ["pdf"] + + +MEDIA_MANAGER = PDFMediaManager diff --git a/mediagoblin/media_types/stl/__init__.py b/mediagoblin/media_types/stl/__init__.py index edffc633..6ae8a8b9 100644 --- a/mediagoblin/media_types/stl/__init__.py +++ b/mediagoblin/media_types/stl/__init__.py @@ -14,14 +14,18 @@ # 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/>. +from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.stl.processing import process_stl, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "stereo lithographics", - "processor": process_stl, - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/stl.html", - "default_thumb": "images/media_thumbs/video.jpg", - "accepted_extensions": ["obj", "stl"]} +class STLMediaManager(MediaManagerBase): + human_readable = "stereo lithographics" + processor = staticmethod(process_stl) + sniff_handler = staticmethod(sniff_handler) + display_template = "mediagoblin/media_displays/stl.html" + default_thumb = "images/media_thumbs/video.jpg" + accepted_extensions = ["obj", "stl"] + + +MEDIA_MANAGER = STLMediaManager diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py index fab601f6..569cf11a 100644 --- a/mediagoblin/media_types/video/__init__.py +++ b/mediagoblin/media_types/video/__init__.py @@ -14,21 +14,23 @@ # 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/>. +from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.video.processing import process_video, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "Video", - "processor": process_video, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/video.html", - "default_thumb": "images/media_thumbs/video.jpg", - "accepted_extensions": [ - "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"], - +class VideoMediaManager(MediaManagerBase): + human_readable = "Video" + processor = staticmethod(process_video) + sniff_handler = staticmethod(sniff_handler) + display_template = "mediagoblin/media_displays/video.html" + default_thumb = "images/media_thumbs/video.jpg" + accepted_extensions = [ + "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"] + # Used by the media_entry.get_display_media method - "media_fetch_order": [u'webm_640', u'original'], - "default_webm_type": 'video/webm; codecs="vp8, vorbis"', -} + media_fetch_order = [u'webm_640', u'original'] + default_webm_type = 'video/webm; codecs="vp8, vorbis"' + + +MEDIA_MANAGER = VideoMediaManager diff --git a/mediagoblin/media_types/video/models.py b/mediagoblin/media_types/video/models.py index f696a892..0b52c53f 100644 --- a/mediagoblin/media_types/video/models.py +++ b/mediagoblin/media_types/video/models.py @@ -90,7 +90,7 @@ class VideoData(Base): return '%s; codecs="%s, %s"' % ( mimetype, video_codec, audio_codec) else: - return video.MEDIA_MANAGER["default_webm_type"] + return video.VideoMediaManager.default_webm_type DATA_MODEL = VideoData diff --git a/mediagoblin/plugins/api/__init__.py b/mediagoblin/plugins/api/__init__.py index d3fdf2ef..1eddd9e0 100644 --- a/mediagoblin/plugins/api/__init__.py +++ b/mediagoblin/plugins/api/__init__.py @@ -23,11 +23,11 @@ _log = logging.getLogger(__name__) PLUGIN_DIR = os.path.dirname(__file__) -config = pluginapi.get_config(__name__) - def setup_plugin(): _log.info('Setting up API...') + config = pluginapi.get_config(__name__) + _log.debug('API config: {0}'.format(config)) routes = [ diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py index 081b590e..99b6a4b0 100644 --- a/mediagoblin/plugins/httpapiauth/__init__.py +++ b/mediagoblin/plugins/httpapiauth/__init__.py @@ -15,9 +15,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -import base64 -from werkzeug.exceptions import BadRequest, Unauthorized +from werkzeug.exceptions import Unauthorized from mediagoblin.plugins.api.tools import Auth diff --git a/mediagoblin/plugins/piwigo/__init__.py b/mediagoblin/plugins/piwigo/__init__.py index 73326e9e..c4da708a 100644 --- a/mediagoblin/plugins/piwigo/__init__.py +++ b/mediagoblin/plugins/piwigo/__init__.py @@ -17,6 +17,8 @@ import logging from mediagoblin.tools import pluginapi +from mediagoblin.tools.session import SessionManager +from .tools import PWGSession _log = logging.getLogger(__name__) @@ -32,6 +34,9 @@ def setup_plugin(): pluginapi.register_routes(routes) + PWGSession.session_manager = SessionManager("pwg_id", "plugins.piwigo") + + hooks = { 'setup': setup_plugin } diff --git a/mediagoblin/plugins/piwigo/forms.py b/mediagoblin/plugins/piwigo/forms.py index 5bb12e62..18cbd5c5 100644 --- a/mediagoblin/plugins/piwigo/forms.py +++ b/mediagoblin/plugins/piwigo/forms.py @@ -26,3 +26,19 @@ class AddSimpleForm(wtforms.Form): # tags = wtforms.FieldList(wtforms.TextField()) category = wtforms.IntegerField() level = wtforms.IntegerField() + + +_md5_validator = wtforms.validators.Regexp(r"^[0-9a-fA-F]{32}$") + + +class AddForm(wtforms.Form): + original_sum = wtforms.TextField(None, + [_md5_validator, + wtforms.validators.Required()]) + thumbnail_sum = wtforms.TextField(None, + [wtforms.validators.Optional(False), + _md5_validator]) + file_sum = wtforms.TextField(None, [_md5_validator]) + name = wtforms.TextField() + date_creation = wtforms.TextField() + categories = wtforms.TextField() diff --git a/mediagoblin/plugins/piwigo/tools.py b/mediagoblin/plugins/piwigo/tools.py index 4d2e985a..400be615 100644 --- a/mediagoblin/plugins/piwigo/tools.py +++ b/mediagoblin/plugins/piwigo/tools.py @@ -18,8 +18,9 @@ import logging import six import lxml.etree as ET -from werkzeug.exceptions import MethodNotAllowed +from werkzeug.exceptions import MethodNotAllowed, BadRequest +from mediagoblin.tools.request import setup_user_in_request from mediagoblin.tools.response import Response @@ -106,3 +107,46 @@ class CmdTable(object): _log.warn("Method %s only allowed for POST", cmd_name) raise MethodNotAllowed() return func + + +def check_form(form): + if not form.validate(): + _log.error("form validation failed for form %r", form) + for f in form: + if len(f.error): + _log.error("Errors for %s: %r", f.name, f.errors) + raise BadRequest() + dump = [] + for f in form: + dump.append("%s=%r" % (f.name, f.data)) + _log.debug("form: %s", " ".join(dump)) + + +class PWGSession(object): + session_manager = None + + def __init__(self, request): + self.request = request + self.in_pwg_session = False + + def __enter__(self): + # Backup old state + self.old_session = self.request.session + self.old_user = self.request.user + # Load piwigo session into state + self.request.session = self.session_manager.load_session_from_cookie( + self.request) + setup_user_in_request(self.request) + self.in_pwg_session = True + return self + + def __exit__(self, *args): + # Restore state + self.request.session = self.old_session + self.request.user = self.old_user + self.in_pwg_session = False + + def save_to_cookie(self, response): + assert self.in_pwg_session + self.session_manager.save_session_to_cookie(self.request.session, + self.request, response) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index bd3f9320..b59247ad 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -20,11 +20,12 @@ import re from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented from werkzeug.wrappers import BaseResponse -from mediagoblin import mg_globals from mediagoblin.meddleware.csrf import csrf_exempt from mediagoblin.submit.lib import check_file_field -from .tools import CmdTable, PwgNamedArray, response_xml -from .forms import AddSimpleForm +from mediagoblin.auth.lib import fake_login_attempt +from .tools import CmdTable, PwgNamedArray, response_xml, check_form, \ + PWGSession +from .forms import AddSimpleForm, AddForm _log = logging.getLogger(__name__) @@ -34,13 +35,25 @@ _log = logging.getLogger(__name__) def pwg_login(request): username = request.form.get("username") password = request.form.get("password") - _log.info("Login for %r/%r...", username, password) + _log.debug("Login for %r/%r...", username, password) + user = request.db.User.query.filter_by(username=username).first() + if not user: + _log.info("User %r not found", username) + fake_login_attempt() + return False + if not user.check_login(password): + _log.warn("Wrong password for %r", username) + return False + _log.info("Logging %r in", username) + request.session["user_id"] = user.id + request.session.save() return True @CmdTable("pwg.session.logout") def pwg_logout(request): _log.info("Logout") + request.session.delete() return True @@ -51,7 +64,11 @@ def pwg_getversion(request): @CmdTable("pwg.session.getStatus") def pwg_session_getStatus(request): - return {'username': "fake_user"} + if request.user: + username = request.user.username + else: + username = "guest" + return {'username': username} @CmdTable("pwg.categories.getList") @@ -133,17 +150,13 @@ def pwg_images_addChunk(request): return True -def possibly_add_cookie(request, response): - # TODO: We should only add a *real* cookie, if - # authenticated. And if there is no cookie already. - if True: - response.set_cookie( - 'pwg_id', - "some_fake_for_now", - path=request.environ['SCRIPT_NAME'], - domain=mg_globals.app_config.get('csrf_cookie_domain'), - secure=(request.scheme.lower() == 'https'), - httponly=True) +@CmdTable("pwg.images.add", True) +def pwg_images_add(request): + _log.info("add: %r", request.form) + form = AddForm(request.form) + check_form(form) + + return {'image_id': 123456, 'url': ''} @csrf_exempt @@ -158,13 +171,13 @@ def ws_php(request): request.args, request.form) raise NotImplemented() - result = func(request) - - if isinstance(result, BaseResponse): - return result + with PWGSession(request) as session: + result = func(request) - response = response_xml(result) + if isinstance(result, BaseResponse): + return result - possibly_add_cookie(request, response) + response = response_xml(result) + session.save_to_cookie(response) - return response + return response diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html index 2b790584..694eb979 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html @@ -41,9 +41,10 @@ <div class="form_submit_buttons"> {# TODO: This isn't a button really... might do unexpected things :) #} - <a class="button_action" href="{{ request.urlgen('mediagoblin.user_pages.user_collection', - collection=collection.slug, - user=request.user.username) }}">{% trans %}Cancel{% endtrans %}</a> + <a class="button_action" href=" + {{- collection.url_for_self(request.urlgen) }}"> + {%- trans %}Cancel{% endtrans -%} + </a> <input type="submit" value="{% trans %}Delete permanently{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html index 449cc3ce..dc31d90f 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html @@ -47,9 +47,10 @@ <div class="form_submit_buttons"> {# TODO: This isn't a button really... might do unexpected things :) #} - <a class="button_action" href="{{ request.urlgen('mediagoblin.user_pages.user_collection', - collection=collection_item.in_collection.slug, - user=request.user.username) }}">{% trans %}Cancel{% endtrans %}</a> + <a class="button_action" href=" + {{- collection_item.in_collection.url_for_self(request.urlgen) }}"> + {%- trans %}Cancel{% endtrans -%} + </a> <input type="submit" value="{% trans %}Remove{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html index abf22623..8ac0b988 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html @@ -15,7 +15,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/>. #} -{% extends "mediagoblin/base.html" %} +{%- extends "mediagoblin/base.html" %} {% block title %} {%- trans username=user.username -%} @@ -39,17 +39,17 @@ <a href="{{ request.urlgen('mediagoblin.submit.collection', user=user.username) }}"> {%- trans %}Create new collection{% endtrans -%} + </a> </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> + {%- set coll_url = coll.url_for_self(request.urlgen) %} + <li> + <a href="{{ coll_url }}">{{ coll.title }}</a> + </li> {% endfor %} </ul> diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 7dea3f09..6d32d009 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -43,7 +43,7 @@ {%- endtrans -%} </p> {% include "mediagoblin/utils/prev_next.html" %} - <div class="media_pane"> + <div class="media_pane"> <div class="media_image_container"> {% block mediagoblin_media %} {% set display_media = request.app.public_store.file_url( @@ -71,7 +71,7 @@ {{ media.title }} </h2> {% if request.user and - (media.uploader == request.user.id or + (media.uploader == request.user.id or request.user.is_admin) %} {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', user= media.get_uploader.username, @@ -90,11 +90,13 @@ {% if not request.user %} href="{{ request.urlgen('mediagoblin.auth.login') }}" {% endif %} - class="button_action" id="button_addcomment" title="Add a comment"> - {% trans %}Add a comment{% endtrans %} + {% if app_config['allow_comments'] %} + class="button_action" id="button_addcomment" title="Add a comment"> + {% trans %}Add a comment{% endtrans %} + {% endif %} </a> {% if request.user %} - <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', + <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', user= media.get_uploader.username, media_id=media.id) }}" method="POST" id="form_comment"> {{ wtforms_util.render_divs(comment_form) }} @@ -160,7 +162,7 @@ {% include "mediagoblin/utils/license.html" %} {% include "mediagoblin/utils/exif.html" %} - + {%- if media.attachment_files|count %} <h3>{% trans %}Attachments{% endtrans %}</h3> <ul> diff --git a/mediagoblin/tests/appconfig_plugin_specs.ini b/mediagoblin/tests/appconfig_plugin_specs.ini new file mode 100644 index 00000000..5511cd97 --- /dev/null +++ b/mediagoblin/tests/appconfig_plugin_specs.ini @@ -0,0 +1,21 @@ +[mediagoblin] +direct_remote_path = /mgoblin_static/ +email_sender_address = "notice@mediagoblin.example.org" + +## Uncomment and change to your DB's appropiate setting. +## Default is a local sqlite db "mediagoblin.db". +# sql_engine = postgresql:///gmg + +# set to false to enable sending notices +email_debug_mode = true + +# Set to false to disable registrations +allow_registration = true + +[plugins] +[[mediagoblin.tests.testplugins.pluginspec]] +some_string = "not blork" +some_int = "not an int" + +# this one shouldn't have its own config +[[mediagoblin.tests.testplugins.callables1]] diff --git a/mediagoblin/tests/test_pluginapi.py b/mediagoblin/tests/test_pluginapi.py index f03e868f..809b5ce9 100644 --- a/mediagoblin/tests/test_pluginapi.py +++ b/mediagoblin/tests/test_pluginapi.py @@ -18,9 +18,12 @@ import sys from configobj import ConfigObj import pytest +import pkg_resources +from validate import VdtTypeError from mediagoblin import mg_globals from mediagoblin.init.plugins import setup_plugins +from mediagoblin.init.config import read_mediagoblin_config from mediagoblin.tools import pluginapi @@ -294,3 +297,29 @@ def test_hook_transform(): assert pluginapi.hook_transform( "expand_tuple", (-1, 0)) == (-1, 0, 1, 2, 3) + + +def test_plugin_config(): + """ + Make sure plugins can set up their own config + """ + config, validation_result = read_mediagoblin_config( + pkg_resources.resource_filename( + 'mediagoblin.tests', 'appconfig_plugin_specs.ini')) + + pluginspec_section = config['plugins'][ + 'mediagoblin.tests.testplugins.pluginspec'] + assert pluginspec_section['some_string'] == 'not blork' + assert pluginspec_section['dont_change_me'] == 'still the default' + + # Make sure validation works... this should be an error + assert isinstance( + validation_result[ + 'plugins'][ + 'mediagoblin.tests.testplugins.pluginspec'][ + 'some_int'], + VdtTypeError) + + # the callables thing shouldn't really have anything though. + assert len(config['plugins'][ + 'mediagoblin.tests.testplugins.callables1']) == 0 diff --git a/mediagoblin/tests/testplugins/pluginspec/__init__.py b/mediagoblin/tests/testplugins/pluginspec/__init__.py new file mode 100644 index 00000000..76ca2b1f --- /dev/null +++ b/mediagoblin/tests/testplugins/pluginspec/__init__.py @@ -0,0 +1,22 @@ +# 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/>. + +def setup_plugin(): + pass + +hooks = { + 'setup': setup_plugin, +} diff --git a/mediagoblin/tests/testplugins/pluginspec/config_spec.ini b/mediagoblin/tests/testplugins/pluginspec/config_spec.ini new file mode 100644 index 00000000..5c9c3bd7 --- /dev/null +++ b/mediagoblin/tests/testplugins/pluginspec/config_spec.ini @@ -0,0 +1,4 @@ +[plugin_spec] +some_string = string(default="blork") +some_int = integer(default=50) +dont_change_me = string(default="still the default")
\ No newline at end of file diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index a028c305..738cc054 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -161,7 +161,13 @@ def media_post_comment(request, media): comment.author = request.user.id comment.content = unicode(request.form['comment_content']) - if not comment.content.strip(): + # 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, @@ -522,9 +528,7 @@ def collection_atom_feed(request): ATOM feed id is a tag URI (see http://en.wikipedia.org/wiki/Tag_URI) """ atomlinks = [{ - 'href': request.urlgen( - 'mediagoblin.user_pages.user_collection', - qualified=True, user=request.matchdict['user'], collection=collection.slug), + 'href': collection.url_for_self(request.urlgen, qualified=True), 'rel': 'alternate', 'type': 'text/html' }] |