113 lines
3.8 KiB
Python
113 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import uuid
|
|
|
|
from django.db.models.loading import get_model
|
|
from django.db.models import Q
|
|
from django.contrib.auth import logout, login, authenticate
|
|
|
|
from rest_framework.decorators import list_route, action
|
|
from rest_framework.response import Response
|
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
|
from rest_framework import status, viewsets
|
|
|
|
from djmail.template_mail import MagicMailBuilder
|
|
|
|
from greenmine.base import exceptions as exc
|
|
from greenmine.base.filters import FilterBackend
|
|
from greenmine.base.api import ModelCrudViewSet, RetrieveModelMixin
|
|
|
|
from .models import User, Role
|
|
from .serializers import UserSerializer, RoleSerializer, RecoverySerializer
|
|
|
|
|
|
|
|
class UsersViewSet(ModelCrudViewSet):
|
|
permission_classes = (IsAuthenticated,)
|
|
serializer_class = UserSerializer
|
|
queryset = User.objects.all()
|
|
filter_fields = [("project", "memberships__project__pk")]
|
|
|
|
def pre_conditions_on_save(self, obj):
|
|
if not self.request.user.is_superuser and obj.id != self.request.user.id:
|
|
raise exc.PreconditionError()
|
|
|
|
def pre_conditions_on_delete(self, obj):
|
|
if not self.request.user.is_superuser and obj.id != self.request.user.id:
|
|
raise exc.PreconditionError()
|
|
|
|
@list_route(permission_classes=[AllowAny], methods=["POST"])
|
|
def password_recovery(self, request, pk=None):
|
|
username_or_email = request.DATA.get('username', None)
|
|
|
|
if not username_or_email:
|
|
raise exc.WrongArguments("Invalid username or email")
|
|
|
|
try:
|
|
queryset = User.objects.all()
|
|
user = queryset.get(Q(username=username_or_email) |
|
|
Q(email=username_or_email))
|
|
except User.DoesNotExist:
|
|
raise exc.WrongArguments("Invalid username or email")
|
|
|
|
user.token = str(uuid.uuid1())
|
|
user.save(update_fields=["token"])
|
|
|
|
mbuilder = MagicMailBuilder()
|
|
email = mbuilder.password_recovery(user.email, {"user": user})
|
|
email.send()
|
|
|
|
return Response({"detail": "Mail sended successful!"})
|
|
|
|
@list_route(permission_classes=[AllowAny], methods=["POST"])
|
|
def change_password_from_recovery(self, request, pk=None):
|
|
"""
|
|
Change password with token (from password recovery step).
|
|
"""
|
|
serializer = RecoverySerializer(data=request.DATA, many=False)
|
|
if not serializer.is_valid():
|
|
raise exc.WrongArguments("Token is invalid")
|
|
|
|
user = User.objects.get(token=serializer.data["token"])
|
|
user.set_password(serializer.data["password"])
|
|
user.token = None
|
|
user.save(update_fields=["password", "token"])
|
|
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
|
@list_route(permission_classes=[IsAuthenticated], methods=["POST"])
|
|
def change_password(self, request, pk=None):
|
|
"""
|
|
Change password to current logged user.
|
|
"""
|
|
password = request.DATA.get("password")
|
|
|
|
if not password:
|
|
raise exc.WrongArguments("incomplete argiments")
|
|
|
|
if len(password) < 6:
|
|
raise exc.WrongArguments("invalid password length")
|
|
|
|
request.user.set_password(password)
|
|
request.user.save(update_fields=["password"])
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
|
|
|
class RolesViewSet(viewsets.ViewSet):
|
|
permission_classes = (IsAuthenticated,)
|
|
serializer_class = RoleSerializer
|
|
|
|
def list(self, request, pk=None):
|
|
queryset = Role.objects.all()
|
|
serializer = self.serializer_class(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
def retrieve(self, request, pk=None):
|
|
try:
|
|
role = Role.objects.get(pk=pk)
|
|
except Role.DoesNotExist:
|
|
raise exc.NotFound()
|
|
|
|
serializer = self.serializer_class(role)
|
|
return Response(serializer.data)
|