Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I get 'User' object has no attribute 'is_verified' #39

Open
higorlmanso opened this issue May 11, 2020 · 11 comments
Open

I get 'User' object has no attribute 'is_verified' #39

higorlmanso opened this issue May 11, 2020 · 11 comments

Comments

@higorlmanso
Copy link

Hi, thanks for the awesome project.
I having some problems with a custom login View, when i try to check if user is_verified, looks like that method isnt in the user

@psagers
Copy link
Member

psagers commented May 12, 2020

Sounds rather like the middleware isn't installed.

@illia-v
Copy link
Contributor

illia-v commented Jun 18, 2020

I have faced the same error in a project that uses the old MIDDLEWARE_CLASSES setting.
The django_otp.middleware.OTPMiddleware middleware is incompatible with it

@dwasyl
Copy link

dwasyl commented Aug 8, 2020

Thank you for sharing this!! I ran into this exact issue today after upgrading django-otp and couldn't figure out what was going on. This would be helpful to have noted in the CHANGELOG.

@cca32
Copy link

cca32 commented Mar 28, 2021

I am having the same problem. I have the middleware installed, not sure what the issue is

@liveashish
Copy link

I had to override the OTPAdminSite class and had to remove request.user.is_verified() condition from has_permission

Below it the overridden code in my urls.py

class OTPAdmin(OTPAdminSite):
    def has_permission(self, request):
        """
	overriding OTPAdminSite class to fix 'is_verified' attribute issue
        """
        return super(OTPAdminSite, self).has_permission(request)

@isrplo
Copy link

isrplo commented Sep 29, 2021

Has anyone solved this? Im really clueless here...

@some1ataplace
Copy link

It looks like the issue you're experiencing might be caused by the fact that the is_verified method is not defined on the default User model in Django. This method is added by the django-otp package to provide verification functionality.

To use the is_verified method in your custom login view, you'll need to make sure that your user model is a subclass of AbstractBaseUser and includes the OTPUserMixin from django-otp. This will ensure that the is_verified method is available on your user model.

Once you've made sure that your user model includes the OTPUserMixin, you should be able to use the is_verified method in your custom login view.

As for the issue with the django_otp.middleware.OTPMiddleware middleware, it's hard to know exactly what's causing the incompatibility without more information about the error you're seeing. However, it's possible that the middleware is assuming that the is_verified method is available on the User model, which is causing the error you're seeing.

If you're unable to resolve the issue with the OTPMiddleware, you may need to remove it from your middleware stack. In many cases, the functionality provided by OTPMiddleware can be duplicated using other middleware or custom code.

It's worth noting that removing OTPMiddleware could reduce the security of your application, since it's responsible for enforcing two-factor authentication for your users. If you do decide to remove it, make sure that you have other security measures in place to protect your user's accounts.

from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login
from django.shortcuts import render, redirect
from django_otp.decorators import otp_required
from django_otp import user_has_device
from django_otp.plugins.otp_totp.models import TOTPDevice

@otp_required
def custom_login_view(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            user = form.get_user()

            if user_has_device(user):
                device = user.totpdevice_set.first() or TOTPDevice.objects.create(user=user)

                if device:
                    is_verified = device.verify(request.POST.get('otp_token', ''))
                    if not is_verified:
                        form.add_error('otp_token', 'Invalid token')

            if user.is_authenticated and user.is_verified:
                login(request, user)
                return redirect('home')

    else:
        form = AuthenticationForm(request)

    return render(request, 'login.html', {'form': form})


Here's an example of how you can define a custom User model that subclasses AbstractBaseUser and includes the OTPUserMixin from django-otp:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django_otp.models import OTPUserMixin

class CustomUser(OTPUserMixin, AbstractBaseUser):
    email = models.EmailField(unique=True)
    full_name = models.CharField(max_length=255)

    USERNAME_FIELD = 'email'

In this example, our custom User model includes an email field (which we're using as the USERNAME_FIELD for authentication), a full_name field, and inherits from both OTPUserMixin and AbstractBaseUser.

To use the is_verified method in a custom login view, make sure to import your CustomUser model instead of the default User model. Here's an example of a custom login view that checks whether the user is verified:

from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from myapp.models import CustomUser

def login_view(request):
    if request.method == 'POST':
        email = request.POST['email']
        password = request.POST['password']

        user = authenticate(request, email=email, password=password)
        if user is not None:
            if user.is_verified():
                login(request, user)
                return HttpResponse('You have successfully logged in!')
            else:
                return HttpResponse('Your account is not yet verified.')
        else:
            return HttpResponse('Invalid login credentials.')
    else:
        # Display login form
        return HttpResponse('Please log in.')

In this example, we import our CustomUser model and use the is_verified method to check whether the user is verified before logging them in. If the user is not verified, we return an error message instead.

Keep in mind that this is just one example of how you can use the is_verified method in a custom login view. Depending on the specific requirements of your application, you may need to modify this code or use a different approach to achieve your goals.

@kimberlymcm
Copy link

Hi I'm having this problem (only in production, not local development), but I don't see an OTPUserMixin class in django_otp.models. Is this still the correct approach?

@LuizDMM
Copy link

LuizDMM commented Jun 15, 2023

Hey, same problem here, any solutions so far? The middleware is correctly installed and as @kimberlymcm mentioned, there's no OTPUserMixin Class to import.

@some1ataplace
Copy link

Maybe try adding the class itself if it does not exist:

class OTPUserMixin(models.Model):
    @property
    def devices(self):
        return Device.objects.filter(user=self)

    def is_verified(self):
        return self.devices.filter(confirmed=True).exists()

    class Meta:
        abstract = True

@wdifruscio
Copy link

yeah i just added to my user manager a property. Maybe some conflicts with other middlewares or your user setup, which was my issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests