You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
6.8 KiB

10 years ago
8 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
5 years ago
  1. from django.contrib import admin
  2. from django.contrib.auth import login as auth_login
  3. from django.contrib.auth.admin import UserAdmin
  4. from django.contrib.auth.models import User
  5. from django.db.models import Count, F
  6. from django.shortcuts import redirect
  7. from django.template.loader import render_to_string
  8. from django.urls import reverse
  9. from django.utils.html import escape
  10. from django.utils.safestring import mark_safe
  11. from hc.accounts.models import Credential, Profile, Project
  12. @mark_safe
  13. def _format_usage(num_checks, num_channels):
  14. result = ""
  15. if num_checks == 0:
  16. result += "0 checks, "
  17. elif num_checks == 1:
  18. result += "1 check, "
  19. else:
  20. result += f"<strong>{num_checks} checks</strong>, "
  21. if num_channels == 0:
  22. result += "0 channels"
  23. elif num_channels == 1:
  24. result += "1 channel"
  25. else:
  26. result += f"<strong>{num_channels} channels</strong>"
  27. return result
  28. class Fieldset:
  29. name = None
  30. fields = []
  31. @classmethod
  32. def tuple(cls):
  33. return (cls.name, {"fields": cls.fields})
  34. class ProfileFieldset(Fieldset):
  35. name = "User Profile"
  36. fields = (
  37. "email",
  38. "reports",
  39. "tz",
  40. "theme",
  41. "next_report_date",
  42. "nag_period",
  43. "next_nag_date",
  44. "deletion_notice_date",
  45. "token",
  46. "sort",
  47. )
  48. class TeamFieldset(Fieldset):
  49. name = "Team"
  50. fields = (
  51. "team_limit",
  52. "check_limit",
  53. "ping_log_limit",
  54. "sms_limit",
  55. "sms_sent",
  56. "last_sms_date",
  57. "call_limit",
  58. "calls_sent",
  59. "last_call_date",
  60. )
  61. class NumChecksFilter(admin.SimpleListFilter):
  62. title = "check count"
  63. parameter_name = "num_checks"
  64. def lookups(self, request, model_admin):
  65. return (
  66. ("10", "more than 10"),
  67. ("20", "more than 20"),
  68. ("50", "more than 50"),
  69. ("100", "more than 100"),
  70. ("500", "more than 500"),
  71. ("1000", "more than 1000"),
  72. )
  73. def queryset(self, request, queryset):
  74. if not self.value():
  75. return
  76. value = int(self.value())
  77. return queryset.filter(num_checks__gt=value)
  78. @admin.register(Profile)
  79. class ProfileAdmin(admin.ModelAdmin):
  80. class Media:
  81. css = {"all": ("css/admin/profiles.css",)}
  82. readonly_fields = ("user", "email")
  83. search_fields = ["id", "user__email"]
  84. list_per_page = 30
  85. list_select_related = ("user",)
  86. list_display = (
  87. "id",
  88. "email",
  89. "checks",
  90. "date_joined",
  91. "last_active_date",
  92. "projects",
  93. "invited",
  94. "sms",
  95. "reports",
  96. )
  97. list_filter = (
  98. "user__date_joined",
  99. "last_active_date",
  100. "reports",
  101. "check_limit",
  102. NumChecksFilter,
  103. "theme",
  104. )
  105. actions = ("login",)
  106. fieldsets = (ProfileFieldset.tuple(), TeamFieldset.tuple())
  107. def get_queryset(self, request):
  108. qs = super(ProfileAdmin, self).get_queryset(request)
  109. qs = qs.prefetch_related("user__project_set")
  110. qs = qs.annotate(num_members=Count("user__project__member", distinct=True))
  111. qs = qs.annotate(num_checks=Count("user__project__check", distinct=True))
  112. qs = qs.annotate(plan=F("user__subscription__plan_name"))
  113. return qs
  114. @mark_safe
  115. def email(self, obj):
  116. s = escape(obj.user.email)
  117. if obj.plan:
  118. s = "%s <span>%s</span>" % (s, obj.plan)
  119. return s
  120. def date_joined(self, obj):
  121. return obj.user.date_joined
  122. @mark_safe
  123. def projects(self, obj):
  124. return render_to_string("admin/profile_list_projects.html", {"profile": obj})
  125. @mark_safe
  126. def checks(self, obj):
  127. s = "%d of %d" % (obj.num_checks, obj.check_limit)
  128. if obj.num_checks > 1:
  129. s = "<b>%s</b>" % s
  130. return s
  131. def invited(self, obj):
  132. return "%d of %d" % (obj.num_members, obj.team_limit)
  133. def sms(self, obj):
  134. return "%d of %d" % (obj.sms_sent, obj.sms_limit)
  135. def login(self, request, qs):
  136. profile = qs.get()
  137. auth_login(request, profile.user, "hc.accounts.backends.EmailBackend")
  138. return redirect("hc-index")
  139. @admin.register(Project)
  140. class ProjectAdmin(admin.ModelAdmin):
  141. readonly_fields = ("code", "owner")
  142. list_select_related = ("owner",)
  143. list_display = ("id", "name_", "users", "usage", "switch")
  144. search_fields = ["id", "name", "owner__email"]
  145. class Media:
  146. css = {"all": ("css/admin/projects.css",)}
  147. def get_queryset(self, request):
  148. qs = super(ProjectAdmin, self).get_queryset(request)
  149. qs = qs.annotate(num_channels=Count("channel", distinct=True))
  150. qs = qs.annotate(num_checks=Count("check", distinct=True))
  151. qs = qs.annotate(num_members=Count("member", distinct=True))
  152. return qs
  153. def name_(self, obj):
  154. if obj.name:
  155. return obj.name
  156. return "Default Project for %s" % obj.owner.email
  157. @mark_safe
  158. def users(self, obj):
  159. if obj.num_members == 0:
  160. return obj.owner.email
  161. else:
  162. return render_to_string("admin/project_list_team.html", {"project": obj})
  163. def email(self, obj):
  164. return obj.owner.email
  165. def usage(self, obj):
  166. return _format_usage(obj.num_checks, obj.num_channels)
  167. @mark_safe
  168. def switch(self, obj):
  169. url = reverse("hc-checks", args=[obj.code])
  170. return "<a href='%s'>Show Checks</a>" % url
  171. class HcUserAdmin(UserAdmin):
  172. actions = ["send_report", "send_nag"]
  173. list_display = (
  174. "id",
  175. "email",
  176. "usage",
  177. "date_joined",
  178. "last_login",
  179. "is_staff",
  180. )
  181. list_display_links = ("id", "email")
  182. list_filter = ("last_login", "date_joined", "is_staff", "is_active")
  183. ordering = ["-id"]
  184. def get_queryset(self, request):
  185. qs = super().get_queryset(request)
  186. qs = qs.annotate(num_checks=Count("project__check", distinct=True))
  187. qs = qs.annotate(num_channels=Count("project__channel", distinct=True))
  188. return qs
  189. @mark_safe
  190. def usage(self, user):
  191. return _format_usage(user.num_checks, user.num_channels)
  192. def send_report(self, request, qs):
  193. for user in qs:
  194. user.profile.send_report()
  195. self.message_user(request, "%d email(s) sent" % qs.count())
  196. def send_nag(self, request, qs):
  197. for user in qs:
  198. user.profile.send_report(nag=True)
  199. self.message_user(request, "%d email(s) sent" % qs.count())
  200. admin.site.unregister(User)
  201. admin.site.register(User, HcUserAdmin)
  202. @admin.register(Credential)
  203. class CredentialAdmin(admin.ModelAdmin):
  204. list_display = ("id", "created", "email", "name")
  205. search_fields = ["id", "code", "name", "user__email"]
  206. list_filter = ["created"]
  207. def email(self, obj):
  208. return obj.user.email