Browse Source

Make auth by request meta

devel
Dmitry Novikov 8 years ago
parent
commit
cad5a8f5fa
  1. 3
      accounts_app/locale/ru/LC_MESSAGES/django.po
  2. 35
      accounts_app/templates/accounts/login.html
  3. 15
      accounts_app/templatetags/acc_tags.py
  4. 6
      accounts_app/urls.py
  5. 66
      accounts_app/views.py
  6. 26
      djing/lib/auth_backends.py
  7. 3
      djing/settings.py

3
accounts_app/locale/ru/LC_MESSAGES/django.po

@ -296,3 +296,6 @@ msgstr "Ответственность за группы"
msgid "Profile" msgid "Profile"
msgstr "Учётная запись" msgstr "Учётная запись"
msgid "Login by location"
msgstr "Войти по местоположению"

35
accounts_app/templates/accounts/login.html

@ -1,4 +1,4 @@
<!DOCTYPE html>{% load i18n %}
<!DOCTYPE html>{% load i18n %}{% load acc_tags %}{% load bootstrap3 %}
<html lang="{{ LANGUAGE_CODE }}"> <html lang="{{ LANGUAGE_CODE }}">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
@ -28,33 +28,26 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form role="form" action="{% url 'acc_app:login' %}{% if next %}?next={{ next }}{% endif %}" method="POST">{% csrf_token %} <form role="form" action="{% url 'acc_app:login' %}{% if next %}?next={{ next }}{% endif %}" method="POST">{% csrf_token %}
{% if errmsg %}
<div class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ errmsg }}
</div>
{% endif %}
{% include '_messages.html' %}
<div class="form-group">
<label for="inp_uname">{% trans 'User name' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
<input type="text" id="inp_uname" placeholder="username" name="login" autofocus required class="form-control">
</div>
</div>
{# Username #}
{% bootstrap_icon 'user' as ic %}
{% bootstrap_field form.username addon_before=ic %}
<div class="form-group">
<label for="inp_pass">{% trans 'Password' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>
<input type="password" id="inp_pass" name="password" class="form-control">
</div>
</div>
{# Password #}
{% bootstrap_icon 'lock' as ic %}
{% bootstrap_field form.password addon_before=ic %}
<div class="btn-group btn-group-sm"> <div class="btn-group btn-group-sm">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-log-in"></span> {% trans 'Login' %} <span class="glyphicon glyphicon-log-in"></span> {% trans 'Login' %}
</button> </button>
{% can_login_by_location request as can_lbl %}
{% if can_lbl %}
<a href="{% url 'acc_app:llogin' %}" class="btn btn-default">
<span class="glyphicon glyphicon-map-marker"></span> {% trans 'Login by location' %}
</a>
{% endif %}
</div> </div>
</form> </form>

15
accounts_app/templatetags/acc_tags.py

@ -1,6 +1,9 @@
from ipaddress import ip_address, AddressValueError
from django import template from django import template
from django.db.models import Model from django.db.models import Model
from django.apps import apps from django.apps import apps
from ip_pool.models import IpLeaseModel
from six import string_types, class_types from six import string_types, class_types
register = template.Library() register = template.Library()
@ -16,3 +19,15 @@ def klass_name(klass):
else: else:
return 'Type not detected' return 'Type not detected'
return kl._meta.verbose_name 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

6
accounts_app/urls.py

@ -1,4 +1,5 @@
from django.urls import path, re_path from django.urls import path, re_path
from django.contrib.auth.views import LogoutView
from . import views from . import views
@ -6,8 +7,9 @@ app_name = 'account_app'
urlpatterns = [ urlpatterns = [
path('', views.AccountsListView.as_view(), name='accounts_list'), 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'), path('me/', views.profile_show, name='profile'),

66
accounts_app/views.py

@ -1,13 +1,14 @@
from django.contrib.auth.decorators import login_required 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.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect 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.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib import messages from django.contrib import messages
from django.urls import NoReverseMatch
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _ 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 django.conf import settings
from group_app.models import Group 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 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 = request.GET.get('next')
nextl = '' if nextl == 'None' or nextl is None or nextl.isspace() else nextl nextl = '' if nextl == 'None' or nextl is None or nextl.isspace() else nextl
try: 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', { return render(request, 'accounts/login.html', {
'next': nextl 'next': nextl
}) })
except NoReverseMatch: 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 @login_required
@ -181,7 +173,9 @@ def delete_profile(request, uid):
@method_decorator((login_required, only_admins), name='dispatch') @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' template_name = 'accounts/acc_list.html'
context_object_name = 'users' context_object_name = 'users'
@ -209,7 +203,9 @@ def perms(request, uid):
@method_decorator(login_required, name='dispatch') @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' template_name = 'accounts/perms/objects_of_type.html'
context_object_name = 'objects' context_object_name = 'objects'

26
djing/lib/auth_backends.py

@ -1,6 +1,9 @@
from ipaddress import ip_address, AddressValueError
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.backends import ModelBackend
from accounts_app.models import BaseAccount, UserProfile from accounts_app.models import BaseAccount, UserProfile
from abonapp.models import Abon from abonapp.models import Abon
from ip_pool.models import IpLeaseModel
class CustomAuthBackend(ModelBackend): class CustomAuthBackend(ModelBackend):
@ -29,5 +32,26 @@ class CustomAuthBackend(ModelBackend):
else: else:
user = Abon._default_manager.get(pk=user_id) user = Abon._default_manager.get(pk=user_id)
except BaseAccount.DoesNotExist: 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 return user if self.user_can_authenticate(user) else None

3
djing/settings.py

@ -27,7 +27,8 @@ ALLOWED_HOSTS = local_settings.ALLOWED_HOSTS
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
'djing.lib.auth_backends.CustomAuthBackend', 'djing.lib.auth_backends.CustomAuthBackend',
# 'django.contrib.auth.backends.ModelBackend', # default # 'django.contrib.auth.backends.ModelBackend', # default
'guardian.backends.ObjectPermissionBackend'
'guardian.backends.ObjectPermissionBackend',
'djing.lib.auth_backends.LocationAuthBackend'
) )
# Application definition # Application definition

Loading…
Cancel
Save