models.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import binascii
  2. import os
  3. from django.contrib.auth.models import User
  4. from django.core.validators import MinLengthValidator
  5. from django.db import models
  6. from django.utils import timezone
  7. class Token(models.Model):
  8. """
  9. An API token used for user authentication. This extends the stock model to allow each user to have multiple tokens.
  10. It also supports setting an expiration time and toggling write ability.
  11. """
  12. user = models.ForeignKey(
  13. to=User,
  14. on_delete=models.CASCADE,
  15. related_name='tokens'
  16. )
  17. created = models.DateTimeField(
  18. auto_now_add=True
  19. )
  20. expires = models.DateTimeField(
  21. blank=True,
  22. null=True
  23. )
  24. key = models.CharField(
  25. max_length=40,
  26. unique=True,
  27. validators=[MinLengthValidator(40)]
  28. )
  29. write_enabled = models.BooleanField(
  30. default=True,
  31. help_text='Permit create/update/delete operations using this key'
  32. )
  33. description = models.CharField(
  34. max_length=100,
  35. blank=True
  36. )
  37. class Meta:
  38. pass
  39. def __str__(self):
  40. # Only display the last 24 bits of the token to avoid accidental exposure.
  41. return "{} ({})".format(self.key[-6:], self.user)
  42. def save(self, *args, **kwargs):
  43. if not self.key:
  44. self.key = self.generate_key()
  45. return super().save(*args, **kwargs)
  46. def generate_key(self):
  47. # Generate a random 160-bit key expressed in hexadecimal.
  48. return binascii.hexlify(os.urandom(20)).decode()
  49. @property
  50. def is_expired(self):
  51. if self.expires is None or timezone.now() < self.expires:
  52. return False
  53. return True