diff --git a/MisplaceAI/MisplaceAI/settings.py b/MisplaceAI/MisplaceAI/settings.py index 0319f3b179831fcde8418fed69f6c084058385d4..e2b86b8340c039d479e037a682e89017831832da 100644 --- a/MisplaceAI/MisplaceAI/settings.py +++ b/MisplaceAI/MisplaceAI/settings.py @@ -1,5 +1,6 @@ """ - MisplaceAi/MisplaceAI/settings.py +MisplaceAI/MisplaceAI/settings.py + Django settings for MisplaceAI project. Generated by 'django-admin startproject' using Django 4.0.2. @@ -24,25 +25,32 @@ BASE_DIR = Path(__file__).resolve().parent.parent # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-34gsb7^)t!ltchc4#2^sn_#+$(4i=ts107$(2yjy#ung+%mrn2' +# Media files configuration +# URL that handles the media served from MEDIA_ROOT, used for managing stored files. MEDIA_URL = '/media/' +# Path where media files are stored. MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # SECURITY WARNING: don't run with debug turned on in production! +# Enable debug mode only during development. DEBUG = True -# ALLOWED_HOSTS = [] -ALLOWED_HOSTS = ['*'] # This allows all hosts. Use with caution. + +ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ + # Default Django apps 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + + # Custom apps for the MisplaceAI project 'rules.apps.RulesConfig', 'authentication.apps.AuthenticationConfig', 'core.apps.CoreConfig', @@ -51,17 +59,19 @@ INSTALLED_APPS = [ 'placement_rules.apps.PlacementRulesConfig', 'results_viewer.apps.ResultsViewerConfig', 'process_misplaced_manager.apps.ProcessMisplacedManagerConfig', + + # Third-party apps 'rest_framework', 'corsheaders', 'user_dashboard', 'rest_framework_simplejwt', 'rest_framework_simplejwt.token_blacklist', - ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + # Middleware to handle Cross-Origin Resource Sharing (CORS) 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -70,31 +80,36 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] +# List of origins that are allowed to make cross-site HTTP requests CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] +# List of trusted origins for CSRF protection CSRF_TRUSTED_ORIGINS = [ "http://localhost:3000", ] -# Note: CORS_ORIGIN_ALLOW_ALL is set to False for security reasons +# Whether to allow all origins to make cross-site HTTP requests (set to False for security) CORS_ORIGIN_ALLOW_ALL = False +# Allow cookies to be included in cross-site HTTP requests CORS_ALLOW_CREDENTIALS = True + +# Whether the CSRF cookie is accessible only by the HTTP protocol (True for security) CSRF_COOKIE_HTTPONLY = True -ROOT_URLCONF = 'MisplaceAI.urls' +ROOT_URLCONF = 'MisplaceAI.urls' +# Session settings SESSION_COOKIE_AGE = 1209600 # 2 weeks in seconds -SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Do not expire the session when the browser closes -SESSION_COOKIE_SECURE = False # Set to True if using HTTPS -SESSION_SAVE_EVERY_REQUEST = True # Save the session cookie on every request (optional, based on your needs) +SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Do not expire the session when the browser closes +SESSION_COOKIE_SECURE = False # Set to True if using HTTPS +SESSION_SAVE_EVERY_REQUEST = True # Save the session cookie on every request -# Configuration of the session engine +# Configuration of the session engine to use database-backed sessions SESSION_ENGINE = 'django.contrib.sessions.backends.db' - TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -113,6 +128,7 @@ TEMPLATES = [ WSGI_APPLICATION = 'MisplaceAI.wsgi.application' +# Django REST framework configuration REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', @@ -124,14 +140,18 @@ REST_FRAMEWORK = { ], } +# Configuration for Simple JWT (JSON Web Token) authentication SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), - 'ROTATE_REFRESH_TOKENS': True, - 'BLACKLIST_AFTER_ROTATION': True, + 'ROTATE_REFRESH_TOKENS': True, # Automatically issue new refresh tokens + 'BLACKLIST_AFTER_ROTATION': True, # Blacklist old refresh tokens after rotation } + +# Allow all origins for CORS CORS_ALLOW_ALL_ORIGINS = True -# Database + +# Database configuration # https://docs.djangoproject.com/en/4.0/ref/settings/#databases DATABASES = { @@ -166,20 +186,28 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] -# Internationalization +# Internationalization settings # https://docs.djangoproject.com/en/4.0/topics/i18n/ +# Language code for the project LANGUAGE_CODE = 'en-us' +# Time zone for the project TIME_ZONE = 'UTC' +# Enable internationalization USE_I18N = True +# Enable time zone support USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.0/howto/static-files/ + +# URL to use when referring to static files STATIC_URL = '/static/' + +# Directories where static files are stored STATICFILES_DIRS = [ BASE_DIR / "static", BASE_DIR / "authentication/static", @@ -190,11 +218,15 @@ STATICFILES_DIRS = [ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +# Ngrok configuration for development if DEBUG: import requests try: + # Get the public URL for the Ngrok tunnel ngrok_tunnel = requests.get('http://localhost:4040/api/tunnels').json()['tunnels'][0]['public_url'] + # Extract the hostname from the Ngrok URL ngrok_hostname = ngrok_tunnel.split("//")[-1].split(":")[0] + # Add the Ngrok hostname to allowed hosts ALLOWED_HOSTS.append(ngrok_hostname) except requests.exceptions.RequestException: pass diff --git a/MisplaceAI/MisplaceAI/urls.py b/MisplaceAI/MisplaceAI/urls.py index a74789831728d5c059f465920366830dde8b1b0c..8fb4f47cc96ae03b05c097d5f385800c84b38a6a 100644 --- a/MisplaceAI/MisplaceAI/urls.py +++ b/MisplaceAI/MisplaceAI/urls.py @@ -1,22 +1,44 @@ -# MisplaceAI/urls.py +# MisplaceAI/MisplaceAI/urls.py + +# This file defines the URL patterns for the entire MisplaceAI Django project. +# It includes routes for the admin interface and various applications within the project. + from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include +# Define the URL patterns for the project urlpatterns = [ + # Admin interface URL path('admin/', admin.site.urls), + + # Core application URLs path('api/', include('core.urls')), path('', include('core.urls')), + + # Rules application URLs path('api/rules/', include('rules.urls')), + + # Authentication application URLs path('api/auth/', include('authentication.urls')), + + # Admin app URLs for managing the application path('api/admin-app/', include('admin_app.urls')), + + # Process misplaced manager URLs with namespace path('api/process_misplaced_manager/', include('process_misplaced_manager.urls', namespace='process_misplaced_manager')), + + # Results viewer URLs with namespace path('api/results_viewer/', include('results_viewer.urls', namespace='results_viewer')), + + # Placement rules URLs path('api/placement_rules/', include('placement_rules.urls')), - path('api/user_dashboard/', include('user_dashboard.urls')), + # User dashboard URLs + path('api/user_dashboard/', include('user_dashboard.urls')), ] +# Media URL configuration if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/MisplaceAI/rules/forms.py b/MisplaceAI/rules/forms.py index 0ebbef1aac84e3691b3dad1ffff00fea95a1fa94..676b980f34e83265123e04e7bc4a8372d7535080 100644 --- a/MisplaceAI/rules/forms.py +++ b/MisplaceAI/rules/forms.py @@ -1,19 +1,31 @@ # MisplaceAI/rules/forms.py +# This file defines forms for the rules app. +# Forms are used to handle user input and validate the data before it is saved to the database. + from django import forms from .models import Rule, Location, Item class RuleForm(forms.ModelForm): + """ + Form for creating and updating rules. + """ class Meta: model = Rule fields = ['user', 'item', 'locations'] class LocationForm(forms.ModelForm): + """ + Form for creating and updating locations. + """ class Meta: model = Location fields = ['name'] class ItemForm(forms.ModelForm): + """ + Form for creating and updating items. + """ class Meta: model = Item fields = ['name'] diff --git a/MisplaceAI/rules/models.py b/MisplaceAI/rules/models.py index 5c84efff58c91a5c0fdcdf9f8bdcc1f56560c55f..5f6966345073013d66c4c77e6bdf0e111075b507 100644 --- a/MisplaceAI/rules/models.py +++ b/MisplaceAI/rules/models.py @@ -1,24 +1,51 @@ # MisplaceAI/rules/models.py +# This file defines the models for the rules app. +# Models are used to define the structure of the database tables and the relationships between them. +# Each model maps to a single table in the database. + from django.db import models from django.contrib.auth.models import User class Location(models.Model): + """ + Model to represent a location. + """ + # Field to store the name of the location, must be unique name = models.CharField(max_length=255, unique=True) def __str__(self): + """ + String representation of the Location model. + """ return self.name class Item(models.Model): + """ + Model to represent an item. + """ + # Field to store the name of the item, must be unique name = models.CharField(max_length=255, unique=True) def __str__(self): + """ + String representation of the Item model. + """ return self.name class Rule(models.Model): + """ + Model to represent a rule linking users, items, and locations. + """ + # ForeignKey field to create a relationship with the User model user = models.ForeignKey(User, on_delete=models.CASCADE) + # ForeignKey field to create a relationship with the Item model item = models.ForeignKey(Item, on_delete=models.CASCADE) + # ManyToManyField to create a relationship with the Location model locations = models.ManyToManyField(Location) def __str__(self): + """ + String representation of the Rule model. + """ return f"{self.item.name} Rule" diff --git a/MisplaceAI/rules/urls.py b/MisplaceAI/rules/urls.py index 198f11a255bea9de596e50d2282149db943082bc..2faa132f335ecb96b65f7ebc2bd825bcb9395a7a 100644 --- a/MisplaceAI/rules/urls.py +++ b/MisplaceAI/rules/urls.py @@ -1,15 +1,36 @@ +# MisplaceAI/rules/urls.py + +# This file defines the URL patterns for the rules app. +# It includes routes for managing users, items, locations, and rules. + from django.urls import path from .views import ( UserListView, AdminManageItemView, AdminManageLocationView, AdminManageRuleView ) +# Define the app name for namespacing URL names app_name = 'rules' + +# Define the URL patterns for the rules app urlpatterns = [ + # Route for listing all users path('users/', UserListView.as_view(), name='user-list'), + + # Route for managing items (list, create) path('admin_manage_item/', AdminManageItemView.as_view(), name='admin_manage_item'), + + # Route for managing a specific item (retrieve, update, delete) path('admin_manage_item/<int:item_id>/', AdminManageItemView.as_view(), name='admin_manage_item_detail'), + + # Route for managing locations (list, create) path('admin_manage_location/', AdminManageLocationView.as_view(), name='admin_manage_location'), + + # Route for managing a specific location (retrieve, update, delete) path('admin_manage_location/<int:location_id>/', AdminManageLocationView.as_view(), name='admin_manage_location_detail'), + + # Route for managing rules (list, create) path('admin_manage_rule/', AdminManageRuleView.as_view(), name='admin_manage_rule'), + + # Route for managing a specific rule (retrieve, update, delete) path('admin_manage_rule/<int:rule_id>/', AdminManageRuleView.as_view(), name='admin_manage_rule_detail'), ] diff --git a/MisplaceAI/rules/utils.py b/MisplaceAI/rules/utils.py index 3de4b76f0db17f871d44b4184f9b7cc284f950a6..9836a74171062e5b8920fa329cb4e6313b559b59 100644 --- a/MisplaceAI/rules/utils.py +++ b/MisplaceAI/rules/utils.py @@ -1,3 +1,4 @@ +# MisplaceAI/rules/utils.py from django.core.exceptions import ValidationError from .models import Rule diff --git a/MisplaceAI/rules/views.py b/MisplaceAI/rules/views.py index 3409a85f070434243c39eebaee2fc99c7669132a..615067a6c01355a62f8cf19c99513e99054583c3 100644 --- a/MisplaceAI/rules/views.py +++ b/MisplaceAI/rules/views.py @@ -1,4 +1,9 @@ # misplaceAI/rules/views.py + +# This file defines the views for the rules app. +# Views handle the logic for different endpoints, providing appropriate responses +# based on the request and the business logic. This includes managing users, items, locations, and rules. + from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status @@ -9,122 +14,194 @@ from .serializers import LocationSerializer, ItemSerializer, RuleSerializer, Use from django.shortcuts import get_object_or_404 class UserListView(APIView): + """ + View to list all users. Only accessible by authenticated users. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): + # Retrieve all user objects from the database users = User.objects.all() + # Serialize the user objects into JSON format serializer = UserSerializer(users, many=True) + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) class AdminManageItemView(APIView): + """ + View to manage items. Only accessible by authenticated users. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): + # Retrieve all item objects from the database, ordered by name items = Item.objects.all().order_by('name') + # Serialize the item objects into JSON format serializer = ItemSerializer(items, many=True) + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): + # Deserialize the incoming data into an ItemSerializer serializer = ItemSerializer(data=request.data) + # Validate the data if serializer.is_valid(): + # Save the new item object to the database serializer.save() + # Return the serialized data with a 201 Created status return Response(serializer.data, status=status.HTTP_201_CREATED) + # Return validation errors with a 400 Bad Request status return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def put(self, request, item_id, *args, **kwargs): + # Retrieve the existing item object from the database item = get_object_or_404(Item, id=item_id) + # Deserialize the incoming data into an ItemSerializer serializer = ItemSerializer(item, data=request.data) + # Validate the data if serializer.is_valid(): + # Update the existing item object in the database serializer.save() + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) + # Return validation errors with a 400 Bad Request status return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, item_id, *args, **kwargs): + # Retrieve the existing item object from the database item = get_object_or_404(Item, id=item_id) + # Delete the item object from the database item.delete() + # Return a 204 No Content status to indicate successful deletion return Response(status=status.HTTP_204_NO_CONTENT) class AdminManageLocationView(APIView): + """ + View to manage locations. Only accessible by authenticated users. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): + # Retrieve all location objects from the database, ordered by name locations = Location.objects.all().order_by('name') + # Serialize the location objects into JSON format serializer = LocationSerializer(locations, many=True) + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): + # Deserialize the incoming data into a LocationSerializer serializer = LocationSerializer(data=request.data) + # Validate the data if serializer.is_valid(): + # Save the new location object to the database serializer.save() + # Return the serialized data with a 201 Created status return Response(serializer.data, status=status.HTTP_201_CREATED) + # Return validation errors with a 400 Bad Request status return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def put(self, request, location_id, *args, **kwargs): + # Retrieve the existing location object from the database location = get_object_or_404(Location, id=location_id) + # Deserialize the incoming data into a LocationSerializer serializer = LocationSerializer(location, data=request.data) + # Validate the data if serializer.is_valid(): + # Update the existing location object in the database serializer.save() + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) + # Return validation errors with a 400 Bad Request status return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, location_id, *args, **kwargs): + # Retrieve the existing location object from the database location = get_object_or_404(Location, id=location_id) + # Delete the location object from the database location.delete() + # Return a 204 No Content status to indicate successful deletion return Response(status=status.HTTP_204_NO_CONTENT) - - - - class AdminManageRuleView(APIView): + """ + View to manage rules. Only accessible by authenticated users. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): # Filter rules based on the authenticated user rules = Rule.objects.filter(user=request.user).order_by('id') + # Serialize the rule objects into JSON format serializer = RuleSerializer(rules, many=True) + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): + # Extract the item ID and location IDs from the request data data = request.data item_id = data.get('item') location_ids = data.get('locations', []) + # Get the authenticated user user = request.user + # Retrieve the item object from the database item = get_object_or_404(Item, id=item_id) + # Retrieve the location objects from the database locations = Location.objects.filter(id__in=location_ids) + # Check if the locations exist if not locations.exists(): + # Return an error if one or more locations are invalid return Response({'error': 'One or more locations are invalid.'}, status=status.HTTP_400_BAD_REQUEST) + # Create a new rule object rule = Rule(user=user, item=item) + # Save the rule object to the database rule.save() + # Set the locations for the rule rule.locations.set(locations) + # Save the rule object to the database rule.save() + # Serialize the rule object into JSON format serializer = RuleSerializer(rule) + # Return the serialized data with a 201 Created status return Response(serializer.data, status=status.HTTP_201_CREATED) def put(self, request, rule_id, *args, **kwargs): + # Retrieve the existing rule object from the database rule = get_object_or_404(Rule, id=rule_id) + # Extract the item ID and location IDs from the request data data = request.data item_id = data.get('item') location_ids = data.get('locations', []) + # Retrieve the item object from the database item = get_object_or_404(Item, id=item_id) + # Retrieve the location objects from the database locations = Location.objects.filter(id__in=location_ids) + # Check if the locations exist if not locations.exists(): + # Return an error if one or more locations are invalid return Response({'error': 'One or more locations are invalid.'}, status=status.HTTP_400_BAD_REQUEST) + # Update the rule object with the new item and locations rule.item = item rule.locations.set(locations) + # Save the updated rule object to the database rule.save() + # Serialize the rule object into JSON format serializer = RuleSerializer(rule) + # Return the serialized data with a 200 OK status return Response(serializer.data, status=status.HTTP_200_OK) def delete(self, request, rule_id, *args, **kwargs): + # Retrieve the existing rule object from the database rule = get_object_or_404(Rule, id=rule_id) + # Delete the rule object from the database rule.delete() + # Return a 204 No Content status to indicate successful deletion return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/MisplaceAI/user_dashboard/serializers.py b/MisplaceAI/user_dashboard/serializers.py index a7fce826a9b2eb508b2c14e2d37df96f43ec14e2..81d06a74b81edf9ce641c9c177888b89c2c368e7 100644 --- a/MisplaceAI/user_dashboard/serializers.py +++ b/MisplaceAI/user_dashboard/serializers.py @@ -1,18 +1,34 @@ # MisplaceAI/user_dashboard/serializers.py + +# This file defines serializers for the user_dashboard app. +# Serializers are used to convert complex data types such as querysets and model instances +# into native Python datatypes that can then be easily rendered into JSON, XML, or other content types. +# They also provide deserialization, allowing parsed data to be converted back into complex types, +# after first validating the incoming data. + from django.contrib.auth.models import User from rest_framework import serializers class UserSerializer(serializers.ModelSerializer): + """ + Serializer for retrieving user information. + """ class Meta: model = User fields = ['username', 'email', 'first_name', 'last_name'] class UserUpdateSerializer(serializers.ModelSerializer): + """ + Serializer for updating user information. + """ class Meta: model = User fields = ['username', 'email', 'first_name', 'last_name'] def update(self, instance, validated_data): + """ + Update the user instance with the validated data. + """ instance.username = validated_data.get('username', instance.username) instance.email = validated_data.get('email', instance.email) instance.first_name = validated_data.get('first_name', instance.first_name) @@ -21,15 +37,23 @@ class UserUpdateSerializer(serializers.ModelSerializer): return instance class UserUpdateEmailSerializer(serializers.Serializer): + """ + Serializer for updating user email. + """ email = serializers.EmailField() password = serializers.CharField(write_only=True) class UserUpdateUsernameSerializer(serializers.Serializer): + """ + Serializer for updating user username. + """ username = serializers.CharField(max_length=150) password = serializers.CharField(write_only=True) - class UserUpdatePasswordSerializer(serializers.Serializer): + """ + Serializer for updating user password. + """ current_password = serializers.CharField(write_only=True) new_password = serializers.CharField(write_only=True) - confirm_password = serializers.CharField(write_only=True) \ No newline at end of file + confirm_password = serializers.CharField(write_only=True) diff --git a/MisplaceAI/user_dashboard/urls.py b/MisplaceAI/user_dashboard/urls.py index a730bd1b77bcbf947471500b953bf595c2e9dd69..588d8e0432c8690b7ae30cda6bc3b48d94359ab8 100644 --- a/MisplaceAI/user_dashboard/urls.py +++ b/MisplaceAI/user_dashboard/urls.py @@ -1,7 +1,12 @@ # MisplaceAI/user_dashboard/urls.py + +# This file defines the URL patterns for the user_dashboard app. +# It includes routes for viewing and updating user information. + from django.urls import path -from .views import UserDashboardView, UserUpdateView, UpdateEmailView,CurrentUserEmailView,CurrentUserUsernameView,UpdateUsernameView,UpdatePasswordView +from .views import UserDashboardView, UserUpdateView, UpdateEmailView, CurrentUserEmailView, CurrentUserUsernameView, UpdateUsernameView, UpdatePasswordView +# Define the URL patterns for the user_dashboard app urlpatterns = [ path('dashboard/', UserDashboardView.as_view(), name='user-dashboard'), path('update/', UserUpdateView.as_view(), name='user-update'), @@ -10,5 +15,4 @@ urlpatterns = [ path('username/', CurrentUserUsernameView.as_view(), name='user-current-username'), path('update_username/', UpdateUsernameView.as_view(), name='user-update-username'), path('update_password/', UpdatePasswordView.as_view(), name='user-update-password'), - ] diff --git a/MisplaceAI/user_dashboard/views.py b/MisplaceAI/user_dashboard/views.py index 3a4904f38e0ea052a37badcd927bcdc63b33fc30..f89c3ae16c6ecbb21e89392b104eb2b27d65c2e0 100644 --- a/MisplaceAI/user_dashboard/views.py +++ b/MisplaceAI/user_dashboard/views.py @@ -1,5 +1,9 @@ # MisplaceAI/user_dashboard/views.py +# This file defines the views for the user_dashboard app. +# Views handle the logic for different endpoints, providing appropriate responses +# based on the request and the business logic. This includes viewing and updating user information. + from django.contrib.auth.models import User from rest_framework import generics from rest_framework.permissions import IsAuthenticated @@ -10,22 +14,33 @@ from rest_framework import status from django.contrib.auth import authenticate class UserDashboardView(generics.RetrieveAPIView): + """ + View for retrieving the current user's information. + """ queryset = User.objects.all() serializer_class = UserSerializer permission_classes = [IsAuthenticated] def get_object(self): + # Return the current authenticated user return self.request.user class UserUpdateView(generics.UpdateAPIView): + """ + View for updating the current user's information. + """ queryset = User.objects.all() serializer_class = UserUpdateSerializer permission_classes = [IsAuthenticated] def get_object(self): + # Return the current authenticated user return self.request.user - + class UpdateEmailView(APIView): + """ + View for updating the current user's email address. + """ permission_classes = [IsAuthenticated] def put(self, request, *args, **kwargs): @@ -46,6 +61,9 @@ class UpdateEmailView(APIView): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class UpdateUsernameView(APIView): + """ + View for updating the current user's username. + """ permission_classes = [IsAuthenticated] def put(self, request, *args, **kwargs): @@ -66,6 +84,9 @@ class UpdateUsernameView(APIView): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class CurrentUserEmailView(APIView): + """ + View for retrieving the current user's email address. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): @@ -73,14 +94,19 @@ class CurrentUserEmailView(APIView): return Response({'email': user.email}, status=status.HTTP_200_OK) class CurrentUserUsernameView(APIView): + """ + View for retrieving the current user's username. + """ permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): user = request.user return Response({'username': user.username}, status=status.HTTP_200_OK) - class UpdatePasswordView(APIView): + """ + View for updating the current user's password. + """ permission_classes = [IsAuthenticated] def put(self, request, *args, **kwargs): @@ -102,4 +128,4 @@ class UpdatePasswordView(APIView): user.save() return Response({'message': 'Password updated successfully'}, status=status.HTTP_200_OK) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)