aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin')
-rw-r--r--mediagoblin/config_spec.ini3
-rw-r--r--mediagoblin/init/config.py42
-rw-r--r--mediagoblin/media_types/ascii/__init__.py20
-rw-r--r--mediagoblin/media_types/audio/__init__.py17
-rw-r--r--mediagoblin/media_types/pdf/__init__.py20
-rw-r--r--mediagoblin/media_types/stl/__init__.py18
-rw-r--r--mediagoblin/media_types/video/__init__.py28
-rw-r--r--mediagoblin/media_types/video/models.py2
-rw-r--r--mediagoblin/plugins/api/__init__.py4
-rw-r--r--mediagoblin/plugins/httpapiauth/__init__.py3
-rw-r--r--mediagoblin/plugins/piwigo/__init__.py5
-rw-r--r--mediagoblin/plugins/piwigo/forms.py16
-rw-r--r--mediagoblin/plugins/piwigo/tools.py46
-rw-r--r--mediagoblin/plugins/piwigo/views.py59
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html7
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html7
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection_list.html12
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html14
-rw-r--r--mediagoblin/tests/appconfig_plugin_specs.ini21
-rw-r--r--mediagoblin/tests/test_pluginapi.py29
-rw-r--r--mediagoblin/tests/testplugins/pluginspec/__init__.py22
-rw-r--r--mediagoblin/tests/testplugins/pluginspec/config_spec.ini4
-rw-r--r--mediagoblin/user_pages/views.py12
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'
}]