from rest_framework import routers, viewsets, serializers, permissions from rest_framework.decorators import api_view, permission_classes, authentication_classes from rest_framework.authtoken.serializers import AuthTokenSerializer from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from django.contrib.auth import login from django.urls import path from django.dispatch import receiver from django.db.models.signals import post_save from knox.models import AuthToken from knox.views import LoginView as KnoxLoginView from authentication.models import ExtendedUser class UserSerializer(serializers.ModelSerializer): permissions = serializers.SerializerMethodField() class Meta: model = ExtendedUser fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions') read_only_fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions') def collect_permissions(self, obj): for permission in obj.get_all_permissions(): yield "*:" + permission for permission in obj.event_permissions.all(): yield permission.event.slug + ":" + permission.permission.codename def get_permissions(self, obj): return list(self.collect_permissions(obj)) @receiver(post_save, sender=ExtendedUser) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: AuthToken.objects.create(user=instance) class UserViewSet(viewsets.ModelViewSet): queryset = ExtendedUser.objects.all() serializer_class = UserSerializer @api_view(['GET']) @permission_classes([IsAuthenticated]) def selfUser(request): serializer = UserSerializer(request.user) return Response(serializer.data, status=200) @api_view(['POST']) @permission_classes([]) @authentication_classes([]) def registerUser(request): try: username = request.data.get('username') password = request.data.get('password') email = request.data.get('email') errors = {} if not username: errors['username'] = 'Username is required' if not password: errors['password'] = 'Password is required' if not email: errors['email'] = 'Email is required' if ExtendedUser.objects.filter(email=email).exists(): errors['email'] = 'Email already exists' if ExtendedUser.objects.filter(username=username).exists(): errors['username'] = 'Username already exists' if errors: return Response({'errors': errors}, status=400) user = ExtendedUser.objects.create_user(username, email, password) return Response({'username': user.username, 'email': user.email}, status=201) except Exception as e: return Response({'errors': str(e)}, status=400) class LoginView(KnoxLoginView): permission_classes = (permissions.AllowAny,) authentication_classes = () def post(self, request, format=None): serializer = AuthTokenSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] login(request, user) return super(LoginView, self).post(request, format=None) router = routers.SimpleRouter() router.register(r'users', UserViewSet, basename='users') urlpatterns = router.urls + [ path('self/', selfUser), path('login/', LoginView.as_view()), path('register/', registerUser), ]