0
0
Fork 0
mirror of https://github.com/healthchecks/healthchecks.git synced 2025-04-10 23:40:11 +00:00

Email reports list checks from all teams the user has access to.

This commit is contained in:
Pēteris Caune 2017-10-14 21:36:39 +03:00
parent f3c6b0fb0d
commit f611a23f0b
6 changed files with 44 additions and 23 deletions
hc
accounts
front/templatetags
templates

View file

@ -27,14 +27,14 @@ class Command(BaseCommand):
# Old accounts, never logged in, no team memberships
q = User.objects
q = q.annotate(n_teams=Count("member"))
q = q.annotate(n_teams=Count("memberships"))
q = q.filter(date_joined__lt=cutoff, last_login=None, n_teams=0)
n1, _ = q.delete()
# Not logged in for 1 month, 0 checks, no team memberships
q = User.objects
q = q.annotate(n_checks=Count("check"))
q = q.annotate(n_teams=Count("member"))
q = q.annotate(n_teams=Count("memberships"))
q = q.filter(last_login__lt=cutoff, n_checks=0, n_teams=0)
n2, _ = q.delete()

View file

@ -116,13 +116,24 @@ class Profile(models.Model):
self.api_key = base64.urlsafe_b64encode(os.urandom(24))
self.save()
def checks_from_all_teams(self):
""" Return a queryset of checks from all teams we have access for. """
team_ids = set(self.user.memberships.values_list("team_id", flat=True))
team_ids.add(self.id)
from hc.api.models import Check
return Check.objects.filter(user__profile__id__in=team_ids)
def send_report(self, nag=False):
# Are there any non-new checks in the account?
q = self.user.check_set.filter(last_ping__isnull=False)
if not q.exists():
checks = self.checks_from_all_teams()
# Is there at least one check that has received a ping?
if not checks.filter(last_ping__isnull=False).exists():
return False
num_down = q.filter(status="down").count()
# Is there at least one check that is down?
num_down = checks.filter(status="down").count()
if nag and num_down == 0:
return False
@ -130,8 +141,12 @@ class Profile(models.Model):
path = reverse("hc-unsubscribe-reports", args=[self.user.username])
unsub_link = "%s%s?token=%s" % (settings.SITE_ROOT, path, token)
# Sort checks by team name, then by email, and then by creation date:
checks = checks.order_by(
"user__profile__team_name", "user__email", "created")
ctx = {
"checks": self.user.check_set.order_by("created"),
"checks": checks,
"now": timezone.now(),
"unsub_link": unsub_link,
"notifications_url": self.notifications_url,
@ -184,7 +199,7 @@ class Profile(models.Model):
""" Set next_nag_date for all members of this team. """
is_owner = models.Q(id=self.id)
is_member = models.Q(user__member__team=self)
is_member = models.Q(user__memberships__team=self)
q = Profile.objects.filter(is_owner | is_member)
q = q.exclude(nag_period=NO_NAG)
@ -193,4 +208,4 @@ class Profile(models.Model):
class Member(models.Model):
team = models.ForeignKey(Profile, models.CASCADE)
user = models.ForeignKey(User, models.CASCADE)
user = models.ForeignKey(User, models.CASCADE, related_name="memberships")

View file

@ -364,8 +364,8 @@ def unsubscribe_reports(request, username):
@login_required
def switch_team(request, target_username):
try:
other_user = User.objects.get(username=target_username)
except User.DoesNotExist:
target_team = Profile.objects.get(user__username=target_username)
except Profile.DoesNotExist:
return HttpResponseForbidden()
# The rules:
@ -373,20 +373,17 @@ def switch_team(request, target_username):
access_ok = request.user.is_superuser
# Users can switch to their own teams.
if not access_ok and other_user.id == request.user.id:
if not access_ok and target_team == request.profile:
access_ok = True
# Users can switch to teams they are members of.
if not access_ok:
for membership in request.user.member_set.all():
if membership.team.user.id == other_user.id:
access_ok = True
break
access_ok = request.user.memberships.filter(team=target_team).exists()
if not access_ok:
return HttpResponseForbidden()
request.profile.current_team = other_user.profile
request.profile.current_team = target_team
request.profile.save()
return redirect("hc-checks")

View file

@ -1,5 +1,6 @@
from django import template
from django.conf import settings
from django.utils.html import escape
from django.utils.safestring import mark_safe
from hc.lib.date import format_duration
@ -22,6 +23,11 @@ def escaped_site_name():
return mark_safe(settings.SITE_NAME.replace(".", "<span>.</span>"))
@register.filter
def mangle_link(s):
return mark_safe(escape(s).replace(".", "<span>.</span>"))
@register.simple_tag
def site_root():
return settings.SITE_ROOT

View file

@ -40,7 +40,7 @@
type="checkbox"
{% if profile.reports_allowed %} checked {% endif %}>
<span class="checkmark"></span>
The status of checks my checks
The status of checks in all teams I belong to
</label>
<br>

View file

@ -1,12 +1,14 @@
{% load humanize hc_extras %}
<br />
{% regroup checks by user as groups %}
<table style="margin: 0; width: 100%; font-size: 16px;" cellpadding="0" cellspacing="0">
{% for group in groups %}
<tr>
<td style="padding: 8px; margin: 0; font-size: 12px; color: #9BA2AB; font-family: Helvetica, Arial, sans-serif;"></td>
<td style="padding: 8px; margin: 0; font-size: 12px; color: #9BA2AB; font-family: Helvetica, Arial, sans-serif;">Name</td>
<td class="mobile-hide" style="padding: 8px; margin: 0; font-size: 12px; color: #9BA2AB; font-family: Helvetica, Arial, sans-serif;">Last Ping</td>
<td colspan="2" style="font-weight: bold; padding: 32px 8px 8px 8px; color: #333;">
{{ group.grouper.profile|mangle_link }}
</td>
<td class="mobile-hide" style="padding: 32px 8px 8px 8px; margin: 0; font-size: 12px; color: #9BA2AB; font-family: Helvetica, Arial, sans-serif;">Last Ping</td>
</tr>
{% for check in checks %}
{% for check in group.list %}
<tr>
<td style="border-top: 1px solid #EDEFF2; padding: 16px 8px;">
<table cellpadding="0" cellspacing="0">
@ -65,5 +67,6 @@
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
<br />