django-axes lockout not working - django

Has anyone here successfully configured django-axes? Axes is a module which provides you with the ability to lock out a user after a specified number of unsuccessful login attempts. I'm having three problems which I haven't been able to solve. First, my application continues to allow me to try to login even if I've exceeded the failure limit, second my site isn't displaying the lockout template if I exceed the failure limit, and third my administrative site isn't showing any login failures. I've read the docs on Github but I still don't see what I'm doing wrong. My files are shown below. Thanks for your help.
# Relevant settings in settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
'axes',
)
# MIDDLEWARE_CLASSES contains usual classes
MIDDLEWARE_CLASSES += (
'axes.middleware.FailedLoginMiddleware',
)
AXES_LOGIN_FAILURE_LIMIT = 1
import datetime as dt
delta = dt.timedelta(minutes=1)
AXES_COOLOFF_TIME = delta
AXES_LOCKOUT_URL = '/accounts/locked_out/'
AXES_LOCKOUT_TEMPLATE = 'registration/locked_out.html'
# Relevant routes in urls.py
urlpatterns = patterns('',
# This is my login view, nothing special there
url(r'^$', 'login.views.firewall_login'),
# The view for Axes lockout
url(r'^accounts/locked_out/$',
'login.views.locked_out',
{'template': 'registration/locked_out.html'}),
url(r'^admin/', include(admin.site.urls)),
)
# views.py
def locked_out(request, template):
"""User is redirected here after they're locked out."""
return render(request, template)

Add this to your setting.py:
AUTHENTICATION_BACKENDS = [
# AxesBackend should be the first backend in the AUTHENTICATION_BACKENDS list.
'axes.backends.AxesBackend',
# Django ModelBackend is the default authentication backend.
'django.contrib.auth.backends.ModelBackend',
]

All I can help with is that you need to add
AXES_ENABLE_ACCESS_FAILURE_LOG = True # log access failures to the database.
Not sure about the other questions myself, unfortunately

Related

Why is Django is not loading my template view but it once was

My view was running fine until Ill tried to override an admin view. Which i eventually got to work. However in the process I broke the path to my view that was working. The admin view had nothing to do with my originally working view.
Now I copied my view into every possible level of my project structure. Yet the django template loader fails to find my order_input.html
The error shows the correct path to my order_input.html. I made copies of order_input.html at every single possible level of my project... but django still cant find it.
APP - URLS.PY
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^hw/$', views.helloworld, name='helloworld'),
url(r'^order_input/$', views.order_input, name='order_input'),
url(r'^time/$', views.today_is, name='time'),
url(r'^$', views.index, name='index'),
]
SETTINGS.PY
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
# 'django.contrib.staticfiles',
'import_export',
'hw_app',
]
PROJECT URLS.PY
urlpatterns = [
url('r', include('hw_app.urls')),
url('admin/', admin.site.urls),
path('clearfile', views.clearfile),
path('readfile', views.readfile),
path('writefile', views.writefile),
path('helloworld', views.helloworld),
path('order_input', views.order_input),
path('ajax_view', views.ajax_view),
]
You have the order_input url defined in both your project and your app urls.py files, only in the hw_app version it has a trailing slash. The slashless project URL may be looking in the wrong places for things as it will assume there is a related view at its level.
Try removing that path from the project urls.py file. Assuming it should be going to the same place, it's already included when you include(hw_apps.urls) (as url() is just a more up-to-date path() ). Then try calling the page with a trailing slash.
The only view file then relevant should be hw_apps/views.py. For consistency place the HTML template file is in hw_app/templates/hw_app/order_input.html so you know django should be able to find it.

Django is not invoking my app's ready method [duplicate]

Trying to catch the basics of Django. Namely how Applications work.
The docs: https://docs.djangoproject.com/en/stable/ref/applications/#methods
And in the code of the class AppConfig we can read:
def ready(self):
"""
Override this method in subclasses to run code when Django starts.
"""
Well, this is my example:
my_app/apps.py
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
print('My app')
I just want to make the ready method work. That is, when Django finds my_app, let it run the ready method.
The app is registered in INSTALLED_APPS.
I execute 'python manage.py runserver'. And nothing is printed.
If I place a breakpoint inside the ready method, the debugger don't stop there.
Could you help me: what is my mistake in understanding here. Thank you in advance.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'my_app',
]
And I created a view
my_app/views.py
def index(request):
print('Print index')
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', my_app_views.index, name='home')
]
Well, the view is working. This means that the application is registered.
You need to do one of two things. Either explicitly say which AppConfig you want in INSTALLED_APPS:
INSTALLED_APPS = [
'my_app.apps.MyAppConfig'
]
Or, define a default_app_config in the __init__.py of your app:
# my_app/__init__.py
default_app_config = 'my_app.apps.MyAppConfig'
(and leave INSTALLED_APPS as-is).
As it is currently Django can't find any AppConfig for the app and just assumes there isn't one. So your views etc. will work, but the ready() method will never get called.
Here's the relevant section of the documentation.
Edit: as of Django 3.2, specifying a default_app_config is no longer necessary, and is in fact deprecated - so this answer is redundant for anyone using Django 3.2 or later.

Using PUBLIC_SCHEMA_URLCONF in django-tenant-schemas

I am trying to have django-tenant-schemas re-route users if they visit the base domain using the optional setting PUBLIC_SCHEMA_URLCONF. Whenever I visit the
base url I get this response:
I'm hoping someone can tell me what the value of PUBLIC_SCHEMA_URLCONF should be based on my project structure or if anything else might be wrong. I want to use the urls from public_website when people try to access the base domain.
My project directory looks like this:
website
├──approvals
├──batches
├──customauth
├──email_portal
├──exports
├──file_downloads
├──password_reset
├──payroll
├──payroll_codes
├──reports
├──scheduling
├──shifts
├──static
├──templates
├──website
| ├──migrations
| ├──static
| ├──templates
| └──settings
| ├──__init__.py
| ├──base.py
| ├──prod.py
| └──dev.py
├──scheduling
├──public_website
| ├──__init__.py
| └──urls.py
└──manage.py
And I want PUBLIC_SCHEMA_URLCONF to refer to the urls in public_website, which look like:
from django.conf.urls import include, url
import website.views as website_views
from django.contrib import admin
from django.http import HttpResponse
url_patterns = [
url(r'^$', lambda request: HttpResponse('ok')),
url(r'^admin/login/', website_views.Login.as_view()),
url(r'^admin/', include(admin.site.urls)) # user authentication urls
]
Here are the relevant bits in my settings:
DJANGO_APPS = (
'jet',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'django.contrib.admin',
'django_user_agents',
'django_ses',
# 'admin_reorder'
)
MY_APPS_WITH_MODELS = (
'customauth',
'payroll_codes',
'scheduling',
'payroll',
'shifts',
'email_portal',
'tutor_training_tracker'
)
MY_APPS_WITHOUT_MODELS = (
'exports',
'reports',
'file_downloads',
'batches',
'approvals'
)
SHARED_APPS = (
'tenant_schemas',
'website',
'public_website'
)
TENANT_APPS = DJANGO_APPS + MY_APPS_WITH_MODELS
INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + DJANGO_APPS + MY_APPS_WITHOUT_MODELS + MY_APPS_WITH_MODELS))
ROOT_URLCONF = 'website.urls'
PUBLIC_SCHEMA_URLCONF = 'public_website.urls'
TENANT_MODEL = "website.Client"
DEFAULT_FILE_STORAGE = "tenant_schemas.storage.TenantFileSystemStorage"
Any help would be greatly appreciated.
Solution:
(Thanks to Thomas for writing the middleware for me)
Add custom middleware class:
from django.conf import settings
from django.db import connection
from tenant_schemas.middleware import MIDDLEWARE_MIXIN
from tenant_schemas.utils import remove_www, get_tenant_model, get_public_schema_name
class CustomTenantMiddleware(MIDDLEWARE_MIXIN):
def get_tenant(self, model, hostname, request):
return model.objects.get(domain_url=hostname)
def hostname_from_request(self, request):
""" Extracts hostname from request. Used for custom requests filtering.
By default removes the request's port and common prefixes.
"""
return remove_www(request.get_host().split(':')[0]).lower()
def process_request(self, request):
# Connection needs first to be at the public schema, as this is where
# the tenant metadata is stored.
connection.set_schema_to_public()
hostname = self.hostname_from_request(request)
TenantModel = get_tenant_model()
try:
# get_tenant must be implemented by extending this class.
tenant = self.get_tenant(TenantModel, hostname, request)
assert isinstance(tenant, TenantModel)
request.tenant = tenant
connection.set_tenant(request.tenant)
except (TenantModel.DoesNotExist, AssertionError):
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
request.public_tenant = True
return
if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
and reference it in settings:
MIDDLEWARE_CLASSES = (
# 'tenant_schemas.middleware.TenantMiddleware',
'website.middleware.CustomTenantMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django_user_agents.middleware.UserAgentMiddleware',
'admin_reorder.middleware.ModelAdminReorder',
'website.middleware.CustomTenantMiddleware',
# 'djadmin.middleware.DJMiddleware',
)
I maintain Django-Tenants which is a fork of django-tenant-schemas. The public url file gets called when the domain doesn't match a tenant. However depending on the middleware you have this can result in this not working. If this is the case write custom middleware for the tenant. You may also want edit you host file as it hard to test with out editing. What middleware are you using?
Make sure you have installed latest version of django-tenants and these settings are set in settings.py:
SHOW_PUBLIC_IF_NO_TENANT_FOUND = True # I wonder why this setting is not meintioned in docs.
PUBLIC_SCHEMA_URLCONF = 'project_name.urls_public'

django rest_framework viewset has no route

I started a new django application with django rest_framework. One thing is odd though - when I try the example from the quickstart it works fine: I get a route at http://localhost:8000/users/ that I can query. But it doesn't work with my own app which is as minimal as it could be. My route http://localhost:8000/listings/ is not available and I get no error. I'm using django 1.8.2 and djangorestframework 3.1.3.
settings.py:
#...
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_swagger',
'debug_toolbar',
'listing',
)
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
#...
urls.py:
from rest_framework import routers, serializers, viewsets
from listing.models import Listing
class ListingSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Listing
fields = ('description',)
class ListingViewSet(viewsets.ViewSet):
queryset = Listing.objects.all()
serializer_class = ListingSerializer
router = routers.DefaultRouter()
router.register(r'listings', ListingViewSet)
urlpatterns = router.urls
models.py:
from django.db import models
class Listing(models.Model):
description = models.TextField()
Edit:
The error:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/listings/
Using the URLconf defined in djangoway.urls, Django tried these URL patterns, in this order:
^__debug__/
^$ [name='api-root']
^\.(?P<format>[a-z0-9]+)$ [name='api-root']
The current URL, listings/, didn't match any of these.
Edit:
Answered my question and took the code down, because there was nothing odd with it.
I should have used the ModelViewSet:
class ListingViewSet(viewsets.ModelViewSet):
^^^^^
Thanks to xordoquy for pointing it out in the issue I opened.

django-debug-toolbar won't display from production server

I'd like to view the Django Debug Toolbar when accessing my production website which is running Django 1.6. My server is running Debian 7.8, Nginx 1.2.1, and Gunicorn 19.1.1. However, when I try to access the site after adding DDT to my installed apps, I get the following error:
NoReverseMatch at /
u'djdt' is not a registered namespace
Exception Location: /home/mysite/venv/mysite/local/lib/python2.7/site-packages/django/core/urlresolvers.py in reverse, line 505
Error during template rendering
In template /home/mysite/venv/mysite/local/lib/python2.7/site-packages/debug_toolbar/templates/debug_toolbar/base.html, error at line 12
data-store-id="{{ toolbar.store_id }}" data-render-panel-url="{% url 'djdt:render_panel' %}"
I know it's not recommended that you run the toolbar in production but I just want to run it while I do some testing on my production server prior to opening it up for public use. As you might expect, it works just fine in my development environment on my laptop. I did some research and have ensured that I'm using the "explicit" setup as recommended here. I also ran the command "django-admin.py collectstatic" to ensure the toolbar's static files were collected into my STATIC_ROOT.
Since I'm running behind a proxy server, I also added some middleware to ensure that the client's IP address is being passed to the toolbar's middleware instead of my proxy's IP address. That didn't fix the problem either.
I'm showing all the settings which seem pertinent to this problem below. Is there something else I'm missing?
Thanks!
These are the pertinent base settings:
SETTINGS_ROOT = os.path.abspath(os.path.dirname(__file__).decode('utf-8'))
STATIC_ROOT = '/var/www/mysite/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(SETTINGS_ROOT, "../../static"),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.common.BrokenLinkEmailsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
TEMPLATE_DIRS = (
os.path.join(SETTINGS_ROOT, "../../templates"),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Django management commands in 'scripts'
'scripts',
'apps.account',
)
These production-only settings get added to base settings in production:
DEBUG = True # DDT needs this to be True
TEMPLATE_DEBUG = DEBUG
INSTALLED_APPS += (
'django_extensions',
# I'm using Django 1.6
'debug_toolbar',
)
if 'debug_toolbar' in INSTALLED_APPS:
MIDDLEWARE_CLASSES += ('conf.middleware.DjangoDebugToolbarFix',
'debug_toolbar.middleware.DebugToolbarMiddleware', )
# I had to add this next setting after upgrading my OS to Mavericks
DEBUG_TOOLBAR_PATCH_SETTINGS = False
# IP for laptop and external IP needed by DDT
INTERNAL_IPS = ('76.123.67.152', )
DEBUG_TOOLBAR_CONFIG = {
'DISABLE_PANELS': [
'debug_toolbar.panels.redirects.RedirectsPanel',
],
'SHOW_TEMPLATE_CONTEXT': True,
'INTERCEPT_REDIRECTS': False
}
This is in my urls.py:
if 'debug_toolbar' in dev.INSTALLED_APPS:
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)
Here is the additional middleware:
class DjangoDebugToolbarFix(object):
"""Sets 'REMOTE_ADDR' based on 'HTTP_X_FORWARDED_FOR', if the latter is
set."""
def process_request(self, request):
if 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META['HTTP_X_FORWARDED_FOR'].split(",")[0].strip()
request.META['REMOTE_ADDR'] = ip
I am using the exact same setup as OP describes, with the noticeable exception of running everything in a separate Docker container which make the IP of each service hard to predict.
This is how you force Django Debug Toolbar to always show (only use this locally, never in production):
def custom_show_toolbar(request):
return True # Always show toolbar, for example purposes only.
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
}
Actually, you shouldn't set DEBUG to True on your production server, keep it False and check my solution below:
The default DDT callback (debug_toolbar.middleware.show_toolbar) checks are that DEBUG must be set to True, the IP of the request must be in INTERNAL_IPS, and the request must not be an AJAX request.
We can provide our own callback which excludes the DEBUG setting condition:
settings:
INTERNAL_IPS = ['YOUR.IP.ADDRESS.HERE'] # put your client IP address here (not server IP!)
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': lambda request: not request.is_ajax() and request.META.get('REMOTE_ADDR', None) in INTERNAL_IPS
}
You can check HTTP_X_FORWARDED_FOR if you wish too, it is up to you.
urls:
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
If you are on docker the following code helped me get the internal ip.
# Debug Toolbar
if DEBUG:
import os
import socket
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS = [ip[:-1] + '1' for ip in ips] + ['127.0.0.1', '10.0.2.2', ]
credit goes here https://gist.github.com/douglasmiranda/9de51aaba14543851ca3#file-option2-py
And this answer has additional options: https://stackoverflow.com/a/49818040/317346
So django-debug-toolbar uses JavaScript to run as well. have you confirmed you have n conflicting JS scripts affecting your setup? I had a hell of a time with one project using DjDT and it was a back-to-top script that was interfering...
Also, I know you have lots of extra code to handle your proxy situation, but have you uan it straight out of the box to see if that works on your server? I might create a new virtualenv, start from scratch and make sure it works on your server and then proceed to add apps and additional configuration.
These are probably thing you have thought of but I thought I'd add them anyway since your question hasn't received much action.
Good luck.
I had to add the following to the project url.py file to fix the issue. After that debug tool bar is displayed.
from django.conf.urls import include
from django.conf.urls import patterns
from django.conf import settings
if settings.DEBUG:
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)