Coverage for jutil/middleware.py: 90%

# Coverage for jutil/middleware.py : 90%

## 74 statements

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

1 import logging

2 import traceback

3 from typing import Dict, Optional

4 from django.conf import settings

5 from django.http import HttpRequest

6 from django.utils import timezone

7 from ipware import get_client_ip # type: ignore

8 from jutil.email import send_email

9

10

11 logger = logging.getLogger(__name__)

12

13

14 class 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

37 class 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(full_path=full_path, user=user,

59 ip=get_client_ip(request)[0], err=e,

60 trace=str(traceback.format_exc()))

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

67 class 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 _languages: Optional[Dict[str, str]]

80

81 def __init__(self, get_response=None):

82 self.get_response = get_response

83 self._languages = None

84

85 @property

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

87 if self._languages is None:

88 self._languages = dict(settings.LANGUAGES)

89 return self._languages

90

91 def __call__(self, request):

92 lang_cookie_name = settings.LANGUAGE_COOKIE_NAME if hasattr(settings, 'LANGUAGE_COOKIE_NAME') else 'django_language'

93 lang_cookie = request.COOKIES.get(lang_cookie_name)

94 lang = request.GET.get(lang_cookie_name)

95 if not lang:

96 lang = lang_cookie

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

98 lang = settings.LANGUAGE_CODE if hasattr(settings, 'LANGUAGE_CODE') else 'en'

99 request.COOKIES[lang_cookie_name] = lang

100

101 res = self.get_response(request)

102

103 if lang_cookie is None or lang != lang_cookie:

104 secure = hasattr(settings, 'LANGUAGE_COOKIE_SECURE') and settings.LANGUAGE_COOKIE_SECURE

105 httponly = hasattr(settings, 'LANGUAGE_COOKIE_HTTPONLY') and settings.LANGUAGE_COOKIE_HTTPONLY

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

107 return res

108

109

110 class ActivateUserProfileTimezoneMiddleware:

111 """

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

113 """

114 def __init__(self, get_response=None):

115 self.get_response = get_response

116

117 def __call__(self, request):

118 # Code to be executed for each request before

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

120 activated = False

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

122 user = request.user

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

124 up = user.profile

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

126 timezone.activate(up.timezone)

127 activated = True

128 else:

129 logger.warning('User profile timezone missing so user.profile.timezone could not be activated')

130 else:

131 logger.warning('User profile missing so user.profile.timezone could not be activated')

132

133 # get response

134 response = self.get_response(request)

135

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

137 # the view is called.

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

139 timezone.deactivate()

140 return response