Skip to content

Commit 5ecec79

Browse files
committed
Fix typo
1 parent 16d0bce commit 5ecec79

File tree

102 files changed

+7340
-11312
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+7340
-11312
lines changed

backend/api/views.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,16 @@ def post(self, request, *args, **kwargs):
5757

5858
if user is not None:
5959
auth_login(request, user)
60-
return JsonResponse({"detail": "Successfully logged in."})
60+
return JsonResponse({
61+
"detail": "Successfully logged in.",
62+
"user": {
63+
"id": user.id,
64+
"username": user.username,
65+
"email": user.email,
66+
"is_staff": user.is_staff,
67+
"is_superuser": user.is_superuser,
68+
},
69+
})
6170
else:
6271
return JsonResponse(
6372
{"detail": "Invalid login credentials."},

backend/backend/database_router.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ def load_database_settings(self):
1313
settings.DATABASES["default"] = self.get_database_config()
1414

1515
def get_database_config(self):
16+
# Get the global TIME_ZONE setting
17+
time_zone = getattr(settings, 'TIME_ZONE', 'UTC')
18+
19+
# Print debug information
20+
print(f"Database configuration:")
21+
print(f"POSTGRES_DB: {os.getenv('POSTGRES_DB')}")
22+
print(f"POSTGRES_USER: {os.getenv('POSTGRES_USER')}")
23+
print(f"POSTGRES_HOST: {os.getenv('POSTGRES_HOST')}")
24+
print(f"POSTGRES_PORT: {os.getenv('POSTGRES_PORT')}")
25+
print(f"TIME_ZONE: {time_zone}")
26+
1627
return {
1728
"ENGINE": "django.db.backends.postgresql",
1829
"NAME": os.getenv("POSTGRES_DB"),
@@ -21,7 +32,7 @@ def get_database_config(self):
2132
"HOST": os.getenv("POSTGRES_HOST"),
2233
"PORT": os.getenv("POSTGRES_PORT"),
2334
"ATOMIC_REQUESTS": True,
24-
"TIME_ZONE": "UTC",
35+
"TIME_ZONE": time_zone,
2536
"CONN_HEALTH_CHECKS": True,
2637
"CONN_MAX_AGE": None,
2738
"OPTIONS": {},

backend/backend/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ def get_secret(secret_name, default=None):
141141
"HOST": os.getenv("POSTGRES_HOST"),
142142
"PORT": os.getenv("POSTGRES_PORT"),
143143
"ATOMIC_REQUESTS": False, # Set to False initially
144-
"TIME_ZONE": TIME_ZONE,
145144
}
146145
}
147146

backend/blog/views.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,21 @@ def get_queryset(self):
107107
class CommentViewSet(viewsets.ModelViewSet):
108108
queryset = Comment.objects.all().order_by("-pub_date")
109109
serializer_class = CommentSerializer
110-
permission_classes = [IsAuthenticatedOrReadOnly, (IsNotHidden | IsAuthorOrAdmin)]
111110
lookup_field = "pk"
112111

112+
def get_permissions(self):
113+
"""
114+
Instantiates and returns the list of permissions that this view requires.
115+
"""
116+
if self.action == 'create':
117+
# For creating comments, only require authentication
118+
permission_classes = [IsAuthenticated]
119+
else:
120+
# For other actions (retrieve, update, delete), check object permissions
121+
permission_classes = [IsAuthenticatedOrReadOnly, (IsNotHidden | IsAuthorOrAdmin)]
122+
123+
return [permission() for permission in permission_classes]
124+
113125
def perform_create(self, serializer):
114126
post_id = self.kwargs.get("post_id")
115127
post = get_object_or_404(BlogPost, pk=post_id)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 5.1.8 on 2025-04-06 23:16
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('core', '0015_smtpsettings'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='smtpsettings',
15+
name='is_configured',
16+
),
17+
]

backend/core/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ class Meta:
5353
verbose_name = "SMTP Settings"
5454
verbose_name_plural = "SMTP Settings"
5555

56+
@property
57+
def is_configured(self):
58+
"""
59+
Calculate if SMTP is configured on-the-fly instead of storing in database.
60+
Returns True if all required fields are filled.
61+
"""
62+
return bool(self.host and self.port and self.username and self.password and self.from_email)
63+
5664
def save(self, *args, **kwargs):
5765
if not self.pk and SMTPSettings.objects.exists():
5866
raise ValidationError("Only one SMTP settings instance can exist.")

backend/users/serializers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ def get_last_name(self, obj):
6868
return None
6969

7070

71+
class UserProfileUpdateSerializer(serializers.ModelSerializer):
72+
"""Serializer for updating user profile information (first_name, last_name)"""
73+
74+
class Meta:
75+
model = User
76+
fields = ["first_name", "last_name"]
77+
78+
def validate_first_name(self, value):
79+
if value and len(value.strip()) > 150:
80+
raise serializers.ValidationError("First name cannot exceed 150 characters.")
81+
return value.strip() if value else ""
82+
83+
def validate_last_name(self, value):
84+
if value and len(value.strip()) > 150:
85+
raise serializers.ValidationError("Last name cannot exceed 150 characters.")
86+
return value.strip() if value else ""
87+
88+
7189
class ProfileBioSerializer(serializers.ModelSerializer):
7290
class Meta:
7391
model = Profile

backend/users/signals.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.db import transaction
66
from django.db.models.signals import post_delete, post_save
77
from django.dispatch import receiver
8+
from django.utils import timezone
89

910
from core.models import SiteInfo
1011
from core.tasks import send_scheduled_email
@@ -71,9 +72,15 @@ def send_password_change_notification(sender, instance, created, **kwargs):
7172
site_info = SiteInfo.objects.first()
7273
site_title = site_info.site_title if site_info else "Our Platform"
7374

75+
# Get current timestamp
76+
change_time = timezone.now()
77+
7478
context = {
7579
"username": instance.username,
7680
"site_title": site_title,
81+
"change_date": change_time.strftime("%B %d, %Y"),
82+
"change_time": change_time.strftime("%I:%M %p %Z"),
83+
"change_datetime": change_time.strftime("%B %d, %Y at %I:%M %p %Z"),
7784
}
7885

7986
# Schedule the password change notification email

backend/users/templates/emails/password_change_notification.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Dear {{ username }},
22

3-
This email is to notify you that your password for your {{ site_title }} account has been changed successfully.
3+
This email is to notify you that your password for your {{ site_title }} account has been changed successfully on {{ change_datetime }}.
44

55
If you did not make this change, please contact our support team immediately.
66

backend/users/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
UserBioRetrieveUpdateView,
1616
UserFollowersListView,
1717
UserFollowingListView,
18+
UserProfileUpdateView,
1819
UserRegistrationView,
20+
ProfileDetailByIdView,
1921
)
2022

2123
app_name = "users"
2224

2325
urlpatterns = [
2426
path("me/", CurrentUserView.as_view(), name="current_user"),
27+
path("me/update/", UserProfileUpdateView.as_view(), name="user-profile-update"),
2528
path("me/delete/", ProfileDeleteView.as_view(), name="profile-delete"),
2629
path("me/change-password/", ChangePasswordView.as_view(), name="change-password"),
2730
path(
@@ -45,6 +48,7 @@
4548
name="profile-image-delete",
4649
),
4750
path("register/", UserRegistrationView.as_view(), name="register"),
51+
path("id/<int:user_id>/", ProfileDetailByIdView.as_view(), name="profile_detail_by_id"),
4852
path("<str:username>/check/", CheckUsernameView.as_view(), name="check-username"),
4953
path("<str:username>/bio/", UserBioRetrieveUpdateView.as_view(), name="bio-detail"),
5054
path("<str:username>/", ProfileDetailView.as_view(), name="profile_detail"),

0 commit comments

Comments
 (0)