added endpoints for user profile
This commit is contained in:
parent
dd99c395a0
commit
6f4282d96e
4 changed files with 138 additions and 5 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from .models import Prediction, SavedPoint, SavedRateProfile, PreditctionTemplate
|
from .models import Prediction, SavedPoint, SavedRateProfile, PreditctionTemplate
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from django.contrib.auth.password_validation import validate_password
|
||||||
|
from django.core.validators import validate_email
|
||||||
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from .validators import (
|
from .validators import (
|
||||||
validate_custom_curve, rate_clip,
|
validate_custom_curve, rate_clip,
|
||||||
_rfc3339_to_timestamp, base64_to_curve
|
_rfc3339_to_timestamp, base64_to_curve
|
||||||
|
|
@ -11,6 +15,7 @@ class PredictionSerializer(serializers.ModelSerializer):
|
||||||
model = Prediction
|
model = Prediction
|
||||||
fields = ['id', 'created_at', 'updated_at', 'result']
|
fields = ['id', 'created_at', 'updated_at', 'result']
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
PROFILE_STANDARD = "standard_profile"
|
PROFILE_STANDARD = "standard_profile"
|
||||||
PROFILE_FLOAT = "float_profile"
|
PROFILE_FLOAT = "float_profile"
|
||||||
|
|
@ -151,3 +156,30 @@ class PreditctionTemplateSerializer(serializers.ModelSerializer):
|
||||||
model = PreditctionTemplate
|
model = PreditctionTemplate
|
||||||
fields = ['id', 'name', 'template_data', 'is_default']
|
fields = ['id', 'name', 'template_data', 'is_default']
|
||||||
read_only_fields = ['id']
|
read_only_fields = ['id']
|
||||||
|
|
||||||
|
|
||||||
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ['username', 'email', 'first_name', 'last_name']
|
||||||
|
extra_kwargs = {
|
||||||
|
'username': {'read_only': True}
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate_email(self, value):
|
||||||
|
try:
|
||||||
|
validate_email(value)
|
||||||
|
except DjangoValidationError:
|
||||||
|
raise serializers.ValidationError("Invalid email format")
|
||||||
|
return value
|
||||||
|
|
||||||
|
class ChangePasswordSerializer(serializers.Serializer):
|
||||||
|
old_password = serializers.CharField(required=True)
|
||||||
|
new_password = serializers.CharField(required=True)
|
||||||
|
|
||||||
|
def validate_new_password(self, value):
|
||||||
|
validate_password(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
class DeleteAccountSerializer(serializers.Serializer):
|
||||||
|
password = serializers.CharField(required=True)
|
||||||
16
api/urls.py
16
api/urls.py
|
|
@ -10,7 +10,12 @@ from .views import (
|
||||||
login_view,
|
login_view,
|
||||||
logout_view,
|
logout_view,
|
||||||
SessionView,
|
SessionView,
|
||||||
WhoAmIView
|
WhoAmIView,
|
||||||
|
UserProfileView,
|
||||||
|
ChangePasswordView,
|
||||||
|
TokenManagementView,
|
||||||
|
DeleteUserDataView,
|
||||||
|
DeleteAccountView
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,7 +37,12 @@ urlpatterns = [
|
||||||
path('csrf/', get_csrf, name='api-csrf'),
|
path('csrf/', get_csrf, name='api-csrf'),
|
||||||
path('login/', login_view, name='api-login'),
|
path('login/', login_view, name='api-login'),
|
||||||
path('logout/', logout_view, name='api-logout'),
|
path('logout/', logout_view, name='api-logout'),
|
||||||
path('session/', SessionView.as_view(), name='api-session'), # new
|
path('session/', SessionView.as_view(), name='api-session'),
|
||||||
path('whoami/', WhoAmIView.as_view(), name='api-whoami'), # new
|
path('whoami/', WhoAmIView.as_view(), name='api-whoami'),
|
||||||
|
path("profile/", UserProfileView.as_view(), name='api-profile'),
|
||||||
|
path("profile/change-password/", ChangePasswordView.as_view(), name='api-change-password'),
|
||||||
|
path("profile/token/", TokenManagementView.as_view(), name='api-token'),
|
||||||
|
path("profile/delete-data/", DeleteUserDataView.as_view(), name='api-delete-data'),
|
||||||
|
path("profile/delete-account/", DeleteAccountView.as_view(), name='api-delete-account'),
|
||||||
]
|
]
|
||||||
urlpatterns += router.urls
|
urlpatterns += router.urls
|
||||||
|
|
|
||||||
93
api/views.py
93
api/views.py
|
|
@ -9,6 +9,7 @@ from rest_framework.exceptions import APIException
|
||||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
|
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
|
||||||
from rest_framework.decorators import api_view, permission_classes, authentication_classes, action
|
from rest_framework.decorators import api_view, permission_classes, authentication_classes, action
|
||||||
|
from rest_framework.authtoken.models import Token
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
|
|
@ -18,7 +19,7 @@ from django.middleware.csrf import get_token
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.dateparse import parse_datetime
|
from django.utils.dateparse import parse_datetime
|
||||||
from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate, TelemetryPacket
|
from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate, TelemetryPacket
|
||||||
from .serializers import PredictionSerializer, TelemetryPacketSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer
|
from .serializers import PredictionSerializer, TelemetryPacketSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer, UserSerializer, ChangePasswordSerializer, DeleteAccountSerializer
|
||||||
from .services.tawhiri import TawhiriClient
|
from .services.tawhiri import TawhiriClient
|
||||||
from drf_spectacular.utils import extend_schema
|
from drf_spectacular.utils import extend_schema
|
||||||
from .permissions import ReadOnlyOrAuthenticated, IsOwner
|
from .permissions import ReadOnlyOrAuthenticated, IsOwner
|
||||||
|
|
@ -248,6 +249,96 @@ class PreditctionTemplateViewset(ModelViewSet):
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
serializer.save(user=self.request.user)
|
serializer.save(user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class UserProfileView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
serializer = UserSerializer(request.user)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def patch(self, request):
|
||||||
|
user = request.user
|
||||||
|
serializer = UserSerializer(user, data=request.data, partial=True)
|
||||||
|
|
||||||
|
if not serializer.is_valid():
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
class ChangePasswordView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
user = request.user
|
||||||
|
serializer = ChangePasswordSerializer(data=request.data)
|
||||||
|
|
||||||
|
if not serializer.is_valid():
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
if not user.check_password(serializer.validated_data['old_password']):
|
||||||
|
return Response({'detail': 'Old password is incorrect'},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
user.set_password(serializer.validated_data['new_password'])
|
||||||
|
user.save()
|
||||||
|
return Response({'detail': 'Password changed successfully'})
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteAccountView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def delete(self, request):
|
||||||
|
user = request.user
|
||||||
|
serializer = DeleteAccountSerializer(data=request.data)
|
||||||
|
|
||||||
|
if not serializer.is_valid():
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
if not user.check_password(serializer.validated_data['password']):
|
||||||
|
return Response({'detail': 'Incorrect password'},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
Prediction.objects.filter(user=user).delete()
|
||||||
|
SavedPoint.objects.filter(user=user).delete()
|
||||||
|
PreditctionTemplate.objects.filter(user=user).delete()
|
||||||
|
|
||||||
|
user.delete()
|
||||||
|
|
||||||
|
return Response({'detail': 'Account deleted successfully'})
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteUserDataView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def delete(self, request):
|
||||||
|
user = request.user
|
||||||
|
|
||||||
|
Prediction.objects.filter(user=user).delete()
|
||||||
|
SavedPoint.objects.filter(user=user).delete()
|
||||||
|
PreditctionTemplate.objects.filter(user=user).delete()
|
||||||
|
|
||||||
|
return Response({'detail': 'All user data deleted successfully'})
|
||||||
|
|
||||||
|
|
||||||
|
class TokenManagementView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
|
||||||
|
token, created = Token.objects.get_or_create(user=request.user)
|
||||||
|
return Response({"token": token.key})
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
|
||||||
|
Token.objects.filter(user=request.user).delete()
|
||||||
|
token = Token.objects.create(user=request.user)
|
||||||
|
return Response({"token": token.key})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# class PredictionCreateView(APIView):
|
# class PredictionCreateView(APIView):
|
||||||
# permission_classes = [IsAuthenticated]
|
# permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ INSTALLED_APPS = [
|
||||||
'drf_spectacular',
|
'drf_spectacular',
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
'api.apps.ApiConfig',
|
'api.apps.ApiConfig',
|
||||||
|
'channels',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue