Gramex - DBAuth Login only when user is active

71 Views Asked by At

I am trying to implement a way by which I can check the value of an is_active column from user database before letting the user log in. So along with the password check, I also want to check if is_active column is True, only then the user must be able to login, otherwise I want restrict login and show an error that "The user is inactive"(even if the password is correct). I went through the Gramex documentation but could not find a way to configure this requirement.

Is there any way to implement this in DBAuth?

2

There are 2 best solutions below

0
On BEST ANSWER

If you want to validate if the is_active column in the database is true, and to prevent login before the fact, use prepare:. For example:

url:
  login:
    pattern: /login/
    handler: DBAuth
    kwargs:
      prepare: mymodule.check_active(args)
      ...

... where mymodule.py has:

def check_active(args)
    if handler.request.method == 'POST':
        is_active = gramex.data.filter(
            url, table='user', args={'user': args['user'], 'is_active': [True]})
        if not is_active:
            raise HTTPError(403, 'Cannot log in as inactive user')

More flexible solution. Create a subclass of DBAuth called ValidatedDBAuth:

import gramex.data
from tornado.gen import coroutine
from gramexenterprise.handlers import DBAuth
from gramex.config import variables

class ValidatedDBAuth(DBAuth):
    @coroutine
    def post(handler):
        user = handler.get_argument('user')
        is_active = gramex.data.filter(
            variables['CONNECTION_STRING'],
            table='user',
            args={'user': [user]}
        )['is_active'].iloc[0]
        if is_active:
            yield super().post()
        else:
            handler.redirect('/login/?msg=inactive')

Now use this instead of your DBAuth. For example:

url:
  login:
    pattern: /login/
    handler: mymodule.ValidatedDBAuth
    kwargs:
      ... # Same as for DBAuth
0
On

You can copy the default auth.template.html locally as custom-login.html.

Then you can check if the user is already logged in (i.e. is_active) by checking handler.current_user. For example:

{% set is_active = handler.current_user %}
{% if not is_active %}
  <p>The user is inactive. You can't log in.</p>
{% else %}
  ... continue with default form
{% end %}

In your gramex.yaml, you could add template: $YAMLPATH/custom-login.html like this:

  login:
    pattern: /login/
    handler: DBAuth
    kwargs:
      url: $YAMLPATH/auth.xlsx
      user:
        column: user
      password:
        column: password
      template: $YAMLPATH/custom-login.html

NOTE: By only allowing logged-in users to log in, no user will be able to log in for the first time. So you'll need some mechanism to figure out how to let users log in for the first time.