Mark__C
Mark__C

Reputation: 825

Handling Django user subscription expiry date

I have a User model which extends AbstractBaseUser

class User(AbstractBaseUser):
    email = models.EmailField(max_length=255, unique=True, default='[email protected]')
    forename = models.CharField(max_length=20, default='')
    surname = models.CharField(max_length=20, default='')
    account_expiry = models.DateField(default=datetime.now() + timedelta(days=365))

In all of my views I authenticate using the LoginRequiredMixin e.g.

class IndexView(LoginRequiredMixin, generic.TemplateView):

I want to authenticate users not just by email and password, but also by checking that the account expiry date has not been reached.

My question is - what is the best (simplest?) way to achieve this. Do I write my own custom authentication backend as described here? Or should I be looking to write a custom Mixin or Middleware?

Upvotes: 2

Views: 2478

Answers (2)

Mark__C
Mark__C

Reputation: 825

So in the end my solution was to create my own custom middleware.

I found How to Create a Custom Django Middleware a useful starting point, but it wouldn't work for me because I am using Django 2.0.1. The official docs explained how to update the solution and I also found this SO post useful.

So my code looks like:

class AccountExpiry:

def __init__(self, get_response):
    self.get_response = get_response

def __call__(self, request):
    current_user = request.user
    response = self.get_response(request)
    expiry_path = reverse('accounts:account-expired')

    if current_user.is_anonymous is False:
        if current_user.admin is False and current_user.staff is False:
            if request.path not in [expiry_path]:
                expiry_date = current_user.school.account_expiry
                todays_date = datetime.today().date()

                if todays_date > expiry_date:
                    return HttpResponseRedirect(expiry_path)
    return response

(note that account_expiry is actually a field in a related table (school) and not in the user model as per my original question above).

I updated settings MIDDLEWARE= to include

'common.middleware.AccountExpiry',

and it works as I want it to.

Upvotes: 7

kristaps
kristaps

Reputation: 1723

You could reimplement the is_authenticated property of AbstractBaseUser to return False when the account has expired.

To prevent expired users from logging in you could also override check_password to return False when the account has expired.

Upvotes: 1

Related Questions