Coverage for benefits/core/admin/enrollment.py: 89%
104 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-13 23:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-13 23:09 +0000
1from django import forms
2from django.conf import settings
3from django.core.exceptions import ValidationError
4from django.contrib import admin
5from django.http import HttpRequest
7from adminsortable2.admin import SortableAdminMixin
9from benefits.core import models
10from .users import is_staff_member_or_superuser
13@admin.register(models.EnrollmentEvent)
14class EnrollmentEventAdmin(admin.ModelAdmin):
15 list_display = ("enrollment_datetime", "transit_agency", "enrollment_flow", "enrollment_method", "verified_by")
17 def has_add_permission(self, request: HttpRequest, obj=None):
18 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD:
19 return False
20 elif request.user and is_staff_member_or_superuser(request.user): 20 ↛ 23line 20 didn't jump to line 23 because the condition on line 20 was always true
21 return True
22 else:
23 return False
25 def has_change_permission(self, request: HttpRequest, obj=None):
26 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD:
27 return False
28 elif request.user and request.user.is_superuser:
29 return True
30 else:
31 return False
33 def has_delete_permission(self, request: HttpRequest, obj=None):
34 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD: 34 ↛ 35line 34 didn't jump to line 35 because the condition on line 34 was never true
35 return False
36 elif request.user and is_staff_member_or_superuser(request.user): 36 ↛ 39line 36 didn't jump to line 39 because the condition on line 36 was always true
37 return True
38 else:
39 return False
41 def has_view_permission(self, request: HttpRequest, obj=None):
42 if request.user and is_staff_member_or_superuser(request.user): 42 ↛ 45line 42 didn't jump to line 45 because the condition on line 42 was always true
43 return True
44 else:
45 return False
48class EnrollmentFlowForm(forms.ModelForm):
49 def has_field(self, field_name):
50 return self.fields.get(field_name) is not None
52 def get(self, cleaned_data, field_name):
53 """
54 If the field is present on the form, simply get the value from the cleaned_data.
56 If the field is not present on the form, that means the user doesn't have access to the field,
57 so get the value from the form's instance of the object.
58 """
59 return cleaned_data.get(field_name) if self.has_field(field_name) else getattr(self.instance, field_name)
61 def clean(self):
62 cleaned_data = super().clean()
64 field_errors = {}
65 non_field_errors = []
67 supports_expiration = cleaned_data.get("supports_expiration")
69 if supports_expiration:
70 expiration_days = cleaned_data.get("expiration_days")
71 expiration_reenrollment_days = cleaned_data.get("expiration_reenrollment_days")
72 reenrollment_error_template = self.get(cleaned_data, "reenrollment_error_template")
74 message = "When support_expiration is True, this value must be greater than 0."
75 if expiration_days is None or expiration_days <= 0:
76 field_errors.update(expiration_days=ValidationError(message))
77 if expiration_reenrollment_days is None or expiration_reenrollment_days <= 0:
78 field_errors.update(expiration_reenrollment_days=ValidationError(message))
79 if not reenrollment_error_template:
80 message = "Required when supports expiration is True"
81 field_name = "reenrollment_error_template"
82 if self.has_field(field_name):
83 field_errors.update(reenrollment_error_template=ValidationError(f"{message}."))
84 else:
85 non_field_errors.append(ValidationError(f"{message}: {field_name}"))
87 transit_agency = cleaned_data.get("transit_agency")
89 if transit_agency:
90 # these fields might not be on the form, so use helper method to correctly get the value
91 eligibility_api_url = self.get(cleaned_data, "eligibility_api_url")
92 eligibility_form_class = self.get(cleaned_data, "eligibility_form_class")
94 if cleaned_data.get("claims_provider"):
95 message = "Required for claims verification"
96 needed = dict(
97 claims_scope=cleaned_data.get("claims_scope"),
98 claims_eligibility_claim=cleaned_data.get("claims_eligibility_claim"),
99 )
100 for k, v in needed.items():
101 if self.has_field(k) and not v:
102 field_errors.update({k: ValidationError(f"{message}.")})
103 elif not v: 103 ↛ 104line 103 didn't jump to line 104 because the condition on line 103 was never true
104 non_field_errors.append(ValidationError(f"{message}: {k}"))
105 elif eligibility_api_url and eligibility_form_class:
106 message = "Required for Eligibility API verification."
107 needed = dict(
108 eligibility_api_auth_header=self.get(cleaned_data, "eligibility_api_auth_header"),
109 eligibility_api_auth_key_secret_name=self.get(cleaned_data, "eligibility_api_auth_key_secret_name"),
110 eligibility_api_jwe_cek_enc=self.get(cleaned_data, "eligibility_api_jwe_cek_enc"),
111 eligibility_api_jwe_encryption_alg=self.get(cleaned_data, "eligibility_api_jwe_encryption_alg"),
112 eligibility_api_jws_signing_alg=self.get(cleaned_data, "eligibility_api_jws_signing_alg"),
113 eligibility_api_public_key=self.get(cleaned_data, "eligibility_api_public_key"),
114 )
115 for k, v in needed.items():
116 if self.has_field(k) and not v: 116 ↛ 118line 116 didn't jump to line 118 because the condition on line 116 was always true
117 field_errors.update({k: ValidationError(f"{message}.")})
118 elif not v:
119 non_field_errors.append(ValidationError(f"{message}: {k}"))
120 else:
121 message = (
122 "Must configure either claims verification or Eligibility API verification before"
123 + " adding to a transit agency."
124 )
125 non_field_errors.append(ValidationError(message))
127 if field_errors:
128 raise ValidationError(field_errors)
129 if non_field_errors:
130 raise ValidationError(non_field_errors)
133@admin.register(models.EnrollmentFlow)
134class SortableEnrollmentFlowAdmin(SortableAdminMixin, admin.ModelAdmin):
135 list_display = ("label", "transit_agency", "supported_enrollment_methods")
136 form = EnrollmentFlowForm
138 def get_exclude(self, request, obj=None):
139 fields = []
141 if not request.user.is_superuser:
142 fields.extend(
143 [
144 "eligibility_api_auth_header",
145 "eligibility_api_auth_key_secret_name",
146 "eligibility_api_public_key",
147 "eligibility_api_jwe_cek_enc",
148 "eligibility_api_jwe_encryption_alg",
149 "eligibility_api_jws_signing_alg",
150 ]
151 )
153 return fields or super().get_exclude(request, obj)
155 def get_readonly_fields(self, request, obj=None):
156 fields = []
158 if not request.user.is_superuser:
159 fields.extend(
160 [
161 "eligibility_api_url",
162 "eligibility_form_class",
163 "selection_label_template_override",
164 "eligibility_start_template_override",
165 "eligibility_unverified_template_override",
166 "help_template",
167 "enrollment_index_template_override",
168 "reenrollment_error_template",
169 "enrollment_success_template_override",
170 ]
171 )
173 return fields or super().get_readonly_fields(request, obj)
175 def has_add_permission(self, request: HttpRequest, obj=None):
176 if settings.RUNTIME_ENVIRONMENT() != settings.RUNTIME_ENVS.PROD:
177 return True
178 elif request.user and is_staff_member_or_superuser(request.user): 178 ↛ 181line 178 didn't jump to line 181 because the condition on line 178 was always true
179 return True
180 else:
181 return False