Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / oa2 / models.py @ e28a4841

History | View | Annotate | Download (4.1 kB)

1
import datetime
2
import urlparse
3

    
4
from django.db import models
5
from django.utils.translation import ugettext_lazy as _
6
from django.core.exceptions import ValidationError
7

    
8
CLIENT_TYPES = (
9
    ('confidential', _('Confidential')),
10
    ('public', _('Public'))
11
)
12

    
13
CONFIDENTIAL_TYPES = ['confidential']
14

    
15
TOKEN_TYPES = (('Basic', _('Basic')),
16
               ('Bearer', _('Bearer')))
17

    
18
GRANT_TYPES = (('authorization_code', _('Authorization code')),
19
               ('password', _('Password')),
20
               ('client_credentials', _('Client Credentials')))
21

    
22

    
23
class RedirectUrl(models.Model):
24
    client = models.ForeignKey('oa2.Client', on_delete=models.PROTECT)
25
    is_default = models.BooleanField(default=True)
26
    url = models.URLField(unique=True)
27

    
28
    class Meta:
29
        ordering = ('is_default', )
30
        unique_together = ('client', 'url',)
31

    
32

    
33
class Client(models.Model):
34
    name = models.CharField(max_length=100)
35
    identifier = models.CharField(max_length=255, unique=True)
36
    secret = models.CharField(max_length=255, null=True, default=None)
37
    url = models.CharField(max_length=255)
38
    type = models.CharField(max_length=100, choices=CLIENT_TYPES,
39
                            default='confidential')
40
    is_trusted = models.BooleanField(default=False)
41

    
42
    def save(self, **kwargs):
43
        if self.secret is None and self.type == 'confidential':
44
            raise ValidationError("Confidential clients require a secret")
45
        super(Client, self).save(**kwargs)
46

    
47
    def requires_auth(self):
48
        return self.type in CONFIDENTIAL_TYPES
49

    
50
    def get_default_redirect_uri(self):
51
        return self.redirecturl_set.get().url
52

    
53
    def redirect_uri_is_valid(self, uri):
54
        # ignore user specific uri part
55
        parts = list(urlparse.urlsplit(uri))
56
        path = parts[2]
57
        pieces = path.rsplit('/', 3)
58
        parts[2] = '/'.join(pieces[:-3]) if len(pieces) > 3 else path
59
        uri = urlparse.urlunsplit(parts)
60

    
61
        # TODO: handle trailing slashes
62
        return self.redirecturl_set.filter(url=uri).count() > 0
63

    
64
    def get_id(self):
65
        return self.identifier
66

    
67

    
68
class AuthorizationCode(models.Model):
69
    user = models.ForeignKey('im.AstakosUser', on_delete=models.PROTECT)
70
    code = models.TextField()
71
    redirect_uri = models.CharField(max_length=255)
72
    client = models.ForeignKey('oa2.Client', on_delete=models.PROTECT)
73
    scope = models.TextField(null=True, default=None)
74
    created_at = models.DateTimeField(default=datetime.datetime.now())
75

    
76
    # not really useful
77
    state = models.TextField(null=True, default=None)
78

    
79
    def client_id_is_valid(self, client_id):
80
        return self.client_id == client_id
81

    
82
    def redirect_uri_is_valid(self, redirect_uri, client):
83
        return (self.redirect_uri == redirect_uri and
84
                client.redirect_uri_is_valid(redirect_uri))
85

    
86
    def __repr__(self):
87
        return ("Authorization code: %s "
88
                "(user: %s, client: %s, redirect_uri: %s, scope: %s)" % (
89
                    self.code,
90
                    self.user.log_display,
91
                    self.client.get_id(),
92
                    self.redirect_uri, self.scope))
93

    
94

    
95
class Token(models.Model):
96
    code = models.TextField()
97
    created_at = models.DateTimeField(default=datetime.datetime.now())
98
    expires_at = models.DateTimeField()
99
    token_type = models.CharField(max_length=100, choices=TOKEN_TYPES,
100
                                  default='Bearer')
101
    grant_type = models.CharField(max_length=100, choices=GRANT_TYPES,
102
                                  default='authorization_code')
103

    
104
    # authorization fields
105
    user = models.ForeignKey('im.AstakosUser', on_delete=models.PROTECT)
106
    redirect_uri = models.CharField(max_length=255)
107
    client = models.ForeignKey('oa2.Client', on_delete=models.PROTECT)
108
    scope = models.TextField(null=True, default=None)
109

    
110
    # not really useful
111
    state = models.TextField(null=True, default=None)
112

    
113
    def __repr__(self):
114
        return ("Token: %s (token_type: %s, grant_type: %s, "
115
                "user: %s, client: %s, scope: %s)" % (
116
                    self.code, self.token_type, self.grant_type,
117
                    self.user.log_display, self.client.get_id(), self.scope))