Coverage for benefits / core / admin / users.py: 100%

50 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-22 19:08 +0000

1import logging 

2 

3from django.conf import settings 

4from django.contrib import admin 

5from django.contrib.auth.models import Group, User 

6from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin, UserAdmin as BaseUserAdmin 

7 

8import requests 

9 

10from benefits.core.admin.mixins import StaffPermissionMixin 

11 

12 

13logger = logging.getLogger(__name__) 

14 

15 

16GOOGLE_USER_INFO_URL = "https://www.googleapis.com/oauth2/v3/userinfo" 

17 

18 

19# We unregister and re-register both User and Group admins to hide 

20# the database-level "permissions" fields, making our ModelAdmin 

21# mixins the single source of truth. 

22# 

23# For GroupAdmin, we can just use `exclude` because its default form 

24# is simple and doesn't use `fieldsets`. 

25# 

26# For UserAdmin, we must override `get_fieldsets()` because: 

27# 1. The default UserAdmin uses `fieldsets`. 

28# 2. `fieldsets` takes precedence over `exclude`. 

29admin.site.unregister(Group) 

30admin.site.unregister(User) 

31 

32 

33@admin.register(Group) 

34class GroupAdmin(StaffPermissionMixin, BaseGroupAdmin): 

35 # This will remove the "Permissions" multi-select box 

36 # from the Group change page. 

37 exclude = ("permissions",) 

38 

39 

40@admin.register(User) 

41class UserAdmin(StaffPermissionMixin, BaseUserAdmin): 

42 def get_fieldsets(self, request, obj=None): 

43 # get the default fieldsets 

44 # ensures we get any new fields from future Django versions 

45 fieldsets = super().get_fieldsets(request, obj) 

46 # Build a set of fields to remove from the "Permissions" section 

47 fields_to_remove = set() 

48 fields_to_remove.add("user_permissions") 

49 if not request.user.is_superuser: 

50 fields_to_remove.add("is_superuser") 

51 # create a new list of fieldsets to return 

52 new_fieldsets = [] 

53 for name, options in fieldsets: 

54 # find the 'Permissions' fieldset 

55 if name == "Permissions": 

56 # copy the fields, but filter out 'user_permissions' 

57 new_fields = tuple(f for f in options.get("fields", ()) if f not in fields_to_remove) 

58 options["fields"] = new_fields 

59 # append the (potentially modified) options for this fieldset 

60 new_fieldsets.append((name, options)) 

61 

62 return new_fieldsets 

63 

64 

65def add_google_sso_userinfo(user, request): 

66 token = request.session.get("google_sso_access_token") 

67 if token: 

68 headers = { 

69 "Authorization": f"Bearer {token}", 

70 } 

71 

72 # Request Google user info to get name and email 

73 response = requests.get(GOOGLE_USER_INFO_URL, headers=headers, timeout=settings.REQUESTS_TIMEOUT) 

74 user_data = response.json() 

75 logger.debug(f"Updating user data from Google for user with email: {user_data['email']}") 

76 

77 user.first_name = user_data["given_name"] 

78 user.last_name = user_data["family_name"] 

79 user.username = user_data["email"] 

80 user.email = user_data["email"] 

81 user.save() 

82 else: 

83 logger.warning("google_sso_access_token not found in session.") 

84 

85 

86def add_staff_user_to_group(user, request): 

87 if user.email in settings.GOOGLE_SSO_STAFF_LIST: 

88 staff_group = Group.objects.get(name=settings.STAFF_GROUP_NAME) 

89 staff_group.user_set.add(user) 

90 

91 

92def pre_login_user(user, request): 

93 logger.debug(f"Running pre-login callback for user: {user.username}") 

94 add_google_sso_userinfo(user, request) 

95 add_staff_user_to_group(user, request)