@@ -2020,6 +2020,33 @@ def filter_mitigated_on(self, queryset, name, value):
20202020 return queryset .filter (mitigated = value )
20212021
20222022
2023+ def get_finding_group_queryset_for_context (pid = None , eid = None , tid = None ):
2024+ """
2025+ Helper function to build finding group queryset based on context hierarchy.
2026+ Context priority: test > engagement > product > global
2027+
2028+ Args:
2029+ pid: Product ID (least specific)
2030+ eid: Engagement ID
2031+ tid: Test ID (most specific)
2032+
2033+ Returns:
2034+ QuerySet of Finding_Group filtered by context
2035+
2036+ """
2037+ if tid is not None :
2038+ # Most specific: filter by test
2039+ return Finding_Group .objects .filter (test_id = tid ).only ("id" , "name" )
2040+ if eid is not None :
2041+ # Filter by engagement's tests
2042+ return Finding_Group .objects .filter (test__engagement_id = eid ).only ("id" , "name" )
2043+ if pid is not None :
2044+ # Filter by product's tests
2045+ return Finding_Group .objects .filter (test__engagement__product_id = pid ).only ("id" , "name" )
2046+ # Global: return all (authorization will be applied separately)
2047+ return Finding_Group .objects .all ().only ("id" , "name" )
2048+
2049+
20232050class FindingFilterWithoutObjectLookups (FindingFilterHelper , FindingTagStringFilter ):
20242051 test__engagement__product__prod_type = NumberFilter (widget = HiddenInput ())
20252052 test__engagement__product = NumberFilter (widget = HiddenInput ())
@@ -2111,20 +2138,45 @@ class Meta:
21112138 def __init__ (self , * args , ** kwargs ):
21122139 self .user = None
21132140 self .pid = None
2141+ self .eid = None
2142+ self .tid = None
21142143 if "user" in kwargs :
21152144 self .user = kwargs .pop ("user" )
21162145
21172146 if "pid" in kwargs :
21182147 self .pid = kwargs .pop ("pid" )
2148+ if "eid" in kwargs :
2149+ self .eid = kwargs .pop ("eid" )
2150+ if "tid" in kwargs :
2151+ self .tid = kwargs .pop ("tid" )
21192152 super ().__init__ (* args , ** kwargs )
21202153 # Set some date fields
21212154 self .set_date_fields (* args , ** kwargs )
2122- # Don't show the product filter on the product finding view
2123- if self .pid :
2124- del self .form .fields ["test__engagement__product__name" ]
2125- del self .form .fields ["test__engagement__product__name_contains" ]
2126- del self .form .fields ["test__engagement__product__prod_type__name" ]
2127- del self .form .fields ["test__engagement__product__prod_type__name_contains" ]
2155+ # Don't show the product/engagement/test filter fields when in specific context
2156+ if self .tid or self .eid or self .pid :
2157+ if "test__engagement__product__name" in self .form .fields :
2158+ del self .form .fields ["test__engagement__product__name" ]
2159+ if "test__engagement__product__name_contains" in self .form .fields :
2160+ del self .form .fields ["test__engagement__product__name_contains" ]
2161+ if "test__engagement__product__prod_type__name" in self .form .fields :
2162+ del self .form .fields ["test__engagement__product__prod_type__name" ]
2163+ if "test__engagement__product__prod_type__name_contains" in self .form .fields :
2164+ del self .form .fields ["test__engagement__product__prod_type__name_contains" ]
2165+ # Also hide engagement and test fields if in test or engagement context
2166+ if self .tid :
2167+ if "test__engagement__name" in self .form .fields :
2168+ del self .form .fields ["test__engagement__name" ]
2169+ if "test__engagement__name_contains" in self .form .fields :
2170+ del self .form .fields ["test__engagement__name_contains" ]
2171+ if "test__name" in self .form .fields :
2172+ del self .form .fields ["test__name" ]
2173+ if "test__name_contains" in self .form .fields :
2174+ del self .form .fields ["test__name_contains" ]
2175+ elif self .eid :
2176+ if "test__engagement__name" in self .form .fields :
2177+ del self .form .fields ["test__engagement__name" ]
2178+ if "test__engagement__name_contains" in self .form .fields :
2179+ del self .form .fields ["test__engagement__name_contains" ]
21282180
21292181
21302182class FindingFilter (FindingFilterHelper , FindingTagFilter ):
@@ -2163,38 +2215,79 @@ class Meta:
21632215 def __init__ (self , * args , ** kwargs ):
21642216 self .user = None
21652217 self .pid = None
2218+ self .eid = None
2219+ self .tid = None
21662220 if "user" in kwargs :
21672221 self .user = kwargs .pop ("user" )
21682222
21692223 if "pid" in kwargs :
21702224 self .pid = kwargs .pop ("pid" )
2225+ if "eid" in kwargs :
2226+ self .eid = kwargs .pop ("eid" )
2227+ if "tid" in kwargs :
2228+ self .tid = kwargs .pop ("tid" )
21712229 super ().__init__ (* args , ** kwargs )
21722230 # Set some date fields
21732231 self .set_date_fields (* args , ** kwargs )
21742232 # Don't show the product filter on the product finding view
21752233 self .set_related_object_fields (* args , ** kwargs )
21762234
21772235 def set_related_object_fields (self , * args : list , ** kwargs : dict ):
2178- finding_group_query = Finding_Group .objects .all ()
2179- if self .pid is not None :
2180- del self .form .fields ["test__engagement__product" ]
2181- del self .form .fields ["test__engagement__product__prod_type" ]
2236+ # Use helper to get contextual finding group queryset
2237+ finding_group_query = get_finding_group_queryset_for_context (
2238+ pid = self .pid ,
2239+ eid = self .eid ,
2240+ tid = self .tid ,
2241+ )
2242+
2243+ # Filter by most specific context: test > engagement > product
2244+ if self .tid is not None :
2245+ # Test context: filter finding groups by test
2246+ if "test__engagement__product" in self .form .fields :
2247+ del self .form .fields ["test__engagement__product" ]
2248+ if "test__engagement__product__prod_type" in self .form .fields :
2249+ del self .form .fields ["test__engagement__product__prod_type" ]
2250+ if "test__engagement" in self .form .fields :
2251+ del self .form .fields ["test__engagement" ]
2252+ if "test" in self .form .fields :
2253+ del self .form .fields ["test" ]
2254+ elif self .eid is not None :
2255+ # Engagement context: filter finding groups by engagement
2256+ if "test__engagement__product" in self .form .fields :
2257+ del self .form .fields ["test__engagement__product" ]
2258+ if "test__engagement__product__prod_type" in self .form .fields :
2259+ del self .form .fields ["test__engagement__product__prod_type" ]
2260+ if "test__engagement" in self .form .fields :
2261+ del self .form .fields ["test__engagement" ]
2262+ # Filter tests by engagement - get_authorized_tests doesn't support engagement param
2263+ engagement = Engagement .objects .filter (id = self .eid ).select_related ("product" ).first ()
2264+ if engagement :
2265+ self .form .fields ["test" ].queryset = get_authorized_tests (Permissions .Test_View , product = engagement .product ).filter (engagement_id = self .eid ).prefetch_related ("test_type" )
2266+ elif self .pid is not None :
2267+ # Product context: filter finding groups by product
2268+ if "test__engagement__product" in self .form .fields :
2269+ del self .form .fields ["test__engagement__product" ]
2270+ if "test__engagement__product__prod_type" in self .form .fields :
2271+ del self .form .fields ["test__engagement__product__prod_type" ]
21822272 # TODO: add authorized check to be sure
2183- self .form .fields ["test__engagement" ].queryset = Engagement .objects .filter (
2184- product_id = self .pid ,
2185- ).all ()
2186- self .form .fields ["test" ].queryset = get_authorized_tests (Permissions .Test_View , product = self .pid ).prefetch_related ("test_type" )
2187- finding_group_query = Finding_Group .objects .filter (test__engagement__product_id = self .pid )
2273+ if "test__engagement" in self .form .fields :
2274+ self .form .fields ["test__engagement" ].queryset = Engagement .objects .filter (
2275+ product_id = self .pid ,
2276+ ).all ()
2277+ if "test" in self .form .fields :
2278+ self .form .fields ["test" ].queryset = get_authorized_tests (Permissions .Test_View , product = self .pid ).prefetch_related ("test_type" )
21882279 else :
2280+ # Global context: show all authorized finding groups
21892281 self .form .fields [
21902282 "test__engagement__product__prod_type" ].queryset = get_authorized_product_types (Permissions .Product_Type_View )
21912283 self .form .fields ["test__engagement" ].queryset = get_authorized_engagements (Permissions .Engagement_View )
2192- del self .form .fields ["test" ]
2284+ if "test" in self .form .fields :
2285+ del self .form .fields ["test" ]
21932286
21942287 if self .form .fields .get ("test__engagement__product" ):
21952288 self .form .fields ["test__engagement__product" ].queryset = get_authorized_products (Permissions .Product_View )
21962289 if self .form .fields .get ("finding_group" , None ):
2197- self .form .fields ["finding_group" ].queryset = get_authorized_finding_groups_for_queryset (Permissions .Finding_Group_View , finding_group_query )
2290+ self .form .fields ["finding_group" ].queryset = get_authorized_finding_groups_for_queryset (Permissions .Finding_Group_View , finding_group_query , user = self . user )
21982291 self .form .fields ["reporter" ].queryset = get_authorized_users (Permissions .Finding_View )
21992292 self .form .fields ["reviewers" ].queryset = self .form .fields ["reporter" ].queryset
22002293
0 commit comments