| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| import time |
| from copy import deepcopy |
| from datetime import datetime, timedelta |
| |
| from openid.store import nonce |
| from openid.association import Association |
| |
| from ming.orm import FieldProperty |
| from ming.orm.declarative import MappedClass |
| from .session import main_doc_session, main_orm_session |
| from .session import project_doc_session, project_orm_session |
| |
| class OpenIdAssociation(MappedClass): |
| class __mongometa__: |
| name='oid_store_assoc' |
| session = main_orm_session |
| |
| _id = FieldProperty(str) # server url |
| assocs = FieldProperty([dict( |
| key=str, value=str)]) |
| |
| # Mimic openid.store.memstore.ServerAssocs |
| def set_assoc(self, assoc): |
| for a in self.assocs: |
| if a['key'] == assoc.handle: |
| a['value'] = assoc.serialize() |
| return |
| self.assocs.append(dict(key=assoc.handle, value=assoc.serialize())) |
| |
| def get_assoc(self, handle): |
| for a in self.assocs: |
| if a['key'] == handle: |
| return Association.deserialize(a['value']) |
| return None |
| |
| def remove_assoc(self, handle): |
| old_len = len(self.assocs) |
| self.assocs = [ |
| a for a in self.assocs |
| if a['key'] != handle ] |
| return old_len != len(self.assocs) |
| |
| def best_assoc(self): |
| best = None |
| for assoc in self.assocs: |
| assoc = Association.deserialize(assoc['value']) |
| if best is None or best.issued < assoc.issued: |
| best = assoc |
| if best: |
| return best |
| else: |
| return None |
| |
| def cleanup_assocs(self): |
| old_len = len(self.assocs) |
| self.assocs = [ a for a in self.assocs |
| if Association.deserialize(a['value']).getExpiresIn() != 0 ] |
| new_len = len(self.assocs) |
| return (old_len - new_len), new_len |
| |
| class OpenIdNonce(MappedClass): |
| class __mongometa__: |
| name='oid_store_nonce' |
| session = main_orm_session |
| |
| _id = FieldProperty(str) # Nonce value |
| timestamp = FieldProperty(datetime, if_missing=datetime.utcnow) |
| |
| class OpenIdStore(object): |
| |
| def _get_assocs(self, server_url): |
| assoc = OpenIdAssociation.query.get(_id=server_url) |
| if assoc is None: |
| assoc = OpenIdAssociation(_id=server_url) |
| return assoc |
| |
| def storeAssociation(self, server_url, association): |
| assocs = self._get_assocs(server_url) |
| assocs.set_assoc(deepcopy(association)) |
| |
| def getAssociation(self, server_url, handle=None): |
| assocs = self._get_assocs(server_url) |
| if handle is None: |
| return assocs.best_assoc() |
| else: |
| return assocs.get_assoc(handle) |
| |
| def removeAssociation(self, server_url, handle): |
| assocs = self._get_assocs(server_url) |
| return assocs.remove_assoc(handle) |
| |
| def useNonce(self, server_url, timestamp, salt): |
| if abs(timestamp - time.time()) > nonce.SKEW: |
| return False |
| key = str((server_url, timestamp, salt)) |
| if OpenIdNonce.query.get(_id=key) is None: |
| OpenIdNonce(_id=key) |
| return True |
| else: |
| return False |
| |
| def cleanupNonces(self): |
| now = datetime.utcnow() |
| cutoff = now - timedelta(seconds=nonce.SKEW) |
| num_removed = OpenIdNonce.query.remove(dict( |
| timestamp={'$lt': cutoff})) |
| return num_removed |
| |