diff --git a/ai/__pycache__/local_ai_api.cpython-311.pyc b/ai/__pycache__/local_ai_api.cpython-311.pyc index ae12bda..bef71ec 100644 Binary files a/ai/__pycache__/local_ai_api.cpython-311.pyc and b/ai/__pycache__/local_ai_api.cpython-311.pyc differ diff --git a/ai/local_ai_api.py b/ai/local_ai_api.py index bcff732..436012d 100644 --- a/ai/local_ai_api.py +++ b/ai/local_ai_api.py @@ -145,6 +145,7 @@ def request(path: Optional[str], payload: Dict[str, Any], options: Optional[Dict "Content-Type": "application/json", "Accept": "application/json", cfg["project_header"]: project_uuid, + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", } extra_headers = options.get("headers") if isinstance(extra_headers, Iterable): @@ -180,6 +181,7 @@ def fetch_status(ai_request_id: Any, options: Optional[Dict[str, Any]] = None) - headers: Dict[str, str] = { "Accept": "application/json", cfg["project_header"]: project_uuid, + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", } extra_headers = options.get("headers") if isinstance(extra_headers, Iterable): diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index eb6fa69..36cc1a3 100644 Binary files a/core/__pycache__/forms.cpython-311.pyc and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 86f05eb..7163804 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 3c22c03..c984148 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/forms.py b/core/forms.py index 556b2da..82bcc16 100644 --- a/core/forms.py +++ b/core/forms.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import User from django.utils.translation import gettext_lazy as _ from django.utils.translation import get_language from .models import Profile, Parcel, Country, Governate, City, DriverRating, DriverReport, ParcelType -from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm class LoginForm(AuthenticationForm): def __init__(self, *args, **kwargs): @@ -11,6 +11,25 @@ class LoginForm(AuthenticationForm): for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) +class CustomPasswordResetForm(PasswordResetForm): + def get_users(self, email): + """ + Custom version that returns only the first matching user to avoid + sending multiple emails if multiple accounts share the same email. + Returns the most recently active account. + """ + users = list(super().get_users(email)) + if users: + # Sort by last login (descending) to get the most active account + users.sort(key=lambda u: (u.last_login is not None, u.last_login, u.date_joined), reverse=True) + return [users[0]] + return [] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + for field in self.fields.values(): + field.widget.attrs.update({'class': 'form-control', 'placeholder': _('Your Email Address')}) + class ContactForm(forms.Form): name = forms.CharField(max_length=100, label=_("Name"), widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Your Name')})) email = forms.EmailField(label=_("Email"), widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': _('Your Email')})) @@ -419,4 +438,4 @@ class DriverReportForm(forms.ModelForm): labels = { 'reason': _('Reason for Reporting'), 'description': _('Details'), - } + } \ No newline at end of file diff --git a/core/templates/core/emails/password_reset_email.txt b/core/templates/core/emails/password_reset_email.txt index 0927723..067b8bc 100644 --- a/core/templates/core/emails/password_reset_email.txt +++ b/core/templates/core/emails/password_reset_email.txt @@ -5,13 +5,13 @@ {% trans "You are receiving this email because you requested a password reset for your account at" %} {{ site_name }}. -{% trans "Please go to the following page and choose a new password:" %} +{% trans "Please follow the link below to choose a new password:" %} {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} -{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }} - -{% trans "Thanks," %} -{% trans "The" %} {{ site_name }} {% trans "Team" %} +{% trans "Your username is:" %} {{ user.get_username }} {% trans "If you did not request this, please ignore this email." %} + +{% trans "Thanks," %} +{% trans "The" %} {{ site_name }} {% trans "Team" %} \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 759da82..1b89696 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,6 +1,7 @@ from django.urls import path from django.contrib.auth import views as auth_views from . import views, api_views +from .forms import CustomPasswordResetForm urlpatterns = [ path('', views.index, name='index'), @@ -36,7 +37,13 @@ urlpatterns = [ path('rate-driver//', views.rate_driver, name='rate_driver'), # Password Reset - path('password-reset/', auth_views.PasswordResetView.as_view(template_name='core/password_reset_form.html', email_template_name='core/emails/password_reset_email.html', subject_template_name='core/emails/password_reset_subject.txt'), name='password_reset'), + path('password-reset/', auth_views.PasswordResetView.as_view( + template_name='core/password_reset_form.html', + email_template_name='core/emails/password_reset_email.txt', + html_email_template_name='core/emails/password_reset_email.html', + subject_template_name='core/emails/password_reset_subject.txt', + form_class=CustomPasswordResetForm + ), name='password_reset'), path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='core/password_reset_done.html'), name='password_reset_done'), path('password-reset-confirm///', auth_views.PasswordResetConfirmView.as_view(template_name='core/password_reset_confirm.html'), name='password_reset_confirm'), path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='core/password_reset_complete.html'), name='password_reset_complete'), @@ -71,4 +78,4 @@ urlpatterns = [ path('api/v1/pricing/', api_views.PriceCalculatorView.as_view(), name='api_pricing'), path('api/v1/calculate-price/', api_views.PriceCalculatorView.as_view(), name='api_calculate_price'), path('api/v1/profile/', api_views.UserProfileView.as_view(), name='api_profile'), -] +] \ No newline at end of file