Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import logging 

2import traceback 

3from typing import Dict, Optional 

4from urllib.parse import urlencode 

5from django.conf import settings 

6from django.http import HttpRequest 

7from django.utils import timezone 

8from ipware import get_client_ip # type: ignore 

9from jutil.email import send_email 

10 

11logger = logging.getLogger(__name__) 

12 

13 

14class EnsureOriginMiddleware: 

15 """ 

16 Ensures that request META 'HTTP_ORIGIN' is set. 

17 Uses request get_host() to set it if missing. 

18 """ 

19 

20 def __init__(self, get_response=None): 

21 self.get_response = get_response 

22 

23 def __call__(self, request): 

24 # Code to be executed for each request before 

25 # the view (and later middleware) are called. 

26 if not request.META.get("HTTP_ORIGIN", None): 26 ↛ 30line 26 didn't jump to line 30, because the condition on line 26 was never false

27 request.META["HTTP_ORIGIN"] = request.get_host() 

28 

29 # get response 

30 response = self.get_response(request) 

31 

32 # Code to be executed for each request/response after 

33 # the view is called. 

34 return response 

35 

36 

37class LogExceptionMiddleware: 

38 """ 

39 Logs exception and sends email to admins about it. 

40 Uses list of emails from settings.ADMINS. 

41 """ 

42 

43 def __init__(self, get_response=None): 

44 self.get_response = get_response 

45 

46 def __call__(self, request): 

47 return self.get_response(request) 

48 

49 def process_exception(self, request, e): 

50 """ 

51 Logs exception error message and sends email to ADMINS if hostname is not testserver and DEBUG=False. 

52 :param request: HttpRequest 

53 :param e: Exception 

54 """ 

55 assert isinstance(request, HttpRequest) 

56 full_path = request.get_full_path() 

57 user = request.user 

58 msg = "{full_path}\n{err} (IP={ip}, user={user}) {trace}".format( 

59 full_path=full_path, user=user, ip=get_client_ip(request)[0], err=e, trace=str(traceback.format_exc()) 

60 ) 

61 logger.error(msg) 

62 hostname = request.get_host() 

63 if not settings.DEBUG and hostname != "testserver": 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true

64 send_email(settings.ADMINS, "Error @ {}".format(hostname), msg) 

65 

66 

67class EnsureLanguageCookieMiddleware: 

68 """ 

69 Ensures language cookie (by name settings.LANGUAGE_COOKIE_NAME) is set. 

70 Sets it as settings.LANGUAGE_CODE if missing. 

71 Allows changing settings by passing querystring parameter named settings.LANGUAGE_COOKIE_NAME 

72 (default: django_language). 

73 

74 Order of preference for the language (must be one of settings.LANGUAGES to be used): 

75 1) Explicit querystring GET parameter (e.g. ?lang=en) 

76 2) Previously stored cookie 

77 3) settings.LANGUAGE_CODE 

78 """ 

79 

80 _languages: Optional[Dict[str, str]] 

81 

82 def __init__(self, get_response=None): 

83 self.get_response = get_response 

84 self._languages = None 

85 

86 @property 

87 def languages(self) -> Dict[str, str]: 

88 if self._languages is None: 

89 self._languages = dict(settings.LANGUAGES) 

90 return self._languages 

91 

92 def __call__(self, request): 

93 lang_cookie_name = ( 

94 settings.LANGUAGE_COOKIE_NAME if hasattr(settings, "LANGUAGE_COOKIE_NAME") else "django_language" 

95 ) 

96 lang_cookie = request.COOKIES.get(lang_cookie_name) 

97 lang = request.GET.get(lang_cookie_name) 

98 if not lang: 

99 lang = lang_cookie 

100 if not lang or lang not in self.languages: 

101 lang = settings.LANGUAGE_CODE if hasattr(settings, "LANGUAGE_CODE") else "en" 

102 request.COOKIES[lang_cookie_name] = lang 

103 

104 res = self.get_response(request) 

105 

106 if lang_cookie is None or lang != lang_cookie: 

107 secure = hasattr(settings, "LANGUAGE_COOKIE_SECURE") and settings.LANGUAGE_COOKIE_SECURE 

108 httponly = hasattr(settings, "LANGUAGE_COOKIE_HTTPONLY") and settings.LANGUAGE_COOKIE_HTTPONLY 

109 res.set_cookie(lang_cookie_name, lang, secure=secure, httponly=httponly) 

110 return res 

111 

112 

113class ActivateUserProfileTimezoneMiddleware: 

114 """ 

115 Uses 'timezone' string in request.user.profile to activate user-specific timezone. 

116 """ 

117 

118 def __init__(self, get_response=None): 

119 self.get_response = get_response 

120 

121 def __call__(self, request): 

122 # Code to be executed for each request before 

123 # the view (and later middleware) are called. 

124 activated = False 

125 if request.user.is_authenticated: 125 ↛ 138line 125 didn't jump to line 138, because the condition on line 125 was never false

126 user = request.user 

127 if hasattr(user, "profile") and user.profile: 127 ↛ 135line 127 didn't jump to line 135, because the condition on line 127 was never false

128 up = user.profile 

129 if hasattr(up, "timezone") and up.timezone: 129 ↛ 133line 129 didn't jump to line 133, because the condition on line 129 was never false

130 timezone.activate(up.timezone) 

131 activated = True 

132 else: 

133 logger.warning("User profile timezone missing so user.profile.timezone could not be activated") 

134 else: 

135 logger.warning("User profile missing so user.profile.timezone could not be activated") 

136 

137 # get response 

138 response = self.get_response(request) 

139 

140 # Code to be executed for each request/response after 

141 # the view is called. 

142 if activated: 142 ↛ 144line 142 didn't jump to line 144, because the condition on line 142 was never false

143 timezone.deactivate() 

144 return response 

145 

146 

147class TestClientLogger: 

148 """ 

149 Logs requests for Django test client. 

150 """ 

151 

152 ignored_paths = { 

153 "/admin/jsi18n/", 

154 "/favicon.ico", 

155 } 

156 

157 def __init__(self, get_response=None): 

158 self.get_response = get_response 

159 

160 def __call__(self, request): 

161 if settings.DEBUG: 

162 assert isinstance(request, HttpRequest) 

163 if request.path not in self.ignored_paths: 

164 url = request.path 

165 qs = request.GET.dict() 

166 if qs: 

167 url += "?" + urlencode(request.GET.dict()) 

168 logger.debug( 

169 '[TestClientLogger] self.client.%s("%s", data=%s)', request.method.lower(), url, request.POST.dict() 

170 ) 

171 response = self.get_response(request) 

172 return response