admin.py
 1  from django.contrib import admin
 2  from django import forms
 3  
 4  from django_magic_authorization.models import AccessToken
 5  from django_magic_authorization.middleware import MagicAuthorizationRouter
 6  from django_magic_authorization.settings import get_setting
 7  
 8  
 9  class AccessTokenForm(forms.ModelForm):
10      def get_routes():
11          router = MagicAuthorizationRouter()
12          return ((p, p) for p in router.get_protected_paths())
13  
14      path_choice = forms.ChoiceField(choices=get_routes)
15  
16      def save(self, commit=True):
17          instance = super().save(commit=False)
18          instance.path = self.cleaned_data.get("path_choice")
19          if commit:
20              instance.save()
21          return instance
22  
23      class Meta:
24          model = AccessToken
25          exclude = ["path"]
26  
27  
28  class AccessTokenAdmin(admin.ModelAdmin):
29      """Admin interface for managing access tokens.
30  
31      Provides a dropdown of registered protected paths, displays computed
32      access links, and flags tokens whose paths no longer match a route.
33      """
34  
35      date_hierarchy = "created_at"
36      list_display = (
37          "description",
38          "display_path",
39          "is_valid",
40          "expires_at",
41          "max_uses",
42          "access_link",
43          "created_at",
44          "last_accessed",
45          "times_accessed",
46      )
47      readonly_fields = (
48          "created_at",
49          "last_accessed",
50          "times_accessed",
51          "token",
52          "access_link",
53      )
54      form = AccessTokenForm
55      list_filter = ["is_valid", "created_at", "expires_at"]
56      search_fields = ["description", "path"]
57  
58      def changelist_view(self, request, extra_context=None):
59          self._request = request
60          return super().changelist_view(request, extra_context)
61  
62      def change_view(self, request, object_id, form_url="", extra_context=None):
63          self._request = request
64          return super().change_view(request, object_id, form_url, extra_context)
65  
66      def display_path(self, obj):
67          router = MagicAuthorizationRouter()
68          if obj.path not in router.get_protected_paths():
69              return f"❗ {obj.path}"
70          else:
71              return obj.path
72  
73      display_path.short_description = "Path"
74  
75      def access_link(self, obj):
76          token_param = get_setting("TOKEN_PARAM")
77          if hasattr(self, "_request") and self._request:
78              relative_url = f"{obj.path}?{token_param}={obj.token}"
79              # Ensure path starts with /
80              if not relative_url.startswith("/"):
81                  relative_url = f"/{relative_url}"
82              return self._request.build_absolute_uri(relative_url)
83          return f"{obj.path}?{token_param}={obj.token}"
84  
85      access_link.short_description = "Access Link"
86  
87  
88  admin.site.register(AccessToken, AccessTokenAdmin)