Support for Django up to 3.1. Dropped support for Django<1.10 and Python<3.5.
[django-cas-provider.git] / cas_provider / models.py
1 from django.conf import settings
2 from django.db import models
3 from django.utils.translation import ugettext_lazy as _
4 from random import Random
5 import string
6 from urllib.parse import urlencode, urlparse, parse_qs, ParseResult
7
8
9 __all__ = ['ServiceTicket', 'LoginTicket', 'ProxyGrantingTicket', 'ProxyTicket', 'ProxyGrantingTicketIOU']
10
11 class BaseTicket(models.Model):
12     ticket = models.CharField(_('ticket'), max_length=32)
13     created = models.DateTimeField(_('created'), auto_now=True)
14
15     class Meta:
16         abstract = True
17
18     def __init__(self, *args, **kwargs):
19         if 'ticket' not in kwargs:
20             kwargs['ticket'] = self._generate_ticket()
21         super(BaseTicket, self).__init__(*args, **kwargs)
22
23     def __unicode__(self):
24         return self.ticket
25
26     def _generate_ticket(self, length=ticket.max_length, chars=string.ascii_letters + string.digits):
27         """ Generates a random string of the requested length. Used for creation of tickets. """
28         return "%s-%s" % (self.prefix, ''.join(Random().sample(chars, length - (len(self.prefix) + 1))))
29
30
31 class ServiceTicket(BaseTicket):
32     user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
33     service = models.URLField(_('service'), max_length=2048)
34
35     prefix = 'ST'
36
37     class Meta:
38         verbose_name = _('Service Ticket')
39         verbose_name_plural = _('Service Tickets')
40
41     def get_redirect_url(self):
42         parsed = urlparse(self.service)
43         query = parse_qs(parsed.query)
44         query['ticket'] = [self.ticket]
45         query = [((k, v) if len(v) > 1 else (k, v[0])) for k, v in query.items()]
46         parsed = ParseResult(parsed.scheme, parsed.netloc,
47                                       parsed.path, parsed.params,
48                                       urlencode(query), parsed.fragment)
49         return parsed.geturl()
50
51
52 class LoginTicket(BaseTicket):
53     prefix = 'LT'
54
55     class Meta:
56         verbose_name = _('Login Ticket')
57         verbose_name_plural = _('Login Tickets')
58
59
60 class ProxyGrantingTicket(BaseTicket):
61     user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), on_delete=models.CASCADE)
62     service = models.URLField(_('service'), null=True)
63     pgt = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
64     pgtiou = models.CharField(max_length=256, verbose_name=_('PGTiou'))
65     prefix = 'PGT'
66
67     def __init__(self, *args, **kwargs):
68         if 'pgtiou' not in kwargs:
69             kwargs['pgtiou'] = "PGTIOU-%s" % (''.join(Random().sample(string.ascii_letters + string.digits, 50)))
70         super(ProxyGrantingTicket, self).__init__(*args, **kwargs)
71
72     class Meta:
73         verbose_name = _('Proxy Granting Ticket')
74         verbose_name_plural = _('Proxy Granting Tickets')
75
76
77 class ProxyTicket(ServiceTicket):
78     proxyGrantingTicket = models.ForeignKey(ProxyGrantingTicket, verbose_name=_('Proxy Granting Ticket'), on_delete=models.CASCADE)
79
80     prefix = 'PT'
81
82     class Meta:
83         verbose_name = _('Proxy Ticket')
84         verbose_name_plural = _('Proxy Tickets')
85
86
87 class ProxyGrantingTicketIOU(BaseTicket):
88     proxyGrantingTicket = models.ForeignKey(ProxyGrantingTicket, verbose_name=_('Proxy Granting Ticket'), on_delete=models.CASCADE)
89
90     prefix = 'PGTIOU'
91
92     class Meta:
93         verbose_name = _('Proxy Granting Ticket IOU')
94         verbose_name_plural = _('Proxy Granting Tickets IOU')
95