2016-01-25 20:52:24 +00:00
# -*- coding: utf-8 -*-
from hashlib import md5
2015-01-28 18:19:36 +00:00
import json
2014-12-19 15:27:43 +00:00
from django . db import models
from django . utils import timezone
2015-12-04 16:55:04 +00:00
from django . utils . translation import ugettext_lazy as _
2015-07-21 13:57:23 +00:00
from django . conf import settings
2014-12-19 15:27:43 +00:00
class Client ( models . Model ) :
2016-04-04 20:19:49 +00:00
CLIENT_TYPE_CHOICES = [
( ' confidential ' , ' Confidential ' ) ,
( ' public ' , ' Public ' ) ,
]
2014-12-19 15:27:43 +00:00
RESPONSE_TYPE_CHOICES = [
2015-01-08 20:55:24 +00:00
( ' code ' , ' code (Authorization Code Flow) ' ) ,
( ' id_token ' , ' id_token (Implicit Flow) ' ) ,
( ' id_token token ' , ' id_token token (Implicit Flow) ' ) ,
2014-12-19 15:27:43 +00:00
]
name = models . CharField ( max_length = 100 , default = ' ' )
2016-04-04 20:19:49 +00:00
client_type = models . CharField ( max_length = 30 , choices = CLIENT_TYPE_CHOICES , default = ' confidential ' , help_text = _ ( u ' <b>Confidential</b> clients are capable of maintaining the confidentiality of their credentials. <b>Public</b> clients are incapable. ' ) )
2014-12-19 15:27:43 +00:00
client_id = models . CharField ( max_length = 255 , unique = True )
2016-04-05 21:31:08 +00:00
client_secret = models . CharField ( max_length = 255 , blank = True , default = ' ' )
2016-04-04 20:19:49 +00:00
response_type = models . CharField ( max_length = 30 , choices = RESPONSE_TYPE_CHOICES )
2016-01-11 19:04:04 +00:00
date_created = models . DateField ( auto_now_add = True )
2014-12-19 15:27:43 +00:00
2015-12-04 16:55:04 +00:00
_redirect_uris = models . TextField ( default = ' ' , verbose_name = _ ( u ' Redirect URI ' ) , help_text = _ ( u ' Enter each URI on a new line. ' ) )
class Meta :
verbose_name = _ ( u ' Client ' )
verbose_name_plural = _ ( u ' Clients ' )
2015-05-30 11:54:04 +00:00
def __str__ ( self ) :
2015-11-02 16:19:03 +00:00
return u ' {0} ' . format ( self . name )
2015-05-30 11:54:04 +00:00
def __unicode__ ( self ) :
return self . __str__ ( )
2015-01-06 19:29:31 +00:00
def redirect_uris ( ) :
def fget ( self ) :
return self . _redirect_uris . splitlines ( )
def fset ( self , value ) :
self . _redirect_uris = ' \n ' . join ( value )
return locals ( )
redirect_uris = property ( * * redirect_uris ( ) )
2014-12-19 15:27:43 +00:00
@property
def default_redirect_uri ( self ) :
2015-01-16 18:03:41 +00:00
return self . redirect_uris [ 0 ] if self . redirect_uris else ' '
2014-12-19 15:27:43 +00:00
2015-01-28 18:19:36 +00:00
2015-04-21 18:19:43 +00:00
class BaseCodeTokenModel ( models . Model ) :
2014-12-19 15:27:43 +00:00
2015-07-21 13:57:23 +00:00
user = models . ForeignKey ( settings . AUTH_USER_MODEL )
2014-12-19 15:27:43 +00:00
client = models . ForeignKey ( Client )
expires_at = models . DateTimeField ( )
2015-01-12 22:13:48 +00:00
_scope = models . TextField ( default = ' ' )
2015-05-30 11:54:04 +00:00
2015-04-21 18:19:43 +00:00
def scope ( ) :
def fget ( self ) :
return self . _scope . split ( )
def fset ( self , value ) :
self . _scope = ' ' . join ( value )
return locals ( )
scope = property ( * * scope ( ) )
2014-12-19 15:27:43 +00:00
def has_expired ( self ) :
return timezone . now ( ) > = self . expires_at
2015-05-30 11:54:04 +00:00
def __str__ ( self ) :
2015-11-02 16:19:03 +00:00
return u ' {0} - {1} ( {2} ) ' . format ( self . client , self . user . email , self . expires_at )
2015-05-30 11:54:04 +00:00
def __unicode__ ( self ) :
return self . __str__ ( )
2015-04-21 18:19:43 +00:00
class Meta :
abstract = True
2015-01-28 18:19:36 +00:00
2014-12-19 15:27:43 +00:00
2015-04-21 18:19:43 +00:00
class Code ( BaseCodeTokenModel ) :
2015-02-06 17:26:34 +00:00
2015-04-21 18:19:43 +00:00
code = models . CharField ( max_length = 255 , unique = True )
2015-07-15 19:23:36 +00:00
nonce = models . CharField ( max_length = 255 , blank = True , default = ' ' )
2016-02-16 20:33:12 +00:00
is_authentication = models . BooleanField ( default = False )
2016-04-07 19:18:47 +00:00
code_challenge = models . CharField ( max_length = 255 , null = True )
code_challenge_method = models . CharField ( max_length = 255 , null = True )
2014-12-19 15:27:43 +00:00
2015-12-04 16:55:04 +00:00
class Meta :
verbose_name = _ ( u ' Authorization Code ' )
verbose_name_plural = _ ( u ' Authorization Codes ' )
2015-01-28 18:19:36 +00:00
2015-04-21 18:19:43 +00:00
class Token ( BaseCodeTokenModel ) :
access_token = models . CharField ( max_length = 255 , unique = True )
2015-09-30 10:42:04 +00:00
refresh_token = models . CharField ( max_length = 255 , unique = True , null = True )
2015-04-21 18:19:43 +00:00
_id_token = models . TextField ( )
2014-12-19 15:27:43 +00:00
def id_token ( ) :
def fget ( self ) :
return json . loads ( self . _id_token )
def fset ( self , value ) :
self . _id_token = json . dumps ( value )
return locals ( )
id_token = property ( * * id_token ( ) )
2015-12-04 16:55:04 +00:00
class Meta :
verbose_name = _ ( u ' Token ' )
verbose_name_plural = _ ( u ' Tokens ' )
2015-01-28 18:19:36 +00:00
2015-06-22 21:42:04 +00:00
class UserConsent ( BaseCodeTokenModel ) :
2015-12-04 16:55:04 +00:00
2015-11-10 10:29:05 +00:00
class Meta :
unique_together = ( ' user ' , ' client ' )
2016-01-25 20:52:24 +00:00
class RSAKey ( models . Model ) :
key = models . TextField ( help_text = _ ( u ' Paste your private RSA Key here. ' ) )
class Meta :
verbose_name = _ ( u ' RSA Key ' )
verbose_name_plural = _ ( u ' RSA Keys ' )
def __str__ ( self ) :
return u ' {0} ' . format ( self . kid )
def __unicode__ ( self ) :
return self . __str__ ( )
@property
def kid ( self ) :
return u ' {0} ' . format ( md5 ( self . key . encode ( ' utf-8 ' ) ) . hexdigest ( ) if self . key else ' ' )