~ubuntuone-pqm-team/canonical-identity-provider/trunk

« back to all changes in this revision

Viewing changes to identityprovider/models/oauthtoken.py

  • Committer: Danny Tamez
  • Date: 2010-04-21 15:29:24 UTC
  • Revision ID: danny.tamez@canonical.com-20100421152924-lq1m92tstk2iz75a
Canonical SSO Provider (Open Source) - Initial Commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2010 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
import random
 
5
import struct
 
6
import string
 
7
import os.path
 
8
 
 
9
from oauth.oauth import OAuthToken, OAuthDataStore, OAuthConsumer
 
10
 
 
11
from functools import partial
 
12
from django.db import models
 
13
 
 
14
from identityprovider.models import Account
 
15
 
 
16
 
 
17
TOKEN_LENGTH = 50
 
18
TOKEN_SECRET_LENGTH = 50
 
19
CONSUMER_SECRET_LENGTH = 30
 
20
 
 
21
 
 
22
def _set_seed():
 
23
    if (not hasattr(_set_seed, 'seed') and
 
24
        os.path.exists("/dev/random")):
 
25
 
 
26
        data = open("/dev/random").read(struct.calcsize('Q'))
 
27
        random.seed(struct.unpack('Q', data))
 
28
        _set_seed.seed = True
 
29
 
 
30
 
 
31
def generate_random_string(length):
 
32
    _set_seed()
 
33
    return ''.join(random.choice(string.ascii_letters)
 
34
                   for x in range(length))
 
35
 
 
36
 
 
37
class Token(models.Model):
 
38
    consumer = models.ForeignKey('Consumer')
 
39
 
 
40
    token = models.CharField(
 
41
        max_length=TOKEN_LENGTH,
 
42
        default=partial(generate_random_string, TOKEN_LENGTH),
 
43
        primary_key=True)
 
44
 
 
45
    token_secret = models.CharField(
 
46
        max_length=TOKEN_SECRET_LENGTH,
 
47
        default=partial(generate_random_string, TOKEN_SECRET_LENGTH))
 
48
 
 
49
    name = models.CharField(max_length=255, blank=True)
 
50
 
 
51
    created_at = models.DateTimeField(auto_now_add=True)
 
52
    updated_at = models.DateTimeField(auto_now=True)
 
53
 
 
54
    def oauth_token(self):
 
55
        """Return OAuthToken with information contained in this model"""
 
56
        return OAuthToken(self.token, self.token_secret)
 
57
 
 
58
    def serialize(self):
 
59
        return {
 
60
            'consumer_key': self.consumer.key,
 
61
            'consumer_secret': self.consumer.secret,
 
62
            'token': self.token,
 
63
            'token_secret': self.token_secret,
 
64
            'name': self.name
 
65
        }
 
66
 
 
67
    def __unicode__(self):
 
68
        return self.token
 
69
 
 
70
    class Meta:
 
71
        app_label = 'identityprovider'
 
72
        db_table = 'oauth_token'
 
73
 
 
74
 
 
75
class Consumer(models.Model):
 
76
    account = models.OneToOneField(Account, related_name='oauth_consumer')
 
77
 
 
78
    @property
 
79
    def key(self):
 
80
        return self.account.openid_identifier
 
81
 
 
82
    secret = models.CharField(
 
83
        max_length=255,
 
84
        blank=True,
 
85
        null=False,
 
86
        default=partial(generate_random_string, CONSUMER_SECRET_LENGTH)
 
87
    )
 
88
 
 
89
    created_at = models.DateTimeField(auto_now_add=True)
 
90
    updated_at = models.DateTimeField(auto_now=True)
 
91
 
 
92
    def __unicode__(self):
 
93
        return self.key
 
94
 
 
95
    def oauth_consumer(self):
 
96
        """Return OAuthConsumer based on information contained in this model"""
 
97
        return OAuthConsumer(self.key, self.secret)
 
98
 
 
99
    class Meta:
 
100
        app_label = 'identityprovider'
 
101
        db_table = 'oauth_consumer'
 
102
 
 
103
 
 
104
class Nonce(models.Model):
 
105
    token = models.ForeignKey(Token)
 
106
    consumer = models.ForeignKey(Consumer)
 
107
 
 
108
    nonce = models.CharField(max_length=255,
 
109
                             unique=True, editable=False)
 
110
    created_at = models.DateTimeField(auto_now_add=True)
 
111
 
 
112
    @classmethod
 
113
    def create(cls, consumer_key, token_value, nonce):
 
114
        """
 
115
        Create new nonce object linked to given consumer and token
 
116
        """
 
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)
 
121
 
 
122
    class Meta:
 
123
        app_label = 'identityprovider'
 
124
        db_table = 'oauth_nonce'
 
125
 
 
126
 
 
127
class DataStore(OAuthDataStore):
 
128
 
 
129
    def lookup_token(self, token_type, token_field):
 
130
        """
 
131
        :param token_type: type of token to lookup
 
132
        :param token_field: token to look up
 
133
 
 
134
        :note: token_type should always be 'access' as only such tokens are
 
135
               stored in database
 
136
 
 
137
        :returns: OAuthToken object
 
138
        """
 
139
        assert token_type == 'access'
 
140
 
 
141
        try:
 
142
            token = Token.objects.get(token=token_field)
 
143
            return OAuthToken(token.token, token.token_secret)
 
144
        except Token.DoesNotExist:
 
145
            return None
 
146
 
 
147
    def lookup_consumer(self, consumer_key):
 
148
        """
 
149
        :param consumer_key: consumer key to lookup
 
150
 
 
151
        :returns: OAuthConsumer object
 
152
        """
 
153
        try:
 
154
            consumer = Consumer.objects.get(
 
155
                account__openid_identifier=consumer_key)
 
156
            return consumer.oauth_consumer()
 
157
        except Consumer.DoesNotExist:
 
158
            return None
 
159
 
 
160
    def lookup_nonce(self, consumer, token, nonce):
 
161
        """
 
162
        :param consumer: OAuthConsumer object
 
163
        :param token: OAuthToken object
 
164
        :param nonce: nonce to check
 
165
 
 
166
        """
 
167
        count = Nonce.objects.filter(
 
168
            consumer__account__openid_identifier=consumer.key,
 
169
            token__token=token.key,
 
170
            nonce=nonce).count()
 
171
        if count > 0:
 
172
            return True
 
173
        else:
 
174
            Nonce.create(consumer.key, token.key, nonce)
 
175
            return False
 
176
 
 
177
 
 
178
def create_oauth_token_for_account(account, token_name):
 
179
    try:
 
180
        consumer = account.oauth_consumer
 
181
    except Consumer.DoesNotExist:
 
182
        consumer = Consumer.objects.create(account=account)
 
183
 
 
184
    token = consumer.token_set.create(name=token_name)
 
185
    return token