| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- from datetime import datetime, time
- from django.core.mail import send_mail
- from django.db import models
- from django.utils.translation import gettext_lazy as _
- from django.utils.http import base36_to_int, int_to_base36
- from django.conf import settings
- from django.utils.crypto import constant_time_compare, salted_hmac
- from .validators import ASCIIUsernameValidator
- class User(models.Model):
- username = models.CharField(
- _('username'),
- max_length=25,
- unique=True,
- help_text=_('Required. 25 characters or fewer. Letters, digits and _ only.'),
- validators=[ASCIIUsernameValidator()],
- error_messages={
- 'unique': _("A _user with that username already exists."),
- },
- )
- password = models.CharField(_('password'), max_length=128)
- last_login = models.DateTimeField(_('last login'), blank=True, null=True)
- email = models.EmailField(_('email address'), unique=True)
- class Meta:
- db_table = '_user'
- verbose_name = verbose_name_plural = '用户信息表'
- def get_root_folder(self):
- return self.folders.get(father_folder=None)
- def set_password(self, password):
- # TODO: 密码强度检验,密码hash存储
- self.password = password
- def send_email(self, subject, message, from_email=None, **kwargs):
- send_mail(subject, message, from_email, [self.email], **kwargs)
- def make_token(self):
- return self._make_token(_timestamp())
- def check_token(self, token):
- if not token:
- return False
- try:
- ts_b36, hash_str = token.split('-')
- except ValueError:
- return False
- try:
- ts = base36_to_int(ts_b36)
- except ValueError:
- return False
- if self._make_token(ts) != token:
- return False
- timestamp = _timestamp()
- if (timestamp - ts) > settings.PASSWORD_RESET_TIMEOUT:
- return False
- return True
- def _make_token(self, timestamp):
- ts_b36 = int_to_base36(timestamp)
- salt = settings.SALT
- value = self._make_hash_value(timestamp)
- secret = settings.SECRET_KEY
- hash_str = salted_hmac(
- salt, value, secret=secret, algorithm='sha256'
- ).hexdigest()[::2]
- token = "%s-%s" % (ts_b36, hash_str)
- return token
- def _make_hash_value(self, timestamp):
- return f'{self.pk}{self.password}{timestamp}{self.email}'
- def __str__(self):
- return self.username
- def get_user(request):
- username = request.data.get('username', '')
- token = request.data.get('token', '')
- try:
- user = User.objects.get(username=username)
- if user.check_token(token):
- user.tokens.get(token=token)
- return user
- except:
- return None
- return None
- def _timestamp():
- dt = datetime.now()
- return int((dt - datetime(2001, 1, 1)).total_seconds())
- class LoginToken(models.Model):
- user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens')
- token = models.CharField(max_length=256)
|