blob: f9ce26d11ecb7ea74518e9b6936806aa427c98da [file] [log] [blame]
Joe Gregorio20a5aa92011-04-01 17:44:25 -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.
Joe Gregorio7c22ab22011-02-16 15:32:39 -050014
15"""OAuth 2.0 utilities for Django.
16
17Utilities for using OAuth 2.0 in conjunction with
18the Django datastore.
19"""
20
21__author__ = 'jcgregorio@google.com (Joe Gregorio)'
22
Joe Gregoriofc1e2782011-02-15 16:04:03 -050023import oauth2client
24import base64
25import pickle
26
Joe Gregorio695fdc12011-01-16 16:46:55 -050027from django.db import models
Joe Gregoriodeeb0202011-02-15 14:49:57 -050028from oauth2client.client import Storage as BaseStorage
Joe Gregorio695fdc12011-01-16 16:46:55 -050029
30class CredentialsField(models.Field):
31
32 __metaclass__ = models.SubfieldBase
33
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040034 def get_internal_type(self):
35 return "TextField"
Joe Gregorio695fdc12011-01-16 16:46:55 -050036
37 def to_python(self, value):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040038 if value is None:
Joe Gregorio695fdc12011-01-16 16:46:55 -050039 return None
Joe Gregoriofc1e2782011-02-15 16:04:03 -050040 if isinstance(value, oauth2client.client.Credentials):
Joe Gregorio695fdc12011-01-16 16:46:55 -050041 return value
42 return pickle.loads(base64.b64decode(value))
43
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040044 def get_db_prep_value(self, value, connection, prepared=False):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040045 if value is None:
46 return None
Joe Gregorio695fdc12011-01-16 16:46:55 -050047 return base64.b64encode(pickle.dumps(value))
48
49
50class FlowField(models.Field):
51
52 __metaclass__ = models.SubfieldBase
53
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040054 def get_internal_type(self):
55 return "TextField"
Joe Gregorio695fdc12011-01-16 16:46:55 -050056
57 def to_python(self, value):
Joe Gregorio695fdc12011-01-16 16:46:55 -050058 if value is None:
59 return None
Joe Gregoriofc1e2782011-02-15 16:04:03 -050060 if isinstance(value, oauth2client.client.Flow):
Joe Gregorio695fdc12011-01-16 16:46:55 -050061 return value
62 return pickle.loads(base64.b64decode(value))
63
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040064 def get_db_prep_value(self, value, connection, prepared=False):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040065 if value is None:
66 return None
Joe Gregorio695fdc12011-01-16 16:46:55 -050067 return base64.b64encode(pickle.dumps(value))
Joe Gregoriodeeb0202011-02-15 14:49:57 -050068
69
70class Storage(BaseStorage):
71 """Store and retrieve a single credential to and from
72 the datastore.
73
74 This Storage helper presumes the Credentials
75 have been stored as a CredenialsField
76 on a db model class.
77 """
78
79 def __init__(self, model_class, key_name, key_value, property_name):
80 """Constructor for Storage.
81
82 Args:
83 model: db.Model, model class
84 key_name: string, key name for the entity that has the credentials
85 key_value: string, key value for the entity that has the credentials
86 property_name: string, name of the property that is an CredentialsProperty
87 """
88 self.model_class = model_class
89 self.key_name = key_name
90 self.key_value = key_value
91 self.property_name = property_name
92
Joe Gregoriod2ee4d82011-09-15 14:32:45 -040093 def locked_get(self):
Joe Gregoriodeeb0202011-02-15 14:49:57 -050094 """Retrieve Credential from datastore.
95
96 Returns:
97 oauth2client.Credentials
98 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -050099 credential = None
100
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500101 query = {self.key_name: self.key_value}
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500102 entities = self.model_class.objects.filter(**query)
103 if len(entities) > 0:
104 credential = getattr(entities[0], self.property_name)
105 if credential and hasattr(credential, 'set_store'):
Joe Gregorio9da2ad82011-09-11 14:04:44 -0400106 credential.set_store(self)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500107 return credential
108
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400109 def locked_put(self, credentials):
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500110 """Write a Credentials to the datastore.
111
112 Args:
113 credentials: Credentials, the credentials to store.
114 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500115 args = {self.key_name: self.key_value}
116 entity = self.model_class(**args)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500117 setattr(entity, self.property_name, credentials)
118 entity.save()
Joe Gregoriofdb43c02012-02-06 16:57:13 -0500119
120 def locked_delete(self):
121 """Delete Credentials from the datastore."""
122
123 query = {self.key_name: self.key_value}
124 entities = self.model_class.objects.filter(**query).delete()