blob: d54d20c285087afa59b0588d206349decdd31601 [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 Gregorio15423ec2012-08-01 14:23:21 -040034 def __init__(self, *args, **kwargs):
35 if 'null' not in kwargs:
36 kwargs['null'] = True
37 super(CredentialsField, self).__init__(*args, **kwargs)
38
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040039 def get_internal_type(self):
40 return "TextField"
Joe Gregorio695fdc12011-01-16 16:46:55 -050041
42 def to_python(self, value):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040043 if value is None:
Joe Gregorio695fdc12011-01-16 16:46:55 -050044 return None
Joe Gregoriofc1e2782011-02-15 16:04:03 -050045 if isinstance(value, oauth2client.client.Credentials):
Joe Gregorio695fdc12011-01-16 16:46:55 -050046 return value
47 return pickle.loads(base64.b64decode(value))
48
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040049 def get_db_prep_value(self, value, connection, prepared=False):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040050 if value is None:
51 return None
Joe Gregorio695fdc12011-01-16 16:46:55 -050052 return base64.b64encode(pickle.dumps(value))
53
54
55class FlowField(models.Field):
56
57 __metaclass__ = models.SubfieldBase
58
Joe Gregorio15423ec2012-08-01 14:23:21 -040059 def __init__(self, *args, **kwargs):
60 if 'null' not in kwargs:
61 kwargs['null'] = True
62 super(FlowField, self).__init__(*args, **kwargs)
63
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040064 def get_internal_type(self):
65 return "TextField"
Joe Gregorio695fdc12011-01-16 16:46:55 -050066
67 def to_python(self, value):
Joe Gregorio695fdc12011-01-16 16:46:55 -050068 if value is None:
69 return None
Joe Gregoriofc1e2782011-02-15 16:04:03 -050070 if isinstance(value, oauth2client.client.Flow):
Joe Gregorio695fdc12011-01-16 16:46:55 -050071 return value
72 return pickle.loads(base64.b64decode(value))
73
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040074 def get_db_prep_value(self, value, connection, prepared=False):
Joe Gregorio573cb5d2012-06-14 16:11:35 -040075 if value is None:
76 return None
Joe Gregorio695fdc12011-01-16 16:46:55 -050077 return base64.b64encode(pickle.dumps(value))
Joe Gregoriodeeb0202011-02-15 14:49:57 -050078
79
80class Storage(BaseStorage):
81 """Store and retrieve a single credential to and from
82 the datastore.
83
84 This Storage helper presumes the Credentials
85 have been stored as a CredenialsField
86 on a db model class.
87 """
88
89 def __init__(self, model_class, key_name, key_value, property_name):
90 """Constructor for Storage.
91
92 Args:
93 model: db.Model, model class
94 key_name: string, key name for the entity that has the credentials
95 key_value: string, key value for the entity that has the credentials
96 property_name: string, name of the property that is an CredentialsProperty
97 """
98 self.model_class = model_class
99 self.key_name = key_name
100 self.key_value = key_value
101 self.property_name = property_name
102
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400103 def locked_get(self):
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500104 """Retrieve Credential from datastore.
105
106 Returns:
107 oauth2client.Credentials
108 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500109 credential = None
110
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500111 query = {self.key_name: self.key_value}
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500112 entities = self.model_class.objects.filter(**query)
113 if len(entities) > 0:
114 credential = getattr(entities[0], self.property_name)
115 if credential and hasattr(credential, 'set_store'):
Joe Gregorio9da2ad82011-09-11 14:04:44 -0400116 credential.set_store(self)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500117 return credential
118
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400119 def locked_put(self, credentials):
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500120 """Write a Credentials to the datastore.
121
122 Args:
123 credentials: Credentials, the credentials to store.
124 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500125 args = {self.key_name: self.key_value}
126 entity = self.model_class(**args)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500127 setattr(entity, self.property_name, credentials)
128 entity.save()
Joe Gregoriofdb43c02012-02-06 16:57:13 -0500129
130 def locked_delete(self):
131 """Delete Credentials from the datastore."""
132
133 query = {self.key_name: self.key_value}
134 entities = self.model_class.objects.filter(**query).delete()