44 add_form_to_action ,
55 confirm_action ,
66)
7+ from django .conf import settings
78from django .contrib import admin
89from django .contrib .auth import get_permission_codename
10+ from django .core .cache import cache
911from django .db import models
1012from django .utils import timezone
1113from django_better_admin_arrayfield .admin .mixins import DynamicArrayMixin
1618from controller .sentry .models import App
1719from controller .sentry .utils import invalidate_cache
1820
21+ admin .site
22+
1923
2024@admin .register (App )
2125class AppAdmin (
@@ -33,6 +37,8 @@ class AppAdmin(
3337 "default_sample_rate" ,
3438 "active_sample_rate" ,
3539 "active_window_end" ,
40+ "wsgi_collect_metrics" ,
41+ "celery_collect_metrics" ,
3642 ]
3743
3844 search_fields = [
@@ -74,28 +80,76 @@ class AppAdmin(
7480 },
7581 ],
7682 ]
77- actions = ["bump" ]
78- changelist_actions = []
79- change_actions = ["bump" ]
83+ actions = ["bump_sample_rate" ]
84+ changelist_actions = ["panic" , "unpanic" ]
85+ change_actions = ["bump_sample_rate" ]
86+
87+ def get_changelist_actions (self , request ):
88+ allowed_actions = []
89+ for action in self .changelist_actions :
90+ if getattr (self , f"has_{ action } _permission" )(request ):
91+ allowed_actions .append (action )
92+ return allowed_actions
93+
94+ def get_change_actions (self , request , object_id , form_url ):
95+ allowed_actions = []
96+ for action in self .change_actions :
97+ if getattr (self , f"has_{ action } _permission" )(request ):
98+ allowed_actions .append (action )
99+ return allowed_actions
80100
81101 @takes_instance_or_queryset
82102 @add_form_to_action (BumpForm )
83103 @confirm_action ()
84104 @admin .action (description = "Bump Sample Rate" )
85- def bump (self , request , queryset , form : BumpForm = None ):
105+ def bump_sample_rate (self , request , queryset , form : BumpForm = None ):
86106 new_date = timezone .now () + form .cleaned_data ["duration" ]
87107 queryset .update (
88108 active_sample_rate = form .cleaned_data ["new_sample_rate" ],
89109 active_window_end = new_date ,
90110 )
91111
92- bump .allowed_permissions = ("bump_sample_rate" ,)
112+ bump_sample_rate .allowed_permissions = ("bump_sample_rate" ,)
93113
94114 def has_bump_sample_rate_permission (self , request ):
95115 """Does the user have the bump permission?"""
96116 opts = self .opts
97117 codename = get_permission_codename ("bump_sample_rate" , opts )
98- return request .user .has_perm ("%s.%s" % (opts .app_label , codename ))
118+
119+ panic = cache .get (settings .PANIC_KEY )
120+ return not panic and request .user .has_perm ("%s.%s" % (opts .app_label , codename ))
121+
122+ @takes_instance_or_queryset
123+ @confirm_action (display_queryset = False )
124+ @admin .action (description = "Panic" )
125+ def panic (self , request , queryset ):
126+ cache .set (settings .PANIC_KEY , True , timeout = None )
127+
128+ panic .allowed_permissions = ("panic" ,)
129+ panic .attrs = {"style" : "background-color: red;" }
130+
131+ def has_panic_permission (self , request ):
132+ """Does the user have the panic permission?"""
133+ panic = cache .get (settings .PANIC_KEY )
134+ opts = self .opts
135+ codename = get_permission_codename ("panic" , opts )
136+ return not panic and request .user .has_perm ("%s.%s" % (opts .app_label , codename ))
137+
138+ @takes_instance_or_queryset
139+ @confirm_action (display_queryset = False )
140+ @admin .action (description = "UnPanic" )
141+ def unpanic (self , request , queryset ):
142+ cache .delete (settings .PANIC_KEY )
143+
144+ unpanic .allowed_permissions = ("unpanic" ,)
145+ unpanic .attrs = {"style" : "background-color: green;" }
146+
147+ def has_unpanic_permission (self , request ):
148+ """Does the user have the panic permission?"""
149+ panic = cache .get (settings .PANIC_KEY )
150+ opts = self .opts
151+ codename = get_permission_codename ("panic" , opts )
152+ return panic and request .user .has_perm ("%s.%s" % (opts .app_label , codename ))
99153
100154 def save_model (self , request , obj , form , change ) -> None :
101155 invalidate_cache (f"/sentry/apps/{ obj .reference } /" )
0 commit comments