@@ -224,7 +224,8 @@ def create_option(
224224 # label_from_instance() on WidgetRenderedModelMultipleChoiceField returns the
225225 # full object, not a label, this is what makes this work.
226226 obj = label
227- is_appeal = obj .is_appeal
227+ is_developer_appeal = obj .is_developer_appeal
228+ is_reporter_appeal = not is_developer_appeal and obj .is_appeal
228229 queue_moves = list (obj .queue_moves .order_by ('-created' ))
229230 requeued_decisions = list (
230231 obj .decisions .filter (action = DECISION_ACTIONS .AMO_REQUEUE ).order_by (
@@ -261,10 +262,9 @@ def create_option(
261262 for appealed_decision in obj .appealed_decisions .all ()
262263 for appeal_obj in appealed_decision .appeals .all ()
263264 )
264- if is_appeal
265+ if is_reporter_appeal or is_developer_appeal
265266 else ()
266267 )
267- is_developer_appeal = is_appeal and obj .is_developer_appeal
268268 subtexts_gen = [
269269 * internal_notes ,
270270 * (
@@ -278,7 +278,7 @@ def create_option(
278278 '<details><summary>Show detail on {} reports</summary><ul>{}</ul>'
279279 '</details>' ,
280280 format_datetime (obj .created ),
281- '[Appeal] ' if is_appeal else '' ,
281+ '[Appeal] ' if ( is_reporter_appeal or is_developer_appeal ) else '' ,
282282 format_html ('[Forwarded on {}] ' , format_datetime (forwarded ))
283283 if forwarded
284284 else '' ,
@@ -292,21 +292,25 @@ def create_option(
292292 )
293293
294294 attrs = attrs or {}
295- # Reviewers shouldn't use resolve_appeal_job to resolve "regular" jobs,
295+ # Reviewers shouldn't use appeal_deny to resolve "regular" jobs,
296296 # and conversely shouldn't use resolve_reports_job to resolve appeals,
297297 # as resolving appeals is a bit more involved.
298298 # On top of that, they shouldn't resolve *developer* appeals when
299299 # rejecting versions: that would cause the rejection to be no-op and
300300 # that's not always what we want.
301301 # The parent element will have `data-toggle-hide`, so data-value is
302302 # used to hide actions that are not supposed to be used for this job.
303- hide_for_these_actions = [
304- 'resolve_appeal_job' if not is_appeal else 'resolve_reports_job'
305- ]
306- if is_developer_appeal :
307- hide_for_these_actions .extend (
308- ('review_with_policy' , 'reject' , 'reject_multiple_versions' )
309- )
303+ if is_reporter_appeal :
304+ hide_for_these_actions = ['appeal_override' , 'resolve_reports_job' ]
305+ elif is_developer_appeal :
306+ hide_for_these_actions = [
307+ 'review_with_policy' ,
308+ 'reject' ,
309+ 'reject_multiple_versions' ,
310+ 'resolve_reports_job' ,
311+ ]
312+ else :
313+ hide_for_these_actions = ['appeal_deny' , 'appeal_override' ]
310314 attrs ['data-value' ] = ' ' .join (hide_for_these_actions )
311315 return super ().create_option (
312316 name , value , label , selected , index , subindex , attrs
@@ -584,7 +588,7 @@ def is_valid(self):
584588 else :
585589 # we no longer strictly require comments with cinder policies
586590 self .fields ['comments' ].required = False
587- if selected_action == 'resolve_appeal_job ' :
591+ if selected_action == 'appeal_deny ' :
588592 self .fields ['appeal_action' ].required = True
589593 result = super ().is_valid ()
590594 if result :
@@ -600,27 +604,43 @@ def clean(self):
600604 selected_action = self .cleaned_data .get ('action' )
601605 selected_definition = self .helper .actions .get (selected_action , {})
602606 # If the user select a different type of job before changing actions there could
603- # be non-appeal jobs selected as cinder_jobs_to_resolve under resolve_appeal_job
607+ # be non-appeal jobs selected as cinder_jobs_to_resolve under appeal_deny
604608 # action, or appeal jobs under resolve_reports_job/a reject action. So filter
605609 # them out.
606- if selected_action == 'resolve_appeal_job' :
610+ require_jobs = False
611+ if selected_action == 'appeal_deny' :
607612 self .cleaned_data ['cinder_jobs_to_resolve' ] = [
608613 job
609614 for job in self .cleaned_data .get ('cinder_jobs_to_resolve' , ())
610615 if job .is_appeal
611616 ]
617+ require_jobs = True
618+ elif selected_action == 'appeal_override' :
619+ self .cleaned_data ['cinder_jobs_to_resolve' ] = [
620+ job
621+ for job in self .cleaned_data .get ('cinder_jobs_to_resolve' , ())
622+ if job .is_developer_appeal
623+ ]
624+ require_jobs = True
612625 elif selected_action == 'resolve_reports_job' :
613626 self .cleaned_data ['cinder_jobs_to_resolve' ] = [
614627 job
615628 for job in self .cleaned_data .get ('cinder_jobs_to_resolve' , ())
616629 if not job .is_appeal
617630 ]
618- elif selected_action in ('reject' , 'reject_multiple_versions' ):
631+ require_jobs = True
632+ elif selected_action in (
633+ 'reject' ,
634+ 'reject_multiple_versions' ,
635+ 'review_with_policy' ,
636+ ):
619637 self .cleaned_data ['cinder_jobs_to_resolve' ] = [
620638 job
621639 for job in self .cleaned_data .get ('cinder_jobs_to_resolve' , ())
622640 if not job .is_developer_appeal
623641 ]
642+ if require_jobs and not self .cleaned_data .get ('cinder_jobs_to_resolve' ):
643+ self .add_error ('cinder_jobs_to_resolve' , 'This field is required.' )
624644 is_policy_enforcement = selected_definition .get ('policy_enforcement' )
625645 if (
626646 is_policy_enforcement or self .cleaned_data .get ('cinder_jobs_to_resolve' )
@@ -648,23 +668,33 @@ def clean(self):
648668 'cinder_policies' ,
649669 'No policies selected with an associated cinder action.' ,
650670 )
651- elif not is_policy_enforcement and len (all_primary_actions ) > 1 :
652- self .add_error (
653- 'cinder_policies' ,
654- 'Multiple policies selected with different cinder actions.' ,
655- )
656671 elif any (len (actions ) != 1 for actions in all_primary_actions ):
657672 self .add_error (
658673 'cinder_policies' ,
659674 'Invalid policies selected with more than one primary enforcement '
660675 'action.' ,
661676 )
662677
663- if is_policy_enforcement :
664- # get the most aggressive negative policy
665- # TODO: if we expand to support non-negative policies, we'll need to
666- # change this logic (e.g. most_postive_actions, or something).
667- sorted_actions = sorted (
678+ if not is_policy_enforcement :
679+ if len (all_primary_actions ) > 1 :
680+ self .add_error (
681+ 'cinder_policies' ,
682+ 'Multiple policies selected with different cinder actions.' ,
683+ )
684+ else :
685+ negative_primary_actions = {
686+ ea
687+ for ea in all_primary_actions
688+ if len (ea ) and ea [0 ] in DECISION_ACTIONS .ADDON_NEGATIVE_SORTED
689+ }
690+ if not negative_primary_actions and len (all_primary_actions ) > 1 :
691+ self .add_error (
692+ 'cinder_policies' ,
693+ 'Selecting multiple policies selected with different '
694+ 'non-negative cinder actions is not supported.' ,
695+ )
696+
697+ srtd_actions = sorted (
668698 (
669699 filter_enforcement_actions (
670700 policy .split_enforcement_actions , Addon
@@ -675,11 +705,9 @@ def clean(self):
675705 reverse = True ,
676706 )
677707
678- if sorted_actions :
679- self .cleaned_data ['most_aggressive_policy_actions' ] = (
680- sorted_actions [0 ]
681- )
682- if self .cleaned_data ['most_aggressive_policy_actions' ].primary [
708+ if srtd_actions :
709+ self .cleaned_data ['most_important_policy_actions' ] = srtd_actions [0 ]
710+ if self .cleaned_data ['most_important_policy_actions' ].primary [
683711 0
684712 ] in DECISION_ACTIONS .VERSION_SPECIFIC and selected_definition .get (
685713 'multiple_versions'
@@ -691,10 +719,6 @@ def clean(self):
691719 # otherwise, don't confuse logging with versions
692720 self .cleaned_data ['versions' ] = []
693721
694- # TODO: once we support non-negative policies, we'll need to check that
695- # the policy selection is consistent - e.g. you shouldn't be able to
696- # select a positive and negative policy together
697-
698722 if selected_definition .get ('delayable' ):
699723 delayed_rejection = self .cleaned_data .get ('delayed_rejection' )
700724 delayed_rejection_date = self .cleaned_data .get ('delayed_rejection_date' )
0 commit comments