@@ -2016,6 +2016,32 @@ def filter_mitigated_on(self, queryset, name, value):
20162016 return queryset .filter (mitigated = value )
20172017
20182018
2019+ def get_finding_group_queryset_for_context (pid = None , eid = None , tid = None ):
2020+ """
2021+ Helper function to build finding group queryset based on context hierarchy.
2022+ Context priority: test > engagement > product > global
2023+
2024+ Args:
2025+ pid: Product ID (least specific)
2026+ eid: Engagement ID
2027+ tid: Test ID (most specific)
2028+
2029+ Returns:
2030+ QuerySet of Finding_Group filtered by context
2031+ """
2032+ if tid is not None :
2033+ # Most specific: filter by test
2034+ return Finding_Group .objects .filter (test_id = tid ).only ("id" , "name" )
2035+ if eid is not None :
2036+ # Filter by engagement's tests
2037+ return Finding_Group .objects .filter (test__engagement_id = eid ).only ("id" , "name" )
2038+ if pid is not None :
2039+ # Filter by product's tests
2040+ return Finding_Group .objects .filter (test__engagement__product_id = pid ).only ("id" , "name" )
2041+ # Global: return all (authorization will be applied separately)
2042+ return Finding_Group .objects .all ().only ("id" , "name" )
2043+
2044+
20192045class FindingFilterWithoutObjectLookups (FindingFilterHelper , FindingTagStringFilter ):
20202046 test__engagement__product__prod_type = NumberFilter (widget = HiddenInput ())
20212047 test__engagement__product = NumberFilter (widget = HiddenInput ())
@@ -2107,20 +2133,45 @@ class Meta:
21072133 def __init__ (self , * args , ** kwargs ):
21082134 self .user = None
21092135 self .pid = None
2136+ self .eid = None
2137+ self .tid = None
21102138 if "user" in kwargs :
21112139 self .user = kwargs .pop ("user" )
21122140
21132141 if "pid" in kwargs :
21142142 self .pid = kwargs .pop ("pid" )
2143+ if "eid" in kwargs :
2144+ self .eid = kwargs .pop ("eid" )
2145+ if "tid" in kwargs :
2146+ self .tid = kwargs .pop ("tid" )
21152147 super ().__init__ (* args , ** kwargs )
21162148 # Set some date fields
21172149 self .set_date_fields (* args , ** kwargs )
2118- # Don't show the product filter on the product finding view
2119- if self .pid :
2120- del self .form .fields ["test__engagement__product__name" ]
2121- del self .form .fields ["test__engagement__product__name_contains" ]
2122- del self .form .fields ["test__engagement__product__prod_type__name" ]
2123- del self .form .fields ["test__engagement__product__prod_type__name_contains" ]
2150+ # Don't show the product/engagement/test filter fields when in specific context
2151+ if self .tid or self .eid or self .pid :
2152+ if "test__engagement__product__name" in self .form .fields :
2153+ del self .form .fields ["test__engagement__product__name" ]
2154+ if "test__engagement__product__name_contains" in self .form .fields :
2155+ del self .form .fields ["test__engagement__product__name_contains" ]
2156+ if "test__engagement__product__prod_type__name" in self .form .fields :
2157+ del self .form .fields ["test__engagement__product__prod_type__name" ]
2158+ if "test__engagement__product__prod_type__name_contains" in self .form .fields :
2159+ del self .form .fields ["test__engagement__product__prod_type__name_contains" ]
2160+ # Also hide engagement and test fields if in test or engagement context
2161+ if self .tid :
2162+ if "test__engagement__name" in self .form .fields :
2163+ del self .form .fields ["test__engagement__name" ]
2164+ if "test__engagement__name_contains" in self .form .fields :
2165+ del self .form .fields ["test__engagement__name_contains" ]
2166+ if "test__name" in self .form .fields :
2167+ del self .form .fields ["test__name" ]
2168+ if "test__name_contains" in self .form .fields :
2169+ del self .form .fields ["test__name_contains" ]
2170+ elif self .eid :
2171+ if "test__engagement__name" in self .form .fields :
2172+ del self .form .fields ["test__engagement__name" ]
2173+ if "test__engagement__name_contains" in self .form .fields :
2174+ del self .form .fields ["test__engagement__name_contains" ]
21242175
21252176
21262177class FindingFilter (FindingFilterHelper , FindingTagFilter ):
@@ -2159,29 +2210,57 @@ class Meta:
21592210 def __init__ (self , * args , ** kwargs ):
21602211 self .user = None
21612212 self .pid = None
2213+ self .eid = None
2214+ self .tid = None
21622215 if "user" in kwargs :
21632216 self .user = kwargs .pop ("user" )
21642217
21652218 if "pid" in kwargs :
21662219 self .pid = kwargs .pop ("pid" )
2220+ if "eid" in kwargs :
2221+ self .eid = kwargs .pop ("eid" )
2222+ if "tid" in kwargs :
2223+ self .tid = kwargs .pop ("tid" )
21672224 super ().__init__ (* args , ** kwargs )
21682225 # Set some date fields
21692226 self .set_date_fields (* args , ** kwargs )
21702227 # Don't show the product filter on the product finding view
21712228 self .set_related_object_fields (* args , ** kwargs )
21722229
21732230 def set_related_object_fields (self , * args : list , ** kwargs : dict ):
2174- finding_group_query = Finding_Group .objects .all ()
2175- if self .pid is not None :
2231+ # Use helper to get contextual finding group queryset
2232+ finding_group_query = get_finding_group_queryset_for_context (
2233+ pid = self .pid ,
2234+ eid = self .eid ,
2235+ tid = self .tid ,
2236+ )
2237+
2238+ # Filter by most specific context: test > engagement > product
2239+ if self .tid is not None :
2240+ # Test context: filter finding groups by test
2241+ del self .form .fields ["test__engagement__product" ]
2242+ del self .form .fields ["test__engagement__product__prod_type" ]
2243+ del self .form .fields ["test__engagement" ]
2244+ del self .form .fields ["test" ]
2245+ elif self .eid is not None :
2246+ # Engagement context: filter finding groups by engagement
2247+ del self .form .fields ["test__engagement__product" ]
2248+ del self .form .fields ["test__engagement__product__prod_type" ]
2249+ del self .form .fields ["test__engagement" ]
2250+ # Filter tests by engagement - get_authorized_tests doesn't support engagement param
2251+ engagement = Engagement .objects .get (id = self .eid )
2252+ self .form .fields ["test" ].queryset = get_authorized_tests (Permissions .Test_View , product = engagement .product ).filter (engagement_id = self .eid ).prefetch_related ("test_type" )
2253+ elif self .pid is not None :
2254+ # Product context: filter finding groups by product
21762255 del self .form .fields ["test__engagement__product" ]
21772256 del self .form .fields ["test__engagement__product__prod_type" ]
21782257 # TODO: add authorized check to be sure
21792258 self .form .fields ["test__engagement" ].queryset = Engagement .objects .filter (
21802259 product_id = self .pid ,
21812260 ).all ()
21822261 self .form .fields ["test" ].queryset = get_authorized_tests (Permissions .Test_View , product = self .pid ).prefetch_related ("test_type" )
2183- finding_group_query = Finding_Group .objects .filter (test__engagement__product_id = self .pid )
21842262 else :
2263+ # Global context: show all authorized finding groups
21852264 self .form .fields [
21862265 "test__engagement__product__prod_type" ].queryset = get_authorized_product_types (Permissions .Product_Type_View )
21872266 self .form .fields ["test__engagement" ].queryset = get_authorized_engagements (Permissions .Engagement_View )
@@ -2190,7 +2269,7 @@ def set_related_object_fields(self, *args: list, **kwargs: dict):
21902269 if self .form .fields .get ("test__engagement__product" ):
21912270 self .form .fields ["test__engagement__product" ].queryset = get_authorized_products (Permissions .Product_View )
21922271 if self .form .fields .get ("finding_group" , None ):
2193- self .form .fields ["finding_group" ].queryset = get_authorized_finding_groups_for_queryset (Permissions .Finding_Group_View , finding_group_query )
2272+ self .form .fields ["finding_group" ].queryset = get_authorized_finding_groups_for_queryset (Permissions .Finding_Group_View , finding_group_query , user = self . user )
21942273 self .form .fields ["reporter" ].queryset = get_authorized_users (Permissions .Finding_View )
21952274 self .form .fields ["reviewers" ].queryset = self .form .fields ["reporter" ].queryset
21962275
0 commit comments