59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
from datetime import timedelta
|
|
from django.contrib.auth import get_user_model
|
|
from django.db import models
|
|
from django.utils.timezone import now
|
|
from randomslugfield import RandomSlugField
|
|
from model_utils import Choices
|
|
from model_utils.fields import StatusField
|
|
from model_utils.models import TimeStampedModel
|
|
|
|
|
|
class AuthSecret(TimeStampedModel):
|
|
"""
|
|
An AuthSecret is a model with an unguessable primary key, suitable for
|
|
sharing with external sites for secure authentication.
|
|
|
|
AuthSecret is primarily used to factor out the many similarities between
|
|
authorisation codes and tokens in IndieAuth - the two contain many
|
|
identical fields, but just a few differences.
|
|
"""
|
|
id = RandomSlugField(primary_key=True, length=30)
|
|
client_id = models.URLField()
|
|
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
|
|
scope = models.TextField(blank=True)
|
|
|
|
@property
|
|
def me(self):
|
|
return self.user.full_url
|
|
|
|
def __contains__(self, scope):
|
|
return scope in self.scope.split(' ')
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
class IndieAuthCode(AuthSecret):
|
|
"""
|
|
An IndieAuthCode is an authorisation code that a client must provide to us
|
|
to complete the IndieAuth process.
|
|
|
|
Codes are single-use, and if unused will be expired automatically after
|
|
thirty seconds.
|
|
"""
|
|
redirect_uri = models.URLField()
|
|
|
|
RESPONSE_TYPE = Choices('id', 'code')
|
|
response_type = StatusField(choices_name='RESPONSE_TYPE')
|
|
|
|
@property
|
|
def expired(self):
|
|
return self.created + timedelta(seconds=30) < now()
|
|
|
|
|
|
class Token(AuthSecret):
|
|
"""
|
|
A Token grants a client long-term authorisation - it will not expire unless
|
|
explicitly revoked by the user.
|
|
"""
|
|
pass
|