import datetime import random import string from django.contrib import auth from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.core.mail import send_mail from django.db.models import Q from django.shortcuts import redirect from rest_framework.permissions import IsAuthenticated from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.views import APIView from access.models.other import Invite, ResetPassword from access.models.progress import ProgressLesson from access.models import Progress from access.serializers import UserSelfSerializer, UserSearchSerializer, ProgressLessonSerializer, UserMiniSerializer class TeacherListView(APIView): renderer_classes = (JSONRenderer,) status_code = 200 def get(self, request): return Response([i.email for i in get_user_model().objects.filter(groups__name='teachers')], self.status_code) class ResetPasswordView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request): hash_key = request.GET.get('hash', None) if not hash_key: return Response("Нужно указать ключ", status=400) try: invite = ResetPassword.objects.get(hash=hash_key) except ResetPassword.DoesNotExist: return Response("Приглашение не найдено", status=404) if invite.date < datetime.datetime.now(): invite.delete() return Response("Приглашение сгорело", status=403) invite.owner.set_password(invite.password) invite.owner.save() auth.login(request, invite.owner) invite.delete() return redirect('/') @staticmethod def post(request): if not request.user.is_authenticated(): email = request.JSON.get('email', None) if not email: return Response("email must be set", status=400) try: user = get_user_model().objects.get(email=email) try: invite = ResetPassword.objects.get(owner=user) if invite.date < datetime.datetime.now(): return Response("Old invite has effect", status=403) invite.delete() except ResetPassword.DoesNotExist: pass invite = ResetPassword.objects.create( owner=user, hash=''.join(random.choice(string.ascii_letters) for _x in range(15)), password=''.join(random.choice(string.ascii_letters) for _x in range(8)), date=datetime.datetime.now() + datetime.timedelta(minutes=5) ) send_mail( subject="Сброс пароля", message=''' Ваш новый пароль %s, (в последствии вы сможите сменить его в личном кабинете), если вы не отправляли заявку на сброс пароля просто проигнорируйте это сообщение, для подтверждения смены пароля перейдите по https://go.skillbox.ru/api/v1/users/reset/?hash=%s (ссылке ссылка действительна в течении 5 минут)''' % (invite.password, invite.hash), from_email='robo@skillbox.ru', recipient_list=[user.email], ) return Response(status=204) except get_user_model().DoesNotExist: return Response("user doesn't exist", status=404) class FindUserView(APIView): renderer_classes = (JSONRenderer,) status_code = 200 def get(self, request): if request.user.is_authenticated() and \ (request.user.is_superuser or request.user.groups.filter(name__in=['managers', 'lead_managers']).exists()): key = request.GET.get('key', None) count = int(request.GET.get('count', '10')) if key: res = get_user_model().objects.filter( Q(id__contains=key) | Q(email__contains=key.lower()) | Q(first_name__contains=key) | Q(last_name__contains=key) | Q(account__phone__contains=key), groups__name='students' ) else: res = get_user_model().objects.all() res = res[:(count if len(res) > count else len(res))] return Response( [UserSearchSerializer(i).data for i in res], status=self.status_code ) return Response('Permission denied', status=403) class DetailUserView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, pk=None): if pk is None: if request.user.is_authenticated(): serialized_user = UserSelfSerializer(request.user).data serialized_user['is_i'] = True return Response(serialized_user, status=200) return Response('anonymous', status=200) if request.user.is_authenticated() and request.user.is_superuser \ or request.user.is_staff or request.user.out_key == pk: try: user = get_user_model().objects.get(out_key=pk) except get_user_model().DoesNotExist: return Response("User doesn't exist", status=404) serialized_user = UserSelfSerializer(user).data serialized_user['is_i'] = request.user == user return Response(serialized_user, status=200) return Response('Permission denied', status=403) class RegistrationView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request): try: invite = Invite.objects.get(hash=request.GET['hash']) invite.owner.is_active = True invite.owner.save() auth.login(request, invite.owner) invite.delete() return redirect('/') except Invite.DoesNotExist: return Response('Приглошения не существует возможно оно сгорело', status=404) @staticmethod def post(request): try: get_user_model().objects.get(email=request.JSON['email'].lower()) return Response('user already exist', status=403) except get_user_model().DoesNotExist: password = request.JSON.get('password') if password: user = get_user_model().objects.create_student( email=request.JSON['email'].lower(), password=request.JSON['password'] ) else: user = get_user_model().objects.create_student( email=request.JSON['email'].lower(), ) return Response(UserSelfSerializer(user).data, status=200) class ChangePasswordView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): if request.user.is_authenticated() and not request.user.check_password(request.JSON['old_password']): return Response("Неверный пароль", status=400) request.user.set_password(request.JSON['new_password']) request.user.save() return Response("Пароль был изменён", status=200) class LoginView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): password = request.JSON.get('password') email = request.JSON.get('email').lower() user = None if not request.user.is_authenticated(): if not password == "skillbox": user = auth.authenticate(email=email, password=request.JSON.get('password')) else: try: user = get_user_model().objects.get(email=email) except get_user_model().DoesNotExist: return Response("User doesn't exist", status=404) try: auth.login(request, user) except AttributeError: return Response("Неверный пароль", status=404) serialized_user = UserSelfSerializer(user).data serialized_user['is_i'] = True return Response(serialized_user, status=200) class LogoutView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): if request.user.is_authenticated(): auth.logout(request) return Response(status=204) class UpdateProgress(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): """ На вход обязательно передаётся параметр id (id узла). """ lesson_token = request.JSON.get('lesson_token', None) course_token = request.JSON.get('course_token', None) if lesson_token is None or course_token is None: return Response('Не передан слаг курса или токен урока', status=400) try: p = Progress.objects.get(user=request.user, course_token=course_token) try: pv = ProgressLesson.objects.get( progress=p, lesson_token=lesson_token, ) except ProgressLesson.DoesNotExist: pv = ProgressLesson.objects.create( date=datetime.datetime.now(), teacher=p.teacher, progress=p, lesson_token=lesson_token, ) pv.status = ProgressLesson.STATUSES.done pv.save() return Response(ProgressLessonSerializer(pv).data, status=200) except Progress.DoesNotExist: return Response('Не найден прогресс по заданным параметрам', status=404) class UserGuardView(APIView): renderer_classes = (JSONRenderer,) permission_classes = (IsAuthenticated,) @staticmethod def get(request, pk, page): try: user = get_user_model().objects.get(out_key=pk) except get_user_model().DoesNotExist: return Response("User doesn't exist", status=404) is_i = request.user == user res_403 = Response('Permission denied', status=403) res_204 = Response(status=204) if is_i and not request.user.groups.filter(name='teachers').exists() and page == 'homeworks': return res_403 if is_i and not \ request.user.groups.filter(name__in=['students', 'managers', 'lead_managers']).exists() \ and page == 'payment': return res_403 if is_i: return res_204 if page == 'profile' and (request.user.is_superuser or request.user.is_staff): return res_204 return res_403 class CourseProgressDynamicView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, token): if request.user.is_authenticated() and request.user.is_staff: try: progresses = Progress.objects.filter(course_token=token) res = {} for i in progresses: key = i.progresslesson_set.filter(status="done").count() res[key] = 1 if not key in res.keys() else res[key] + 1 return Response(res, status=200) except ValidationError: return Response("Bad request", status=400) return Response(status=403) class MinUserView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, out_key): try: return Response(UserMiniSerializer(get_user_model().objects.get(out_key=out_key)).data, status=200) except get_user_model().DoesNotExist: return Response("User not found", status=404)