""" User views for KeepItGoing. """ from django.contrib.auth import get_user_model, login, logout from django.shortcuts import render, redirect from django.views import View from rest_framework import generics, permissions, status from rest_framework.response import Response from rest_framework.views import APIView from rest_framework_simplejwt.tokens import RefreshToken from .serializers import ( UserSerializer, UserRegistrationSerializer, ChangePasswordSerializer, DeviceTokenSerializer, ) from .models import DeviceToken User = get_user_model() # ============================================================================= # API Views # ============================================================================= class RegisterAPIView(generics.CreateAPIView): """API endpoint for user registration.""" queryset = User.objects.all() serializer_class = UserRegistrationSerializer permission_classes = [permissions.AllowAny] def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.save() # Generate tokens refresh = RefreshToken.for_user(user) return Response({ 'user': UserSerializer(user).data, 'tokens': { 'refresh': str(refresh), 'access': str(refresh.access_token), } }, status=status.HTTP_201_CREATED) class UserProfileAPIView(generics.RetrieveUpdateAPIView): """API endpoint for user profile.""" serializer_class = UserSerializer permission_classes = [permissions.IsAuthenticated] def get_object(self): return self.request.user class ChangePasswordAPIView(APIView): """API endpoint for changing password.""" permission_classes = [permissions.IsAuthenticated] def post(self, request): serializer = ChangePasswordSerializer( data=request.data, context={'request': request} ) serializer.is_valid(raise_exception=True) request.user.set_password(serializer.validated_data['new_password']) request.user.save() return Response({'message': 'Password changed successfully.'}) class DeviceTokenAPIView(generics.ListCreateAPIView): """API endpoint for managing device tokens.""" serializer_class = DeviceTokenSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return DeviceToken.objects.filter(user=self.request.user) class DeviceTokenDeleteAPIView(generics.DestroyAPIView): """API endpoint for deleting a device token.""" serializer_class = DeviceTokenSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return DeviceToken.objects.filter(user=self.request.user) # ============================================================================= # Web Views (Django Templates) # ============================================================================= class LoginView(View): """Web login page.""" def get(self, request): if request.user.is_authenticated: return redirect('dashboard') return render(request, 'users/login.html') def post(self, request): from django.contrib.auth import authenticate email = request.POST.get('email') password = request.POST.get('password') user = authenticate(request, username=email, password=password) if user is not None: login(request, user) next_url = request.GET.get('next', 'dashboard') return redirect(next_url) return render(request, 'users/login.html', { 'error': 'Invalid email or password.' }) class LogoutView(View): """Web logout.""" def get(self, request): logout(request) return redirect('login') def post(self, request): logout(request) return redirect('login') class RegisterView(View): """Web registration page.""" def get(self, request): if request.user.is_authenticated: return redirect('dashboard') return render(request, 'users/register.html') def post(self, request): email = request.POST.get('email') username = request.POST.get('username') password = request.POST.get('password') password_confirm = request.POST.get('password_confirm') errors = {} if password != password_confirm: errors['password_confirm'] = 'Passwords do not match.' if User.objects.filter(email=email).exists(): errors['email'] = 'Email already registered.' if User.objects.filter(username=username).exists(): errors['username'] = 'Username already taken.' if errors: return render(request, 'users/register.html', {'errors': errors}) user = User.objects.create_user( email=email, username=username, password=password ) login(request, user) return redirect('dashboard') class ProfileView(View): """Web profile page.""" def get(self, request): if not request.user.is_authenticated: return redirect('login') return render(request, 'users/profile.html') def post(self, request): if not request.user.is_authenticated: return redirect('login') user = request.user user.first_name = request.POST.get('first_name', '') user.last_name = request.POST.get('last_name', '') user.timezone = request.POST.get('timezone', 'UTC') user.default_reminder_minutes = int(request.POST.get('default_reminder_minutes', 30)) user.email_notifications = request.POST.get('email_notifications') == 'on' user.push_notifications = request.POST.get('push_notifications') == 'on' user.save() return render(request, 'users/profile.html', { 'success': 'Profile updated successfully.' })