Commit b31f8d58 authored by ibuler's avatar ibuler

Add user generate reset password token

parent 5350f832
from __future__ import absolute_import
from celery import shared_task
from django.core.mail import send_mail
from django.conf import settings
@shared_task(name='send_mail_async')
def send_mail_async(*args, **kwargs):
""" Using celery to send email async
You can use it as django send_mail function
Example:
send_mail_sync.delay(subject, message, from_mail, recipient_list, fail_silently=False, html_message=None)
Also you can ignore the from_mail, unlike django send_mail, from_email is not a require args:
Example:
send_mail_sync.delay(subject, message, recipient_list, fail_silently=False, html_message=None)
"""
if len(args) == 3:
args = list(args)
args[0] = settings.EMAIL_SUBJECT_PREFIX + args[0]
args.insert(2, settings.EMAIL_HOST_USER)
args = tuple(args)
send_mail(*args, **kwargs)
# def send_mail_async(subject, message, from_mail, recipient_list, fail_silently=False, html_message=None):
# if settings.CONFIG.MAIL_SUBJECT_PREFIX:
# subject += settings.CONFIG.MAIL_SUBJECT_PREFIX
# send_mail(subject, message, from_mail, recipient_list, fail_silently=fail_silently, html_message=html_message)
......@@ -236,6 +236,16 @@ BOOTSTRAP_COLUMN_COUNT = 11
# Init data or generate fake data source for development
FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures'), ]
# Email config
EMAIL_HOST = CONFIG.EMAIL_HOST
EMAIL_PORT = CONFIG.EMAIL_PORT
EMAIL_HOST_USER = CONFIG.EMAIL_HOST_USER
EMAIL_HOST_PASSWORD = CONFIG.EMAIL_HOST_PASSWORD
EMAIL_USE_SSL = CONFIG.EMAIL_USE_SSL
EMAIL_USE_TLS = CONFIG.EMAIL_USE_TLS
EMAIL_SUBJECT_PREFIX = CONFIG.EMAIL_SUBJECT_PREFIX
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
......
......@@ -3,6 +3,7 @@
from __future__ import unicode_literals
import datetime
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.utils import timezone
......@@ -13,6 +14,7 @@ from django.dispatch import receiver
from django.db import IntegrityError
from rest_framework.authtoken.models import Token
from django.core import signing
# class Role(models.Model):
# name = models.CharField('name', max_length=80, unique=True)
......@@ -113,8 +115,6 @@ class User(AbstractUser):
private_key = models.CharField(max_length=5000, blank=True, verbose_name='ssh私钥') # ssh key max length 4096 bit
public_key = models.CharField(max_length=1000, blank=True, verbose_name='公钥')
comment = models.TextField(max_length=200, blank=True, verbose_name='描述')
confirmed = models.BooleanField(default=False)
date_confirmed = models.DateField(blank=True, null=True, verbose_name='确认时间')
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True, verbose_name='有效期')
created_by = models.CharField(max_length=30, default='')
......@@ -177,22 +177,43 @@ class User(AbstractUser):
# super(User, self).save(*args, **kwargs)
@property
def token(self):
return self.get_token()
def private_token(self):
return self.get_private_token()
def get_token(self):
def get_private_token(self):
try:
token = Token.objects.get(user=self)
return token.key
except Token.DoesNotExist:
return ''
token = Token.objects.create(user=self)
return token.key
def refresh_private_token(self):
Token.objects.filter(user=self).delete()
return Token.objects.create(user=self)
def set_token(self):
@classmethod
def generate_reset_token(cls, email):
try:
return Token.objects.create(user=self)
except IntegrityError:
Token.objects.filter(user=self).delete()
return Token.objects.create(user=self)
user = cls.objects.get(email=email)
return signing.dumps({'reset': user.id, 'email': user.email})
except cls.DoesNotExist:
return None
@classmethod
def reset_password(cls, token, new_password, max_age=3600):
try:
data = signing.loads(token, max_age=max_age)
user_id = data.get('reset', None)
user_email = data.get('email', '')
user = cls.objects.get(id=user_id, email=user_email)
user.set_password(new_password)
user.save()
return True
except signing.BadSignature, cls.DoesNotExist:
pass
return False
class Meta:
db_table = 'user'
......
......@@ -75,6 +75,14 @@ class UserModelTest(TransactionTestCase):
self.assertTrue(user.check_password(password))
self.assertFalse(user.check_password(password*2))
def test_user_reset_password(self):
user = User.objects.first()
token = User.generate_reset_token(user.email)
new_password = gen_username()
User.reset_password(token, new_password)
user_ = User.objects.get(id=user.id)
self.assertTrue(user_.check_password(new_password))
def tearDown(self):
User.objects.all().delete()
UserGroup.objects.all().delete()
......
......@@ -12,6 +12,7 @@ from .base import gen_username, gen_name, gen_email, get_role
class UserListViewTests(TransactionTestCase):
def setUp(self):
init_all_models()
self.client.login(username='admin', password='admin')
def test_a_new_user_in_list(self):
username = gen_username()
......@@ -32,10 +33,14 @@ class UserListViewTests(TransactionTestCase):
response = self.client.get(reverse('users:user-list'))
self.assertEqual(response.context['is_paginated'], True)
def tearDown(self):
self.client.logout()
class UserAddTests(TestCase):
def setUp(self):
init_all_models()
self.client.login(username='admin', password='admin')
def test_add_a_new_user(self):
username = gen_username()
......@@ -56,3 +61,6 @@ class UserAddTests(TestCase):
response = self.client.get(reverse('users:user-list'))
self.assertContains(response, username)
def tearDown(self):
self.client.logout()
......@@ -8,6 +8,7 @@ from paramiko.rsakey import RSAKey
from django.contrib.auth.mixins import UserPassesTestMixin
from django.urls import reverse_lazy
try:
import cStringIO as StringIO
except ImportError:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment