diff --git a/{{cookiecutter.project_slug}}/config/settings/base.py b/{{cookiecutter.project_slug}}/config/settings/base.py index 7c12c07af..e16d675c2 100644 --- a/{{cookiecutter.project_slug}}/config/settings/base.py +++ b/{{cookiecutter.project_slug}}/config/settings/base.py @@ -337,7 +337,7 @@ CELERY_WORKER_HIJACK_ROOT_LOGGER = False # ------------------------------------------------------------------------------ ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True) # https://docs.allauth.org/en/latest/account/configuration.html -ACCOUNT_AUTHENTICATION_METHOD = "{{cookiecutter.username_type}}" +ACCOUNT_LOGIN_METHODS = {"{{cookiecutter.username_type}}"} # https://docs.allauth.org/en/latest/account/configuration.html {%- if cookiecutter.username_type == "username" %} ACCOUNT_SIGNUP_FIELDS = ["email*", "username*", "password1*", "password2*"] diff --git a/{{cookiecutter.project_slug}}/config/settings/local.py b/{{cookiecutter.project_slug}}/config/settings/local.py index f63151239..02185c2d8 100644 --- a/{{cookiecutter.project_slug}}/config/settings/local.py +++ b/{{cookiecutter.project_slug}}/config/settings/local.py @@ -44,7 +44,8 @@ EMAIL_PORT = 1025 {%- else -%} # https://docs.djangoproject.com/en/dev/ref/settings/#email-backend EMAIL_BACKEND = env( - "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend", + "DJANGO_EMAIL_BACKEND", + default="django.core.mail.backends.console.EmailBackend", ) {%- endif %} diff --git a/{{cookiecutter.project_slug}}/docker-compose.production.yml b/{{cookiecutter.project_slug}}/docker-compose.production.yml index d0d06338d..5462ae671 100644 --- a/{{cookiecutter.project_slug}}/docker-compose.production.yml +++ b/{{cookiecutter.project_slug}}/docker-compose.production.yml @@ -9,7 +9,6 @@ volumes: production_redis_data: {} {% endif %} - services: django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %} build: @@ -75,9 +74,7 @@ services: - production_redis_data:/data {% endif %} - {%- if cookiecutter.use_celery == 'y' %} - celeryworker: <<: *django image: {{ cookiecutter.project_slug }}_production_celeryworker diff --git a/{{cookiecutter.project_slug}}/justfile b/{{cookiecutter.project_slug}}/justfile index 38ef8dd47..f4e19ed7c 100644 --- a/{{cookiecutter.project_slug}}/justfile +++ b/{{cookiecutter.project_slug}}/justfile @@ -1,7 +1,7 @@ export COMPOSE_FILE := "docker-compose.local.yml" ## Just does not yet manage signals for subprocesses reliably, which can lead to unexpected behavior. -## Exercise caution before expanding its usage in production environments. +## Exercise caution before expanding its usage in production environments. ## For more information, see https://github.com/casey/just/issues/2473 . diff --git a/{{cookiecutter.project_slug}}/manage.py b/{{cookiecutter.project_slug}}/manage.py index d6c4f110f..3f33ef192 100755 --- a/{{cookiecutter.project_slug}}/manage.py +++ b/{{cookiecutter.project_slug}}/manage.py @@ -1,5 +1,6 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" + import os import sys from pathlib import Path diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py index 582ff935d..79aa13c9e 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py @@ -8,13 +8,12 @@ from allauth.core.exceptions import ImmediateHttpResponse from allauth.socialaccount.adapter import DefaultSocialAccountAdapter from django.conf import settings from django.contrib import messages -from django.http import HttpRequest from django.shortcuts import redirect from django.urls import reverse if typing.TYPE_CHECKING: from allauth.socialaccount.models import SocialLogin - from {{cookiecutter.project_slug}}.users.models import User + from django.http import HttpRequest class AccountAdapter(DefaultAccountAdapter): @@ -30,8 +29,6 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter): ) -> bool: return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) - - def pre_social_login(self, request, sociallogin): # social account already exists, so this is just a login if sociallogin.is_existing: @@ -53,13 +50,13 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter): return if request.user.is_authenticated and request.user.email != verified_email.email: + # Obtener el nombre del proveedor social de manera más segura + provider_name = sociallogin.account.provider.capitalize() messages.error( request, ( - "No es posible enlazar tu cuenta de {}, " + f"No es posible enlazar tu cuenta de {provider_name}, " "ya que no coincide con tu correo en esta plataforma." - ).format( - list(request._socialapp_cache.keys())[0].capitalize() ), ) raise ImmediateHttpResponse(redirect(reverse("socialaccount_connections"))) @@ -68,7 +65,8 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter): # an existing user's account try: existing_email = EmailAddress.objects.get( - email__iexact=verified_email.email, verified=True + email__iexact=verified_email.email, + verified=True ) except EmailAddress.DoesNotExist: return diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/serializers.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/serializers.py index c675449e4..debe5e282 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/serializers.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/serializers.py @@ -12,5 +12,5 @@ class UserSerializer(serializers.ModelSerializer[User]): fields = ["username", "email", "uuid", "first_name", "last_name", "url"] {%- endif %} extra_kwargs = { - "url": {"view_name": "api:user-detail", "lookup_field": "uuid"} + "url": {"view_name": "api:user-detail", "lookup_field": "uuid"}, } diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/views.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/views.py index 59a611673..f9d3a4835 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/views.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/api/views.py @@ -1,4 +1,5 @@ import uuid + from django.contrib.auth import get_user_model from rest_framework import status from rest_framework.decorators import action diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py index 12ee1fcd2..deef67f17 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py @@ -1,9 +1,8 @@ from allauth.account.forms import SignupForm from allauth.socialaccount.forms import SignupForm as SocialSignupForm +from django import forms from django.contrib.auth import forms as admin_forms -{%- if cookiecutter.username_type == "email" %} -from django.forms import EmailField -{%- endif %} +from django.contrib.auth import get_user_model from django.utils.translation import gettext_lazy as _ User = get_user_model() @@ -13,7 +12,7 @@ class UserAdminChangeForm(admin_forms.UserChangeForm): class Meta(admin_forms.UserChangeForm.Meta): # type: ignore[name-defined] model = User {%- if cookiecutter.username_type == "email" %} - field_classes = {"email": EmailField} + field_classes = {"email": forms.EmailField} {%- endif %} @@ -27,7 +26,7 @@ class UserAdminCreationForm(admin_forms.AdminUserCreationForm): model = User {%- if cookiecutter.username_type == "email" %} fields = ("email", "first_name", "last_name") - field_classes = {"email": EmailField} + field_classes = {"email": forms.EmailField} error_messages = { "email": {"unique": _("This email has already been taken.")}, } diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py index add9b4967..7828cb448 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py @@ -4,10 +4,7 @@ from typing import ClassVar {% endif -%} from django.contrib.auth.models import AbstractUser -from django.db.models import CharField -{%- if cookiecutter.username_type == "email" %} -from django.db.models import EmailField -{%- endif %} +from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ {%- if cookiecutter.username_type == "email" %} @@ -24,12 +21,15 @@ class User(AbstractUser): """ uuid = models.UUIDField( - unique=True, db_index=True, default=uuid_lib.uuid4, editable=False + unique=True, + db_index=True, + default=uuid_lib.uuid4, + editable=False ) first_name = models.CharField(_("first name"), max_length=150) last_name = models.CharField(_("last name"), max_length=150) {%- if cookiecutter.username_type == "email" %} - email = EmailField(_("email address"), unique=True) + email = models.EmailField(_("email address"), unique=True) username = None # type: ignore[assignment] USERNAME_FIELD = "email" diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/factories.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/factories.py index 3b3d39d29..b3899aa40 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/factories.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/factories.py @@ -6,6 +6,8 @@ from factory import Faker from factory import post_generation from factory.django import DjangoModelFactory +from {{ cookiecutter.project_slug }}.users.models import User + class UserFactory(DjangoModelFactory[User]): {%- if cookiecutter.username_type == "username" %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py index 97e96d2a7..a48e47b53 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py @@ -5,10 +5,7 @@ from {{ cookiecutter.project_slug }}.users.models import User def test_detail(user: User): - assert ( - reverse("users:detail", kwargs={"uuid": user.uuid}) - == f"/users/{user.uuid}/" - ) + assert reverse("users:detail", kwargs={"uuid": user.uuid}) == f"/users/{user.uuid}/" assert resolve(f"/users/{user.uuid}/").view_name == "users:detail" diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py index aadbea004..0d56db6e1 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py @@ -28,7 +28,7 @@ class UserUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): assert self.request.user.is_authenticated # type guard return self.request.user.get_absolute_url() - def get_object(self, queryset: QuerySet | None=None) -> User: + def get_object(self, queryset: QuerySet | None = None) -> User: assert self.request.user.is_authenticated # type guard return self.request.user