add method for generate new password to students

feature/fix_generate_pass
Dmitriy Shesterkin 8 years ago
parent 6ca8139a68
commit b92e6d0435
  1. 26
      access/serializers.py
  2. 7
      access/urls.py
  3. 39
      access/views.py
  4. 2
      api_v1/urls.py
  5. 10
      lms/settings.py
  6. 3
      pytest.ini
  7. 2
      requirements.txt
  8. 28
      tests/conftest.py
  9. 0
      tests/fixtures/__init__.py
  10. 24
      tests/fixtures/users.py
  11. 42
      tests/test_user.py

@ -1,5 +1,6 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from rest_framework.generics import get_object_or_404
from access.models.other import Account from access.models.other import Account
from achievements.serialers import DiplomaSerializer, AchievementsSerializer from achievements.serialers import DiplomaSerializer, AchievementsSerializer
@ -101,3 +102,28 @@ class UserSearchSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_last_request(self): def get_last_request(self):
return self.useractivity.last_request return self.useractivity.last_request
class UserEmailSerializer(serializers.Serializer):
"""
Serializer for set new password to the student in admin area by manager.
"""
email = serializers.EmailField()
def __init__(self, *args, **kwargs):
super(UserEmailSerializer, self).__init__(*args, **kwargs)
self.user = None
self.password = None
def validate_email(self, email):
self.user = get_object_or_404(get_user_model(), email=email)
if not self.user.is_active:
raise serializers.ValidationError('Учетная запись еще не активирована.')
if not self.user:
raise serializers.ValidationError('Email не зарегистрирован.')
return email
def save(self):
self.password = get_user_model().objects.make_random_password()
self.user.set_password(self.password)
self.user.save()

@ -18,4 +18,9 @@ urlpatterns = [
url(r'logout/$', views.LogoutView.as_view()), url(r'logout/$', views.LogoutView.as_view()),
url(r'reset/$', views.ResetPasswordView.as_view()), url(r'reset/$', views.ResetPasswordView.as_view()),
url(r'progress_detail/upload/(?P<token>[0-9A-Fa-f-]+)/$', progress.views.UploadCourseProgressUserView.as_view()), url(r'progress_detail/upload/(?P<token>[0-9A-Fa-f-]+)/$', progress.views.UploadCourseProgressUserView.as_view()),
] url(
r'management/password/$',
views.ManagementPassword.as_view(),
name='management-password'
)
]

@ -1,6 +1,7 @@
import datetime import datetime
import random import random
import string import string
import logging
from django.contrib import auth from django.contrib import auth
from django.conf import settings from django.conf import settings
@ -8,15 +9,21 @@ from django.contrib.auth import get_user_model
from django.core.mail import send_mail from django.core.mail import send_mail
from django.db.models import Q from django.db.models import Q
from django.shortcuts import redirect from django.shortcuts import redirect
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework import permissions, generics, status
from access.models.other import Invite, ResetPassword, Account from access.models.other import Invite, ResetPassword, Account
from access.serializers import UserSelfSerializer, UserSearchSerializer from access.serializers import (UserSelfSerializer, UserSearchSerializer,
UserEmailSerializer)
from lms.tools import decode_base64 from lms.tools import decode_base64
logger = logging.getLogger(__name__)
class TeacherListView(APIView): class TeacherListView(APIView):
renderer_classes = (JSONRenderer,) renderer_classes = (JSONRenderer,)
status_code = 200 status_code = 200
@ -283,3 +290,33 @@ class MinUserView(APIView):
return Response(UserSearchSerializer(get_user_model().objects.get(out_key=out_key)).data, status=200) return Response(UserSearchSerializer(get_user_model().objects.get(out_key=out_key)).data, status=200)
except get_user_model().DoesNotExist: except get_user_model().DoesNotExist:
return Response("User not found", status=404) return Response("User not found", status=404)
class ManagementPassword(generics.GenericAPIView):
permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser)
serializer_class = UserEmailSerializer
def post(self, request):
"""
Set password to the student in admin area by manager
---
Generate new password to the student and send email with new password
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
logger.info(f'set password: {serializer.password} to the '
f'student with email: {serializer.user.email}')
send_mail(
subject='Установлен новый пароль',
message=f'Ваш новый пароль {serializer.password} '
f'(в последствии вы сможите сменить его в личном кабинете).',
from_email='robo@skillbox.ru',
recipient_list=[serializer.user.email],
)
logger.info(f'send email to {serializer.user.email} '
f'with new password')
return Response(
data={'message': 'Письмо с новым паролем отправлено на email студента.'},
status=status.HTTP_201_CREATED
)

@ -5,7 +5,7 @@ schema_view = get_swagger_view(title='Skillbox LMS API')
urlpatterns = [ urlpatterns = [
url(r'courses/', include('courses.urls')), url(r'courses/', include('courses.urls')),
url(r'users/', include('access.urls')), url(r'users/', include('access.urls', namespace='users')),
url(r'library/', include('library.urls')), url(r'library/', include('library.urls')),
url(r'finance/', include('finance.urls')), url(r'finance/', include('finance.urls')),
url(r'storage/', include('storage.urls')), url(r'storage/', include('storage.urls')),

@ -232,6 +232,16 @@ LOGGING = {
}, },
} }
# Configure loggers for all local apps
LOCAL_APPS_LOGGERS = {}
for app in apps:
LOCAL_APPS_LOGGERS[app] = {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
}
LOGGING['loggers'].update(LOCAL_APPS_LOGGERS)
SWAGGER_SETTINGS = { SWAGGER_SETTINGS = {
'USE_SESSION_AUTH': True, 'USE_SESSION_AUTH': True,
'LOGIN_URL': 'admin:login', 'LOGIN_URL': 'admin:login',

@ -2,7 +2,8 @@
DJANGO_SETTINGS_MODULE = lms.settings DJANGO_SETTINGS_MODULE = lms.settings
norecursedirs = env/* docs/* misc/* static/* norecursedirs = env/* docs/* misc/* static/*
addopts = --flake8 -vvs ;addopts = --flake8 -vvs
addopts = -vvs
python_files = python_files =
test_*.py test_*.py

@ -50,6 +50,8 @@ pytest-sugar==0.9.1
pytest-django==3.1.2 pytest-django==3.1.2
coverage==4.5.1 coverage==4.5.1
pytest-cov==2.5.1 pytest-cov==2.5.1
mock==2.0.0
pytest-mock==1.7.0
# factories # factories
Faker==0.8.11 Faker==0.8.11
factory-boy==2.10.0 factory-boy==2.10.0

@ -0,0 +1,28 @@
import pytest
from tests.client import BetterAPIClient
pytest_plugins = [
'tests.fixtures.users',
]
@pytest.fixture
def api_client():
"""Anonymous client for REST API."""
client = BetterAPIClient()
return client
@pytest.fixture
def staff_client(user_staff):
"""Authorized as staff client for REST API."""
client = BetterAPIClient()
client.force_authenticate(user=user_staff)
return client
@pytest.fixture
def student_client(user_student):
"""Authorized as staff client for REST API."""
client = BetterAPIClient()
client.force_authenticate(user=user_student)
return client

@ -4,11 +4,12 @@ from factories.users import UserFactory
@pytest.fixture @pytest.fixture
def user_admin(): def user_staff():
""" """
Create user as administration with data: Create user as staff with data:
email = 'admin@example.com' email = 'admin@example.com'
password = 'test' password = 'test'
is_staff=True
is_active = True is_active = True
is_superuser = True is_superuser = True
""" """
@ -16,7 +17,26 @@ def user_admin():
last_name='Иванов', last_name='Иванов',
first_name='Иван', first_name='Иван',
email='admin@example.com', email='admin@example.com',
is_staff=True,
is_active=True, is_active=True,
is_superuser=True is_superuser=True
) )
return admin return admin
@pytest.fixture
def user_student():
"""
Create user as student with data:
email = 'student@example.com'
password = 'test'
is_active = True
"""
student = UserFactory(
last_name='Иванов',
first_name='Иван',
email='student@example.com',
is_staff=False,
is_active=True,
)
return student

@ -0,0 +1,42 @@
import mock
import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse
from rest_framework import status
from rest_framework.generics import get_object_or_404
@pytest.mark.django_db
@mock.patch('django.core.mail.send_mail')
def test_generate_password_by_manager(mocked_send_mail, staff_client,
student_client, user_student):
"""
Test generate new password from admin area by manager
"""
assert staff_client.get(
reverse('users:management-password'),
status=status.HTTP_405_METHOD_NOT_ALLOWED
)
assert student_client.get(
reverse('users:management-password'),
status=status.HTTP_403_FORBIDDEN
)
data = {
'email': user_student.email,
}
assert staff_client.post(
reverse('users:management-password'),
data=data,
status=status.HTTP_201_CREATED
)
test_user = get_object_or_404(get_user_model(), email=user_student.email)
assert not test_user.check_password('test')
assert mocked_send_mail.call_count == 1
assert student_client.post(
reverse('users:management-password'),
data=data,
status=status.HTTP_403_FORBIDDEN
)
Loading…
Cancel
Save