130 lines
4.0 KiB
Python
130 lines
4.0 KiB
Python
import re
|
|
|
|
from django.conf import settings
|
|
from django.http import Http404, HttpResponsePermanentRedirect
|
|
from django.shortcuts import redirect
|
|
from django.utils.deprecation import MiddlewareMixin
|
|
from graphene import ResolveInfo
|
|
from sentry_sdk import capture_exception
|
|
|
|
|
|
try:
|
|
from threading import local
|
|
except ImportError:
|
|
from django.utils._threading_local import local
|
|
|
|
_thread_locals = local()
|
|
|
|
|
|
def get_current_request():
|
|
"""returns the request object for this thread"""
|
|
return getattr(_thread_locals, "request", None)
|
|
|
|
|
|
def get_current_user():
|
|
"""returns the current user, if exist, otherwise returns None"""
|
|
request = get_current_request()
|
|
if request:
|
|
return getattr(request, "user", None)
|
|
|
|
|
|
class ThreadLocalMiddleware(MiddlewareMixin):
|
|
"""Simple middleware that adds the request object in thread local storage."""
|
|
|
|
def process_request(self, request):
|
|
_thread_locals.request = request
|
|
|
|
def process_response(self, request, response):
|
|
if hasattr(_thread_locals, "request"):
|
|
del _thread_locals.request
|
|
return response
|
|
|
|
|
|
class CommonRedirectMiddleware(MiddlewareMixin):
|
|
"""
|
|
redirects common bad requests or missing images
|
|
"""
|
|
|
|
DEFAULT_REDIRECTS = [
|
|
(
|
|
re.compile(
|
|
"(?i)(.+\.php|.+wp-admin.+|.+\.htm|\/wordpress\/|\/wp\/|\/mm5\/|\/wp-content\/)"
|
|
),
|
|
"http://example.org/",
|
|
),
|
|
]
|
|
|
|
def process_exception(self, request, exception):
|
|
if exception.__class__ == Http404:
|
|
new_path = self.not_found(request)
|
|
if new_path:
|
|
return redirect(new_path, permanent=True)
|
|
|
|
def process_response(self, request, response):
|
|
if response.status_code == 404:
|
|
new_path = self.not_found(request)
|
|
if new_path:
|
|
return HttpResponsePermanentRedirect(new_path)
|
|
|
|
return response
|
|
|
|
def not_found(self, request):
|
|
path = request.get_full_path().lower()
|
|
# generic stuff
|
|
for re_pattern, to in self.DEFAULT_REDIRECTS:
|
|
if re_pattern.match(path):
|
|
return to
|
|
|
|
if settings.USE_404_FALLBACK_IMAGE:
|
|
# some static image is missing show a placeholder (use full for local dev)
|
|
m = re.match(r".*(max|fill)-(?P<dimensions>\d+x\d+)\.(jpg|png|svg)", path)
|
|
if m:
|
|
return "https://picsum.photos/{}".format(
|
|
m.group("dimensions").replace("x", "/")
|
|
)
|
|
# or dummy image: return 'http://via.placeholder.com/{}'.format(m.group('dimensions'))
|
|
if (
|
|
".png" in path
|
|
or ".jpg" in path
|
|
or ".svg" in path
|
|
or "not-found" in path
|
|
):
|
|
return "https://picsum.photos/400/400"
|
|
|
|
|
|
# https://stackoverflow.com/questions/4898408/how-to-set-a-login-cookie-in-django
|
|
class UserLoggedInCookieMiddleWare(MiddlewareMixin):
|
|
"""
|
|
Middleware to set user cookie
|
|
If user is authenticated and there is no cookie, set the cookie,
|
|
If the user is not authenticated and the cookie remains, delete it
|
|
"""
|
|
|
|
cookie_name = "loginStatus"
|
|
|
|
def process_response(self, request, response):
|
|
# if user and no cookie, set cookie
|
|
if request.user.is_authenticated and not request.COOKIES.get(self.cookie_name):
|
|
response.set_cookie(self.cookie_name, "true")
|
|
elif not request.user.is_authenticated and request.COOKIES.get(
|
|
self.cookie_name
|
|
):
|
|
# else if if no user and cookie remove user cookie, logout
|
|
response.delete_cookie(self.cookie_name)
|
|
return response
|
|
|
|
|
|
class SentryMiddleware(object):
|
|
def on_error(self, error):
|
|
capture_exception(error)
|
|
raise error
|
|
|
|
def resolve(self, next, root, info: ResolveInfo, **args):
|
|
try:
|
|
return next(root, info, **args)
|
|
except Exception as e:
|
|
capture_exception(e)
|
|
raise e
|
|
|
|
|