models.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. from datetime import datetime
  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 salted_hmac
  8. from .utils import encode_password
  9. from .validators import ASCIIUsernameValidator
  10. class User(models.Model):
  11. username = models.CharField(
  12. max_length=25,
  13. unique=True,
  14. validators=[ASCIIUsernameValidator()]
  15. )
  16. password = models.CharField(_('password'), max_length=128)
  17. last_login = models.DateTimeField(_('last login'), blank=True, null=True)
  18. email = models.EmailField(_('email address'), unique=True)
  19. def save(self, *args, **kwargs):
  20. self.password = encode_password(self.username, self.password)
  21. super(User, self).save(*args, **kwargs)
  22. def get_root_folder(self):
  23. return self.folders.get(father_folder=None, group=None)
  24. def send_email(self, subject, message, from_email=None, **kwargs):
  25. send_mail(subject, message, from_email, [self.email], **kwargs)
  26. def make_token(self):
  27. return self._make_token(_timestamp())
  28. def check_token(self, token):
  29. if not token:
  30. return False
  31. try:
  32. ts_b36, hash_str = token.split('-')
  33. except ValueError:
  34. return False
  35. try:
  36. ts = base36_to_int(ts_b36)
  37. except ValueError:
  38. return False
  39. if self._make_token(ts) != token:
  40. return False
  41. timestamp = _timestamp()
  42. if (timestamp - ts) > settings.PASSWORD_RESET_TIMEOUT:
  43. return False
  44. return True
  45. def _make_token(self, timestamp):
  46. ts_b36 = int_to_base36(timestamp)
  47. salt = settings.SALT
  48. value = self._make_hash_value(timestamp)
  49. secret = settings.SECRET_KEY
  50. hash_str = salted_hmac(
  51. salt, value, secret=secret, algorithm='sha256'
  52. ).hexdigest()[::2]
  53. token = "%s-%s" % (ts_b36, hash_str)
  54. return token
  55. def _make_hash_value(self, timestamp):
  56. return f'{self.pk}{self.password}{timestamp}{self.email}'
  57. def __str__(self):
  58. return self.username
  59. def get_user(request):
  60. if hasattr(request, 'user') and isinstance(request.user, User):
  61. print(f'get user from request.user, username={request.user.username}')
  62. return request.user
  63. username = request.POST.get('username', '')
  64. token = request.POST.get('token', '')
  65. try:
  66. user = User.objects.get(username=username)
  67. if user.check_token(token):
  68. user.tokens.get(token=token)
  69. return user
  70. except:
  71. return None
  72. return None
  73. def _timestamp():
  74. dt = datetime.now()
  75. return int((dt - datetime(2001, 1, 1)).total_seconds())
  76. class LoginToken(models.Model):
  77. user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens')
  78. token = models.CharField(max_length=256)