1
+ """Admin."""
2
+ from typing import TYPE_CHECKING , Optional
3
+
1
4
from admin_action_tools import (
2
5
ActionFormMixin ,
3
6
AdminConfirmMixin ,
22
25
from controller .sentry .models import App , Event , Project
23
26
from controller .sentry .utils import invalidate_cache
24
27
28
+ if TYPE_CHECKING : # pragma: no cover # pragma: no cover
29
+ from django .db .models import QuerySet
30
+ from django .forms import ModelForm
31
+ from django .http import HttpRequest
32
+
25
33
26
34
@admin .register (Project )
27
35
class ProjectAdmin (
@@ -32,6 +40,7 @@ class ProjectAdmin(
32
40
DynamicArrayMixin ,
33
41
admin .ModelAdmin ,
34
42
):
43
+ """Project Admin."""
35
44
36
45
list_display = [
37
46
"sentry_id" ,
@@ -61,6 +70,14 @@ class ProjectAdmin(
61
70
inlines = [ProjectEventInline ]
62
71
63
72
def get_chart_data (self , sentry_id ):
73
+ """This method return the chart data.
74
+
75
+ Args:
76
+ sentry_id (str): sentry id
77
+
78
+ Returns:
79
+ Optional[Tuple[dict, dict]]: tuple of data and options
80
+ """
64
81
project = Project .objects .get (sentry_id = sentry_id )
65
82
if project .detection_result is None :
66
83
return None
@@ -123,6 +140,7 @@ class EventAdmin(
123
140
PrettyTypeMixin ,
124
141
admin .ModelAdmin ,
125
142
):
143
+ """Event Admin."""
126
144
127
145
list_display = ["reference" , "pretty_type" , "timestamp" , "get_project" ]
128
146
@@ -150,6 +168,8 @@ class AppAdmin(
150
168
DynamicArrayMixin ,
151
169
admin .ModelAdmin ,
152
170
):
171
+ """App Admin."""
172
+
153
173
read_only_fields = ["last_seen" ]
154
174
155
175
list_display = [
@@ -219,22 +239,48 @@ class AppAdmin(
219
239
inlines = [AppEventInline ]
220
240
221
241
@admin .display (description = "Spamming Sentry" )
222
- def get_event_status (self , obj ):
242
+ def get_event_status (self , obj : App ) -> str :
243
+ """This method return a pretty event status html string.
244
+
245
+ Args:
246
+ obj (App): The app
247
+
248
+ Returns:
249
+ str: The pretty status
250
+ """
223
251
text = '<b style="color:{};">{}</b>'
224
252
if obj .project and (event := obj .project .events .last ()):
225
253
if event .type == EventType .DISCARD :
226
254
return format_html (text , "green" , "No" )
227
255
return format_html (text , "red" , "Yes" )
228
256
return format_html (text , "gray" , "Pending" )
229
257
230
- def get_changelist_actions (self , request ):
258
+ def get_changelist_actions (self , request : "HttpRequest" ) -> list [str ]:
259
+ """This method return allowed changelist actions.
260
+
261
+ Args:
262
+ request (HttpRequest): The request
263
+
264
+ Returns:
265
+ list[str]: All possible actions
266
+ """
231
267
allowed_actions = []
232
268
for action in self .changelist_actions :
233
269
if getattr (self , f"has_{ action } _permission" )(request ):
234
270
allowed_actions .append (action )
235
271
return allowed_actions
236
272
237
- def get_change_actions (self , request , object_id , form_url ):
273
+ def get_change_actions (self , request : "HttpRequest" , object_id : str , form_url : Optional [str ]) -> list [str ]:
274
+ """This method return allowed change actions.
275
+
276
+ Args:
277
+ request (HttpRequest): The request
278
+ object_id (str): The App reference
279
+ form_url (Optional[str]): The form_url
280
+
281
+ Returns:
282
+ list[str]: All possible actions
283
+ """
238
284
allowed_actions = []
239
285
for action in self .change_actions :
240
286
if getattr (self , f"has_{ action } _permission" )(request ):
@@ -246,7 +292,19 @@ def get_change_actions(self, request, object_id, form_url):
246
292
@add_form_to_action (BumpForm )
247
293
@confirm_action ()
248
294
@admin .action (description = "Bump Sample Rate" )
249
- def bump_sample_rate (self , request , queryset , form : BumpForm = None ): # pylint: disable=unused-argument
295
+ def bump_sample_rate (
296
+ self ,
297
+ request : "HttpRequest" ,
298
+ queryset : "QuerySet[App]" ,
299
+ form : BumpForm = None , # pylint: disable=unused-argument
300
+ ) -> None :
301
+ """This method is responsible for the bump sample rate action.
302
+
303
+ Args:
304
+ request (HttpRequest): The request
305
+ queryset (QuerySet[App]): The Apps to change
306
+ form (BumpForm): The form
307
+ """
250
308
new_date = timezone .now () + form .cleaned_data ["duration" ]
251
309
queryset .update (
252
310
active_sample_rate = form .cleaned_data ["new_sample_rate" ],
@@ -257,8 +315,15 @@ def bump_sample_rate(self, request, queryset, form: BumpForm = None): # pylint:
257
315
258
316
bump_sample_rate .allowed_permissions = ("bump_sample_rate" ,)
259
317
260
- def has_bump_sample_rate_permission (self , request ):
261
- """Does the user have the bump permission?"""
318
+ def has_bump_sample_rate_permission (self , request : "HttpRequest" ) -> bool :
319
+ """This method return True if the user have the permission for bump sample rate action.
320
+
321
+ Args:
322
+ request (HttpRequest): The request
323
+
324
+ Returns:
325
+ bool: Is allowed
326
+ """
262
327
opts = self .opts
263
328
codename = get_permission_codename ("bump_sample_rate" , opts )
264
329
@@ -269,7 +334,19 @@ def has_bump_sample_rate_permission(self, request):
269
334
@takes_instance_or_queryset
270
335
@add_form_to_action (MetricForm )
271
336
@admin .action (description = "Enable/Disable Metrics Collection" )
272
- def enable_disable_metrics (self , request , queryset , form : MetricForm = None ): # pylint: disable=unused-argument
337
+ def enable_disable_metrics (
338
+ self ,
339
+ request : "HttpRequest" ,
340
+ queryset : "QuerySet[App]" ,
341
+ form : MetricForm = None , # pylint: disable=unused-argument
342
+ ) -> None :
343
+ """This method is responsible for the enable/disable metrics action.
344
+
345
+ Args:
346
+ request (HttpRequest): The request
347
+ queryset (QuerySet[App]): The Apps to change
348
+ form (MetricForm): The form
349
+ """
273
350
metrics = form .cleaned_data ["metrics" ]
274
351
app : App
275
352
for app in queryset :
@@ -280,8 +357,15 @@ def enable_disable_metrics(self, request, queryset, form: MetricForm = None): #
280
357
281
358
enable_disable_metrics .allowed_permissions = ("enable_disable_metrics" ,)
282
359
283
- def has_enable_disable_metrics_permission (self , request ):
284
- """Does the user have the enable_disable_metrics permission?"""
360
+ def has_enable_disable_metrics_permission (self , request : "HttpRequest" ) -> bool :
361
+ """This method return True if the user have the permission for enable/disable metrics action.
362
+
363
+ Args:
364
+ request (HttpRequest): The request
365
+
366
+ Returns:
367
+ bool: Is allowed
368
+ """
285
369
opts = self .opts
286
370
codename = get_permission_codename ("enable_disable_metrics" , opts )
287
371
@@ -291,14 +375,27 @@ def has_enable_disable_metrics_permission(self, request):
291
375
@takes_instance_or_queryset
292
376
@confirm_action (display_queryset = False )
293
377
@admin .action (description = "Panic" )
294
- def panic (self , request , queryset ): # pylint: disable=unused-argument
378
+ def panic (self , request : "HttpRequest" , queryset : "QuerySet[App]" ) -> None : # pylint: disable=unused-argument
379
+ """This method activate the panic mode.
380
+
381
+ Args:
382
+ request (HttpRequest): The request
383
+ queryset (QuerySet[App]): All the Apps (unused)
384
+ """
295
385
cache .set (settings .PANIC_KEY , True , timeout = None )
296
386
297
387
panic .allowed_permissions = ("panic" ,)
298
388
panic .attrs = {"style" : "background-color: red;" }
299
389
300
- def has_panic_permission (self , request ):
301
- """Does the user have the panic permission?"""
390
+ def has_panic_permission (self , request : "HttpRequest" ) -> bool :
391
+ """This method return True if the user have the permission for panic action.
392
+
393
+ Args:
394
+ request (HttpRequest): The request
395
+
396
+ Returns:
397
+ bool: Is allowed
398
+ """
302
399
panic = cache .get (settings .PANIC_KEY )
303
400
opts = self .opts
304
401
codename = get_permission_codename ("panic" , opts )
@@ -307,20 +404,41 @@ def has_panic_permission(self, request):
307
404
@takes_instance_or_queryset
308
405
@confirm_action (display_queryset = False )
309
406
@admin .action (description = "UnPanic" )
310
- def unpanic (self , request , queryset ): # pylint: disable=unused-argument
407
+ def unpanic (self , request : "HttpRequest" , queryset : "QuerySet[App]" ) -> None : # pylint: disable=unused-argument
408
+ """This method deactivate the panic mode.
409
+
410
+ Args:
411
+ request (HttpRequest): The request
412
+ queryset (QuerySet[App]): All the Apps (unused)
413
+ """
311
414
cache .delete (settings .PANIC_KEY )
312
415
313
416
unpanic .allowed_permissions = ("unpanic" ,)
314
417
unpanic .attrs = {"style" : "background-color: green;" }
315
418
316
- def has_unpanic_permission (self , request ):
317
- """Does the user have the panic permission?"""
419
+ def has_unpanic_permission (self , request : "HttpRequest" ) -> bool :
420
+ """This method return True if the user have the permission for unpanic action.
421
+
422
+ Args:
423
+ request (HttpRequest): The request
424
+
425
+ Returns:
426
+ bool: Is allowed
427
+ """
318
428
panic = cache .get (settings .PANIC_KEY )
319
429
opts = self .opts
320
430
codename = get_permission_codename ("panic" , opts )
321
431
return panic and request .user .has_perm ("%s.%s" % (opts .app_label , codename ))
322
432
323
433
# Save model
324
- def save_model (self , request , obj , form , change ) -> None :
434
+ def save_model (self , request : "HttpRequest" , obj : App , form : "ModelForm" , change : bool ) -> None :
435
+ """This method is responsible to save app in the admin.
436
+
437
+ Args:
438
+ request (HttpRequest): The request
439
+ obj (App): The app to save
440
+ form (ModelForm): form
441
+ change (bool): change
442
+ """
325
443
invalidate_cache (f"/sentry/apps/{ obj .reference } /" )
326
444
return super ().save_model (request , obj , form , change )
0 commit comments