0

I had made a Custom Middelware to secure all my views at once and made a custom decorator to exempt login and register/signup functions so that they're accessible to visitors. But when i tried to reset my password using the password-reset, i couldn't as it redirected me to login page, this system worked earlier when i had not put my Custom middelware inside the settings.py

Middleware.py

from django.contrib.auth.decorators import login_required

def login_exempt(view):        # <-- Custom Decorator
    view.login_exempt = True
    return view


class LoginRequiredMiddleware:            # <-- Custom Middleware
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):
        if getattr(view_func, 'login_exempt', False):
            return

        if request.user.is_authenticated:
            return


        return login_required(view_func)(request, *view_args, **view_kwargs)

Settings.py

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',

#custom auth middleware

'dashboard.middleware.LoginRequiredMiddleware',

]

Now, if i remove my custom middleware i'm able to visit my password-reset. So what should i do to exclude my Auth Views using my Login_exempt Custom Decorator. TIA

UrlCONF

from django.urls import path,include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
path('admin/', admin.site.urls),
path('', include("myapp.urls")),
path('accounts/', include('django.contrib.auth.urls'))


] 


if settings.DEBUG:


urlpatterns += (static(settings.STATIC_URL,document_root=settings.STATIC_ROOT))
ans2human
  • 2,300
  • 1
  • 14
  • 29

2 Answers2

1

You can use django-decorator-include for this.

pip install django-decorator-include

In you project/url.py

from decorator_include import decorator_include
from project/custom_middleware import login_exempt


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include("myapp.urls")),
    # do this 
    path('accounts/', decorator_include(login_exempt, 'django.contrib.auth.urls'))


]

Don't forget to add the package in requirements.txt

0

You could add Django's auth views one by one to your urlpatterns, decorating each with login_exempt.

If you would like to move the checking into the middleware you could try something like:

# urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include("myapp.urls")),
    path('accounts/', include('django.contrib.auth.urls', namespace="accounts"))
] 

# middleware.py
class LoginRequiredMiddleware:            # <-- Custom Middleware
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):

        if getattr(view_func, 'login_exempt', False):
            return

        if 'accounts' in request.resolver_match.namespaces:
            return

Other possibilities would maybe be checking the url or view name in the middleware, but still maybe the cleanest would be using your decorator and add the necessary views one by one.

Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148