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. 52
      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"
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 }}">
<head>
<meta charset="UTF-8">
@ -28,33 +28,26 @@
</div>
<div class="panel-body">
<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">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-log-in"></span> {% trans 'Login' %}
</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>
</form>

15
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

6
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'),

52
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'))
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,
'errmsg': _('Wrong login or password, please try again')
})
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'

26
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

3
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

Loading…
Cancel
Save