From 04e08d422ad179de881e4394b99f2231d1b65a90 Mon Sep 17 00:00:00 2001 From: xray7224 Date: Thu, 27 Jun 2013 19:34:21 +0100 Subject: Moves json_response into tools/json.py --- mediagoblin/tools/json.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 mediagoblin/tools/json.py (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/json.py b/mediagoblin/tools/json.py new file mode 100644 index 00000000..a8437b82 --- /dev/null +++ b/mediagoblin/tools/json.py @@ -0,0 +1,41 @@ +# 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 . + +import json + +from werkzeug.wrappers import Response + +def json_response(serializable, _disable_cors=False, *args, **kw): + ''' + Serializes a json objects and returns a werkzeug Response object with the + serialized value as the response body and Content-Type: application/json. + + :param serializable: A json-serializable object + + Any extra arguments and keyword arguments are passed to the + Response.__init__ method. + ''' + response = Response(json.dumps(serializable), *args, content_type='application/json', **kw) + + if not _disable_cors: + cors_headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} + for key, value in cors_headers.iteritems(): + response.headers.set(key, value) + + return response -- cgit v1.2.3 From 4990b47ce401dc86353a261825771a6811be4a8c Mon Sep 17 00:00:00 2001 From: xray7224 Date: Fri, 28 Jun 2013 17:59:32 +0100 Subject: Working client registration --- mediagoblin/tools/crypto.py | 15 +++++++++++++++ mediagoblin/tools/json.py | 41 ----------------------------------------- mediagoblin/tools/response.py | 27 +++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 43 deletions(-) delete mode 100644 mediagoblin/tools/json.py (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/crypto.py b/mediagoblin/tools/crypto.py index 1379d21b..917e674c 100644 --- a/mediagoblin/tools/crypto.py +++ b/mediagoblin/tools/crypto.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import base64 +import string import errno import itsdangerous import logging @@ -24,6 +26,9 @@ from mediagoblin import mg_globals _log = logging.getLogger(__name__) +# produces base64 alphabet +alphabet = string.ascii_letters + "-_" +base = len(alphabet) # Use the system (hardware-based) random number generator if it exists. # -- this optimization is lifted from Django @@ -111,3 +116,13 @@ def get_timed_signer_url(namespace): assert __itsda_secret is not None return itsdangerous.URLSafeTimedSerializer(__itsda_secret, salt=namespace) + +def random_string(length): + """ Returns a URL safe base64 encoded crypographically strong string """ + rstring = "" + for i in range(length): + n = getrandbits(6) # 6 bytes = 2^6 = 64 + n = divmod(n, base)[1] + rstring += alphabet[n] + + return rstring diff --git a/mediagoblin/tools/json.py b/mediagoblin/tools/json.py deleted file mode 100644 index a8437b82..00000000 --- a/mediagoblin/tools/json.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 . - -import json - -from werkzeug.wrappers import Response - -def json_response(serializable, _disable_cors=False, *args, **kw): - ''' - Serializes a json objects and returns a werkzeug Response object with the - serialized value as the response body and Content-Type: application/json. - - :param serializable: A json-serializable object - - Any extra arguments and keyword arguments are passed to the - Response.__init__ method. - ''' - response = Response(json.dumps(serializable), *args, content_type='application/json', **kw) - - if not _disable_cors: - cors_headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} - for key, value in cors_headers.iteritems(): - response.headers.set(key, value) - - return response diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index 0be1f835..1fd242fb 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import json + import werkzeug.utils from werkzeug.wrappers import Response as wz_Response from mediagoblin.tools.template import render_template @@ -31,7 +33,6 @@ def render_to_response(request, template, context, status=200): render_template(request, template, context), status=status) - def render_error(request, status=500, title=_('Oops!'), err_msg=_('An error occured')): """Render any error page with a given error code, title and text body @@ -44,7 +45,6 @@ def render_error(request, status=500, title=_('Oops!'), {'err_code': status, 'title': title, 'err_msg': err_msg}), status=status) - def render_403(request): """Render a standard 403 page""" _ = pass_to_ugettext @@ -106,3 +106,26 @@ def redirect_obj(request, obj): Requires obj to have a .url_for_self method.""" return redirect(request, location=obj.url_for_self(request.urlgen)) + +def json_response(serializable, _disable_cors=False, *args, **kw): + ''' + Serializes a json objects and returns a werkzeug Response object with the + serialized value as the response body and Content-Type: application/json. + + :param serializable: A json-serializable object + + Any extra arguments and keyword arguments are passed to the + Response.__init__ method. + ''' + + response = wz_Response(json.dumps(serializable), *args, content_type='application/json', **kw) + + if not _disable_cors: + cors_headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} + for key, value in cors_headers.iteritems(): + response.headers.set(key, value) + + return response -- cgit v1.2.3 From c33a34d45964a7e49a5eeeabde0ef4a8132ac591 Mon Sep 17 00:00:00 2001 From: xray7224 Date: Mon, 1 Jul 2013 17:50:39 +0100 Subject: Client registration now supports application/x-www-form-urlencoded now --- mediagoblin/tools/validator.py | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 mediagoblin/tools/validator.py (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/validator.py b/mediagoblin/tools/validator.py new file mode 100644 index 00000000..03598f9c --- /dev/null +++ b/mediagoblin/tools/validator.py @@ -0,0 +1,46 @@ +# 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 . + +from wtforms.validators import Email, URL + +def validate_email(email): + """ + Validates an email + + Returns True if valid and False if invalid + """ + + email_re = Email().regex + result = email_re.match(email) + if result is None: + return False + else: + return result.string + +def validate_url(url): + """ + Validates a url + + Returns True if valid and False if invalid + """ + + url_re = URL().regex + result = url_re.match(url) + if result is None: + return False + else: + return result.string + -- cgit v1.2.3 From d41c6a5349db0ac573e8f0d29d239febc705f7c9 Mon Sep 17 00:00:00 2001 From: xray7224 Date: Mon, 8 Jul 2013 20:35:03 +0100 Subject: Adds oauth support up until authorization --- mediagoblin/tools/request.py | 17 +++++++++++++++++ mediagoblin/tools/response.py | 9 +++++++++ 2 files changed, 26 insertions(+) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index ee342eae..ed903ce0 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.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 . +import json import logging from mediagoblin.db.models import User _log = logging.getLogger(__name__) +# MIME-Types +form_encoded = "application/x-www-form-urlencoded" +json_encoded = "application/json" + def setup_user_in_request(request): """ Examine a request and tack on a request.user parameter if that's @@ -36,3 +41,15 @@ def setup_user_in_request(request): # this session. _log.warn("Killing session for user id %r", request.session['user_id']) request.session.delete() + +def decode_request(request): + """ Decodes a request based on MIME-Type """ + data = request.get_data() + + if request.content_type == json_encoded: + data = json.loads(data) + elif request.content_type == form_encoded: + data = request.form + else: + data = "" + return data diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index 1fd242fb..db8fc388 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -45,6 +45,15 @@ def render_error(request, status=500, title=_('Oops!'), {'err_code': status, 'title': title, 'err_msg': err_msg}), status=status) +def render_400(request, err_msg=None): + """ Render a standard 400 page""" + _ = pass_to_ugettext + title = _("Bad Request") + if err_msg is None: + err_msg = _("The request sent to the server is invalid, please double check it") + + return render_error(request, 400, title, err_msg) + def render_403(request): """Render a standard 403 page""" _ = pass_to_ugettext -- cgit v1.2.3 From 405aa45adc14d3c67a120618ecc0ae792f5881de Mon Sep 17 00:00:00 2001 From: xray7224 Date: Wed, 10 Jul 2013 15:49:59 +0100 Subject: Adds more support for oauth - access_token & decorators still to do --- mediagoblin/tools/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index ed903ce0..2c9e609d 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.py @@ -48,7 +48,7 @@ def decode_request(request): if request.content_type == json_encoded: data = json.loads(data) - elif request.content_type == form_encoded: + elif request.content_type == form_encoded or request.content_type == "": data = request.form else: data = "" -- cgit v1.2.3 From 2b60a56cbec44f789ee2efe71294979d7784515c Mon Sep 17 00:00:00 2001 From: xray7224 Date: Thu, 11 Jul 2013 17:58:58 +0100 Subject: Finishes most of oauth, just decorator to complete --- mediagoblin/tools/request.py | 10 ++++++++++ mediagoblin/tools/response.py | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index 2c9e609d..0c0fc557 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.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 . +import re import json import logging from mediagoblin.db.models import User @@ -25,6 +26,9 @@ _log = logging.getLogger(__name__) form_encoded = "application/x-www-form-urlencoded" json_encoded = "application/json" +# Regex for Authorization header +auth_header_re = re.compile('(\w+)[:=] ?"?(\w+)"?') + def setup_user_in_request(request): """ Examine a request and tack on a request.user parameter if that's @@ -53,3 +57,9 @@ def decode_request(request): else: data = "" return data + +def decode_authorization_header(header): + """ Decodes a HTTP Authorization Header to python dictionary """ + authorization = header.get("Authorization", "") + tokens = dict(auth_header_re.findall(authorization)) + return tokens diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index db8fc388..b0401e08 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -138,3 +138,22 @@ def json_response(serializable, _disable_cors=False, *args, **kw): response.headers.set(key, value) return response + +def form_response(data, *args, **kwargs): + """ + Responds using application/x-www-form-urlencoded and returns a werkzeug + Response object with the data argument as the body + and 'application/x-www-form-urlencoded' as the Content-Type. + + Any extra arguments and keyword arguments are passed to the + Response.__init__ method. + """ + + response = wz_Response( + data, + content_type="application/x-www-form-urlencoded", + *args, + **kwargs + ) + + return response -- cgit v1.2.3 From 786bbd79e8d77c06a9d86aee00edc4dd3e89d651 Mon Sep 17 00:00:00 2001 From: xray7224 Date: Thu, 11 Jul 2013 19:43:00 +0100 Subject: Cleans up some of the OAuth code --- mediagoblin/tools/request.py | 9 --------- 1 file changed, 9 deletions(-) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index 0c0fc557..d4739039 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import re import json import logging from mediagoblin.db.models import User @@ -26,8 +25,6 @@ _log = logging.getLogger(__name__) form_encoded = "application/x-www-form-urlencoded" json_encoded = "application/json" -# Regex for Authorization header -auth_header_re = re.compile('(\w+)[:=] ?"?(\w+)"?') def setup_user_in_request(request): """ @@ -57,9 +54,3 @@ def decode_request(request): else: data = "" return data - -def decode_authorization_header(header): - """ Decodes a HTTP Authorization Header to python dictionary """ - authorization = header.get("Authorization", "") - tokens = dict(auth_header_re.findall(authorization)) - return tokens -- cgit v1.2.3 From 155d234d95a6bdbbdc546d9919b692a95e7a5c9b Mon Sep 17 00:00:00 2001 From: Kenneth Dombrowski Date: Sat, 11 May 2013 17:30:43 -0400 Subject: * create config option for optional jinja2 extensions * add comments & clarify code for jinja2 extensions Conflicts: mediagoblin/config_spec.ini --- mediagoblin/tools/template.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index 615ce129..4c634ea2 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -50,6 +50,12 @@ def get_jinja_env(template_loader, locale): if locale in SETUP_JINJA_ENVS: return SETUP_JINJA_ENVS[locale] + # The default config does not require a [jinja2] block. + # You may create one if you wish to enable additional jinja2 extensions, + # see example in config_spec.ini + jinja2_config = mg_globals.global_config.get('jinja2', {}) + local_exts = jinja2_config.get('extensions', []) + # jinja2.StrictUndefined will give exceptions on references # to undefined/unknown variables in templates. template_env = jinja2.Environment( @@ -57,7 +63,7 @@ def get_jinja_env(template_loader, locale): undefined=jinja2.StrictUndefined, extensions=[ 'jinja2.ext.i18n', 'jinja2.ext.autoescape', - TemplateHookExtension]) + TemplateHookExtension] + local_exts) template_env.install_gettext_callables( mg_globals.thread_scope.translations.ugettext, -- cgit v1.2.3 From 7949d88a751e52a2e0aef42e4801e17283556467 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 14 Aug 2013 15:08:49 -0500 Subject: Avoiding the celery warnings that we seem to be confusing people lately. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Basically, it's shuffling around the notifications stuff. This commit sponsored by Günter Kraft. Thank you! --- mediagoblin/tools/template.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index 4c634ea2..3cc058c9 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -32,7 +32,6 @@ from mediagoblin.tools.timesince import timesince from mediagoblin.meddleware.csrf import render_csrf_form_token - SETUP_JINJA_ENVS = {} @@ -90,6 +89,14 @@ def get_jinja_env(template_loader, locale): template_env.globals = hook_transform( 'template_global_context', template_env.globals) + #### THIS IS TEMPORARY, PLEASE FIX IT + ## Notifications stuff is not yet a plugin (and we're not sure it will be), + ## but it needs to add stuff to the context. This is THE WRONG WAY TO DO IT + from mediagoblin import notifications + template_env.globals['get_notifications'] = notifications.get_notifications + template_env.globals[ + 'get_comment_subscription'] = notifications.get_comment_subscription + if exists(locale): SETUP_JINJA_ENVS[locale] = template_env -- cgit v1.2.3 From 29cd702e4776811a96c3c088bd9ba8fc6f9176f0 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 14 Aug 2013 15:57:58 -0500 Subject: Fix notifications, which I broke. This commit sponsored by Denver Gingerich. Thank you! --- mediagoblin/tools/template.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'mediagoblin/tools') diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index 3cc058c9..fa290611 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -94,6 +94,8 @@ def get_jinja_env(template_loader, locale): ## but it needs to add stuff to the context. This is THE WRONG WAY TO DO IT from mediagoblin import notifications template_env.globals['get_notifications'] = notifications.get_notifications + template_env.globals[ + 'get_notification_count'] = notifications.get_notification_count template_env.globals[ 'get_comment_subscription'] = notifications.get_comment_subscription -- cgit v1.2.3