mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-09-20 19:02:37 +03:00
CC Upgrade 20250602
Fix custom allauth integration
This commit is contained in:
parent
c02d5461bb
commit
3d3d06fb8b
|
@ -337,7 +337,7 @@ CELERY_WORKER_HIJACK_ROOT_LOGGER = False
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
|
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
|
||||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
# 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
|
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||||
{%- if cookiecutter.username_type == "username" %}
|
{%- if cookiecutter.username_type == "username" %}
|
||||||
ACCOUNT_SIGNUP_FIELDS = ["email*", "username*", "password1*", "password2*"]
|
ACCOUNT_SIGNUP_FIELDS = ["email*", "username*", "password1*", "password2*"]
|
||||||
|
|
|
@ -44,7 +44,8 @@ EMAIL_PORT = 1025
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||||
EMAIL_BACKEND = env(
|
EMAIL_BACKEND = env(
|
||||||
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend",
|
"DJANGO_EMAIL_BACKEND",
|
||||||
|
default="django.core.mail.backends.console.EmailBackend",
|
||||||
)
|
)
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ volumes:
|
||||||
production_redis_data: {}
|
production_redis_data: {}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}
|
django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}
|
||||||
build:
|
build:
|
||||||
|
@ -75,9 +74,7 @@ services:
|
||||||
- production_redis_data:/data
|
- production_redis_data:/data
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{%- if cookiecutter.use_celery == 'y' %}
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
|
||||||
celeryworker:
|
celeryworker:
|
||||||
<<: *django
|
<<: *django
|
||||||
image: {{ cookiecutter.project_slug }}_production_celeryworker
|
image: {{ cookiecutter.project_slug }}_production_celeryworker
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""Django's command-line utility for administrative tasks."""
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
@ -8,13 +8,12 @@ from allauth.core.exceptions import ImmediateHttpResponse
|
||||||
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.http import HttpRequest
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from allauth.socialaccount.models import SocialLogin
|
from allauth.socialaccount.models import SocialLogin
|
||||||
from {{cookiecutter.project_slug}}.users.models import User
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
|
||||||
class AccountAdapter(DefaultAccountAdapter):
|
class AccountAdapter(DefaultAccountAdapter):
|
||||||
|
@ -30,8 +29,6 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
) -> bool:
|
) -> bool:
|
||||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def pre_social_login(self, request, sociallogin):
|
def pre_social_login(self, request, sociallogin):
|
||||||
# social account already exists, so this is just a login
|
# social account already exists, so this is just a login
|
||||||
if sociallogin.is_existing:
|
if sociallogin.is_existing:
|
||||||
|
@ -53,13 +50,13 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
return
|
return
|
||||||
|
|
||||||
if request.user.is_authenticated and request.user.email != verified_email.email:
|
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(
|
messages.error(
|
||||||
request,
|
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."
|
"ya que no coincide con tu correo en esta plataforma."
|
||||||
).format(
|
|
||||||
list(request._socialapp_cache.keys())[0].capitalize()
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
raise ImmediateHttpResponse(redirect(reverse("socialaccount_connections")))
|
raise ImmediateHttpResponse(redirect(reverse("socialaccount_connections")))
|
||||||
|
@ -68,7 +65,8 @@ class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
# an existing user's account
|
# an existing user's account
|
||||||
try:
|
try:
|
||||||
existing_email = EmailAddress.objects.get(
|
existing_email = EmailAddress.objects.get(
|
||||||
email__iexact=verified_email.email, verified=True
|
email__iexact=verified_email.email,
|
||||||
|
verified=True
|
||||||
)
|
)
|
||||||
except EmailAddress.DoesNotExist:
|
except EmailAddress.DoesNotExist:
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,5 +12,5 @@ class UserSerializer(serializers.ModelSerializer[User]):
|
||||||
fields = ["username", "email", "uuid", "first_name", "last_name", "url"]
|
fields = ["username", "email", "uuid", "first_name", "last_name", "url"]
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
"url": {"view_name": "api:user-detail", "lookup_field": "uuid"}
|
"url": {"view_name": "api:user-detail", "lookup_field": "uuid"},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from allauth.account.forms import SignupForm
|
from allauth.account.forms import SignupForm
|
||||||
from allauth.socialaccount.forms import SignupForm as SocialSignupForm
|
from allauth.socialaccount.forms import SignupForm as SocialSignupForm
|
||||||
|
from django import forms
|
||||||
from django.contrib.auth import forms as admin_forms
|
from django.contrib.auth import forms as admin_forms
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
from django.contrib.auth import get_user_model
|
||||||
from django.forms import EmailField
|
|
||||||
{%- endif %}
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
@ -13,7 +12,7 @@ class UserAdminChangeForm(admin_forms.UserChangeForm):
|
||||||
class Meta(admin_forms.UserChangeForm.Meta): # type: ignore[name-defined]
|
class Meta(admin_forms.UserChangeForm.Meta): # type: ignore[name-defined]
|
||||||
model = User
|
model = User
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
field_classes = {"email": EmailField}
|
field_classes = {"email": forms.EmailField}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ class UserAdminCreationForm(admin_forms.AdminUserCreationForm):
|
||||||
model = User
|
model = User
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
fields = ("email", "first_name", "last_name")
|
fields = ("email", "first_name", "last_name")
|
||||||
field_classes = {"email": EmailField}
|
field_classes = {"email": forms.EmailField}
|
||||||
error_messages = {
|
error_messages = {
|
||||||
"email": {"unique": _("This email has already been taken.")},
|
"email": {"unique": _("This email has already been taken.")},
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,7 @@ from typing import ClassVar
|
||||||
|
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db.models import CharField
|
from django.db import models
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
|
||||||
from django.db.models import EmailField
|
|
||||||
{%- endif %}
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
|
@ -24,12 +21,15 @@ class User(AbstractUser):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
uuid = models.UUIDField(
|
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)
|
first_name = models.CharField(_("first name"), max_length=150)
|
||||||
last_name = models.CharField(_("last name"), max_length=150)
|
last_name = models.CharField(_("last name"), max_length=150)
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
email = EmailField(_("email address"), unique=True)
|
email = models.EmailField(_("email address"), unique=True)
|
||||||
username = None # type: ignore[assignment]
|
username = None # type: ignore[assignment]
|
||||||
|
|
||||||
USERNAME_FIELD = "email"
|
USERNAME_FIELD = "email"
|
||||||
|
|
|
@ -6,6 +6,8 @@ from factory import Faker
|
||||||
from factory import post_generation
|
from factory import post_generation
|
||||||
from factory.django import DjangoModelFactory
|
from factory.django import DjangoModelFactory
|
||||||
|
|
||||||
|
from {{ cookiecutter.project_slug }}.users.models import User
|
||||||
|
|
||||||
|
|
||||||
class UserFactory(DjangoModelFactory[User]):
|
class UserFactory(DjangoModelFactory[User]):
|
||||||
{%- if cookiecutter.username_type == "username" %}
|
{%- if cookiecutter.username_type == "username" %}
|
||||||
|
|
|
@ -5,10 +5,7 @@ from {{ cookiecutter.project_slug }}.users.models import User
|
||||||
|
|
||||||
|
|
||||||
def test_detail(user: User):
|
def test_detail(user: User):
|
||||||
assert (
|
assert reverse("users:detail", kwargs={"uuid": user.uuid}) == f"/users/{user.uuid}/"
|
||||||
reverse("users:detail", kwargs={"uuid": user.uuid})
|
|
||||||
== f"/users/{user.uuid}/"
|
|
||||||
)
|
|
||||||
assert resolve(f"/users/{user.uuid}/").view_name == "users:detail"
|
assert resolve(f"/users/{user.uuid}/").view_name == "users:detail"
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user