Проблема создания пользователя django с python -social-auth с пользовательской моделью пользователя и UserManager - PullRequest
1 голос
/ 29 января 2020

Похоже, это не уникальная проблема, но я что-то упустил в решении. Я использую python-social-auth и захожу в Google. Кажется, все идет хорошо, пока не доберется до create_user части трубопровода. У меня есть пользовательская модель пользователя и UserManager. В моей модели User у меня есть свойство role, которое подключено к некоторому choices. Когда социальная аутентификация подключается и входит в систему, она вызывает create_user в моем Диспетчере пользователей, однако это только передача электронной почты и никаких дополнительных полей. Я пытался подключиться к конвейеру и добавить обязательное свойство role, добавив его в details социальную аутентификацию, но, похоже, это не имеет никакого эффекта. Как мне go подключиться к свойству create user, чтобы добавить поля, которые не существуют в отношении социальной аутентификации?

Модель пользователя

class User(AbstractBaseUser, PermissionsMixin):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)
    email = models.EmailField(_("email address"), unique=True)
    first_name = models.CharField(max_length=240, blank=True)
    last_name = models.CharField(max_length=240, blank=True)
    role = models.IntegerField(choices=RoleChoices.choices)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self):
        return self.email

    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}".strip()

И мой UserManager:

class UserManager(BaseUserManager):
    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """

    def create_user(self, email, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        if not email:
            raise ValueError(_("The Email must be set"))

        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)

        if password is not None:
            user.set_password(password)

        user.save()
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        """
        Create and save a SuperUser with the given email and password.
        """
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("is_active", True)
        extra_fields.setdefault("role", 1)

        if extra_fields.get("is_staff") is not True:
            raise ValueError(_("Superuser must have is_staff=True."))
        if extra_fields.get("is_superuser") is not True:
            raise ValueError(_("Superuser must have is_superuser=True."))
        return self.create_user(email, password, **extra_fields)

Конфигурация социальной аутентификации:

# Social Auth Config
AUTHENTICATION_BACKENDS = (
    'social_core.backends.google.GoogleOAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

LOGIN_URL = 'login'
LOGOUT_URL = 'logout'
LOGIN_REDIRECT_URL = 'admin'
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.getenv('GOOGLE_CLIENT_ID')
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.getenv('GOOGLE_CLIENT_SECRET')
SOCIAL_AUTH_USER_MODEL = 'search.User'
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
SOCIAL_AUTH_GOOGLE_OAUTH2_IGNORE_DEFAULT_SCOPE = True
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
    'https://www.googleapis.com/auth/calendar',
    'https://www.googleapis.com/auth/calendar.readonly',
    'https://www.googleapis.com/auth/userinfo.profile',
    'profile',
    'email'
]

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'search.socialauth.add_role',
    'social_core.pipeline.user.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

И, наконец, функция add_role:

from .choices import RoleChoices


def add_role(**kwargs):
    kwargs['details']['role'] = RoleChoices.ARTIST
    return kwargs

1 Ответ

1 голос
/ 29 января 2020

Причина, по которой это не работает, заключается в том, что функция create_user явно фильтрует содержимое details, чтобы включить только ключи , указанные в параметре USER_FIELDS . По умолчанию это

USER_FIELDS = ['username', 'email']

, поэтому все остальное просто игнорируется. Кажется, это не задокументировано, но вы должны иметь возможность переопределить это, создав параметр следующим образом:

SOCIAL_AUTH_USER_FIELDS = ['username', 'email', 'role']

, который затем обеспечит передачу вашего role в пользовательский экземпляр.

Остальная часть вашего конвейера и конфигурации выглядит нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...