aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/plugins/openid/store.py
diff options
context:
space:
mode:
authorRodney Ewing <ewing.rj@gmail.com>2013-06-26 11:20:50 -0700
committerChristopher Allan Webber <cwebber@dustycloud.org>2013-07-03 13:49:16 -0500
commit5adb906a0a4da32f22d4ebd868bfa92929c22011 (patch)
tree9c0098faa92869c8e60da60047a56021eb7c0f74 /mediagoblin/plugins/openid/store.py
parentac0bc6a1e1930e1fb898ce664e6ea8eb5efadbc7 (diff)
downloadmediagoblin-5adb906a0a4da32f22d4ebd868bfa92929c22011.tar.lz
mediagoblin-5adb906a0a4da32f22d4ebd868bfa92929c22011.tar.xz
mediagoblin-5adb906a0a4da32f22d4ebd868bfa92929c22011.zip
merge --squash openid branch to take care of a false merge commit in the
basic_auth branch that openid is forked from Commits squashed together (in reverse chronological order): - do the label thing only for boolean fields - made edit_account to autofocus on the first field - added feature to render_divs where if field.label == '' then it will render form.description the same a render_label - added allow_registration check - refactored create_user - removed verification_key from create_user - removed get_user from openid - cleanup after removing openid from template_env.globals - fix for werkzueg 0.9.1 - cleanup after merge - more tests - restored openid extra_validation just for safety - tests for openid - deleted openid extra_validation - passed next parameter in session for openid - fixed a bug that was deleting the messages - implemented openid store using sqlalchemy - ask openid provider for 'nickname' to prefill username in registration form - refactored delete openid url to work with generic urls such as google and to not allow a user to delete a url if it is there only one and they don't have a pw - refactored login to register user workflow, which fixed a problem where the 'or register with a password link' wasn't showing up when the finish_login view called the register view because there wasn't any redirect. - added the ability to remove openid's - added the ability to add openids to an existing account - refactored start_login and finish_login views - modified edit_account.html to use render_divs - modified gmg/edit/views to behave appropriatly if no password authentication is enabled. moved the update email stuff to it's own funtion to make edit_account view cleaner. edit_account now modifies the form depending on the plugins. - minor typos - added retrieving email from openid provider - moved allow_registration check to a decorator - moved check if auth is enabled to a decorator - changed openid user registration to go through login first - cleanup after merge - modified verification emails to use itsdangerous tokens - added error handling on bad token, fixed route, and added tests - added support for user to change email address - added link to login view openid/password in login template - updated openid get_user function - modified get_user function to take kwargs instead of username - no need for user might be email kwarg in check_login_simple - added gen_password_hash and check_password functions to auth/__init__ - added focus to form input - made imports fully qualified - modified basic_auth.check_login to check that the user has a pw_hash first - changed occurances of form.data['whatever'] to form.whatever.data - convert tabs to spaces in register template, remove unsed templates, and fixed trans tags in templates - in process of openid login. it works, but needs major imporvements - make password field required in basic_auth form - check if password field present in basic_auth create_user - modified openid create_user function - modified models based on Elronds suggestions - changed register form action to a variable to be passed in by the view using the template - openid plugin v0, still need to authenticate via openid. - added a register_user function to be able to use in a plugin's register view, and modified auth/views.register to redirect to openid/register if appropriate. - Modified basic_auth plugin to work with modified auth plugin hooks. Added context variables. Removed basic_auth/tools which was previously renamed to basic_auth/lib. - modified auth/__init__ hooks to work better with multiple plugins. Removed auth/lib.py. And added a basic_extra_verification function that all plugins will use. - added models and migrations for openid plugin
Diffstat (limited to 'mediagoblin/plugins/openid/store.py')
-rw-r--r--mediagoblin/plugins/openid/store.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/mediagoblin/plugins/openid/store.py b/mediagoblin/plugins/openid/store.py
new file mode 100644
index 00000000..b54cf5c8
--- /dev/null
+++ b/mediagoblin/plugins/openid/store.py
@@ -0,0 +1,128 @@
+# 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 base64
+import time
+
+from openid.association import Association as OIDAssociation
+from openid.store.interface import OpenIDStore
+from openid.store import nonce
+
+from mediagoblin.plugins.openid.models import Association, Nonce
+
+
+class SQLAlchemyOpenIDStore(OpenIDStore):
+ def __init__(self):
+ self.max_nonce_age = 6 * 60 * 60
+
+ def storeAssociation(self, server_url, association):
+ assoc = Association.query.filter_by(
+ server_url=server_url, handle=association.handle
+ ).first()
+
+ if not assoc:
+ assoc = Association()
+ assoc.server_url = unicode(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.issued = association.issued
+ assoc.lifetime = association.lifetime
+ assoc.assoc_type = association.assoc_type
+ assoc.save()
+
+ def getAssociation(self, server_url, handle=None):
+ assocs = []
+ if handle is not None:
+ assocs = Association.query.filter_by(
+ server_url=server_url, handle=handle
+ )
+ else:
+ assocs = Association.query.filter_by(
+ server_url=server_url
+ )
+
+ if assocs.count() == 0:
+ return None
+ else:
+ associations = []
+ for assoc in assocs:
+ association = OIDAssociation(
+ assoc.handle, base64.decodestring(assoc.secret),
+ assoc.issued, assoc.lifetime, assoc.assoc_type
+ )
+ if association.getExpiresIn() == 0:
+ assoc.delete()
+ else:
+ associations.append((association.issued, association))
+
+ if not associations:
+ return None
+ associations.sort()
+ return associations[-1][1]
+
+ def removeAssociation(self, server_url, handle):
+ assocs = Association.query.filter_by(
+ server_url=server_url, handle=handle
+ ).first()
+
+ assoc_exists = True if assocs else False
+ for assoc in assocs:
+ assoc.delete()
+ return assoc_exists
+
+ def useNonce(self, server_url, timestamp, salt):
+ if abs(timestamp - time.time()) > nonce.SKEW:
+ return False
+
+ ononce = Nonce.query.filter_by(
+ server_url=server_url,
+ timestamp=timestamp,
+ salt=salt
+ ).first()
+
+ if ononce:
+ return False
+ else:
+ ononce = Nonce()
+ ononce.server_url = server_url
+ ononce.timestamp = timestamp
+ ononce.salt = salt
+ ononce.save()
+ return True
+
+ # Need to test these cleanups, not sure if the expired Association query
+ # will work
+ def cleanupNonces(self, _now=None):
+ if _now is None:
+ _now = int(time.time())
+ expired = Nonce.query.filter(
+ Nonce.timestamp < (_now - nonce.SKEW)
+ )
+ count = expired.count()
+ for each in expired:
+ each.delete()
+ return count
+
+ def cleanupAssociations(self):
+ now = int(time.time())
+ expired = Association.query.filter(
+ 'issued + lifetime' < now)
+ count = expired.count()
+ for each in expired:
+ each.delete()
+ return count