From bc34b471d56896acf8d97c403a7f05e24be63c07 Mon Sep 17 00:00:00 2001 From: Mike Linksvayer Date: Fri, 12 Oct 2012 14:03:40 -0700 Subject: [PATCH 01/13] Mention necessary operation per http://lists.mediagoblin.org/pipermail/devel/2012-April/000173.html --- docs/source/siteadmin/media-types.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst index 5653217f..2f2eadbc 100644 --- a/docs/source/siteadmin/media-types.rst +++ b/docs/source/siteadmin/media-types.rst @@ -43,6 +43,11 @@ video media types, then the list would look like this:: media_types = mediagoblin.media_types.image, mediagoblin.media_types.video +After adding new media types to ``mediagoblin_local.ini``, you need to run:: + + ./bin/gmg dbupdate + + How does MediaGoblin decide which media type to use for a file? =============================================================== From 200433dc38a2139462e0331be36ee49a80a81a12 Mon Sep 17 00:00:00 2001 From: Mike Linksvayer Date: Fri, 12 Oct 2012 15:05:29 -0700 Subject: [PATCH 02/13] mention dependencies, dbupdate, refer to docs http://issues.mediagoblin.org/ticket/470 --- mediagoblin.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mediagoblin.ini b/mediagoblin.ini index f10a452f..31877742 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -16,6 +16,8 @@ email_debug_mode = true allow_registration = true ## Uncomment this to turn on video or enable other media types +## You may have to install dependencies, and will have to run ./bin/dbupdate +## See http://docs.mediagoblin.org/siteadmin/media-types.html for details. # media_types = mediagoblin.media_types.image, mediagoblin.media_types.video ## Uncomment this to put some user-overriding templates here From 42ce372e38b28d6e01da76b05d6924d04c2710ae Mon Sep 17 00:00:00 2001 From: Mike Linksvayer Date: Thu, 20 Dec 2012 12:52:31 -0800 Subject: [PATCH 03/13] actual upgrade instructions --- docs/source/siteadmin/relnotes.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index 25d4d83f..55a8279d 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -27,7 +27,19 @@ MongoDB-based MediaGoblin instance to the newer SQL-based system. **Do this to upgrade** -1. Make sure to run ``bin/gmg dbupdate`` after upgrading. + # directory of your mediagoblin install + cd /srv/mediagoblin.example.org + + # copy source for this release + git fetch + git checkout tags/v0.3.2 + + # perform any needed database updates + bin/gmg dbupdate + + # restart your servers however you do that, e.g., + sudo service mediagoblin-paster restart + sudo service mediagoblin-celeryd restart **New features** From 20f8f50ccb3076bbea500b3307fe6ed2310e298a Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 13 Apr 2013 09:40:01 -0400 Subject: [PATCH 04/13] Add allow_comments configuration setting. --- mediagoblin/config_spec.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index e830e863..545d02e2 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=50) +# Enable/disable comments +allow_comments = boolean(default=True) + # Whether comments are ascending or descending comments_ascending = boolean(default=True) From aa4f958a40b933e94eb8ea86093eedf0bcc0e029 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 13 Apr 2013 09:40:34 -0400 Subject: [PATCH 05/13] Do not render 'Add a comment' button if comments are disabled. --- .../templates/mediagoblin/user_pages/media.html | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index b77c12b9..04be81aa 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -43,7 +43,7 @@ {%- endtrans -%}

{% include "mediagoblin/utils/prev_next.html" %} -
+
{% block mediagoblin_media %} {% set display_media = request.app.public_store.file_url( @@ -71,7 +71,7 @@ {{ media.title }} {% 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 %} {% if request.user %} -
{{ wtforms_util.render_divs(comment_form) }} @@ -154,7 +156,7 @@ {% include "mediagoblin/utils/license.html" %} {% include "mediagoblin/utils/exif.html" %} - + {%- if media.attachment_files|count %}

{% trans %}Attachments{% endtrans %}

    From 99338b6a6419e6d8c044b82b2dd398a435e477f0 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 13 Apr 2013 10:42:40 -0400 Subject: [PATCH 06/13] Do not allow comments to be posted when they are disabled. --- mediagoblin/user_pages/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 61c23f16..b3e613c4 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -159,7 +159,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, From 230b5eb2eb9ae9c2b0930bbd2e32dc963b90b9fc Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 8 May 2013 15:20:27 -0500 Subject: [PATCH 07/13] Fixing API setup with new plugin "config spec" world It shouldn't reference the config until in the setup_plugin() method, else there's a race condition. --- mediagoblin/plugins/api/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 = [ From e5cdd742945e134d87f368aa7064c708f53f3098 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 8 May 2013 15:21:15 -0500 Subject: [PATCH 08/13] Fix the new config "plugin spec" loading code so it doesn't break on no plugins section --- mediagoblin/init/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/init/config.py b/mediagoblin/init/config.py index d6fc6875..11a91cff 100644 --- a/mediagoblin/init/config.py +++ b/mediagoblin/init/config.py @@ -70,7 +70,7 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): config_path, interpolation='ConfigParser') - plugins = config["plugins"].keys() + plugins = config.get("plugins", {}).keys() plugin_configs = {} for plugin in plugins: From 180a0081007532ed7f6adad8fe3f2cde97031a2f Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 5 May 2013 16:45:37 +0200 Subject: [PATCH 09/13] piwigo: Remove possibly_add_cookie. This one was a fake thing to make clients happy. Real sessions coming sonn. --- mediagoblin/plugins/piwigo/views.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index bd3f9320..e064b418 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -133,19 +133,6 @@ 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) - - @csrf_exempt def ws_php(request): if request.method not in ("GET", "POST"): @@ -165,6 +152,4 @@ def ws_php(request): response = response_xml(result) - possibly_add_cookie(request, response) - return response From c1df8d19630b1e60598db1bd93171926234b633b Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 25 Mar 2013 15:34:21 +0100 Subject: [PATCH 10/13] piwigo: Add .images.add including form handling. To make things a bit easier, switch to WTForms for validating the received data. --- mediagoblin/plugins/piwigo/forms.py | 16 ++++++++++++++++ mediagoblin/plugins/piwigo/tools.py | 15 ++++++++++++++- mediagoblin/plugins/piwigo/views.py | 13 +++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) 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..cd466367 100644 --- a/mediagoblin/plugins/piwigo/tools.py +++ b/mediagoblin/plugins/piwigo/tools.py @@ -18,7 +18,7 @@ import logging import six import lxml.etree as ET -from werkzeug.exceptions import MethodNotAllowed +from werkzeug.exceptions import MethodNotAllowed, BadRequest from mediagoblin.tools.response import Response @@ -106,3 +106,16 @@ 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)) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index e064b418..837d8eca 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -23,8 +23,8 @@ 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 .tools import CmdTable, PwgNamedArray, response_xml, check_form +from .forms import AddSimpleForm, AddForm _log = logging.getLogger(__name__) @@ -133,6 +133,15 @@ def pwg_images_addChunk(request): return 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 def ws_php(request): if request.method not in ("GET", "POST"): From 7fb419ddd2bd1770d62fffadc674c53b670cba81 Mon Sep 17 00:00:00 2001 From: Elrond Date: Fri, 29 Mar 2013 14:49:13 +0100 Subject: [PATCH 11/13] Create new session system for piwigo plugin. Using the brand new itsdangerous sessions to power the sessions for piwigo. The real point is: Clients want to have the session in a "pwg_id" cookie and don't accept any other cookie name. --- mediagoblin/plugins/piwigo/__init__.py | 5 +++++ mediagoblin/plugins/piwigo/tools.py | 31 ++++++++++++++++++++++++++ mediagoblin/plugins/piwigo/views.py | 26 +++++++++++++++------ 3 files changed, 55 insertions(+), 7 deletions(-) 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/tools.py b/mediagoblin/plugins/piwigo/tools.py index cd466367..400be615 100644 --- a/mediagoblin/plugins/piwigo/tools.py +++ b/mediagoblin/plugins/piwigo/tools.py @@ -20,6 +20,7 @@ import six import lxml.etree as ET from werkzeug.exceptions import MethodNotAllowed, BadRequest +from mediagoblin.tools.request import setup_user_in_request from mediagoblin.tools.response import Response @@ -119,3 +120,33 @@ def check_form(form): 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 837d8eca..6a246f18 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -20,10 +20,11 @@ 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, check_form +from mediagoblin.auth.lib import fake_login_attempt +from .tools import CmdTable, PwgNamedArray, response_xml, check_form, \ + PWGSession from .forms import AddSimpleForm, AddForm @@ -35,12 +36,21 @@ def pwg_login(request): username = request.form.get("username") password = request.form.get("password") _log.info("Login for %r/%r...", username, password) + user = request.db.User.query.filter_by(username=username).first() + if not user: + fake_login_attempt() + return False + if not user.check_login(password): + return False + 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 @@ -154,11 +164,13 @@ def ws_php(request): request.args, request.form) raise NotImplemented() - result = func(request) + with PWGSession(request) as session: + result = func(request) - if isinstance(result, BaseResponse): - return result + if isinstance(result, BaseResponse): + return result - response = response_xml(result) + response = response_xml(result) + session.save_to_cookie(response) - return response + return response From 665946033e1c9eef775a84a538ceebe9f52c657e Mon Sep 17 00:00:00 2001 From: Elrond Date: Fri, 29 Mar 2013 14:48:08 +0100 Subject: [PATCH 12/13] piwigo: Let getStatus return the current user. If there is a user logged in, show his name. --- mediagoblin/plugins/piwigo/views.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 6a246f18..5d7d371d 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -61,7 +61,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") From f035ec3db4c67e4a4d03d78dccd57ea82b9a6a5d Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 5 May 2013 17:02:00 +0200 Subject: [PATCH 13/13] piwigo: Better logging for login. --- mediagoblin/plugins/piwigo/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 5d7d371d..b59247ad 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -35,13 +35,16 @@ _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