Source code for djmvc_api.models

import hashlib
import secrets

from django.conf import settings
from django.db import models
from django.utils import timezone


[docs] class Token(models.Model): """Bearer token for JSON API access without session or CSRF.""" user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='djmvc_api_tokens', ) name = models.CharField(max_length=255) key_hash = models.CharField(max_length=64, unique=True) prefix = models.CharField(max_length=8) created = models.DateTimeField(auto_now_add=True) expires = models.DateTimeField(null=True, blank=True) last_used = models.DateTimeField(null=True, blank=True) class Meta: default_permissions = ('add', 'delete', 'view') verbose_name = 'API token' verbose_name_plural = 'API tokens' def __str__(self): return f'{self.name} ({self.prefix}…)' @classmethod def hash_key(cls, raw_key): return hashlib.sha256(raw_key.encode()).hexdigest()
[docs] @classmethod def generate(cls, user, name, expires=None): """Create a token row and return ``(instance, raw_key)`` (shown once).""" raw_key = secrets.token_urlsafe(32) token = cls.objects.create( user=user, name=name, key_hash=cls.hash_key(raw_key), prefix=raw_key[:8], expires=expires, ) return token, raw_key
def is_expired(self): if self.expires is None: return False return timezone.now() >= self.expires
[docs] @classmethod def authenticate(cls, raw_key): """Return a valid token for *raw_key*, or ``None``.""" if not raw_key: return None try: token = cls.objects.select_related('user').get( key_hash=cls.hash_key(raw_key), ) except cls.DoesNotExist: return None if token.is_expired() or not token.user.is_active: return None return token
def touch_last_used(self): self.last_used = timezone.now() self.save(update_fields=['last_used'])