Source code for provider.oauth2.models

"""
Default model implementations. Custom database or OAuth backends need to
implement these models with fields and and methods to be compatible with the
views in :attr:`provider.views`.
"""

from django.db import models
from django.conf import settings
from .. import constants
from ..constants import CLIENT_TYPES
from ..utils import now, short_token, long_token, get_code_expiry
from ..utils import get_token_expiry, serialize_instance, deserialize_instance
from .managers import AccessTokenManager

try:
    from django.utils import timezone
except ImportError:
    timezone = None

AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')


[docs]class Client(models.Model): """ Default client implementation. Expected fields: * :attr:`user` * :attr:`name` * :attr:`url` * :attr:`redirect_url` * :attr:`client_id` * :attr:`client_secret` * :attr:`client_type` Clients are outlined in the :rfc:`2` and its subsections. """ user = models.ForeignKey(AUTH_USER_MODEL, related_name='oauth2_client', blank=True, null=True) name = models.CharField(max_length=255, blank=True) url = models.URLField(help_text="Your application's URL.") redirect_uri = models.URLField(help_text="Your application's callback URL") client_id = models.CharField(max_length=255, default=short_token) client_secret = models.CharField(max_length=255, default=long_token) client_type = models.IntegerField(choices=CLIENT_TYPES) def __unicode__(self): return self.redirect_uri def get_default_token_expiry(self): public = (self.client_type == 1) return get_token_expiry(public) def serialize(self): return dict(user=serialize_instance(self.user), name=self.name, url=self.url, redirect_uri=self.redirect_uri, client_id=self.client_id, client_secret=self.client_secret, client_type=self.client_type) @classmethod def deserialize(cls, data): if not data: return None kwargs = {} # extract values that we care about for field in cls._meta.fields: name = field.name val = data.get(field.name, None) # handle relations if val and field.rel: val = deserialize_instance(field.rel.to, val) kwargs[name] = val return cls(**kwargs)
[docs]class Grant(models.Model): """ Default grant implementation. A grant is a code that can be swapped for an access token. Grants have a limited lifetime as defined by :attr:`provider.constants.EXPIRE_CODE_DELTA` and outlined in :rfc:`4.1.2` Expected fields: * :attr:`user` * :attr:`client` - :class:`Client` * :attr:`code` * :attr:`expires` - :attr:`datetime.datetime` * :attr:`redirect_uri` * :attr:`scope` """ user = models.ForeignKey(AUTH_USER_MODEL) client = models.ForeignKey(Client) code = models.CharField(max_length=255, default=long_token) expires = models.DateTimeField(default=get_code_expiry) redirect_uri = models.CharField(max_length=255, blank=True) scope = models.IntegerField(default=0) def __unicode__(self): return self.code
[docs]class AccessToken(models.Model): """ Default access token implementation. An access token is a time limited token to access a user's resources. Access tokens are outlined :rfc:`5`. Expected fields: * :attr:`user` * :attr:`token` * :attr:`client` - :class:`Client` * :attr:`expires` - :attr:`datetime.datetime` * :attr:`scope` Expected methods: * :meth:`get_expire_delta` - returns an integer representing seconds to expiry """ user = models.ForeignKey(AUTH_USER_MODEL) token = models.CharField(max_length=255, default=long_token, db_index=True) client = models.ForeignKey(Client) expires = models.DateTimeField() scope = models.IntegerField(default=constants.SCOPES[0][0], choices=constants.SCOPES) objects = AccessTokenManager() def __unicode__(self): return self.token def save(self, *args, **kwargs): if not self.expires: self.expires = self.client.get_default_token_expiry() super(AccessToken, self).save(*args, **kwargs)
[docs] def get_expire_delta(self, reference=None): """ Return the number of seconds until this token expires. """ if reference is None: reference = now() expiration = self.expires if timezone: if timezone.is_aware(reference) and timezone.is_naive(expiration): # MySQL doesn't support timezone for datetime fields # so we assume that the date was stored in the UTC timezone expiration = timezone.make_aware(expiration, timezone.utc) elif timezone.is_naive(reference) and timezone.is_aware(expiration): reference = timezone.make_aware(reference, timezone.utc) timedelta = expiration - reference return timedelta.days*86400 + timedelta.seconds
[docs]class RefreshToken(models.Model): """ Default refresh token implementation. A refresh token can be swapped for a new access token when said token expires. Expected fields: * :attr:`user` * :attr:`token` * :attr:`access_token` - :class:`AccessToken` * :attr:`client` - :class:`Client` * :attr:`expired` - ``boolean`` """ user = models.ForeignKey(AUTH_USER_MODEL) token = models.CharField(max_length=255, default=long_token) access_token = models.OneToOneField(AccessToken, related_name='refresh_token') client = models.ForeignKey(Client) expired = models.BooleanField(default=False) def __unicode__(self): return self.token