diff --git a/accounts_app/locale/ru/LC_MESSAGES/django.po b/accounts_app/locale/ru/LC_MESSAGES/django.po
index 515069c..078323b 100644
--- a/accounts_app/locale/ru/LC_MESSAGES/django.po
+++ b/accounts_app/locale/ru/LC_MESSAGES/django.po
@@ -296,3 +296,6 @@ msgstr "Ответственность за группы"
msgid "Profile"
msgstr "Учётная запись"
+
+msgid "Login by location"
+msgstr "Войти по местоположению"
diff --git a/accounts_app/templates/accounts/login.html b/accounts_app/templates/accounts/login.html
index 30e94a7..da95408 100644
--- a/accounts_app/templates/accounts/login.html
+++ b/accounts_app/templates/accounts/login.html
@@ -1,4 +1,4 @@
-{% load i18n %}
+{% load i18n %}{% load acc_tags %}{% load bootstrap3 %}
diff --git a/accounts_app/templatetags/acc_tags.py b/accounts_app/templatetags/acc_tags.py
index 821835a..d91a879 100644
--- a/accounts_app/templatetags/acc_tags.py
+++ b/accounts_app/templatetags/acc_tags.py
@@ -1,6 +1,9 @@
+from ipaddress import ip_address, AddressValueError
+
from django import template
from django.db.models import Model
from django.apps import apps
+from ip_pool.models import IpLeaseModel
from six import string_types, class_types
register = template.Library()
@@ -16,3 +19,15 @@ def klass_name(klass):
else:
return 'Type not detected'
return kl._meta.verbose_name
+
+
+@register.simple_tag
+def can_login_by_location(request):
+ try:
+ remote_ip = ip_address(request.META.get('REMOTE_ADDR'))
+ if remote_ip.version == 4:
+ has_leases = IpLeaseModel.objects.filter(ip=str(remote_ip)).exists()
+ return has_leases
+ except AddressValueError:
+ pass
+ return False
diff --git a/accounts_app/urls.py b/accounts_app/urls.py
index cb2882f..9f37d72 100644
--- a/accounts_app/urls.py
+++ b/accounts_app/urls.py
@@ -1,4 +1,5 @@
from django.urls import path, re_path
+from django.contrib.auth.views import LogoutView
from . import views
@@ -6,8 +7,9 @@ app_name = 'account_app'
urlpatterns = [
path('', views.AccountsListView.as_view(), name='accounts_list'),
- path('login/', views.to_signin, name='login'),
- path('logout/', views.SignOut.as_view(), name='logout'),
+ path('login/', views.CustomLoginView.as_view(), name='login'),
+ path('logout/', LogoutView.as_view(next_page='acc_app:login'), name='logout'),
+ path('login_by_location/', views.location_login, name='llogin'),
path('me/', views.profile_show, name='profile'),
diff --git a/accounts_app/views.py b/accounts_app/views.py
index bb3bd56..5e36685 100644
--- a/accounts_app/views.py
+++ b/accounts_app/views.py
@@ -1,13 +1,14 @@
from django.contrib.auth.decorators import login_required
-from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth import logout, login, authenticate
+from django.contrib.auth.views import LoginView
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
-from django.urls import NoReverseMatch, reverse_lazy
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib import messages
+from django.urls import NoReverseMatch
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
-from django.views.generic import ListView, UpdateView, RedirectView
+from django.views.generic import ListView, UpdateView
from django.conf import settings
from group_app.models import Group
@@ -20,45 +21,36 @@ from guardian.decorators import permission_required_or_403 as permission_require
from guardian.shortcuts import get_objects_for_user, assign_perm, remove_perm
-class BaseAccListView(ListView):
- http_method_names = ('get',)
- paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
+class CustomLoginView(LoginView):
+ template_name = 'accounts/login.html'
+
+ def form_invalid(self, form):
+ messages.error(self.request, _('Wrong login or password, please try again'))
+ return super().form_invalid(form)
+
+ def get_success_url(self):
+ if self.request.user.is_staff:
+ return resolve_url('acc_app:profile')
+ return resolve_url('client_side:home')
-def to_signin(request):
+def location_login(request):
nextl = request.GET.get('next')
nextl = '' if nextl == 'None' or nextl is None or nextl.isspace() else nextl
-
try:
- if request.POST:
- auser = authenticate(username=request.POST.get('login'), password=request.POST.get('password'))
- if auser:
- login(request, auser)
- if nextl == 'None' or nextl is None or nextl == '':
- if request.user.is_staff:
- return redirect('acc_app:profile')
-
- return redirect('client_side:home')
-
- return redirect(nextl)
-
- return render(request, 'accounts/login.html', {
- 'next': nextl,
- 'errmsg': _('Wrong login or password, please try again')
- })
+ auser = authenticate(request=request, byip=None)
+ if auser:
+ login(request, auser)
+ if nextl == 'None' or nextl is None or nextl == '':
+ if request.user.is_staff:
+ return redirect('acc_app:profile')
+ return redirect('client_side:home')
+ return redirect(nextl)
return render(request, 'accounts/login.html', {
'next': nextl
})
except NoReverseMatch:
- return redirect('acc_app:profile')
-
-
-class SignOut(RedirectView):
- url = reverse_lazy('acc_app:login')
-
- def get(self, request, *args, **kwargs):
- logout(request)
- return super(SignOut, self).get(request, *args, **kwargs)
+ return redirect('client_side:home')
@login_required
@@ -181,7 +173,9 @@ def delete_profile(request, uid):
@method_decorator((login_required, only_admins), name='dispatch')
-class AccountsListView(BaseAccListView):
+class AccountsListView(ListView):
+ http_method_names = 'get',
+ paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
template_name = 'accounts/acc_list.html'
context_object_name = 'users'
@@ -209,7 +203,9 @@ def perms(request, uid):
@method_decorator(login_required, name='dispatch')
-class PermissionClassListView(BaseAccListView):
+class PermissionClassListView(ListView):
+ http_method_names = 'get',
+ paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
template_name = 'accounts/perms/objects_of_type.html'
context_object_name = 'objects'
diff --git a/djing/lib/auth_backends.py b/djing/lib/auth_backends.py
index 4517b04..84c9a76 100644
--- a/djing/lib/auth_backends.py
+++ b/djing/lib/auth_backends.py
@@ -1,6 +1,9 @@
+from ipaddress import ip_address, AddressValueError
+
from django.contrib.auth.backends import ModelBackend
from accounts_app.models import BaseAccount, UserProfile
from abonapp.models import Abon
+from ip_pool.models import IpLeaseModel
class CustomAuthBackend(ModelBackend):
@@ -29,5 +32,26 @@ class CustomAuthBackend(ModelBackend):
else:
user = Abon._default_manager.get(pk=user_id)
except BaseAccount.DoesNotExist:
- return None
+ return
+ return user if self.user_can_authenticate(user) else None
+
+
+class LocationAuthBackend(ModelBackend):
+ def authenticate(self, request, byip, **kwargs):
+ try:
+ remote_ip = ip_address(request.META.get('REMOTE_ADDR'))
+ lease = IpLeaseModel.objects.filter(ip=str(remote_ip)).first()
+ if lease is None:
+ return
+ user = Abon.objects.get(ip_addresses=lease)
+ if self.user_can_authenticate(user):
+ return user
+ except (AddressValueError, Abon.DoesNotExist):
+ return
+
+ def get_user(self, user_id):
+ try:
+ user = Abon.objects.get(pk=user_id)
+ except Abon.DoesNotExist:
+ return
return user if self.user_can_authenticate(user) else None
diff --git a/djing/settings.py b/djing/settings.py
index a52adc4..2ac33ab 100644
--- a/djing/settings.py
+++ b/djing/settings.py
@@ -27,7 +27,8 @@ ALLOWED_HOSTS = local_settings.ALLOWED_HOSTS
AUTHENTICATION_BACKENDS = (
'djing.lib.auth_backends.CustomAuthBackend',
# 'django.contrib.auth.backends.ModelBackend', # default
- 'guardian.backends.ObjectPermissionBackend'
+ 'guardian.backends.ObjectPermissionBackend',
+ 'djing.lib.auth_backends.LocationAuthBackend'
)
# Application definition