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

50 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-13 19:35 +0000

1import logging 

2 

3import requests 

4from django.conf import settings 

5from django.contrib import admin 

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

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

8 

9from benefits.core.admin.mixins import StaffPermissionMixin 

10 

11logger = logging.getLogger(__name__) 

12 

13 

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

15 

16 

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

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

19# mixins the single source of truth. 

20# 

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

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

23# 

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

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

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

27admin.site.unregister(Group) 

28admin.site.unregister(User) 

29 

30 

31@admin.register(Group) 

32class GroupAdmin(StaffPermissionMixin, BaseGroupAdmin): 

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

34 # from the Group change page. 

35 exclude = ("permissions",) 

36 

37 

38@admin.register(User) 

39class UserAdmin(StaffPermissionMixin, BaseUserAdmin): 

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

41 # get the default fieldsets 

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

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

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

45 fields_to_remove = set() 

46 fields_to_remove.add("user_permissions") 

47 if not request.user.is_superuser: 

48 fields_to_remove.add("is_superuser") 

49 # create a new list of fieldsets to return 

50 new_fieldsets = [] 

51 for name, options in fieldsets: 

52 # find the 'Permissions' fieldset 

53 if name == "Permissions": 

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

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

56 options["fields"] = new_fields 

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

58 new_fieldsets.append((name, options)) 

59 

60 return new_fieldsets 

61 

62 

63def add_google_sso_userinfo(user, request): 

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

65 if token: 

66 headers = { 

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

68 } 

69 

70 # Request Google user info to get name and email 

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

72 user_data = response.json() 

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

74 

75 user.first_name = user_data["given_name"] 

76 user.last_name = user_data["family_name"] 

77 user.username = user_data["email"] 

78 user.email = user_data["email"] 

79 user.save() 

80 else: 

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

82 

83 

84def add_staff_user_to_group(user, request): 

85 if user.email in settings.GOOGLE_SSO_STAFF_LIST: 

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

87 staff_group.user_set.add(user) 

88 

89 

90def pre_login_user(user, request): 

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

92 add_google_sso_userinfo(user, request) 

93 add_staff_user_to_group(user, request)