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
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-22 19:08 +0000
1import logging
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
8import requests
10from benefits.core.admin.mixins import StaffPermissionMixin
13logger = logging.getLogger(__name__)
16GOOGLE_USER_INFO_URL = "https://www.googleapis.com/oauth2/v3/userinfo"
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)
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",)
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))
62 return new_fieldsets
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 }
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']}")
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.")
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)
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)