| #!/usr/bin/python |
| # |
| # Copyright (C) 2009 Google Inc. |
| # |
| # Licensed 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. |
| |
| |
| """Provides functions to persist serialized auth tokens in the datastore. |
| |
| The get_token and set_token functions should be used in conjunction with |
| gdata.gauth's token_from_blob and token_to_blob to allow auth token objects |
| to be reused across requests. It is up to your own code to ensure that the |
| token key's are unique. |
| """ |
| |
| __author__ = 'j.s@google.com (Jeff Scudder)' |
| |
| |
| from google.appengine.ext import db |
| from google.appengine.api import memcache |
| |
| |
| class Token(db.Model): |
| """Datastore Model which stores a serialized auth token.""" |
| t = db.BlobProperty() |
| |
| |
| def get_token(unique_key): |
| """Searches for a stored token with the desired key. |
| |
| Checks memcache and then the datastore if required. |
| |
| Args: |
| unique_key: str which uniquely identifies the desired auth token. |
| |
| Returns: |
| A string encoding the auth token data. Use gdata.gauth.token_from_blob to |
| convert back into a usable token object. None if the token was not found |
| in memcache or the datastore. |
| """ |
| token_string = memcache.get(unique_key) |
| if token_string is None: |
| # The token wasn't in memcache, so look in the datastore. |
| token = Token.get_by_key_name(unique_key) |
| if token is None: |
| return None |
| return token.t |
| return token_string |
| |
| |
| def set_token(unique_key, token_str): |
| """Saves the serialized auth token in the datastore. |
| |
| The token is also stored in memcache to speed up retrieval on a cache hit. |
| |
| Args: |
| unique_key: The unique name for this token as a string. It is up to your |
| code to ensure that this token value is unique in your application. |
| Previous values will be silently overwitten. |
| token_str: A serialized auth token as a string. I expect that this string |
| will be generated by gdata.gauth.token_to_blob. |
| |
| Returns: |
| True if the token was stored sucessfully, False if the token could not be |
| safely cached (if an old value could not be cleared). If the token was |
| set in memcache, but not in the datastore, this function will return None. |
| However, in that situation an exception will likely be raised. |
| |
| Raises: |
| Datastore exceptions may be raised from the App Engine SDK in the event of |
| failure. |
| """ |
| # First try to save in memcache. |
| result = memcache.set(unique_key, token_str) |
| # If memcache fails to save the value, clear the cached value. |
| if not result: |
| result = memcache.delete(unique_key) |
| # If we could not clear the cached value for this token, refuse to save. |
| if result == 0: |
| return False |
| # Save to the datastore. |
| if Token(key_name=unique_key, t=token_str).put(): |
| return True |
| return None |
| |
| |
| def delete_token(unique_key): |
| # Clear from memcache. |
| memcache.delete(unique_key) |
| # Clear from the datastore. |
| Token(key_name=unique_key).delete() |