Coverage for product_risk_suite/api/admin.py: 61%

46 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-16 14:44 +0000

1from django.contrib import admin, messages 

2from django.contrib.auth.admin import UserAdmin 

3from django.contrib.auth.models import User 

4 

5from .models import APIToken 

6 

7 

8class APITokenInline(admin.TabularInline): 

9 model = APIToken 

10 fk_name = "owner" 

11 extra = 0 

12 fields = ("name", "display_prefix", "created_at", "last_used_at", "expires_at", "is_active") 

13 readonly_fields = ("display_prefix", "created_at", "last_used_at") 

14 show_change_link = True 

15 

16 

17class UserAdminWithAPITokens(UserAdmin): 

18 inlines = UserAdmin.inlines + (APITokenInline,) 

19 list_display = UserAdmin.list_display + ("api_token_count",) 

20 

21 @admin.display(description="API tokens") 

22 def api_token_count(self, obj): 

23 return obj.api_tokens.count() 

24 

25 

26admin.site.unregister(User) 

27admin.site.register(User, UserAdminWithAPITokens) 

28 

29 

30@admin.register(APIToken) 

31class APITokenAdmin(admin.ModelAdmin): 

32 list_display = ("name", "owner", "display_prefix", "is_active", "created_at", "last_used_at", "expires_at") 

33 list_filter = ("is_active",) 

34 search_fields = ("name", "owner__username", "display_prefix") 

35 autocomplete_fields = ("owner",) 

36 

37 def get_fields(self, request, obj=None): 

38 if obj is None: 

39 return ("name", "owner", "expires_at", "is_active") 

40 return ("name", "owner", "display_prefix", "created_by", "created_at", "last_used_at", "expires_at", "is_active") 

41 

42 def get_readonly_fields(self, request, obj=None): 

43 if obj is None: 

44 return () 

45 return ("display_prefix", "created_by", "created_at", "last_used_at") 

46 

47 def save_model(self, request, obj, form, change): 

48 if not change: 

49 raw_token = APIToken.generate_raw_token() 

50 obj.display_prefix = raw_token[:12] 

51 obj.hashed_key = APIToken.hash_token(raw_token) 

52 obj.created_by = request.user 

53 self._raw_token_to_display = raw_token 

54 super().save_model(request, obj, form, change) 

55 

56 def response_add(self, request, obj, post_url_continue=None): 

57 raw_token = getattr(self, "_raw_token_to_display", None) 

58 if raw_token: 

59 messages.warning( 

60 request, 

61 f"API token created for '{obj.name}'. Copy it now — it will not be shown again: {raw_token}", 

62 ) 

63 return super().response_add(request, obj, post_url_continue)