blob: 687720818b3bd9f8f2e4578248a5cb6bb5f38b15 [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 Gregoriofc1e2782011-02-15 16:04:03 -050038 if not value:
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 Gregorio695fdc12011-01-16 16:46:55 -050045 return base64.b64encode(pickle.dumps(value))
46
47
48class FlowField(models.Field):
49
50 __metaclass__ = models.SubfieldBase
51
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040052 def get_internal_type(self):
53 return "TextField"
Joe Gregorio695fdc12011-01-16 16:46:55 -050054
55 def to_python(self, value):
Joe Gregorio695fdc12011-01-16 16:46:55 -050056 if value is None:
57 return None
Joe Gregoriofc1e2782011-02-15 16:04:03 -050058 if isinstance(value, oauth2client.client.Flow):
Joe Gregorio695fdc12011-01-16 16:46:55 -050059 return value
60 return pickle.loads(base64.b64decode(value))
61
Joe Gregoriof42dfdc2011-10-14 13:55:24 -040062 def get_db_prep_value(self, value, connection, prepared=False):
Joe Gregorio695fdc12011-01-16 16:46:55 -050063 return base64.b64encode(pickle.dumps(value))
Joe Gregoriodeeb0202011-02-15 14:49:57 -050064
65
66class Storage(BaseStorage):
67 """Store and retrieve a single credential to and from
68 the datastore.
69
70 This Storage helper presumes the Credentials
71 have been stored as a CredenialsField
72 on a db model class.
73 """
74
75 def __init__(self, model_class, key_name, key_value, property_name):
76 """Constructor for Storage.
77
78 Args:
79 model: db.Model, model class
80 key_name: string, key name for the entity that has the credentials
81 key_value: string, key value for the entity that has the credentials
82 property_name: string, name of the property that is an CredentialsProperty
83 """
84 self.model_class = model_class
85 self.key_name = key_name
86 self.key_value = key_value
87 self.property_name = property_name
88
Joe Gregoriod2ee4d82011-09-15 14:32:45 -040089 def locked_get(self):
Joe Gregoriodeeb0202011-02-15 14:49:57 -050090 """Retrieve Credential from datastore.
91
92 Returns:
93 oauth2client.Credentials
94 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -050095 credential = None
96
Joe Gregoriodeeb0202011-02-15 14:49:57 -050097 query = {self.key_name: self.key_value}
Joe Gregoriofc1e2782011-02-15 16:04:03 -050098 entities = self.model_class.objects.filter(**query)
99 if len(entities) > 0:
100 credential = getattr(entities[0], self.property_name)
101 if credential and hasattr(credential, 'set_store'):
Joe Gregorio9da2ad82011-09-11 14:04:44 -0400102 credential.set_store(self)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500103 return credential
104
Joe Gregoriod2ee4d82011-09-15 14:32:45 -0400105 def locked_put(self, credentials):
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500106 """Write a Credentials to the datastore.
107
108 Args:
109 credentials: Credentials, the credentials to store.
110 """
Joe Gregoriofc1e2782011-02-15 16:04:03 -0500111 args = {self.key_name: self.key_value}
112 entity = self.model_class(**args)
Joe Gregoriodeeb0202011-02-15 14:49:57 -0500113 setattr(entity, self.property_name, credentials)
114 entity.save()
Joe Gregoriofdb43c02012-02-06 16:57:13 -0500115
116 def locked_delete(self):
117 """Delete Credentials from the datastore."""
118
119 query = {self.key_name: self.key_value}
120 entities = self.model_class.objects.filter(**query).delete()