models.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from datetime import datetime, time
  2. from django.core.mail import send_mail
  3. from django.db import models
  4. from django.utils.translation import gettext_lazy as _
  5. from django.utils.http import base36_to_int, int_to_base36
  6. from django.conf import settings
  7. from django.utils.crypto import constant_time_compare, salted_hmac
  8. from .validators import ASCIIUsernameValidator
  9. class User(models.Model):
  10. username = models.CharField(
  11. _('username'),
  12. max_length=25,
  13. unique=True,
  14. help_text=_('Required. 25 characters or fewer. Letters, digits and _ only.'),
  15. validators=[ASCIIUsernameValidator()],
  16. error_messages={
  17. 'unique': _("A _user with that username already exists."),
  18. },
  19. )
  20. password = models.CharField(_('password'), max_length=128)
  21. last_login = models.DateTimeField(_('last login'), blank=True, null=True)
  22. email = models.EmailField(_('email address'), unique=True)
  23. class Meta:
  24. db_table = '_user'
  25. verbose_name = verbose_name_plural = '用户信息表'
  26. def set_password(self, password):
  27. # TODO: 密码强度检验,密码hash存储
  28. self.password = password
  29. def send_email(self, subject, message, from_email=None, **kwargs):
  30. send_mail(subject, message, from_email, [self.email], **kwargs)
  31. def make_token(self):
  32. return self._make_token(_timestamp())
  33. def check_token(self, token):
  34. if not token:
  35. return False
  36. try:
  37. ts_b36, hash_str = token.split('-')
  38. except ValueError:
  39. return False
  40. try:
  41. ts = base36_to_int(ts_b36)
  42. except ValueError:
  43. return False
  44. if self._make_token(ts) != token:
  45. return False
  46. timestamp = _timestamp()
  47. if (timestamp - ts) > settings.PASSWORD_RESET_TIMEOUT:
  48. return False
  49. return True
  50. def _make_token(self, timestamp):
  51. ts_b36 = int_to_base36(timestamp)
  52. salt = settings.SALT
  53. value = self._make_hash_value(timestamp)
  54. secret = settings.SECRET_KEY
  55. hash_str = salted_hmac(
  56. salt, value, secret=secret, algorithm='sha256'
  57. ).hexdigest()[::2]
  58. token = "%s-%s" % (ts_b36, hash_str)
  59. return token
  60. def _make_hash_value(self, timestamp):
  61. return f'{self.pk}{self.password}{timestamp}{self.email}'
  62. def _timestamp():
  63. dt = datetime.now()
  64. return int((dt - datetime(2001, 1, 1)).total_seconds())
  65. class LoginToken(models.Model):
  66. user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens')
  67. token = models.CharField(max_length=256)
  68. from folder.models import Folder
  69. # 引入内置信号
  70. from django.db.models.signals import post_save
  71. # 引入信号接收器的装饰器
  72. from django.dispatch import receiver
  73. class Profile(models.Model):
  74. # 对应django自带的user
  75. user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
  76. # 对应的根目录
  77. root_folder = models.ForeignKey(Folder, null=True, on_delete=models.DO_NOTHING, related_name='profile')
  78. def __str__(self):
  79. return '_user {}'.format(self.user.username)
  80. # 信号接收函数,每当新建User实例的时候自动调用
  81. @receiver(post_save, sender=User)
  82. def create_user_profile(sender, instance, created, **kwargs):
  83. if created:
  84. Profile.objects.create(user=instance)
  85. # 信号接收函数,每当更新User实例的时候自动调用
  86. @receiver(post_save, sender=User)
  87. def save_user_profile(sender, instance, **kwargs):
  88. pass
  89. # instance.profile.save()
  90. # 信号接收函数,每当新建Profile实例的时候自动调用
  91. @receiver(post_save, sender=Profile)
  92. def create_root_folder(sender, instance, created, **kwargs):
  93. # pass
  94. if created:
  95. root_folder = Folder.objects.create()
  96. instance.root_folder = root_folder
  97. instance.save()