Как обрабатывать токен при UPDATE USERNAME_FIELD с помощью Django REST Framework

Я разрабатываю приложения с использованием Django REST Framework и Angular 4.
Я не знаю, как обрабатывается токен при ОБНОВЛЕНИИ информации пользователя для входа в систему.

Пользовательская модель Django настроена следующим образом.
Ключ входа изменен с имени пользователя на адрес электронной почты.

[models.py]

class Account(AbstractBaseUser):
    username    = models.CharField(_('username'), max_length=30, unique=True)
    first_name  = models.CharField(_('first name'), max_length=30, blank=True)
    last_name   = models.CharField(_('last name'), max_length=30, blank=True)
    email       = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    profile     = models.CharField(_('profile'), max_length=255, blank=True)
    is_active   = models.BooleanField(default=True)
    is_staff    = models.BooleanField(default=False)
    is_admin    = models.BooleanField(default=False)
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = AccountManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def user_has_perm(user, perm, obj):
        return _user_has_perm(user, perm, obj)

    def has_perm(self, perm, obj=None):
        return _user_has_perm(self, perm, obj=obj)

    def has_module_perms(self, app_label):
        return self.is_admin

    def get_short_name(self):
        return self.first_name

    @property
    def is_superuser(self):
        return self.is_admin

    class Meta:
        db_table = 'api_user'
        swappable = 'AUTH_USER_MODEL'

Функция ОБНОВЛЕНИЯ информации о пользователе из Angular 4 реализована следующим образом.
Информация о новом пользователе помещается в Django REST Framework с помощью функции updateUserInfo.

[component.ts]

updateUserInfo() {
  this.authService.updateUserInfo({
    email: this.editUserEmail,
    username: this.editUserName,
    profile: this.edtiUserProfile
  })
  .subscribe(
    data => {
      this.updateSuccessMessage = "success userinfo update";
      this.updateErrorMessage = null;
      this.authService.userInfo;
    },
    error => {
      this.updateErrorMessage = "failed userinfo update";
      this.updateSuccessMessage = null;
    }
  );
}

[service.ts]

updateUserInfo(userUpdateInfo) {
  return this.http
    .put(this.UpdateUserUrl,
      userUpdateInfo,
      this.jwt()
    );
}

jwt() {
  if (this.LoginToken) {
    let headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': 'JWT ' + this.LoginToken.token });
    return new RequestOptions({ headers: headers });
  }
}

Представление и сериализатор для обновления информации о пользователе в Django следующие.

[views.py]

class AuthInfoUpdateView(generics.UpdateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = AccountSerializer
    lookup_field = 'email'
    queryset = Account.objects.all()

    def get_object(self):
        try:
            instance = self.queryset.get(email=self.request.user)
            return instance
        except Account.DoesNotExist:
            raise Http404

[serializers.py]

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Account
        fields = ('id', 'username', 'email', 'profile', 'password')

    def create(self, validated_data):
        return Account.objects.create_user(request_data=validated_data)

    def update(self, instance, validated_data):
        if 'password' in validated_data:
            instance.set_password(validated_data['password'])
        else:
            instance = super().update(instance, validated_data)
        instance.save()
        return instance

Проблема, которая возникает сейчас, заключается в поведении при обновлении электронной почты.
Поскольку USERNAME_FIELD - это электронная почта, при обновлении электронной почты необходимо обновить токен, хранящийся во внешнем интерфейсе.
Но я не знаю, как получить токен с новым Эл. адрес.


person xKxAxKx    schedule 29.06.2017    source источник


Ответы (1)


Я думаю, что единственный способ сохранить аутентификацию пользователя - это сгенерировать новый токен и отправить его обратно, я не знаю другого способа сделать это с помощью django-rest-framework-jwt.

Для этого вам необходимо настроить put метод вашего AuthInfoUpdateView:

def put(self, request, *args, **kwargs):
    serializer = self.serializer_class(self.get_object(), data=request.data, partial=True)

    if serializer.is_valid():
        instance = serializer.save()
        # Generate a new token
        payload = jwt_payload_handler(instance)
        token = jwt.encode(payload, settings.SECRET_KEY)
        response = JsonResponse({'token': token.decode('unicode_escape')})
        response.status = 200
        return response
    else:
        response = JsonResponse({'errors': serializer.errors})
        response.status = 500
        return response

Это так просто, что вам просто нужно обновить токен в своем интерфейсе, не предлагая пользователю снова войти в систему.

Надеюсь это поможет!

person HassenPy    schedule 30.06.2017