Coverage for paperless/signals.py: 21%

49 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 09:07 +0000

1import logging 

2 

3from django.conf import settings 

4from python_ipware import IpWare 

5 

6logger = logging.getLogger("paperless.auth") 

7 

8 

9# https://docs.djangoproject.com/en/4.1/ref/contrib/auth/#django.contrib.auth.signals.user_login_failed 

10def handle_failed_login(sender, credentials, request, **kwargs): 

11 ipware = IpWare(proxy_list=settings.TRUSTED_PROXIES) 

12 client_ip, _ = ipware.get_client_ip( 

13 meta=request.META, 

14 ) 

15 username = credentials.get("username") 

16 log_output = ( 

17 "No authentication provided" 

18 if username is None 

19 else f"Login failed for user `{username}`" 

20 ) 

21 

22 if client_ip is None: 22 ↛ 23line 22 didn't jump to line 23 because the condition on line 22 was never true

23 log_output += ". Unable to determine IP address." 

24 else: 

25 if client_ip.is_global: 25 ↛ 27line 25 didn't jump to line 27 because the condition on line 25 was never true

26 # We got the client's IP address 

27 log_output += f" from IP `{client_ip}`." 

28 else: 

29 # The client's IP address is private 

30 log_output += f" from private IP `{client_ip}`." 

31 

32 logger.info(log_output) 

33 

34 

35def handle_social_account_updated(sender, request, sociallogin, **kwargs): 

36 """ 

37 Handle the social account update signal. 

38 """ 

39 from django.contrib.auth.models import Group 

40 

41 if not sociallogin.user.is_active: 

42 # allauth looks up and updates the social account, firing this 

43 # signal, before checking if the user is allowed to actually log 

44 # in. Syncing groups/roles here would arm a deactivated account 

45 # with permissions it never exercised, which would silently take 

46 # effect if the account is later reactivated for an unrelated 

47 # reason. 

48 logger.debug( 

49 f"Skipping social account sync for inactive user `{sociallogin.user}`", 

50 ) 

51 return 

52 

53 extra_data = sociallogin.account.extra_data or {} 

54 social_account_groups = extra_data.get( 

55 settings.SOCIAL_ACCOUNT_SYNC_GROUPS_CLAIM, 

56 [], 

57 ) # pre-allauth 65.11.0 structure 

58 

59 if not social_account_groups: 

60 # allauth 65.11.0+ nests claims under `userinfo`/`id_token` 

61 social_account_groups = ( 

62 extra_data.get("userinfo", {}).get( 

63 settings.SOCIAL_ACCOUNT_SYNC_GROUPS_CLAIM, 

64 ) 

65 or extra_data.get("id_token", {}).get( 

66 settings.SOCIAL_ACCOUNT_SYNC_GROUPS_CLAIM, 

67 ) 

68 or [] 

69 ) 

70 

71 if isinstance(social_account_groups, str): 

72 social_account_groups = [social_account_groups] 

73 

74 if settings.SOCIAL_ACCOUNT_SYNC_GROUPS and social_account_groups is not None: 

75 groups = Group.objects.filter(name__in=social_account_groups) 

76 logger.debug( 

77 f"Syncing groups for user `{sociallogin.user}`: {social_account_groups}", 

78 ) 

79 sociallogin.user.groups.set(groups, clear=True) 

80 

81 modified_fields = [] 

82 if settings.SOCIAL_ACCOUNT_SYNC_SUPERUSER_GROUP: 

83 is_superuser = ( 

84 settings.SOCIAL_ACCOUNT_SYNC_SUPERUSER_GROUP in social_account_groups 

85 ) 

86 if sociallogin.user.is_superuser != is_superuser: 

87 sociallogin.user.is_superuser = is_superuser 

88 modified_fields.append("is_superuser") 

89 

90 if settings.SOCIAL_ACCOUNT_SYNC_STAFF_GROUP: 

91 is_staff = ( 

92 settings.SOCIAL_ACCOUNT_SYNC_STAFF_GROUP in social_account_groups 

93 ) or sociallogin.user.is_superuser 

94 if sociallogin.user.is_staff != is_staff: 

95 sociallogin.user.is_staff = is_staff 

96 modified_fields.append("is_staff") 

97 elif settings.SOCIAL_ACCOUNT_SYNC_SUPERUSER_GROUP: 

98 is_staff = sociallogin.user.is_superuser or sociallogin.user.is_staff 

99 if sociallogin.user.is_staff != is_staff: 

100 sociallogin.user.is_staff = is_staff 

101 modified_fields.append("is_staff") 

102 

103 if modified_fields: 

104 logger.debug( 

105 f"Syncing roles for user `{sociallogin.user}`: superuser={sociallogin.user.is_superuser}, staff={sociallogin.user.is_staff}", 

106 ) 

107 sociallogin.user.save(update_fields=modified_fields)