admin_users.py 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. __package__ = 'archivebox.core'
  2. from django.contrib import admin
  3. from django.contrib.auth.admin import UserAdmin
  4. from django.utils.html import format_html, mark_safe
  5. from django.contrib.auth import get_user_model
  6. class CustomUserAdmin(UserAdmin):
  7. sort_fields = ['id', 'email', 'username', 'is_superuser', 'last_login', 'date_joined']
  8. list_display = ['username', 'id', 'email', 'is_superuser', 'last_login', 'date_joined']
  9. readonly_fields = ('snapshot_set', 'archiveresult_set', 'tag_set', 'apitoken_set', 'outboundwebhook_set')
  10. # Preserve Django's default user creation form and fieldsets
  11. # This ensures passwords are properly hashed and permissions are set correctly
  12. add_fieldsets = UserAdmin.add_fieldsets
  13. # Extend fieldsets for change form only (not user creation)
  14. fieldsets = [*UserAdmin.fieldsets, ('Data', {'fields': readonly_fields})]
  15. @admin.display(description='Snapshots')
  16. def snapshot_set(self, obj):
  17. total_count = obj.snapshot_set.count()
  18. return mark_safe('<br/>'.join(
  19. format_html(
  20. '<code><a href="/admin/core/snapshot/{}/change"><b>[{}]</b></a></code> <b>📅 {}</b> {}',
  21. snap.pk,
  22. str(snap.id)[:8],
  23. snap.downloaded_at.strftime('%Y-%m-%d %H:%M') if snap.downloaded_at else 'pending...',
  24. snap.url[:64],
  25. )
  26. for snap in obj.snapshot_set.order_by('-modified_at')[:10]
  27. ) + f'<br/><a href="/admin/core/snapshot/?created_by__id__exact={obj.pk}">{total_count} total records...<a>')
  28. @admin.display(description='Archive Result Logs')
  29. def archiveresult_set(self, obj):
  30. total_count = obj.archiveresult_set.count()
  31. return mark_safe('<br/>'.join(
  32. format_html(
  33. '<code><a href="/admin/core/archiveresult/{}/change"><b>[{}]</b></a></code> <b>📅 {}</b> <b>📄 {}</b> {}',
  34. result.pk,
  35. str(result.id)[:8],
  36. result.snapshot.downloaded_at.strftime('%Y-%m-%d %H:%M') if result.snapshot.downloaded_at else 'pending...',
  37. result.extractor,
  38. result.snapshot.url[:64],
  39. )
  40. for result in obj.archiveresult_set.order_by('-modified_at')[:10]
  41. ) + f'<br/><a href="/admin/core/archiveresult/?created_by__id__exact={obj.pk}">{total_count} total records...<a>')
  42. @admin.display(description='Tags')
  43. def tag_set(self, obj):
  44. total_count = obj.tag_set.count()
  45. return mark_safe(', '.join(
  46. format_html(
  47. '<code><a href="/admin/core/tag/{}/change"><b>{}</b></a></code>',
  48. tag.pk,
  49. tag.name,
  50. )
  51. for tag in obj.tag_set.order_by('-modified_at')[:10]
  52. ) + f'<br/><a href="/admin/core/tag/?created_by__id__exact={obj.pk}">{total_count} total records...<a>')
  53. @admin.display(description='API Tokens')
  54. def apitoken_set(self, obj):
  55. total_count = obj.apitoken_set.count()
  56. return mark_safe('<br/>'.join(
  57. format_html(
  58. '<code><a href="/admin/api/apitoken/{}/change"><b>[{}]</b></a></code> {} (expires {})',
  59. apitoken.pk,
  60. str(apitoken.id)[:8],
  61. apitoken.token_redacted[:64],
  62. apitoken.expires,
  63. )
  64. for apitoken in obj.apitoken_set.order_by('-modified_at')[:10]
  65. ) + f'<br/><a href="/admin/api/apitoken/?created_by__id__exact={obj.pk}">{total_count} total records...<a>')
  66. @admin.display(description='API Outbound Webhooks')
  67. def outboundwebhook_set(self, obj):
  68. total_count = obj.outboundwebhook_set.count()
  69. return mark_safe('<br/>'.join(
  70. format_html(
  71. '<code><a href="/admin/api/outboundwebhook/{}/change"><b>[{}]</b></a></code> {} -> {}',
  72. outboundwebhook.pk,
  73. str(outboundwebhook.id)[:8],
  74. outboundwebhook.referenced_model,
  75. outboundwebhook.endpoint,
  76. )
  77. for outboundwebhook in obj.outboundwebhook_set.order_by('-modified_at')[:10]
  78. ) + f'<br/><a href="/admin/api/outboundwebhook/?created_by__id__exact={obj.pk}">{total_count} total records...<a>')
  79. def register_admin(admin_site):
  80. admin_site.register(get_user_model(), CustomUserAdmin)