Dragon.M
Dragon.M

Reputation: 277

How to get remote ip in Django forms.py

I have customized forms.py in virtual environment on path "lib/python3.5/site-packages/django/contrib/auth" and it works great!

However I need now to grab remote ip from user in def confirm_login_allowed

I know that I need to grab from request but in the class AuthenticationForm where this model is located, the request is overwritten in __init_.

Do you know what should I do to get self.request.META['REMOTE_ADDR']

class AuthenticationForm(forms.Form):
    """
    Base class for authenticating users. Extend this to get a form that accepts
    username/password logins.
    """
    username = UsernameField(
        max_length=254,
        widget=forms.TextInput(attrs={'autofocus': True}),
    )
    password = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput,
    )

    error_messages = {
        'invalid_login': _(
            "Please enter a correct %(username)s and password. Note that both "
            "fields may be case-sensitive."
        ),
        'inactive': _("This account is inactive."),
        'IP': _("You tried to login from to much different IP address in last 24 hours. Contact administrator.")
    }

    def __init__(self, request=None, *args, **kwargs):
        """
        The 'request' parameter is set for custom auth use by subclasses.
        The form data comes in via the standard 'data' kwarg.
        """
        self.request = request
        self.user_cache = None
        super(AuthenticationForm, self).__init__(*args, **kwargs)

        # Set the label for the "username" field.
        self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
        if self.fields['username'].label is None:
            self.fields['username'].label = capfirst(self.username_field.verbose_name)

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        if username is not None and password:

            self.user_cache = authenticate(self.request, username=username, password=password)

            # self.ip_remote= self.request.META['REMOTE_ADDR']
            if self.user_cache is None:
                raise forms.ValidationError(
                    self.error_messages['invalid_login'],
                    code='invalid_login',
                    params={'username': self.username_field.verbose_name},
                )
            else:
                self.confirm_login_allowed(self.user_cache)

        return self.cleaned_data

    def confirm_login_allowed(self, user):
        """
        Controls whether the given User may log in. This is a policy setting,
        independent of end-user authentication. This default behavior is to
        allow login by active users, and reject login by inactive users.

        If the given user cannot log in, this method should raise a
        ``forms.ValidationError``.

        If the given user may log in, this method should return None.
        """

        from mysql_queries import user_ips
        #check user status, how many ip's he had over last 24 hours
        user_status = user_ips(user)

        if user_status == 400:
            raise forms.ValidationError(
                self.error_messages['IP'],
                code='IP',
            )

        if not user.is_active:
            raise forms.ValidationError(
                self.error_messages['inactive'],
                code='inactive',
            )

    def get_user_id(self):
        if self.user_cache:
            return self.user_cache.id
        return None

    def get_user(self):
        return self.user_cache 

Upvotes: 1

Views: 293

Answers (1)

Marine Fighter
Marine Fighter

Reputation: 403

This should work. If it doesn't work, check what is current ip address of the user and then check do you have that ip in your table where you record them. You should place this code right after you import module.

        remote_status = self.request.META['REMOTE_ADDR']
        rstat = ip_remote(remote_status) 
        if rstat == 500:
           raise forms.ValidationError(
                self.error_messages['Remote'],
                code='Remote',
           )

Upvotes: 2

Related Questions