import re from django.conf import settings from django.http import HttpResponseRedirect class EnforceLoginMiddleware: """ Middleware class which requires the user to be authenticated for all urls except those defined in PUBLIC_URLS in settings.py. PUBLIC_URLS should be a tuple of regular expressions for the urls you want anonymous users to have access to. If PUBLIC_URLS is not defined, it falls back to LOGIN_URL or failing that '/accounts/login/'. Requests for urls not matching PUBLIC_URLS get redirected to LOGIN_URL with next set to original path of the unauthenticated request. Any urls statically served by django are excluded from this check. To enforce the same validation on these set SERVE_STATIC_TO_PUBLIC to False. """ def __init__(self, get_response): self.get_response = get_response self.login_url = getattr(settings, "LOGIN_URL", "/accounts/login/") if hasattr(settings, "PUBLIC_URLS"): public_urls = [re.compile(url) for url in settings.PUBLIC_URLS] else: public_urls = [re.compile("^%s/?$" % (self.login_url[1:]))] self.public_urls = tuple(public_urls) def __call__(self, request): # Check if user needs to be redirected to login redirect_response = self.check_login(request) if redirect_response: return redirect_response return self.get_response(request) def check_login(self, request): """ Redirect anonymous users to login_url from non public urls """ try: if request.user.is_anonymous: for url in self.public_urls: if url.match(request.path[1:]): return None return HttpResponseRedirect( "%s?next=%s" % (self.login_url, request.path) ) except AttributeError: return HttpResponseRedirect("%s?next=%s" % (self.login_url, request.path)) return None class DetectDevice: """ Middleware to detect the device type from user agent string. """ def __init__(self, get_response): self.get_response = get_response def __call__(self, request): request.device = self.detect_device(request) return self.get_response(request) def detect_device(self, request): device = {} ua = request.META.get("HTTP_USER_AGENT", "").lower() if "iphone" in ua: match = re.search(r"iphone os (\d)", ua) if match: device["iphone"] = "iphone" + match.group(1) else: device["iphone"] = "iphone" if "ipad" in ua: device["ipad"] = "ipad" if "android" in ua: match = re.search(r"android (\d\.\d)", ua) if match: version = match.group(1).replace(".", "") device["android"] = "android" + version else: device["android"] = "android" if "blackberry" in ua: device["blackberry"] = "blackberry" if "windows phone os 7" in ua: device["winphone7"] = "winphone7" if "iemobile" in ua: device["winmo"] = "winmo" if not device: # either desktop, or something we don't care about. device["baseline"] = "baseline" # spits out device names for CSS targeting, to be applied to or . device["classes"] = " ".join(v for (k, v) in device.items()) return device