1# Copyright 2016 Google Inc. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Google App Engine utilities helper. 16 17Classes that directly require App Engine's ndb library. Provided 18as a separate module in case of failure to import ndb while 19other App Engine libraries are present. 20""" 21 22import logging 23 24from google.appengine.ext import ndb 25 26from oauth2client import client 27 28 29NDB_KEY = ndb.Key 30"""Key constant used by :mod:`oauth2client.contrib.appengine`.""" 31 32NDB_MODEL = ndb.Model 33"""Model constant used by :mod:`oauth2client.contrib.appengine`.""" 34 35_LOGGER = logging.getLogger(__name__) 36 37 38class SiteXsrfSecretKeyNDB(ndb.Model): 39 """NDB Model for storage for the sites XSRF secret key. 40 41 Since this model uses the same kind as SiteXsrfSecretKey, it can be 42 used interchangeably. This simply provides an NDB model for interacting 43 with the same data the DB model interacts with. 44 45 There should only be one instance stored of this model, the one used 46 for the site. 47 """ 48 secret = ndb.StringProperty() 49 50 @classmethod 51 def _get_kind(cls): 52 """Return the kind name for this class.""" 53 return 'SiteXsrfSecretKey' 54 55 56class FlowNDBProperty(ndb.PickleProperty): 57 """App Engine NDB datastore Property for Flow. 58 59 Serves the same purpose as the DB FlowProperty, but for NDB models. 60 Since PickleProperty inherits from BlobProperty, the underlying 61 representation of the data in the datastore will be the same as in the 62 DB case. 63 64 Utility property that allows easy storage and retrieval of an 65 oauth2client.Flow 66 """ 67 68 def _validate(self, value): 69 """Validates a value as a proper Flow object. 70 71 Args: 72 value: A value to be set on the property. 73 74 Raises: 75 TypeError if the value is not an instance of Flow. 76 """ 77 _LOGGER.info('validate: Got type %s', type(value)) 78 if value is not None and not isinstance(value, client.Flow): 79 raise TypeError( 80 'Property {0} must be convertible to a flow ' 81 'instance; received: {1}.'.format(self._name, value)) 82 83 84class CredentialsNDBProperty(ndb.BlobProperty): 85 """App Engine NDB datastore Property for Credentials. 86 87 Serves the same purpose as the DB CredentialsProperty, but for NDB 88 models. Since CredentialsProperty stores data as a blob and this 89 inherits from BlobProperty, the data in the datastore will be the same 90 as in the DB case. 91 92 Utility property that allows easy storage and retrieval of Credentials 93 and subclasses. 94 """ 95 96 def _validate(self, value): 97 """Validates a value as a proper credentials object. 98 99 Args: 100 value: A value to be set on the property. 101 102 Raises: 103 TypeError if the value is not an instance of Credentials. 104 """ 105 _LOGGER.info('validate: Got type %s', type(value)) 106 if value is not None and not isinstance(value, client.Credentials): 107 raise TypeError( 108 'Property {0} must be convertible to a credentials ' 109 'instance; received: {1}.'.format(self._name, value)) 110 111 def _to_base_type(self, value): 112 """Converts our validated value to a JSON serialized string. 113 114 Args: 115 value: A value to be set in the datastore. 116 117 Returns: 118 A JSON serialized version of the credential, else '' if value 119 is None. 120 """ 121 if value is None: 122 return '' 123 else: 124 return value.to_json() 125 126 def _from_base_type(self, value): 127 """Converts our stored JSON string back to the desired type. 128 129 Args: 130 value: A value from the datastore to be converted to the 131 desired type. 132 133 Returns: 134 A deserialized Credentials (or subclass) object, else None if 135 the value can't be parsed. 136 """ 137 if not value: 138 return None 139 try: 140 # Uses the from_json method of the implied class of value 141 credentials = client.Credentials.new_from_json(value) 142 except ValueError: 143 credentials = None 144 return credentials 145 146 147class CredentialsNDBModel(ndb.Model): 148 """NDB Model for storage of OAuth 2.0 Credentials 149 150 Since this model uses the same kind as CredentialsModel and has a 151 property which can serialize and deserialize Credentials correctly, it 152 can be used interchangeably with a CredentialsModel to access, insert 153 and delete the same entities. This simply provides an NDB model for 154 interacting with the same data the DB model interacts with. 155 156 Storage of the model is keyed by the user.user_id(). 157 """ 158 credentials = CredentialsNDBProperty() 159 160 @classmethod 161 def _get_kind(cls): 162 """Return the kind name for this class.""" 163 return 'CredentialsModel' 164