blob: 232d4ea3736bfcf7b81aacaceed0a8bd3dc24207 [file] [log] [blame]
Joe Gregorio845a5452010-09-08 13:50:34 -04001# Copyright (C) 2010 Google Inc.
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"""Utilities for Google App Engine
16
17Utilities for making it easier to use the
18Google API Client for Python on Google App Engine.
19"""
20
21__author__ = 'jcgregorio@google.com (Joe Gregorio)'
22
23import pickle
24
25from google.appengine.ext import db
26from apiclient.oauth import OAuthCredentials
27from apiclient.oauth import FlowThreeLegged
28
29
30class FlowThreeLeggedProperty(db.Property):
31 """Utility property that allows easy
32 storage and retreival of an
33 apiclient.oauth.FlowThreeLegged"""
34
35 # Tell what the user type is.
36 data_type = FlowThreeLegged
37
38 # For writing to datastore.
39 def get_value_for_datastore(self, model_instance):
40 flow = super(FlowThreeLeggedProperty,
41 self).get_value_for_datastore(model_instance)
42 return db.Blob(pickle.dumps(flow))
43
44 # For reading from datastore.
45 def make_value_from_datastore(self, value):
46 if value is None:
47 return None
48 return pickle.loads(value)
49
50 def validate(self, value):
51 if value is not None and not isinstance(value, FlowThreeLegged):
52 raise BadValueError('Property %s must be convertible '
53 'to a FlowThreeLegged instance (%s)' %
54 (self.name, value))
55 return super(FlowThreeLeggedProperty, self).validate(value)
56
57 def empty(self, value):
58 return not value
59
60
61class OAuthCredentialsProperty(db.Property):
62 """Utility property that allows easy
63 storage and retrieval of
64 apiclient.oath.OAuthCredentials
65 """
66
67 # Tell what the user type is.
68 data_type = OAuthCredentials
69
70 # For writing to datastore.
71 def get_value_for_datastore(self, model_instance):
72 cred = super(OAuthCredentialsProperty,
73 self).get_value_for_datastore(model_instance)
74 return db.Blob(pickle.dumps(cred))
75
76 # For reading from datastore.
77 def make_value_from_datastore(self, value):
78 if value is None:
79 return None
80 return pickle.loads(value)
81
82 def validate(self, value):
83 if value is not None and not isinstance(value, OAuthCredentials):
84 raise BadValueError('Property %s must be convertible '
85 'to an OAuthCredentials instance (%s)' %
86 (self.name, value))
87 return super(OAuthCredentialsProperty, self).validate(value)
88
89 def empty(self, value):
90 return not value
Joe Gregorio83a7f6a2011-01-04 15:39:15 -050091
92
93class StorageByKeyName(object):
94 """Store and retrieve a single credential to and from
95 the App Engine datastore.
96
97 This Storage helper presumes the Credentials
98 have been stored as a CredenialsProperty
99 on a datastore model class, and that entities
100 are stored by key_name.
101 """
102
103 def __init__(self, model, key_name, property_name):
104 """Constructor for Storage.
105
106 Args:
107 model: db.Model, model class
108 key_name: string, key name for the entity that has the credentials
Joe Gregorio3fada332011-01-07 17:07:45 -0500109 property_name: string, name of the property that is a CredentialsProperty
Joe Gregorio83a7f6a2011-01-04 15:39:15 -0500110 """
111 self.model = model
112 self.key_name = key_name
113 self.property_name = property_name
114
115 def get(self):
116 """Retrieve Credential from datastore.
117
118 Returns:
119 Credentials
120 """
121 entity = self.model.get_or_insert(self.key_name)
122 credential = getattr(entity, self.property_name)
123 if credential and hasattr(credential, 'set_store'):
124 credential.set_store(self.put)
125 return credential
126
127 def put(self, credentials):
128 """Write a Credentials to the datastore.
129
130 Args:
131 credentials: Credentials, the credentials to store.
132 """
133 entity = self.model.get_or_insert(self.key_name)
134 setattr(entity, self.property_name, credentials)
135 entity.put()