aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/plugins')
-rw-r--r--mediagoblin/plugins/api/tools.py4
-rw-r--r--mediagoblin/plugins/api/views.py30
-rw-r--r--mediagoblin/plugins/archivalook/templates/archivalook/feature_displays/audio_head.html2
-rw-r--r--mediagoblin/plugins/basic_auth/forms.py8
-rw-r--r--mediagoblin/plugins/basic_auth/tools.py4
-rw-r--r--mediagoblin/plugins/geolocation/__init__.py6
-rw-r--r--mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html13
-rw-r--r--mediagoblin/plugins/httpapiauth/__init__.py4
-rw-r--r--mediagoblin/plugins/ldap/forms.py4
-rw-r--r--mediagoblin/plugins/ldap/tools.py4
-rw-r--r--mediagoblin/plugins/ldap/views.py5
-rw-r--r--mediagoblin/plugins/oauth/README.rst148
-rw-r--r--mediagoblin/plugins/oauth/__init__.py109
-rw-r--r--mediagoblin/plugins/oauth/forms.py69
-rw-r--r--mediagoblin/plugins/oauth/migrations.py158
-rw-r--r--mediagoblin/plugins/oauth/models.py192
-rw-r--r--mediagoblin/plugins/oauth/templates/oauth/authorize.html31
-rw-r--r--mediagoblin/plugins/oauth/templates/oauth/client/connections.html34
-rw-r--r--mediagoblin/plugins/oauth/templates/oauth/client/list.html45
-rw-r--r--mediagoblin/plugins/oauth/templates/oauth/client/register.html34
-rw-r--r--mediagoblin/plugins/oauth/tools.py114
-rw-r--r--mediagoblin/plugins/oauth/views.py253
-rw-r--r--mediagoblin/plugins/openid/forms.py6
-rw-r--r--mediagoblin/plugins/openid/store.py6
-rw-r--r--mediagoblin/plugins/openid/views.py5
-rw-r--r--mediagoblin/plugins/persona/forms.py6
-rw-r--r--mediagoblin/plugins/persona/views.py4
-rw-r--r--mediagoblin/plugins/piwigo/forms.py18
-rw-r--r--mediagoblin/plugins/piwigo/tools.py2
-rw-r--r--mediagoblin/plugins/piwigo/views.py6
30 files changed, 73 insertions, 1251 deletions
diff --git a/mediagoblin/plugins/api/tools.py b/mediagoblin/plugins/api/tools.py
index d1b3ebb1..56256236 100644
--- a/mediagoblin/plugins/api/tools.py
+++ b/mediagoblin/plugins/api/tools.py
@@ -18,9 +18,11 @@ import logging
import json
from functools import wraps
-from urlparse import urljoin
from werkzeug.exceptions import Forbidden
from werkzeug.wrappers import Response
+
+from six.moves.urllib.parse import urljoin
+
from mediagoblin import mg_globals
from mediagoblin.tools.pluginapi import PluginManager
from mediagoblin.storage.filestorage import BasicFileStorage
diff --git a/mediagoblin/plugins/api/views.py b/mediagoblin/plugins/api/views.py
index e8af7988..23341065 100644
--- a/mediagoblin/plugins/api/views.py
+++ b/mediagoblin/plugins/api/views.py
@@ -17,6 +17,8 @@
import json
import logging
+import six
+
from werkzeug.exceptions import BadRequest
from werkzeug.wrappers import Response
@@ -24,8 +26,7 @@ from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.response import json_response
from mediagoblin.decorators import require_active_login
from mediagoblin.meddleware.csrf import csrf_exempt
-from mediagoblin.media_types import \
- InvalidFileType, FileTypeNotSupported
+from mediagoblin.media_types import FileTypeNotSupported
from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable
from mediagoblin.submit.lib import \
check_file_field, submit_media, get_upload_file_limits, \
@@ -55,16 +56,16 @@ def post_entry(request):
callback_url = request.form.get('callback_url')
if callback_url:
- callback_url = unicode(callback_url)
+ callback_url = six.text_type(callback_url)
try:
entry = submit_media(
mg_app=request.app, user=request.user,
submitted_file=request.files['file'],
filename=request.files['file'].filename,
- title=unicode(request.form.get('title')),
- description=unicode(request.form.get('description')),
- license=unicode(request.form.get('license', '')),
- tags_string=unicode(request.form.get('tags', '')),
+ title=six.text_type(request.form.get('title')),
+ description=six.text_type(request.form.get('description')),
+ license=six.text_type(request.form.get('license', '')),
+ tags_string=six.text_type(request.form.get('tags', '')),
upload_limit=upload_limit, max_file_size=max_file_size,
callback_url=callback_url)
@@ -81,17 +82,8 @@ def post_entry(request):
except UserPastUploadLimit:
raise BadRequest(
_('Sorry, you have reached your upload limit.'))
-
- except Exception as e:
- '''
- This section is intended to catch exceptions raised in
- mediagoblin.media_types
- '''
- if isinstance(e, InvalidFileType) or \
- isinstance(e, FileTypeNotSupported):
- raise BadRequest(unicode(e))
- else:
- raise
+ except FileTypeNotSupported as e:
+ raise BadRequest(e)
@api_auth
@@ -103,7 +95,7 @@ def api_test(request):
# TODO: This is the *only* thing using Response() here, should that
# not simply use json_response()?
- return Response(json.dumps(user_data))
+ return Response(json.dumps(user_data, sort_keys=True))
def get_entries(request):
diff --git a/mediagoblin/plugins/archivalook/templates/archivalook/feature_displays/audio_head.html b/mediagoblin/plugins/archivalook/templates/archivalook/feature_displays/audio_head.html
index a53694b3..d1ea0b9a 100644
--- a/mediagoblin/plugins/archivalook/templates/archivalook/feature_displays/audio_head.html
+++ b/mediagoblin/plugins/archivalook/templates/archivalook/feature_displays/audio_head.html
@@ -1,5 +1,3 @@
<link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/audio.css') }}" />
<script type="text/javascript" src="{{ request.staticdirect(
- '/js/extlib/html5slider.js') }}"></script>
- <script type="text/javascript" src="{{ request.staticdirect(
'/js/audio.js') }}"></script>
diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py
index 42b84bf3..9a6db226 100644
--- a/mediagoblin/plugins/basic_auth/forms.py
+++ b/mediagoblin/plugins/basic_auth/forms.py
@@ -20,7 +20,7 @@ from mediagoblin.auth.tools import normalize_user_or_email_field
class RegistrationForm(wtforms.Form):
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_email=False)])
@@ -28,14 +28,14 @@ class RegistrationForm(wtforms.Form):
_('Password'),
[wtforms.validators.InputRequired(),
wtforms.validators.Length(min=5, max=1024)])
- email = wtforms.TextField(
+ email = wtforms.StringField(
_('Email address'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_user=False)])
class LoginForm(wtforms.Form):
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username or Email'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field()])
@@ -47,7 +47,7 @@ class LoginForm(wtforms.Form):
class ForgotPassForm(wtforms.Form):
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username or email'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field()])
diff --git a/mediagoblin/plugins/basic_auth/tools.py b/mediagoblin/plugins/basic_auth/tools.py
index f943bf39..13f240b2 100644
--- a/mediagoblin/plugins/basic_auth/tools.py
+++ b/mediagoblin/plugins/basic_auth/tools.py
@@ -16,6 +16,8 @@
import bcrypt
import random
+import six
+
from mediagoblin import mg_globals
from mediagoblin.tools.crypto import get_timed_signer_url
from mediagoblin.tools.mail import send_email
@@ -66,7 +68,7 @@ def bcrypt_gen_password_hash(raw_pass, extra_salt=None):
if extra_salt:
raw_pass = u"%s:%s" % (extra_salt, raw_pass)
- return unicode(
+ return six.text_type(
bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt()))
diff --git a/mediagoblin/plugins/geolocation/__init__.py b/mediagoblin/plugins/geolocation/__init__.py
index 5d14590e..06aab68e 100644
--- a/mediagoblin/plugins/geolocation/__init__.py
+++ b/mediagoblin/plugins/geolocation/__init__.py
@@ -21,13 +21,13 @@ PLUGIN_DIR = os.path.dirname(__file__)
def setup_plugin():
config = pluginapi.get_config('mediagoblin.plugins.geolocation')
-
+
# Register the template path.
pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
pluginapi.register_template_hooks(
- {"image_sideinfo": "mediagoblin/plugins/geolocation/map.html",
- "image_head": "mediagoblin/plugins/geolocation/map_js_head.html"})
+ {"location_info": "mediagoblin/plugins/geolocation/map.html",
+ "location_head": "mediagoblin/plugins/geolocation/map_js_head.html"})
hooks = {
diff --git a/mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html b/mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html
index 70f837ff..87f790d1 100644
--- a/mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html
+++ b/mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html
@@ -17,14 +17,13 @@
#}
{% block geolocation_map %}
- {% if media.media_data.gps_latitude is defined
- and media.media_data.gps_latitude
- and media.media_data.gps_longitude is defined
- and media.media_data.gps_longitude %}
- <h3>{% trans %}Location{% endtrans %}</h3>
+ {% if model.location
+ and model.get_location.position
+ and "latitude" in model.get_location.position
+ and "longitude" in model.get_location.position %}
<div>
- {%- set lon = media.media_data.gps_longitude %}
- {%- set lat = media.media_data.gps_latitude %}
+ {%- set lon = model.get_location.position.longitude %}
+ {%- set lat = model.get_location.position.latitude %}
{%- set osm_url = "http://openstreetmap.org/?mlat={lat}&mlon={lon}".format(lat=lat, lon=lon) %}
<div id="tile-map" style="width: 100%; height: 196px;">
<input type="hidden" id="gps-longitude"
diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py
index 2b2d593c..d7180463 100644
--- a/mediagoblin/plugins/httpapiauth/__init__.py
+++ b/mediagoblin/plugins/httpapiauth/__init__.py
@@ -16,6 +16,8 @@
import logging
+import six
+
from werkzeug.exceptions import Unauthorized
from mediagoblin.auth.tools import check_login_simple
@@ -40,7 +42,7 @@ class HTTPAuth(Auth):
if not request.authorization:
return False
- user = check_login_simple(unicode(request.authorization['username']),
+ user = check_login_simple(six.text_type(request.authorization['username']),
request.authorization['password'])
if user:
diff --git a/mediagoblin/plugins/ldap/forms.py b/mediagoblin/plugins/ldap/forms.py
index 1f1439ab..3d966e03 100644
--- a/mediagoblin/plugins/ldap/forms.py
+++ b/mediagoblin/plugins/ldap/forms.py
@@ -24,14 +24,14 @@ class RegisterForm(wtforms.Form):
'',
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_email=False)])
- email = wtforms.TextField(
+ email = wtforms.StringField(
_('Email address'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_user=False)])
class LoginForm(wtforms.Form):
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field()])
diff --git a/mediagoblin/plugins/ldap/tools.py b/mediagoblin/plugins/ldap/tools.py
index 1c436792..2be2dcd7 100644
--- a/mediagoblin/plugins/ldap/tools.py
+++ b/mediagoblin/plugins/ldap/tools.py
@@ -16,6 +16,8 @@
import ldap
import logging
+import six
+
from mediagoblin.tools import pluginapi
_log = logging.getLogger(__name__)
@@ -47,7 +49,7 @@ class LDAP(object):
return email
def login(self, username, password):
- for k, v in self.ldap_settings.iteritems():
+ for k, v in six.iteritems(self.ldap_settings):
try:
self._connect(v)
user_dn = v['LDAP_USER_DN_TEMPLATE'].format(username=username)
diff --git a/mediagoblin/plugins/ldap/views.py b/mediagoblin/plugins/ldap/views.py
index aef1bf56..be434daf 100644
--- a/mediagoblin/plugins/ldap/views.py
+++ b/mediagoblin/plugins/ldap/views.py
@@ -13,6 +13,9 @@
#
# 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 six
+
from mediagoblin import mg_globals, messages
from mediagoblin.auth.tools import register_user
from mediagoblin.db.models import User
@@ -40,7 +43,7 @@ def login(request):
if user:
# set up login in session
- request.session['user_id'] = unicode(user.id)
+ request.session['user_id'] = six.text_type(user.id)
request.session.save()
if request.form.get('next'):
diff --git a/mediagoblin/plugins/oauth/README.rst b/mediagoblin/plugins/oauth/README.rst
deleted file mode 100644
index 753b180f..00000000
--- a/mediagoblin/plugins/oauth/README.rst
+++ /dev/null
@@ -1,148 +0,0 @@
-==============
- OAuth plugin
-==============
-
-.. warning::
- In its current state. This plugin has received no security audit.
- Development has been entirely focused on Making It Work(TM). Use this
- plugin with caution.
-
- Additionally, this and the API may break... consider it pre-alpha.
- There's also a known issue that the OAuth client doesn't do
- refresh tokens so this might result in issues for users.
-
-The OAuth plugin enables third party web applications to authenticate as one or
-more GNU MediaGoblin users in a safe way in order retrieve, create and update
-content stored on the GNU MediaGoblin instance.
-
-The OAuth plugin is based on the `oauth v2.25 draft`_ and is pointing by using
-the ``oauthlib.oauth2.draft25.WebApplicationClient`` from oauthlib_ to a
-mediagoblin instance and building the OAuth 2 provider logic around the client.
-
-There are surely some aspects of the OAuth v2.25 draft that haven't made it
-into this plugin due to the technique used to develop it.
-
-.. _`oauth v2.25 draft`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25
-.. _oauthlib: http://pypi.python.org/pypi/oauthlib
-
-
-Set up the OAuth plugin
-=======================
-
-1. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section::
-
- [[mediagoblin.plugins.oauth]]
-
-2. Run::
-
- gmg dbupdate
-
- in order to create and apply migrations to any database tables that the
- plugin requires.
-
-.. note::
- This only enables the OAuth plugin. To be able to let clients fetch data
- from the MediaGoblin instance you should also enable the API plugin or some
- other plugin that supports authenticating with OAuth credentials.
-
-
-Authenticate against GNU MediaGoblin
-====================================
-
-.. note::
- As mentioned in `capabilities`_ GNU MediaGoblin currently only supports the
- `Authorization Code Grant`_ procedure for obtaining an OAuth access token.
-
-Authorization Code Grant
-------------------------
-
-.. note::
- As mentioned in `incapabilities`_ GNU MediaGoblin currently does not
- support `client registration`_
-
-The `authorization code grant`_ works in the following way:
-
-`Definitions`
-
- Authorization server
- The GNU MediaGoblin instance
- Resource server
- Also the GNU MediaGoblin instance ;)
- Client
- The web application intended to use the data
- Redirect uri
- An URI pointing to a page controlled by the *client*
- Resource owner
- The GNU MediaGoblin user who's resources the client requests access to
- User agent
- Commonly the GNU MediaGoblin user's web browser
- Authorization code
- An intermediate token that is exchanged for an *access token*
- Access token
- A secret token that the *client* uses to authenticate itself agains the
- *resource server* as a specific *resource owner*.
-
-
-Brief description of the procedure
-++++++++++++++++++++++++++++++++++
-
-1. The *client* requests an *authorization code* from the *authorization
- server* by redirecting the *user agent* to the `Authorization Endpoint`_.
- Which parameters should be included in the redirect are covered later in
- this document.
-2. The *authorization server* authenticates the *resource owner* and redirects
- the *user agent* back to the *redirect uri* (covered later in this
- document).
-3. The *client* receives the request from the *user agent*, attached is the
- *authorization code*.
-4. The *client* requests an *access token* from the *authorization server*
-5. \?\?\?\?\?
-6. Profit!
-
-
-Detailed description of the procedure
-+++++++++++++++++++++++++++++++++++++
-
-TBD, in the meantime here is a proof-of-concept GNU MediaGoblin client:
-
-https://github.com/jwandborg/omgmg/
-
-and here are some detailed descriptions from other OAuth 2
-providers:
-
-- https://developers.google.com/accounts/docs/OAuth2WebServer
-- https://developers.facebook.com/docs/authentication/server-side/
-
-and if you're unsure about anything, there's the `OAuth v2.25 draft
-<http://tools.ietf.org/html/draft-ietf-oauth-v2-25>`_, the `OAuth plugin
-source code
-<http://gitorious.org/mediagoblin/mediagoblin/trees/master/mediagoblin/plugins/oauth>`_
-and the `#mediagoblin IRC channel <http://mediagoblin.org/pages/join.html#irc>`_.
-
-
-Capabilities
-============
-
-- `Authorization endpoint`_ - Located at ``/oauth/authorize``
-- `Token endpoint`_ - Located at ``/oauth/access_token``
-- `Authorization Code Grant`_
-- `Client Registration`_
-
-.. _`Authorization endpoint`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.1
-.. _`Token endpoint`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.2
-.. _`Authorization Code Grant`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-4.1
-.. _`Client Registration`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-2
-
-Incapabilities
-==============
-
-- Only `bearer tokens`_ are issued.
-- `Implicit Grant`_
-- `Force TLS for token endpoint`_ - This one is up the the siteadmin
-- Authorization `scope`_ and `state`
-- ...
-
-.. _`bearer tokens`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-08
-.. _`scope`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.3
-.. _`Implicit Grant`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-4.2
-.. _`Force TLS for token endpoint`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.2
diff --git a/mediagoblin/plugins/oauth/__init__.py b/mediagoblin/plugins/oauth/__init__.py
deleted file mode 100644
index 82c1f380..00000000
--- a/mediagoblin/plugins/oauth/__init__.py
+++ /dev/null
@@ -1,109 +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 <http://www.gnu.org/licenses/>.
-
-import os
-import logging
-
-from mediagoblin.tools import pluginapi
-from mediagoblin.plugins.oauth.models import OAuthToken, OAuthClient, \
- OAuthUserClient
-from mediagoblin.plugins.api.tools import Auth
-
-_log = logging.getLogger(__name__)
-
-PLUGIN_DIR = os.path.dirname(__file__)
-
-
-def setup_plugin():
- config = pluginapi.get_config('mediagoblin.plugins.oauth')
-
- _log.info('Setting up OAuth...')
- _log.debug('OAuth config: {0}'.format(config))
-
- routes = [
- ('mediagoblin.plugins.oauth.authorize',
- '/oauth-2/authorize',
- 'mediagoblin.plugins.oauth.views:authorize'),
- ('mediagoblin.plugins.oauth.authorize_client',
- '/oauth-2/client/authorize',
- 'mediagoblin.plugins.oauth.views:authorize_client'),
- ('mediagoblin.plugins.oauth.access_token',
- '/oauth-2/access_token',
- 'mediagoblin.plugins.oauth.views:access_token'),
- ('mediagoblin.plugins.oauth.list_connections',
- '/oauth-2/client/connections',
- 'mediagoblin.plugins.oauth.views:list_connections'),
- ('mediagoblin.plugins.oauth.register_client',
- '/oauth-2/client/register',
- 'mediagoblin.plugins.oauth.views:register_client'),
- ('mediagoblin.plugins.oauth.list_clients',
- '/oauth-2/client/list',
- 'mediagoblin.plugins.oauth.views:list_clients')]
-
- pluginapi.register_routes(routes)
- pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
-
-
-class OAuthAuth(Auth):
- def trigger(self, request):
- if 'access_token' in request.GET:
- return True
-
- return False
-
- def __call__(self, request, *args, **kw):
- self.errors = []
- # TODO: Add suport for client credentials authorization
- client_id = request.GET.get('client_id') # TODO: Not used
- client_secret = request.GET.get('client_secret') # TODO: Not used
- access_token = request.GET.get('access_token')
-
- _log.debug('Authorizing request {0}'.format(request.url))
-
- if access_token:
- token = OAuthToken.query.filter(OAuthToken.token == access_token)\
- .first()
-
- if not token:
- self.errors.append('Invalid access token')
- return False
-
- _log.debug('Access token: {0}'.format(token))
- _log.debug('Client: {0}'.format(token.client))
-
- relation = OAuthUserClient.query.filter(
- (OAuthUserClient.user == token.user)
- & (OAuthUserClient.client == token.client)
- & (OAuthUserClient.state == u'approved')).first()
-
- _log.debug('Relation: {0}'.format(relation))
-
- if not relation:
- self.errors.append(
- u'Client has not been approved by the resource owner')
- return False
-
- request.user = token.user
- return True
-
- self.errors.append(u'No access_token specified')
-
- return False
-
-hooks = {
- 'setup': setup_plugin,
- 'auth': OAuthAuth()
- }
diff --git a/mediagoblin/plugins/oauth/forms.py b/mediagoblin/plugins/oauth/forms.py
deleted file mode 100644
index ddf4d390..00000000
--- a/mediagoblin/plugins/oauth/forms.py
+++ /dev/null
@@ -1,69 +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 <http://www.gnu.org/licenses/>.
-
-import wtforms
-
-from urlparse import urlparse
-
-from mediagoblin.tools.extlib.wtf_html5 import URLField
-from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
-
-
-class AuthorizationForm(wtforms.Form):
- client_id = wtforms.HiddenField(u'',
- validators=[wtforms.validators.InputRequired()])
- next = wtforms.HiddenField(u'', validators=[wtforms.validators.InputRequired()])
- allow = wtforms.SubmitField(_(u'Allow'))
- deny = wtforms.SubmitField(_(u'Deny'))
-
-
-class ClientRegistrationForm(wtforms.Form):
- name = wtforms.TextField(_('Name'), [wtforms.validators.InputRequired()],
- description=_('The name of the OAuth client'))
- description = wtforms.TextAreaField(_('Description'),
- [wtforms.validators.Length(min=0, max=500)],
- description=_('''This will be visible to users allowing your
- application to authenticate as them.'''))
- type = wtforms.SelectField(_('Type'),
- [wtforms.validators.InputRequired()],
- choices=[
- ('confidential', 'Confidential'),
- ('public', 'Public')],
- description=_('''<strong>Confidential</strong> - The client can
- make requests to the GNU MediaGoblin instance that can not be
- intercepted by the user agent (e.g. server-side client).<br />
- <strong>Public</strong> - The client can't make confidential
- requests to the GNU MediaGoblin instance (e.g. client-side
- JavaScript client).'''))
-
- redirect_uri = URLField(_('Redirect URI'),
- [wtforms.validators.Optional(), wtforms.validators.URL()],
- description=_('''The redirect URI for the applications, this field
- is <strong>required</strong> for public clients.'''))
-
- def __init__(self, *args, **kw):
- wtforms.Form.__init__(self, *args, **kw)
-
- def validate(self):
- if not wtforms.Form.validate(self):
- return False
-
- if self.type.data == 'public' and not self.redirect_uri.data:
- self.redirect_uri.errors.append(
- _('This field is required for public clients'))
- return False
-
- return True
diff --git a/mediagoblin/plugins/oauth/migrations.py b/mediagoblin/plugins/oauth/migrations.py
deleted file mode 100644
index d7b89da3..00000000
--- a/mediagoblin/plugins/oauth/migrations.py
+++ /dev/null
@@ -1,158 +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 <http://www.gnu.org/licenses/>.
-
-from datetime import datetime, timedelta
-from sqlalchemy import (MetaData, Table, Column,
- Integer, Unicode, Enum, DateTime, ForeignKey)
-from sqlalchemy.ext.declarative import declarative_base
-
-from mediagoblin.db.migration_tools import RegisterMigration
-from mediagoblin.db.models import User
-
-
-MIGRATIONS = {}
-
-
-class OAuthClient_v0(declarative_base()):
- __tablename__ = 'oauth__client'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
-
- name = Column(Unicode)
- description = Column(Unicode)
-
- identifier = Column(Unicode, unique=True, index=True)
- secret = Column(Unicode, index=True)
-
- owner_id = Column(Integer, ForeignKey(User.id))
- redirect_uri = Column(Unicode)
-
- type = Column(Enum(
- u'confidential',
- u'public',
- name=u'oauth__client_type'))
-
-
-class OAuthUserClient_v0(declarative_base()):
- __tablename__ = 'oauth__user_client'
- id = Column(Integer, primary_key=True)
-
- user_id = Column(Integer, ForeignKey(User.id))
- client_id = Column(Integer, ForeignKey(OAuthClient_v0.id))
-
- state = Column(Enum(
- u'approved',
- u'rejected',
- name=u'oauth__relation_state'))
-
-
-class OAuthToken_v0(declarative_base()):
- __tablename__ = 'oauth__tokens'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
- expires = Column(DateTime, nullable=False,
- default=lambda: datetime.now() + timedelta(days=30))
- token = Column(Unicode, index=True)
- refresh_token = Column(Unicode, index=True)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False,
- index=True)
-
- client_id = Column(Integer, ForeignKey(OAuthClient_v0.id), nullable=False)
-
- def __repr__(self):
- return '<{0} #{1} expires {2} [{3}, {4}]>'.format(
- self.__class__.__name__,
- self.id,
- self.expires.isoformat(),
- self.user,
- self.client)
-
-
-class OAuthCode_v0(declarative_base()):
- __tablename__ = 'oauth__codes'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
- expires = Column(DateTime, nullable=False,
- default=lambda: datetime.now() + timedelta(minutes=5))
- code = Column(Unicode, index=True)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False,
- index=True)
-
- client_id = Column(Integer, ForeignKey(OAuthClient_v0.id), nullable=False)
-
-
-class OAuthRefreshToken_v0(declarative_base()):
- __tablename__ = 'oauth__refresh_tokens'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
-
- token = Column(Unicode, index=True)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False)
-
- # XXX: Is it OK to use OAuthClient_v0.id in this way?
- client_id = Column(Integer, ForeignKey(OAuthClient_v0.id), nullable=False)
-
-
-@RegisterMigration(1, MIGRATIONS)
-def remove_and_replace_token_and_code(db):
- metadata = MetaData(bind=db.bind)
-
- token_table = Table('oauth__tokens', metadata, autoload=True,
- autoload_with=db.bind)
-
- token_table.drop()
-
- code_table = Table('oauth__codes', metadata, autoload=True,
- autoload_with=db.bind)
-
- code_table.drop()
-
- OAuthClient_v0.__table__.create(db.bind)
- OAuthUserClient_v0.__table__.create(db.bind)
- OAuthToken_v0.__table__.create(db.bind)
- OAuthCode_v0.__table__.create(db.bind)
-
- db.commit()
-
-
-@RegisterMigration(2, MIGRATIONS)
-def remove_refresh_token_field(db):
- metadata = MetaData(bind=db.bind)
-
- token_table = Table('oauth__tokens', metadata, autoload=True,
- autoload_with=db.bind)
-
- refresh_token = token_table.columns['refresh_token']
-
- refresh_token.drop()
- db.commit()
-
-@RegisterMigration(3, MIGRATIONS)
-def create_refresh_token_table(db):
- OAuthRefreshToken_v0.__table__.create(db.bind)
-
- db.commit()
diff --git a/mediagoblin/plugins/oauth/models.py b/mediagoblin/plugins/oauth/models.py
deleted file mode 100644
index 439424d3..00000000
--- a/mediagoblin/plugins/oauth/models.py
+++ /dev/null
@@ -1,192 +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 <http://www.gnu.org/licenses/>.
-
-
-from datetime import datetime, timedelta
-
-
-from sqlalchemy import (
- Column, Unicode, Integer, DateTime, ForeignKey, Enum)
-from sqlalchemy.orm import relationship, backref
-from mediagoblin.db.base import Base
-from mediagoblin.db.models import User
-from mediagoblin.plugins.oauth.tools import generate_identifier, \
- generate_secret, generate_token, generate_code, generate_refresh_token
-
-# Don't remove this, I *think* it applies sqlalchemy-migrate functionality onto
-# the models.
-from migrate import changeset
-
-
-class OAuthClient(Base):
- __tablename__ = 'oauth__client'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
-
- name = Column(Unicode)
- description = Column(Unicode)
-
- identifier = Column(Unicode, unique=True, index=True,
- default=generate_identifier)
- secret = Column(Unicode, index=True, default=generate_secret)
-
- owner_id = Column(Integer, ForeignKey(User.id))
- owner = relationship(
- User,
- backref=backref('registered_clients', cascade='all, delete-orphan'))
-
- redirect_uri = Column(Unicode)
-
- type = Column(Enum(
- u'confidential',
- u'public',
- name=u'oauth__client_type'))
-
- def update_secret(self):
- self.secret = generate_secret()
-
- def __repr__(self):
- return '<{0} {1}:{2} ({3})>'.format(
- self.__class__.__name__,
- self.id,
- self.name.encode('ascii', 'replace'),
- self.owner.username.encode('ascii', 'replace'))
-
-
-class OAuthUserClient(Base):
- __tablename__ = 'oauth__user_client'
- id = Column(Integer, primary_key=True)
-
- user_id = Column(Integer, ForeignKey(User.id))
- user = relationship(
- User,
- backref=backref('oauth_client_relations',
- cascade='all, delete-orphan'))
-
- client_id = Column(Integer, ForeignKey(OAuthClient.id))
- client = relationship(
- OAuthClient,
- backref=backref('oauth_user_relations', cascade='all, delete-orphan'))
-
- state = Column(Enum(
- u'approved',
- u'rejected',
- name=u'oauth__relation_state'))
-
- def __repr__(self):
- return '<{0} #{1} {2} [{3}, {4}]>'.format(
- self.__class__.__name__,
- self.id,
- self.state.encode('ascii', 'replace'),
- self.user,
- self.client)
-
-
-class OAuthToken(Base):
- __tablename__ = 'oauth__tokens'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
- expires = Column(DateTime, nullable=False,
- default=lambda: datetime.now() + timedelta(days=30))
- token = Column(Unicode, index=True, default=generate_token)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False,
- index=True)
- user = relationship(
- User,
- backref=backref('oauth_tokens', cascade='all, delete-orphan'))
-
- client_id = Column(Integer, ForeignKey(OAuthClient.id), nullable=False)
- client = relationship(
- OAuthClient,
- backref=backref('oauth_tokens', cascade='all, delete-orphan'))
-
- def __repr__(self):
- return '<{0} #{1} expires {2} [{3}, {4}]>'.format(
- self.__class__.__name__,
- self.id,
- self.expires.isoformat(),
- self.user,
- self.client)
-
-class OAuthRefreshToken(Base):
- __tablename__ = 'oauth__refresh_tokens'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
-
- token = Column(Unicode, index=True,
- default=generate_refresh_token)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False)
-
- user = relationship(User, backref=backref('oauth_refresh_tokens',
- cascade='all, delete-orphan'))
-
- client_id = Column(Integer, ForeignKey(OAuthClient.id), nullable=False)
- client = relationship(OAuthClient,
- backref=backref(
- 'oauth_refresh_tokens',
- cascade='all, delete-orphan'))
-
- def __repr__(self):
- return '<{0} #{1} [{3}, {4}]>'.format(
- self.__class__.__name__,
- self.id,
- self.user,
- self.client)
-
-
-class OAuthCode(Base):
- __tablename__ = 'oauth__codes'
-
- id = Column(Integer, primary_key=True)
- created = Column(DateTime, nullable=False,
- default=datetime.now)
- expires = Column(DateTime, nullable=False,
- default=lambda: datetime.now() + timedelta(minutes=5))
- code = Column(Unicode, index=True, default=generate_code)
-
- user_id = Column(Integer, ForeignKey(User.id), nullable=False,
- index=True)
- user = relationship(User, backref=backref('oauth_codes',
- cascade='all, delete-orphan'))
-
- client_id = Column(Integer, ForeignKey(OAuthClient.id), nullable=False)
- client = relationship(OAuthClient, backref=backref(
- 'oauth_codes',
- cascade='all, delete-orphan'))
-
- def __repr__(self):
- return '<{0} #{1} expires {2} [{3}, {4}]>'.format(
- self.__class__.__name__,
- self.id,
- self.expires.isoformat(),
- self.user,
- self.client)
-
-
-MODELS = [
- OAuthToken,
- OAuthRefreshToken,
- OAuthCode,
- OAuthClient,
- OAuthUserClient]
diff --git a/mediagoblin/plugins/oauth/templates/oauth/authorize.html b/mediagoblin/plugins/oauth/templates/oauth/authorize.html
deleted file mode 100644
index 8a00c925..00000000
--- a/mediagoblin/plugins/oauth/templates/oauth/authorize.html
+++ /dev/null
@@ -1,31 +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.
-#, se, seee
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
--#}
-{% extends "mediagoblin/base.html" %}
-{% import "mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-<form action="{{ request.urlgen('mediagoblin.plugins.oauth.authorize_client') }}"
- method="POST">
- <div class="form_box_xl">
- {{ csrf_token }}
- <h2>Authorize {{ client.name }}?</h2>
- <p class="client-description">{{ client.description }}</p>
- {{ wtforms_util.render_divs(form) }}
- </div>
-</form>
-{% endblock %}
diff --git a/mediagoblin/plugins/oauth/templates/oauth/client/connections.html b/mediagoblin/plugins/oauth/templates/oauth/client/connections.html
deleted file mode 100644
index 63b0230a..00000000
--- a/mediagoblin/plugins/oauth/templates/oauth/client/connections.html
+++ /dev/null
@@ -1,34 +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 <http://www.gnu.org/licenses/>.
--#}
-{% extends "mediagoblin/base.html" %}
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-<h1>{% trans %}OAuth client connections{% endtrans %}</h1>
-{% if connections %}
-<ul>
- {% for connection in connections %}
- <li><span title="{{ connection.client.description }}">{{
- connection.client.name }}</span> - {{ connection.state }}
- </li>
- {% endfor %}
-</ul>
-{% else %}
-<p>You haven't connected using an OAuth client before.</p>
-{% endif %}
-{% endblock %}
diff --git a/mediagoblin/plugins/oauth/templates/oauth/client/list.html b/mediagoblin/plugins/oauth/templates/oauth/client/list.html
deleted file mode 100644
index 21024bb7..00000000
--- a/mediagoblin/plugins/oauth/templates/oauth/client/list.html
+++ /dev/null
@@ -1,45 +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 <http://www.gnu.org/licenses/>.
--#}
-{% extends "mediagoblin/base.html" %}
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-<h1>{% trans %}Your OAuth clients{% endtrans %}</h1>
-{% if clients %}
-<ul>
- {% for client in clients %}
- <li>{{ client.name }}
- <dl>
- <dt>Type</dt>
- <dd>{{ client.type }}</dd>
- <dt>Description</dt>
- <dd>{{ client.description }}</dd>
- <dt>Identifier</dt>
- <dd>{{ client.identifier }}</dd>
- <dt>Secret</dt>
- <dd>{{ client.secret }}</dd>
- <dt>Redirect URI<dt>
- <dd>{{ client.redirect_uri }}</dd>
- </dl>
- </li>
- {% endfor %}
-</ul>
-{% else %}
-<p>You don't have any clients yet. <a href="{{ request.urlgen('mediagoblin.plugins.oauth.register_client') }}">Add one</a>.</p>
-{% endif %}
-{% endblock %}
diff --git a/mediagoblin/plugins/oauth/templates/oauth/client/register.html b/mediagoblin/plugins/oauth/templates/oauth/client/register.html
deleted file mode 100644
index 6fd700d3..00000000
--- a/mediagoblin/plugins/oauth/templates/oauth/client/register.html
+++ /dev/null
@@ -1,34 +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 <http://www.gnu.org/licenses/>.
--#}
-{% extends "mediagoblin/base.html" %}
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-<form action="{{ request.urlgen('mediagoblin.plugins.oauth.register_client') }}"
- method="POST">
- <div class="form_box_xl">
- <h1>Register OAuth client</h1>
- {{ wtforms_util.render_divs(form) }}
- <div class="form_submit_buttons">
- {{ csrf_token }}
- <input type="submit" value="{% trans %}Add{% endtrans %}"
- class="button_form" />
- </div>
- </div>
-</form>
-{% endblock %}
diff --git a/mediagoblin/plugins/oauth/tools.py b/mediagoblin/plugins/oauth/tools.py
deleted file mode 100644
index af0a3305..00000000
--- a/mediagoblin/plugins/oauth/tools.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# -*- coding: utf-8 -*-
-# 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/>.
-
-import uuid
-
-from random import getrandbits
-
-from datetime import datetime
-
-from functools import wraps
-
-from mediagoblin.tools.response import json_response
-
-
-def require_client_auth(controller):
- '''
- View decorator
-
- - Requires the presence of ``?client_id``
- '''
- # Avoid circular import
- from mediagoblin.plugins.oauth.models import OAuthClient
-
- @wraps(controller)
- def wrapper(request, *args, **kw):
- if not request.GET.get('client_id'):
- return json_response({
- 'status': 400,
- 'errors': [u'No client identifier in URL']},
- _disable_cors=True)
-
- client = OAuthClient.query.filter(
- OAuthClient.identifier == request.GET.get('client_id')).first()
-
- if not client:
- return json_response({
- 'status': 400,
- 'errors': [u'No such client identifier']},
- _disable_cors=True)
-
- return controller(request, client)
-
- return wrapper
-
-
-def create_token(client, user):
- '''
- Create an OAuthToken and an OAuthRefreshToken entry in the database
-
- Returns the data structure expected by the OAuth clients.
- '''
- from mediagoblin.plugins.oauth.models import OAuthToken, OAuthRefreshToken
-
- token = OAuthToken()
- token.user = user
- token.client = client
- token.save()
-
- refresh_token = OAuthRefreshToken()
- refresh_token.user = user
- refresh_token.client = client
- refresh_token.save()
-
- # expire time of token in full seconds
- # timedelta.total_seconds is python >= 2.7 or we would use that
- td = token.expires - datetime.now()
- exp_in = 86400*td.days + td.seconds # just ignore µsec
-
- return {'access_token': token.token, 'token_type': 'bearer',
- 'refresh_token': refresh_token.token, 'expires_in': exp_in}
-
-
-def generate_identifier():
- ''' Generates a ``uuid.uuid4()`` '''
- return unicode(uuid.uuid4())
-
-
-def generate_token():
- ''' Uses generate_identifier '''
- return generate_identifier()
-
-
-def generate_refresh_token():
- ''' Uses generate_identifier '''
- return generate_identifier()
-
-
-def generate_code():
- ''' Uses generate_identifier '''
- return generate_identifier()
-
-
-def generate_secret():
- '''
- Generate a long string of pseudo-random characters
- '''
- # XXX: We might not want it to use bcrypt, since bcrypt takes its time to
- # generate the result.
- return unicode(getrandbits(192))
-
diff --git a/mediagoblin/plugins/oauth/views.py b/mediagoblin/plugins/oauth/views.py
deleted file mode 100644
index de637d6b..00000000
--- a/mediagoblin/plugins/oauth/views.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# -*- coding: utf-8 -*-
-# 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/>.
-
-import logging
-
-from urllib import urlencode
-
-from werkzeug.exceptions import BadRequest
-
-from mediagoblin.tools.response import render_to_response, redirect, json_response
-from mediagoblin.decorators import require_active_login
-from mediagoblin.messages import add_message, SUCCESS
-from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.plugins.oauth.models import OAuthCode, OAuthClient, \
- OAuthUserClient, OAuthRefreshToken
-from mediagoblin.plugins.oauth.forms import ClientRegistrationForm, \
- AuthorizationForm
-from mediagoblin.plugins.oauth.tools import require_client_auth, \
- create_token
-
-_log = logging.getLogger(__name__)
-
-
-@require_active_login
-def register_client(request):
- '''
- Register an OAuth client
- '''
- form = ClientRegistrationForm(request.form)
-
- if request.method == 'POST' and form.validate():
- client = OAuthClient()
- client.name = unicode(form.name.data)
- client.description = unicode(form.description.data)
- client.type = unicode(form.type.data)
- client.owner_id = request.user.id
- client.redirect_uri = unicode(form.redirect_uri.data)
-
- client.save()
-
- add_message(request, SUCCESS, _('The client {0} has been registered!')\
- .format(
- client.name))
-
- return redirect(request, 'mediagoblin.plugins.oauth.list_clients')
-
- return render_to_response(
- request,
- 'oauth/client/register.html',
- {'form': form})
-
-
-@require_active_login
-def list_clients(request):
- clients = request.db.OAuthClient.query.filter(
- OAuthClient.owner_id == request.user.id).all()
- return render_to_response(request, 'oauth/client/list.html',
- {'clients': clients})
-
-
-@require_active_login
-def list_connections(request):
- connections = OAuthUserClient.query.filter(
- OAuthUserClient.user == request.user).all()
- return render_to_response(request, 'oauth/client/connections.html',
- {'connections': connections})
-
-
-@require_active_login
-def authorize_client(request):
- form = AuthorizationForm(request.form)
-
- client = OAuthClient.query.filter(OAuthClient.id ==
- form.client_id.data).first()
-
- if not client:
- _log.error('No such client id as received from client authorization \
-form.')
- raise BadRequest()
-
- if form.validate():
- relation = OAuthUserClient()
- relation.user_id = request.user.id
- relation.client_id = form.client_id.data
- if form.allow.data:
- relation.state = u'approved'
- elif form.deny.data:
- relation.state = u'rejected'
- else:
- raise BadRequest()
-
- relation.save()
-
- return redirect(request, location=form.next.data)
-
- return render_to_response(
- request,
- 'oauth/authorize.html',
- {'form': form,
- 'client': client})
-
-
-@require_client_auth
-@require_active_login
-def authorize(request, client):
- # TODO: Get rid of the JSON responses in this view, it's called by the
- # user-agent, not the client.
- user_client_relation = OAuthUserClient.query.filter(
- (OAuthUserClient.user == request.user)
- & (OAuthUserClient.client == client))
-
- if user_client_relation.filter(OAuthUserClient.state ==
- u'approved').count():
- redirect_uri = None
-
- if client.type == u'public':
- if not client.redirect_uri:
- return json_response({
- 'status': 400,
- 'errors':
- [u'Public clients should have a redirect_uri pre-set.']},
- _disable_cors=True)
-
- redirect_uri = client.redirect_uri
-
- if client.type == u'confidential':
- redirect_uri = request.GET.get('redirect_uri', client.redirect_uri)
- if not redirect_uri:
- return json_response({
- 'status': 400,
- 'errors': [u'No redirect_uri supplied!']},
- _disable_cors=True)
-
- code = OAuthCode()
- code.user = request.user
- code.client = client
- code.save()
-
- redirect_uri = ''.join([
- redirect_uri,
- '?',
- urlencode({'code': code.code})])
-
- _log.debug('Redirecting to {0}'.format(redirect_uri))
-
- return redirect(request, location=redirect_uri)
- else:
- # Show prompt to allow client to access data
- # - on accept: send the user agent back to the redirect_uri with the
- # code parameter
- # - on deny: send the user agent back to the redirect uri with error
- # information
- form = AuthorizationForm(request.form)
- form.client_id.data = client.id
- form.next.data = request.url
- return render_to_response(
- request,
- 'oauth/authorize.html',
- {'form': form,
- 'client': client})
-
-
-def access_token(request):
- '''
- Access token endpoint provides access tokens to any clients that have the
- right grants/credentials
- '''
-
- client = None
- user = None
-
- if request.GET.get('code'):
- # Validate the code arg, then get the client object from the db.
- code = OAuthCode.query.filter(OAuthCode.code ==
- request.GET.get('code')).first()
-
- if not code:
- return json_response({
- 'error': 'invalid_request',
- 'error_description':
- 'Invalid code.'})
-
- client = code.client
- user = code.user
-
- elif request.args.get('refresh_token'):
- # Validate a refresh token, then get the client object from the db.
- refresh_token = OAuthRefreshToken.query.filter(
- OAuthRefreshToken.token ==
- request.args.get('refresh_token')).first()
-
- if not refresh_token:
- return json_response({
- 'error': 'invalid_request',
- 'error_description':
- 'Invalid refresh token.'})
-
- client = refresh_token.client
- user = refresh_token.user
-
- if client:
- client_identifier = request.GET.get('client_id')
-
- if not client_identifier:
- return json_response({
- 'error': 'invalid_request',
- 'error_description':
- 'Missing client_id in request.'})
-
- if not client_identifier == client.identifier:
- return json_response({
- 'error': 'invalid_client',
- 'error_description':
- 'Mismatching client credentials.'})
-
- if client.type == u'confidential':
- client_secret = request.GET.get('client_secret')
-
- if not client_secret:
- return json_response({
- 'error': 'invalid_request',
- 'error_description':
- 'Missing client_secret in request.'})
-
- if not client_secret == client.secret:
- return json_response({
- 'error': 'invalid_client',
- 'error_description':
- 'Mismatching client credentials.'})
-
-
- access_token_data = create_token(client, user)
-
- return json_response(access_token_data, _disable_cors=True)
-
- return json_response({
- 'error': 'invalid_request',
- 'error_description':
- 'Missing `code` or `refresh_token` parameter in request.'})
diff --git a/mediagoblin/plugins/openid/forms.py b/mediagoblin/plugins/openid/forms.py
index d47369dc..6dfde0c8 100644
--- a/mediagoblin/plugins/openid/forms.py
+++ b/mediagoblin/plugins/openid/forms.py
@@ -23,18 +23,18 @@ class RegistrationForm(wtforms.Form):
openid = wtforms.HiddenField(
'',
[wtforms.validators.InputRequired()])
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_email=False)])
- email = wtforms.TextField(
+ email = wtforms.StringField(
_('Email address'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_user=False)])
class LoginForm(wtforms.Form):
- openid = wtforms.TextField(
+ openid = wtforms.StringField(
_('OpenID'),
[wtforms.validators.InputRequired(),
# Can openid's only be urls?
diff --git a/mediagoblin/plugins/openid/store.py b/mediagoblin/plugins/openid/store.py
index 8f9a7012..24726814 100644
--- a/mediagoblin/plugins/openid/store.py
+++ b/mediagoblin/plugins/openid/store.py
@@ -16,6 +16,8 @@
import base64
import time
+import six
+
from openid.association import Association as OIDAssociation
from openid.store.interface import OpenIDStore
from openid.store import nonce
@@ -34,12 +36,12 @@ class SQLAlchemyOpenIDStore(OpenIDStore):
if not assoc:
assoc = Association()
- assoc.server_url = unicode(server_url)
+ assoc.server_url = six.text_type(server_url)
assoc.handle = association.handle
# django uses base64 encoding, python-openid uses a blob field for
# secret
- assoc.secret = unicode(base64.encodestring(association.secret))
+ assoc.secret = six.text_type(base64.encodestring(association.secret))
assoc.issued = association.issued
assoc.lifetime = association.lifetime
assoc.assoc_type = association.assoc_type
diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py
index bb2de7ab..71f444fa 100644
--- a/mediagoblin/plugins/openid/views.py
+++ b/mediagoblin/plugins/openid/views.py
@@ -13,6 +13,9 @@
#
# 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 six
+
from openid.consumer import consumer
from openid.consumer.discover import DiscoveryFailure
from openid.extensions.sreg import SRegRequest, SRegResponse
@@ -186,7 +189,7 @@ def finish_login(request):
if user:
# Set up login in session
- request.session['user_id'] = unicode(user.id)
+ request.session['user_id'] = six.text_type(user.id)
request.session.save()
if request.session.get('next'):
diff --git a/mediagoblin/plugins/persona/forms.py b/mediagoblin/plugins/persona/forms.py
index 7d632344..f74d97fa 100644
--- a/mediagoblin/plugins/persona/forms.py
+++ b/mediagoblin/plugins/persona/forms.py
@@ -20,11 +20,11 @@ from mediagoblin.auth.tools import normalize_user_or_email_field
class RegistrationForm(wtforms.Form):
- username = wtforms.TextField(
+ username = wtforms.StringField(
_('Username'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_email=False)])
- email = wtforms.TextField(
+ email = wtforms.StringField(
_('Email address'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_user=False)])
@@ -35,7 +35,7 @@ class RegistrationForm(wtforms.Form):
class EditForm(wtforms.Form):
- email = wtforms.TextField(
+ email = wtforms.StringField(
_('Email address'),
[wtforms.validators.InputRequired(),
normalize_user_or_email_field(allow_user=False)])
diff --git a/mediagoblin/plugins/persona/views.py b/mediagoblin/plugins/persona/views.py
index 1bba3b8c..41d38353 100644
--- a/mediagoblin/plugins/persona/views.py
+++ b/mediagoblin/plugins/persona/views.py
@@ -17,6 +17,8 @@ import json
import logging
import requests
+import six
+
from werkzeug.exceptions import BadRequest
from mediagoblin import messages, mg_globals
@@ -63,7 +65,7 @@ def login(request):
user = query.user if query else None
if user:
- request.session['user_id'] = unicode(user.id)
+ request.session['user_id'] = six.text_type(user.id)
request.session['persona_login_email'] = email
request.session.save()
diff --git a/mediagoblin/plugins/piwigo/forms.py b/mediagoblin/plugins/piwigo/forms.py
index fd545a3e..b501562b 100644
--- a/mediagoblin/plugins/piwigo/forms.py
+++ b/mediagoblin/plugins/piwigo/forms.py
@@ -20,10 +20,10 @@ import wtforms
class AddSimpleForm(wtforms.Form):
image = wtforms.FileField()
- name = wtforms.TextField(
+ name = wtforms.StringField(
validators=[wtforms.validators.Length(min=0, max=500)])
- comment = wtforms.TextField()
- # tags = wtforms.FieldList(wtforms.TextField())
+ comment = wtforms.StringField()
+ # tags = wtforms.FieldList(wtforms.StringField())
category = wtforms.IntegerField()
level = wtforms.IntegerField()
@@ -32,13 +32,13 @@ _md5_validator = wtforms.validators.Regexp(r"^[0-9a-fA-F]{32}$")
class AddForm(wtforms.Form):
- original_sum = wtforms.TextField(None,
+ original_sum = wtforms.StringField(None,
[_md5_validator,
wtforms.validators.InputRequired()])
- thumbnail_sum = wtforms.TextField(None,
+ thumbnail_sum = wtforms.StringField(None,
[wtforms.validators.Optional(),
_md5_validator])
- file_sum = wtforms.TextField(None, [_md5_validator])
- name = wtforms.TextField()
- date_creation = wtforms.TextField()
- categories = wtforms.TextField()
+ file_sum = wtforms.StringField(None, [_md5_validator])
+ name = wtforms.StringField()
+ date_creation = wtforms.StringField()
+ categories = wtforms.StringField()
diff --git a/mediagoblin/plugins/piwigo/tools.py b/mediagoblin/plugins/piwigo/tools.py
index 484ea531..7b9b7af3 100644
--- a/mediagoblin/plugins/piwigo/tools.py
+++ b/mediagoblin/plugins/piwigo/tools.py
@@ -47,7 +47,7 @@ class PwgNamedArray(list):
def _fill_element_dict(el, data, as_attr=()):
- for k, v in data.iteritems():
+ for k, v in six.iteritems(data):
if k in as_attr:
if not isinstance(v, six.string_types):
v = str(v)
diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py
index f913a730..1fe1e576 100644
--- a/mediagoblin/plugins/piwigo/views.py
+++ b/mediagoblin/plugins/piwigo/views.py
@@ -17,6 +17,8 @@
import logging
import re
+import six
+
from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented
from werkzeug.wrappers import BaseResponse
@@ -133,8 +135,8 @@ def pwg_images_addSimple(request):
mg_app=request.app, user=request.user,
submitted_file=request.files['image'],
filename=request.files['image'].filename,
- title=unicode(form.name.data),
- description=unicode(form.comment.data),
+ title=six.text_type(form.name.data),
+ description=six.text_type(form.comment.data),
upload_limit=upload_limit, max_file_size=max_file_size)
collection_id = form.category.data