auth_backend.py 6.18 KB
Newer Older
Patrick's avatar
Patrick committed
1 2
# -*- coding: utf-8
from __future__ import unicode_literals
Patrick's avatar
Patrick committed
3 4

import re
Patrick's avatar
Patrick committed
5
from django import forms
Patrick Colmant's avatar
Patrick Colmant committed
6
from django.contrib.auth.backends import ModelBackend
7
from django.contrib.auth.models import Permission
Patrick Colmant's avatar
Patrick Colmant committed
8
from django.contrib.auth.models import User
Patrick Colmant's avatar
Patrick Colmant committed
9
from django.db.models import F, Q
Patrick's avatar
Patrick committed
10
from django.utils import translation
Patrick's avatar
Patrick committed
11
from django.utils.translation import ugettext_lazy as _
Patrick Colmant's avatar
Patrick Colmant committed
12

Patrick's avatar
Patrick committed
13 14 15 16
from const import DECIMAL_ZERO, DECIMAL_ONE, DECIMAL_THREE
from models import Customer, Staff, Configuration

ACTION_RE = re.compile(r"(?<=\.)(.*?)(?=\_)")
17

18

Patrick Colmant's avatar
Patrick Colmant committed
19
class RepanierCustomBackend(ModelBackend):
Patrick's avatar
Patrick committed
20 21 22
    user = None

    def __init__(self, *args, **kwargs):
23
        super(RepanierCustomBackend, self).__init__()
Patrick's avatar
Patrick committed
24 25 26

    def authenticate(self, username=None, password=None, confirm=None, **kwargs):
        self.user = None
Patrick's avatar
Patrick committed
27 28
        user_username = User.objects.filter(Q(username=username[:30]) | Q(email=username)).order_by('?').first()
        admin = staff = customer = None
29
        login_attempt_counter = DECIMAL_THREE
Patrick's avatar
Patrick committed
30
        if user_username is not None:
Patrick Colmant's avatar
Patrick Colmant committed
31
            username = user_username.username
32
            customer = Customer.objects.filter(
Patrick's avatar
Patrick committed
33
                user=user_username, is_active=True
Patrick's avatar
Patrick committed
34
            ).order_by('?').first()
35 36
            if customer is None:
                staff = Staff.objects.filter(
Patrick Colmant's avatar
Patrick Colmant committed
37
                    user=user_username, is_active=True
Patrick's avatar
Patrick committed
38
                ).order_by('?').first()
39 40 41 42 43 44
                if staff is None:
                    login_attempt_counter = Configuration.objects.filter(
                        id=DECIMAL_ONE
                    ).only(
                        'login_attempt_counter'
                    ).first().login_attempt_counter
Patrick's avatar
Patrick committed
45
                else:
Patrick's avatar
Patrick committed
46
                    admin = True
47 48 49 50 51 52 53 54 55 56 57
                    login_attempt_counter = staff.login_attempt_counter
            else:
                login_attempt_counter = customer.login_attempt_counter

        user_or_none = super(RepanierCustomBackend, self).authenticate(username, password)

        if user_or_none is None:
            # Failed to log in
            if login_attempt_counter < 20:
                # Do not increment indefinitely
                if customer is not None:
Patrick's avatar
Patrick committed
58
                    Customer.objects.filter(id=customer.id).update(
59
                        login_attempt_counter=F('login_attempt_counter') +
Patrick's avatar
Patrick committed
60
                                              DECIMAL_ONE
Patrick's avatar
Patrick committed
61
                    )
62 63 64
                elif staff is not None:
                    Staff.objects.filter(id=staff.id).update(
                        login_attempt_counter=F('login_attempt_counter') +
Patrick's avatar
Patrick committed
65
                                              DECIMAL_ONE
66
                    )
Patrick's avatar
Patrick committed
67
                elif admin is not None:
68 69
                    Configuration.objects.filter(id=DECIMAL_ONE).update(
                        login_attempt_counter=F('login_attempt_counter') +
Patrick's avatar
Patrick committed
70
                                              DECIMAL_ONE
71
                    )
Patrick's avatar
Patrick committed
72
            if login_attempt_counter > DECIMAL_THREE:
73
                raise forms.ValidationError(
Patrick's avatar
Patrick committed
74 75
                    _(
                        "Because you tried to log in too many time without success, you must now first reset your password."),
76 77 78
                    code='attempt',
                )
        else:
Patrick's avatar
Patrick committed
79
            if login_attempt_counter > DECIMAL_THREE:
80
                raise forms.ValidationError(
Patrick's avatar
Patrick committed
81 82
                    _(
                        "Because you tried to log in too many time without success, you must now first reset your password."),
83 84 85 86
                    code='attempt',
                )
            else:
                # Reset login_attempt_counter
Patrick's avatar
Patrick committed
87
                # and if it's a customer, update/save the customer's language
88 89 90
                if customer is not None:
                    if login_attempt_counter > DECIMAL_ZERO:
                        Customer.objects.filter(id=customer.id).update(
Patrick's avatar
Patrick committed
91 92 93 94 95 96
                            login_attempt_counter=DECIMAL_ZERO,
                            language=translation.get_language()
                        )
                    else:
                        Customer.objects.filter(id=customer.id).update(
                            language=translation.get_language()
97 98 99 100 101
                        )
                elif staff is not None:
                    if login_attempt_counter > DECIMAL_ZERO:
                        Staff.objects.filter(id=staff.id).update(
                            login_attempt_counter=DECIMAL_ZERO
Patrick Colmant's avatar
Patrick Colmant committed
102
                        )
Patrick's avatar
Patrick committed
103
                elif admin is not None:
104
                    if login_attempt_counter > DECIMAL_ZERO:
Patrick Colmant's avatar
Patrick Colmant committed
105 106 107
                        Configuration.objects.filter(id=DECIMAL_ONE).update(
                            login_attempt_counter=DECIMAL_ZERO
                        )
108 109 110

        self.user = user_or_none
        return user_or_none
Patrick Colmant's avatar
Patrick Colmant committed
111

112
    def get_user(self, user_id):
Patrick's avatar
Patrick committed
113 114
        if self.user is not None and self.user.id == user_id:
            return self.user
Patrick's avatar
Patrick committed
115
        user_or_none = User.objects.filter(pk=user_id).only("id", "is_superuser").order_by('?').first()
Patrick's avatar
Patrick committed
116
        if user_or_none is not None and not user_or_none.is_superuser:
Patrick's avatar
Patrick committed
117 118
            a = Customer.objects.filter(user_id=user_or_none.id) \
                .only("is_active").order_by('?').first()
Patrick's avatar
Patrick committed
119 120 121 122
            if a is not None:
                if not a.is_active:
                    user_or_none = None
            else:
Patrick's avatar
Patrick committed
123 124
                a = Staff.objects.filter(user_id=user_or_none.id) \
                    .only("is_active").order_by('?').first()
Patrick's avatar
Patrick committed
125
                if a is not None:
Patrick's avatar
Patrick committed
126 127
                    if not a.is_active:
                        user_or_none = None
Patrick's avatar
Patrick committed
128 129 130
                else:
                    user_or_none = None
        self.user = user_or_none
Patrick's avatar
Patrick committed
131 132
        return user_or_none

133 134 135 136 137 138 139 140 141 142
    # def has_perm(self, user_obj, perm, obj=None):
    #     # if perm.startswith('dummy_cmsplugin_cascade'):
    #     if perm.startswith('cascade_dummy'):
    #         codename = perm.split('.', 1)[1]
    #         if not Permission.objects.filter(codename=codename).exists():
    #             perm_splitted = codename.split('_', 1)
    #             # codename = '%s_bootstrapcontainerpluginmodel' % perm_splitted[0]
    #             codename = '%s_cascadeelement' % perm_splitted[0]
    #         perm = 'cmsplugin_cascade.%s' % codename
    #     return super(RepanierCustomBackend, self).has_perm(user_obj, perm, obj)
143