1
# Copyright 2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
9
from oauth.oauth import OAuthToken, OAuthDataStore, OAuthConsumer
11
from functools import partial
12
from django.db import models
14
from identityprovider.models import Account
18
TOKEN_SECRET_LENGTH = 50
19
CONSUMER_SECRET_LENGTH = 30
23
if (not hasattr(_set_seed, 'seed') and
24
os.path.exists("/dev/random")):
26
data = open("/dev/random").read(struct.calcsize('Q'))
27
random.seed(struct.unpack('Q', data))
31
def generate_random_string(length):
33
return ''.join(random.choice(string.ascii_letters)
34
for x in range(length))
37
class Token(models.Model):
38
consumer = models.ForeignKey('Consumer')
40
token = models.CharField(
41
max_length=TOKEN_LENGTH,
42
default=partial(generate_random_string, TOKEN_LENGTH),
45
token_secret = models.CharField(
46
max_length=TOKEN_SECRET_LENGTH,
47
default=partial(generate_random_string, TOKEN_SECRET_LENGTH))
49
name = models.CharField(max_length=255, blank=True)
51
created_at = models.DateTimeField(auto_now_add=True)
52
updated_at = models.DateTimeField(auto_now=True)
54
def oauth_token(self):
55
"""Return OAuthToken with information contained in this model"""
56
return OAuthToken(self.token, self.token_secret)
60
'consumer_key': self.consumer.key,
61
'consumer_secret': self.consumer.secret,
63
'token_secret': self.token_secret,
67
def __unicode__(self):
71
app_label = 'identityprovider'
72
db_table = 'oauth_token'
75
class Consumer(models.Model):
76
account = models.OneToOneField(Account, related_name='oauth_consumer')
80
return self.account.openid_identifier
82
secret = models.CharField(
86
default=partial(generate_random_string, CONSUMER_SECRET_LENGTH)
89
created_at = models.DateTimeField(auto_now_add=True)
90
updated_at = models.DateTimeField(auto_now=True)
92
def __unicode__(self):
95
def oauth_consumer(self):
96
"""Return OAuthConsumer based on information contained in this model"""
97
return OAuthConsumer(self.key, self.secret)
100
app_label = 'identityprovider'
101
db_table = 'oauth_consumer'
104
class Nonce(models.Model):
105
token = models.ForeignKey(Token)
106
consumer = models.ForeignKey(Consumer)
108
nonce = models.CharField(max_length=255,
109
unique=True, editable=False)
110
created_at = models.DateTimeField(auto_now_add=True)
113
def create(cls, consumer_key, token_value, nonce):
115
Create new nonce object linked to given consumer and token
117
consumer = Consumer.objects.get(
118
account__openid_identifier=consumer_key)
119
token = consumer.token_set.get(token=token_value)
120
return consumer.nonce_set.create(token=token, nonce=nonce)
123
app_label = 'identityprovider'
124
db_table = 'oauth_nonce'
127
class DataStore(OAuthDataStore):
129
def lookup_token(self, token_type, token_field):
131
:param token_type: type of token to lookup
132
:param token_field: token to look up
134
:note: token_type should always be 'access' as only such tokens are
137
:returns: OAuthToken object
139
assert token_type == 'access'
142
token = Token.objects.get(token=token_field)
143
return OAuthToken(token.token, token.token_secret)
144
except Token.DoesNotExist:
147
def lookup_consumer(self, consumer_key):
149
:param consumer_key: consumer key to lookup
151
:returns: OAuthConsumer object
154
consumer = Consumer.objects.get(
155
account__openid_identifier=consumer_key)
156
return consumer.oauth_consumer()
157
except Consumer.DoesNotExist:
160
def lookup_nonce(self, consumer, token, nonce):
162
:param consumer: OAuthConsumer object
163
:param token: OAuthToken object
164
:param nonce: nonce to check
167
count = Nonce.objects.filter(
168
consumer__account__openid_identifier=consumer.key,
169
token__token=token.key,
174
Nonce.create(consumer.key, token.key, nonce)
178
def create_oauth_token_for_account(account, token_name):
180
consumer = account.oauth_consumer
181
except Consumer.DoesNotExist:
182
consumer = Consumer.objects.create(account=account)
184
token = consumer.token_set.create(name=token_name)