## Summary - Closes #1 - Replace broken `csrf_exempt` `reset_password` FBV (responses never returned; missing `requests` import) with working DRF `ResetUserPassword` - Deduplicate reset email helper; build set-password links from `FRONTEND_BASE_URL` - Harden `SetUserPassword`: require unusable password, min 8 chars, handle missing slug - Accept reCAPTCHA v2 (success only) and v3 (score ≥ 0.5); avoid email enumeration (200 after valid captcha) - Add unit tests for reset + set-password edge cases ## Test plan - [ ] `manage.py test chat_backend.tests.test_views_users.ResetPasswordTestCase chat_backend.tests.test_views_users.SetPasswordTestCase` - [ ] With SMTP configured: request reset for known email → receive link → set password → sign in - [ ] Unknown email still returns 200 and sends no mail - [ ] Failed captcha returns 400 - [ ] Pair with chat_web_app `feature/password-reset-1` PRReviewed-on: #27
This commit was merged in pull request #27.
This commit is contained in:
@@ -11,10 +11,10 @@ from .models import (
|
||||
PromptMetric,
|
||||
DocumentWorkspace,
|
||||
Document,
|
||||
UserAuthEvent,
|
||||
OutboundEmail,
|
||||
)
|
||||
|
||||
# Register your models here.
|
||||
|
||||
|
||||
class AnnouncmentAdmin(admin.ModelAdmin):
|
||||
model = Announcement
|
||||
@@ -24,6 +24,32 @@ class CompanyAdmin(admin.ModelAdmin):
|
||||
model = Company
|
||||
|
||||
|
||||
class UserAuthEventInline(admin.TabularInline):
|
||||
model = UserAuthEvent
|
||||
extra = 0
|
||||
can_delete = False
|
||||
fields = ("created", "event_type", "detail", "ip_address")
|
||||
readonly_fields = ("created", "event_type", "detail", "ip_address")
|
||||
ordering = ("-created",)
|
||||
show_change_link = False
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
class OutboundEmailInline(admin.TabularInline):
|
||||
model = OutboundEmail
|
||||
extra = 0
|
||||
can_delete = False
|
||||
fields = ("created", "kind", "status", "subject", "to_email", "sent_at")
|
||||
readonly_fields = ("created", "kind", "status", "subject", "to_email", "sent_at")
|
||||
ordering = ("-created",)
|
||||
show_change_link = True
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
class CustomUserAdmin(admin.ModelAdmin):
|
||||
model = CustomUser
|
||||
list_display = (
|
||||
@@ -41,7 +67,63 @@ class CustomUserAdmin(admin.ModelAdmin):
|
||||
"slug",
|
||||
"get_set_password_url",
|
||||
)
|
||||
search_fields = ("fields", "username", "first_name", "last_name", "slug")
|
||||
search_fields = ("email", "username", "first_name", "last_name", "slug")
|
||||
readonly_fields = ("last_login", "date_joined", "get_set_password_url", "slug")
|
||||
inlines = (UserAuthEventInline, OutboundEmailInline)
|
||||
|
||||
|
||||
class UserAuthEventAdmin(admin.ModelAdmin):
|
||||
model = UserAuthEvent
|
||||
list_display = ("created", "user", "event_type", "detail", "ip_address")
|
||||
list_filter = ("event_type",)
|
||||
search_fields = ("user__email", "user__username", "detail", "ip_address")
|
||||
readonly_fields = ("user", "event_type", "created", "detail", "ip_address")
|
||||
ordering = ("-created",)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
class OutboundEmailAdmin(admin.ModelAdmin):
|
||||
model = OutboundEmail
|
||||
list_display = (
|
||||
"created",
|
||||
"kind",
|
||||
"status",
|
||||
"subject",
|
||||
"to_email",
|
||||
"user",
|
||||
"sent_at",
|
||||
)
|
||||
list_filter = ("kind", "status")
|
||||
search_fields = ("to_email", "subject", "user__email", "id")
|
||||
readonly_fields = (
|
||||
"id",
|
||||
"kind",
|
||||
"status",
|
||||
"to_email",
|
||||
"from_email",
|
||||
"subject",
|
||||
"html_template",
|
||||
"text_template",
|
||||
"context",
|
||||
"error_message",
|
||||
"user",
|
||||
"created",
|
||||
"updated",
|
||||
"sent_at",
|
||||
)
|
||||
ordering = ("-created",)
|
||||
date_hierarchy = "created"
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
class FeedbackAdmin(admin.ModelAdmin):
|
||||
@@ -59,6 +141,7 @@ class LLMModelsAdmin(admin.ModelAdmin):
|
||||
class PromptInline(admin.TabularInline):
|
||||
model = Prompt
|
||||
|
||||
|
||||
class ConversationAdmin(admin.ModelAdmin):
|
||||
model = Conversation
|
||||
list_display = (
|
||||
@@ -70,12 +153,14 @@ class ConversationAdmin(admin.ModelAdmin):
|
||||
"tokens_total",
|
||||
)
|
||||
search_fields = ("title",)
|
||||
inlines = [PromptInline,]
|
||||
inlines = [
|
||||
PromptInline,
|
||||
]
|
||||
|
||||
def _token_sum(self, conversation, field):
|
||||
total = PromptMetric.objects.filter(
|
||||
conversation_id=conversation.id
|
||||
).aggregate(total=Sum(field))["total"]
|
||||
total = PromptMetric.objects.filter(conversation_id=conversation.id).aggregate(
|
||||
total=Sum(field)
|
||||
)["total"]
|
||||
return total or 0
|
||||
|
||||
@admin.display(description="Tokens in")
|
||||
@@ -93,7 +178,7 @@ class ConversationAdmin(admin.ModelAdmin):
|
||||
|
||||
class PromptAdmin(admin.ModelAdmin):
|
||||
model = Prompt
|
||||
list_display = ("id","message", "user_created", "get_conversation_title","created")
|
||||
list_display = ("id", "message", "user_created", "get_conversation_title", "created")
|
||||
search_fields = ("message",)
|
||||
|
||||
|
||||
@@ -110,7 +195,7 @@ class PromptMetricAdmin(admin.ModelAdmin):
|
||||
"has_file",
|
||||
"file_type",
|
||||
"get_duration",
|
||||
"created"
|
||||
"created",
|
||||
)
|
||||
list_filter = ("event", "model_name", "has_file")
|
||||
|
||||
@@ -136,6 +221,8 @@ class DocumentAdmin(admin.ModelAdmin):
|
||||
admin.site.register(Announcement, AnnouncmentAdmin)
|
||||
admin.site.register(Company, CompanyAdmin)
|
||||
admin.site.register(CustomUser, CustomUserAdmin)
|
||||
admin.site.register(UserAuthEvent, UserAuthEventAdmin)
|
||||
admin.site.register(OutboundEmail, OutboundEmailAdmin)
|
||||
|
||||
admin.site.register(LLMModels, LLMModelsAdmin)
|
||||
admin.site.register(Conversation, ConversationAdmin)
|
||||
|
||||
Reference in New Issue
Block a user