diff --git a/apps/users/forms.py b/apps/users/forms.py
index 47ca32653..cbd459060 100644
--- a/apps/users/forms.py
+++ b/apps/users/forms.py
@@ -29,13 +29,12 @@ class UserUpdateForm(ModelForm):
class Meta:
model = User
fields = [
- 'name', 'email', 'groups', 'wechat', 'avatar',
+ 'name', 'email', 'groups', 'wechat',
'phone', 'enable_otp', 'role', 'date_expired', 'comment',
]
help_texts = {
'username': '* required',
- 'name': '* required',
'email': '* required',
'groups': '* required'
}
diff --git a/apps/users/models.py b/apps/users/models.py
index f5fc7b7ec..46ffefcdb 100644
--- a/apps/users/models.py
+++ b/apps/users/models.py
@@ -7,6 +7,7 @@ from django.contrib.auth.hashers import make_password
from django.utils import timezone
from django.db import models
from django.contrib.auth.models import AbstractUser, Permission
+from django.db import OperationalError
class Role(models.Model):
@@ -23,6 +24,12 @@ class Role(models.Model):
def __unicode__(self):
return self.name
+ def delete(self, using=None, keep_parents=False):
+ if self.user_set.all().count() > 0:
+ raise OperationalError('Role %s has some member, should not be delete.' % self.name)
+ else:
+ return super(Role, self).delete(using=using, keep_parents=keep_parents)
+
class Meta:
db_table = 'role'
@@ -56,7 +63,7 @@ class UserGroup(models.Model):
@classmethod
def initial(cls):
- group_or_create = cls.objects.get_or_create(name='All', comment='Default user group for all user',
+ group_or_create = cls.objects.get_or_create(name='Default', comment='Default user group for all user',
created_by='System')
return group_or_create[0]
@@ -93,7 +100,7 @@ class User(AbstractUser):
phone = models.CharField(max_length=20, blank=True, verbose_name='手机号')
enable_otp = models.BooleanField(default=False, verbose_name='启用二次验证')
secret_key_otp = models.CharField(max_length=16, blank=True)
- role = models.ForeignKey(Role, on_delete=models.PROTECT, verbose_name='角色')
+ role = models.ForeignKey(Role, on_delete=models.SET('None'), verbose_name='角色')
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='描述')
@@ -124,10 +131,12 @@ class User(AbstractUser):
if not self.name:
self.name = self.username
super(User, self).save(args, **kwargs)
-
# Set user default group 'All'
+ # Todo: It's have bug
group = UserGroup.initial()
- self.groups.add(group)
+ if group not in self.groups.all():
+ self.groups.add(group)
+ super(User, self).save(args, **kwargs)
class Meta:
db_table = 'user'
diff --git a/apps/users/templates/users/_user.html b/apps/users/templates/users/_user.html
index 88337e85b..66d350056 100644
--- a/apps/users/templates/users/_user.html
+++ b/apps/users/templates/users/_user.html
@@ -41,13 +41,14 @@
角色安全
{{ form.role|bootstrap_horizontal }}
-
+
diff --git a/apps/users/tests.py b/apps/users/tests.py
index b3fac7c25..dd43e0616 100644
--- a/apps/users/tests.py
+++ b/apps/users/tests.py
@@ -4,26 +4,12 @@ from random import choice
import forgery_py
from django.utils import timezone
+from django.shortcuts import reverse
from django.test import TestCase, Client, TransactionTestCase
from django.test.utils import setup_test_environment
from django.db import IntegrityError, transaction
from .models import User, UserGroup, Role, init_all_models
-
-
-setup_test_environment()
-client = Client()
-
-
-def create_usergroup(name):
- pass
-
-
-def get_random_usergroup():
- pass
-
-
-def create_user(username, name, email, groups):
- pass
+from django.contrib.auth.models import Permission
def gen_username():
@@ -42,54 +28,113 @@ class UserModelTest(TransactionTestCase):
def setUp(self):
init_all_models()
- def test_user_duplicate(self):
- # 创建一个基准测试用户
+ # 创建一个用户用于测试
role = choice(Role.objects.all())
user = User(name='test', username='test', email='test@email.org', role=role)
user.save()
- # 创建一个姓名一致的用户, 应该创建成功
+ def test_initial(self):
+ self.assertEqual(User.objects.all().count(), 2)
+ self.assertEqual(Role.objects.all().count(), 3)
+ self.assertEqual(UserGroup.objects.all().count(), 1)
+
+ @property
+ def role(self):
+ return choice(Role.objects.all())
+
+ # 创建一个姓名一致的用户, 应该创建成功
+ def test_user_name_duplicate(self):
user1 = User(name='test', username=gen_username(), password_raw=gen_username(),
- email=gen_email(), role=role)
+ email=gen_email(), role=self.role)
try:
user1.save()
user1.delete()
except IntegrityError:
self.assertTrue(0, 'Duplicate not allowed.')
- # 创建一个用户名一致的用户, 应该创建不成功
- user2 = User(username='test', email=gen_email(), role=role)
-
+ # 创建一个用户名一致的用户, 应该创建不成功
+ def test_user_username_duplicate(self):
+ user2 = User(username='test', email=gen_email(), role=self.role)
try:
user2.save()
self.assertTrue(0, 'Duplicate allowed.')
except IntegrityError:
pass
- # 创建一个Email一致的用户,应该创建不成功
- user3 = User(username=gen_username(), email='test@email.org', role=role)
+ # 创建一个Email一致的用户,应该创建不成功
+ def test_user_email_duplicate(self):
+ user3 = User(username=gen_username(), email='test@email.org', role=self.role)
try:
user3.save()
self.assertTrue(0, 'Duplicate allowed.')
except IntegrityError:
pass
+ # 用户过期测试
def test_user_was_expired(self):
- role = choice(Role.objects.all())
date = timezone.now() - timezone.timedelta(days=1)
user = User(name=gen_name(), username=gen_username(),
- email=gen_email(), role=role, date_expired=date)
+ email=gen_email(), role=self.role, date_expired=date)
self.assertTrue(user.is_expired())
+ # 测试用户默认会输入All用户组
def test_user_with_default_group(self):
role = choice(Role.objects.all())
user = User(username=gen_username(), email=gen_email(), role=role)
user.save()
self.assertEqual(user.groups.count(), 1)
- self.assertEqual(user.groups.first().name, 'All')
+ self.assertEqual(user.groups.first().name, 'Default')
+
+ def test_user_password_authenticated(self):
+ password = gen_username() * 3
+ user = User(username=gen_username(), password_raw=password, role=self.role)
+ user.save()
+ self.assertTrue(user.check_password(password))
+ self.assertFalse(user.check_password(password*2))
+
+ def tearDown(self):
+ User.objects.all().delete()
+ UserGroup.objects.all().delete()
+ Role.objects.all().delete()
+
+
+class RoleModelTestCase(TransactionTestCase):
+ def setUp(self):
+ Role.objects.all().delete()
+ Role.initial()
+
+ def test_role_initial(self):
+ self.assertEqual(Role.objects.all().count(), 3)
+
+ def test_create_new_role(self):
+ role = Role(name=gen_name(), comment=gen_name()*3)
+ role.save()
+ role.permissions = Permission.objects.all()
+ role.save()
+
+ self.assertEqual(Role.objects.count(), 4)
+ role = Role.objects.last()
+ self.assertEqual(role.permissions.all().count(), Permission.objects.all().count())
+
+
+class UserGroupModelTestCase(TransactionTestCase):
+ pass
class UserListViewTests(TestCase):
- pass
+ def setUp(self):
+ init_all_models()
+ User.generate_fake()
+
+ def test_list_view_with_one_user(self):
+ response = self.client.get(reverse('users:user-list'))
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(response, 'Admin')
+ self.assertQuerysetEqual(response.context['user_list'], [repr(user) for user in User.objects.all()])
+
+ def test_pagination(self):
+ response = self.client.get(reverse('users:user-list'))
+ self.assertContains(response.status_code, 200)
+
diff --git a/apps/users/views.py b/apps/users/views.py
index 66ca0294f..fb7483bdc 100644
--- a/apps/users/views.py
+++ b/apps/users/views.py
@@ -72,6 +72,10 @@ class UserUpdateView(UpdateView):
user.set_password(password)
return super(UserUpdateView, self).form_valid(form)
+ def form_invalid(self, form):
+ print(form.errors)
+ return super(UserUpdateView, self).form_invalid(form)
+
class UserDeleteView(DeleteView):
model = User