Skip to content

Conversation

@joyanna27
Copy link

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds editable profile functionality by introducing three new fields to the User model: bio, projects, and experience. These fields allow users to add biographical information and structured data about their projects and work experience.

Key Changes

  • Added bio, projects, and experience fields to the User model with JSONField types for structured data
  • Created a new UserProfileView API endpoint with GET and PATCH methods to retrieve and update profile information
  • Added URL routing for the new profile endpoint

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
db/user.py Adds three new optional fields to User model: bio (CharField), projects (JSONField), and experience (JSONField)
api/dashboard/urls.py Imports UserProfileView and adds new profile endpoint route
api/dashboard/profile_views.py New API view implementing GET and PATCH endpoints for user profile with bio, projects, and experience fields

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

path("coupon/", include("api.dashboard.coupon.urls")),
path("projects/", include("api.dashboard.projects.urls")),
path("achievement/", include("api.dashboard.achievement.urls")),
path('profile/user-profile/',UserProfileView.as_view()),
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after comma in the path definition. Should be path('profile/user-profile/', UserProfileView.as_view()) for consistency with Python style conventions.

Suggested change
path('profile/user-profile/',UserProfileView.as_view()),
path('profile/user-profile/', UserProfileView.as_view()),

Copilot uses AI. Check for mistakes.
from db.user import User

class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This view uses permission_classes = [IsAuthenticated] which is inconsistent with the rest of the codebase. All other dashboard views use authentication_classes = [CustomizePermission] for JWT-based authentication (see examples in api/dashboard/profile/profile_view.py, api/dashboard/projects/projects_view.py, etc.). The IsAuthenticated permission class expects Django's default authentication, which doesn't align with the JWT authentication pattern used throughout this project. Change this to use authentication_classes = [CustomizePermission] instead, and use JWTUtils.fetch_user_id(request) to get the user.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +26
def patch(self, request):
user = request.user
data = request.data

if 'bio' in data:
user.bio = data['bio']
if 'projects' in data:
user.projects = data['projects']
if 'experience' in data:
user.experience = data['experience']
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PATCH endpoint lacks input validation and error handling. The code accepts any data from request.data without validating the structure or content of bio, projects, and experience fields. This could allow:

  1. Bio strings exceeding the 2000 character limit (which would cause a database error)
  2. Invalid JSON structures for projects/experience that don't match expected schemas
  3. Injection of malicious data

Following the pattern in api/dashboard/profile/profile_view.py:UserProfileEditView (lines 66-81), you should use a serializer for validation. Create a serializer that validates max_length for bio and validates the structure of projects/experience JSONFields before saving.

Copilot uses AI. Check for mistakes.
if 'experience' in data:
user.experience = data['experience']

user.save()
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling for the user.save() operation. If the save fails (e.g., database connection issues, constraint violations, or bio exceeding max_length), the endpoint will return a 500 error instead of a proper error response. The codebase pattern (see api/dashboard/projects/projects_view.py lines 42-53) uses try-except blocks or serializer validation to handle such errors gracefully and return CustomResponse(...).get_failure_response() with appropriate error messages.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +38
projects = models.JSONField(default=list, blank=True, null=True)
experience = models.JSONField(default=list, blank=True, null=True)
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a mutable default value (list) directly in JSONField can lead to unexpected behavior where all instances share the same list object. While Django's JSONField handles this differently than regular Python defaults, it's safer and more explicit to use a callable. Consider changing default=list to default=list (which Django serializes properly), or use a lambda function default=lambda: [] to be more explicit about creating a new list for each instance.

Suggested change
projects = models.JSONField(default=list, blank=True, null=True)
experience = models.JSONField(default=list, blank=True, null=True)
projects = models.JSONField(default=lambda: [], blank=True, null=True)
experience = models.JSONField(default=lambda: [], blank=True, null=True)

Copilot uses AI. Check for mistakes.
@@ -1,5 +1,5 @@
from django.urls import path, include

from.profile_views import UserProfileView
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after 'from' keyword. The import should be from .profile_views import UserProfileView instead of from.profile_views import UserProfileView.

Suggested change
from.profile_views import UserProfileView
from .profile_views import UserProfileView

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +15

class UserProfileView(APIView):
permission_classes = [IsAuthenticated]

def get(self, request):
user = request.user
return Response({
"bio": user.bio,
"projects": user.projects,
"experience": user.experience
})
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GET endpoint doesn't follow the codebase's standard response pattern. Other views in this codebase (e.g., api/dashboard/profile/profile_view.py:UserProfileEditView, api/dashboard/projects/projects_view.py) use CustomResponse for consistent API responses with proper error handling structure. Consider refactoring to return CustomResponse(response={...}).get_success_response() instead of a plain Response object.

Suggested change
class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
return Response({
"bio": user.bio,
"projects": user.projects,
"experience": user.experience
})
from utils.custom_response import CustomResponse
class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
response_data = {
"bio": user.bio,
"projects": user.projects,
"experience": user.experience,
}
return CustomResponse(response=response_data).get_success_response()

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +29

class UserProfileView(APIView):
permission_classes = [IsAuthenticated]

def get(self, request):
user = request.user
return Response({
"bio": user.bio,
"projects": user.projects,
"experience": user.experience
})

def patch(self, request):
user = request.user
data = request.data

if 'bio' in data:
user.bio = data['bio']
if 'projects' in data:
user.projects = data['projects']
if 'experience' in data:
user.experience = data['experience']

user.save()
return Response({"message": "Profile updated successfully"}) No newline at end of file
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The response doesn't follow the codebase's standard pattern. Similar to the GET endpoint, this should use CustomResponse for consistency. The success response should return the updated data (like api/dashboard/profile/profile_view.py:UserProfileEditView line 79 does with CustomResponse(response=serializer.data).get_success_response()), not just a message.

Suggested change
class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
return Response({
"bio": user.bio,
"projects": user.projects,
"experience": user.experience
})
def patch(self, request):
user = request.user
data = request.data
if 'bio' in data:
user.bio = data['bio']
if 'projects' in data:
user.projects = data['projects']
if 'experience' in data:
user.experience = data['experience']
user.save()
return Response({"message": "Profile updated successfully"})
from utils.custom_response import CustomResponse
class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
profile_data = {
"bio": user.bio,
"projects": user.projects,
"experience": user.experience,
}
return CustomResponse(response=profile_data).get_success_response()
def patch(self, request):
user = request.user
data = request.data
if 'bio' in data:
user.bio = data['bio']
if 'projects' in data:
user.projects = data['projects']
if 'experience' in data:
user.experience = data['experience']
user.save()
updated_profile_data = {
"bio": user.bio,
"projects": user.projects,
"experience": user.experience,
}
return CustomResponse(response=updated_profile_data).get_success_response()

Copilot uses AI. Check for mistakes.
path("coupon/", include("api.dashboard.coupon.urls")),
path("projects/", include("api.dashboard.projects.urls")),
path("achievement/", include("api.dashboard.achievement.urls")),
path('profile/user-profile/',UserProfileView.as_view()),
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a duplicate endpoint. There's already a 'user-profile/' path defined in api/dashboard/profile/urls.py (line 8) which maps to UserProfileAPI. This new endpoint would conflict with or shadow that existing endpoint depending on URL resolution order. The new editable profile fields (bio, projects, experience) should either be added to the existing UserProfileAPI/UserProfileEditView in api/dashboard/profile/profile_view.py, or this new view should be added to api/dashboard/profile/urls.py with a different, non-conflicting path name.

Suggested change
path('profile/user-profile/',UserProfileView.as_view()),
path('profile/user-profile-view/', UserProfileView.as_view()),

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +5
from db.user import User

Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'User' is not used.

Suggested change
from db.user import User

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant