forked from GithubBackups/healthchecks
Allow simultaneous access to checks from different teams
This commit is contained in:
parent
d36d4fb543
commit
c2f200fa02
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
### Improvements
|
### Improvements
|
||||||
- Set Pushover alert priorities for "down" and "up" events separately
|
- Set Pushover alert priorities for "down" and "up" events separately
|
||||||
- Additional python usage examples
|
- Additional python usage examples
|
||||||
|
- Allow simultaneous access to checks from different teams
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
- Fix after-login redirects (the "?next=" query parameter)
|
- Fix after-login redirects (the "?next=" query parameter)
|
||||||
@ -52,4 +53,4 @@ All notable changes to this project will be documented in this file.
|
|||||||
- A new "Check Details" page.
|
- A new "Check Details" page.
|
||||||
- Updated django-compressor, psycopg2, pytz, requests package versions.
|
- Updated django-compressor, psycopg2, pytz, requests package versions.
|
||||||
- C# usage example.
|
- C# usage example.
|
||||||
- Checks have a "Description" field.
|
- Checks have a "Description" field.
|
||||||
|
@ -29,7 +29,7 @@ class DetailsTestCase(BaseTestCase):
|
|||||||
def test_it_checks_ownership(self):
|
def test_it_checks_ownership(self):
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.get(self.url)
|
r = self.client.get(self.url)
|
||||||
assert r.status_code == 403
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_shows_cron_expression(self):
|
def test_it_shows_cron_expression(self):
|
||||||
self.check.kind = "cron"
|
self.check.kind = "cron"
|
||||||
@ -38,3 +38,11 @@ class DetailsTestCase(BaseTestCase):
|
|||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(self.url)
|
r = self.client.get(self.url)
|
||||||
self.assertContains(r, "Cron Expression", status_code=200)
|
self.assertContains(r, "Cron Expression", status_code=200)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.get(self.url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
@ -52,7 +52,7 @@ class LogTestCase(BaseTestCase):
|
|||||||
url = "/checks/%s/log/" % self.check.code
|
url = "/checks/%s/log/" % self.check.code
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 403)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_shows_pushover_notifications(self):
|
def test_it_shows_pushover_notifications(self):
|
||||||
ch = Channel(kind="po", user=self.alice)
|
ch = Channel(kind="po", user=self.alice)
|
||||||
@ -77,3 +77,12 @@ class LogTestCase(BaseTestCase):
|
|||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertContains(r, "Called webhook foo/$NAME", status_code=200)
|
self.assertContains(r, "Called webhook foo/$NAME", status_code=200)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
url = "/checks/%s/log/" % self.check.code
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.get(url)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
@ -24,3 +24,13 @@ class PauseTestCase(BaseTestCase):
|
|||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 405)
|
self.assertEqual(r.status_code, 405)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
url = "/checks/%s/pause/" % self.check.code
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.post(url)
|
||||||
|
self.assertRedirects(r, "/checks/")
|
||||||
|
@ -17,7 +17,7 @@ class LastPingTestCase(BaseTestCase):
|
|||||||
def test_it_requires_user(self):
|
def test_it_requires_user(self):
|
||||||
check = Check.objects.create()
|
check = Check.objects.create()
|
||||||
r = self.client.get("/checks/%s/last_ping/" % check.code)
|
r = self.client.get("/checks/%s/last_ping/" % check.code)
|
||||||
self.assertEqual(r.status_code, 403)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_accepts_n(self):
|
def test_it_accepts_n(self):
|
||||||
check = Check(user=self.alice)
|
check = Check(user=self.alice)
|
||||||
@ -34,3 +34,16 @@ class LastPingTestCase(BaseTestCase):
|
|||||||
|
|
||||||
r = self.client.get("/checks/%s/pings/2/" % check.code)
|
r = self.client.get("/checks/%s/pings/2/" % check.code)
|
||||||
self.assertContains(r, "bar-456", status_code=200)
|
self.assertContains(r, "bar-456", status_code=200)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
check = Check(user=self.alice)
|
||||||
|
check.save()
|
||||||
|
|
||||||
|
Ping.objects.create(owner=check, body="this is body")
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.get("/checks/%s/last_ping/" % check.code)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
@ -9,37 +9,32 @@ class RemoveCheckTestCase(BaseTestCase):
|
|||||||
self.check = Check(user=self.alice)
|
self.check = Check(user=self.alice)
|
||||||
self.check.save()
|
self.check.save()
|
||||||
|
|
||||||
def test_it_works(self):
|
self.remove_url = "/checks/%s/remove/" % self.check.code
|
||||||
url = "/checks/%s/remove/" % self.check.code
|
|
||||||
|
|
||||||
|
def test_it_works(self):
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(self.remove_url)
|
||||||
self.assertRedirects(r, "/checks/")
|
self.assertRedirects(r, "/checks/")
|
||||||
|
|
||||||
assert Check.objects.count() == 0
|
self.assertEqual(Check.objects.count(), 0)
|
||||||
|
|
||||||
def test_team_access_works(self):
|
def test_team_access_works(self):
|
||||||
url = "/checks/%s/remove/" % self.check.code
|
|
||||||
|
|
||||||
# Logging in as bob, not alice. Bob has team access so this
|
# Logging in as bob, not alice. Bob has team access so this
|
||||||
# should work.
|
# should work.
|
||||||
self.client.login(username="bob@example.org", password="password")
|
self.client.login(username="bob@example.org", password="password")
|
||||||
self.client.post(url)
|
self.client.post(self.remove_url)
|
||||||
assert Check.objects.count() == 0
|
|
||||||
|
self.assertEqual(Check.objects.count(), 0)
|
||||||
|
|
||||||
def test_it_handles_bad_uuid(self):
|
def test_it_handles_bad_uuid(self):
|
||||||
url = "/checks/not-uuid/remove/"
|
|
||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post("/checks/not-uuid/remove/")
|
||||||
self.assertEqual(r.status_code, 404)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_checks_owner(self):
|
def test_it_checks_owner(self):
|
||||||
url = "/checks/%s/remove/" % self.check.code
|
|
||||||
|
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(self.remove_url)
|
||||||
assert r.status_code == 403
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_missing_uuid(self):
|
def test_it_handles_missing_uuid(self):
|
||||||
# Valid UUID but there is no check for it:
|
# Valid UUID but there is no check for it:
|
||||||
@ -47,10 +42,17 @@ class RemoveCheckTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(url)
|
||||||
assert r.status_code == 404
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_rejects_get(self):
|
def test_it_rejects_get(self):
|
||||||
url = "/checks/%s/remove/" % self.check.code
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(self.remove_url)
|
||||||
self.assertEqual(r.status_code, 405)
|
self.assertEqual(r.status_code, 405)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.post(self.remove_url)
|
||||||
|
self.assertRedirects(r, "/checks/")
|
||||||
|
@ -46,3 +46,11 @@ class StatusSingleTestCase(BaseTestCase):
|
|||||||
doc = r.json()
|
doc = r.json()
|
||||||
|
|
||||||
self.assertFalse("events" in doc)
|
self.assertFalse("events" in doc)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.get("/checks/%s/status/" % self.check.code)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
@ -32,7 +32,7 @@ class SwitchChannelTestCase(BaseTestCase):
|
|||||||
def test_it_checks_ownership(self):
|
def test_it_checks_ownership(self):
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.post(self.url, {"state": "on"})
|
r = self.client.post(self.url, {"state": "on"})
|
||||||
self.assertEqual(r.status_code, 403)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_checks_channels_ownership(self):
|
def test_it_checks_channels_ownership(self):
|
||||||
cc = Check(user=self.charlie)
|
cc = Check(user=self.charlie)
|
||||||
@ -43,4 +43,12 @@ class SwitchChannelTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.post(self.url, {"state": "on"})
|
r = self.client.post(self.url, {"state": "on"})
|
||||||
self.assertEqual(r.status_code, 403)
|
self.assertEqual(r.status_code, 400)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.post(self.url, {"state": "on"})
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
@ -12,10 +12,8 @@ class UpdateNameTestCase(BaseTestCase):
|
|||||||
self.url = "/checks/%s/name/" % self.check.code
|
self.url = "/checks/%s/name/" % self.check.code
|
||||||
|
|
||||||
def test_it_works(self):
|
def test_it_works(self):
|
||||||
payload = {"name": "Alice Was Here"}
|
|
||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(self.url, data=payload)
|
r = self.client.post(self.url, data={"name": "Alice Was Here"})
|
||||||
self.assertRedirects(r, "/checks/")
|
self.assertRedirects(r, "/checks/")
|
||||||
|
|
||||||
self.check.refresh_from_db()
|
self.check.refresh_from_db()
|
||||||
@ -32,12 +30,22 @@ class UpdateNameTestCase(BaseTestCase):
|
|||||||
self.check.refresh_from_db()
|
self.check.refresh_from_db()
|
||||||
self.assertEqual(self.check.name, "Bob Was Here")
|
self.assertEqual(self.check.name, "Bob Was Here")
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
# Bob's current team is not set
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
# But this should still work:
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.post(self.url, data={"name": "Bob Was Here"})
|
||||||
|
self.assertRedirects(r, "/checks/")
|
||||||
|
|
||||||
def test_it_checks_ownership(self):
|
def test_it_checks_ownership(self):
|
||||||
payload = {"name": "Charlie Sent This"}
|
payload = {"name": "Charlie Sent This"}
|
||||||
|
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.post(self.url, data=payload)
|
r = self.client.post(self.url, data=payload)
|
||||||
self.assertEqual(r.status_code, 403)
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_handles_bad_uuid(self):
|
def test_it_handles_bad_uuid(self):
|
||||||
url = "/checks/not-uuid/name/"
|
url = "/checks/not-uuid/name/"
|
||||||
|
@ -145,10 +145,21 @@ class UpdateTimeoutTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
r = self.client.post(url, data=payload)
|
r = self.client.post(url, data=payload)
|
||||||
assert r.status_code == 403
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
def test_it_rejects_get(self):
|
def test_it_rejects_get(self):
|
||||||
url = "/checks/%s/timeout/" % self.check.code
|
url = "/checks/%s/timeout/" % self.check.code
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
self.assertEqual(r.status_code, 405)
|
self.assertEqual(r.status_code, 405)
|
||||||
|
|
||||||
|
def test_it_allows_cross_team_access(self):
|
||||||
|
self.bobs_profile.current_team = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
|
url = "/checks/%s/timeout/" % self.check.code
|
||||||
|
payload = {"kind": "simple", "timeout": 3600, "grace": 60}
|
||||||
|
|
||||||
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
r = self.client.post(url, data=payload)
|
||||||
|
self.assertRedirects(r, "/checks/")
|
||||||
|
@ -60,6 +60,23 @@ def _tags_statuses(checks):
|
|||||||
return tags, num_down
|
return tags, num_down
|
||||||
|
|
||||||
|
|
||||||
|
def _get_check_for_user(request, code):
|
||||||
|
""" Return specified check if current user has access to it. """
|
||||||
|
|
||||||
|
if not request.user.is_authenticated:
|
||||||
|
raise Http404("not found")
|
||||||
|
|
||||||
|
if request.user.is_superuser:
|
||||||
|
q = Check.objects
|
||||||
|
else:
|
||||||
|
q = request.profile.checks_from_all_teams()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return q.get(code=code)
|
||||||
|
except Check.DoesNotExist:
|
||||||
|
raise Http404("not found")
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def my_checks(request):
|
def my_checks(request):
|
||||||
if request.GET.get("sort") in VALID_SORT_VALUES:
|
if request.GET.get("sort") in VALID_SORT_VALUES:
|
||||||
@ -136,13 +153,11 @@ def status(request):
|
|||||||
@login_required
|
@login_required
|
||||||
@require_POST
|
@require_POST
|
||||||
def switch_channel(request, code, channel_code):
|
def switch_channel(request, code, channel_code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user_id != request.team.user.id:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
channel = get_object_or_404(Channel, code=channel_code)
|
channel = get_object_or_404(Channel, code=channel_code)
|
||||||
if channel.user_id != request.team.user.id:
|
if channel.user_id != check.user_id:
|
||||||
return HttpResponseForbidden()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
if request.POST.get("state") == "on":
|
if request.POST.get("state") == "on":
|
||||||
channel.checks.add(check)
|
channel.checks.add(check)
|
||||||
@ -228,10 +243,7 @@ def add_check(request):
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def update_name(request, code):
|
def update_name(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user_id != request.team.user.id:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
form = NameTagsForm(request.POST)
|
form = NameTagsForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
check.name = form.cleaned_data["name"]
|
check.name = form.cleaned_data["name"]
|
||||||
@ -248,9 +260,7 @@ def update_name(request, code):
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def update_timeout(request, code):
|
def update_timeout(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user != request.team.user:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
kind = request.POST.get("kind")
|
kind = request.POST.get("kind")
|
||||||
if kind == "simple":
|
if kind == "simple":
|
||||||
@ -304,13 +314,7 @@ def cron_preview(request):
|
|||||||
|
|
||||||
|
|
||||||
def ping_details(request, code, n=None):
|
def ping_details(request, code, n=None):
|
||||||
if not request.user.is_authenticated:
|
check = _get_check_for_user(request, code)
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
check = get_object_or_404(Check, code=code)
|
|
||||||
if check.user_id != request.team.user.id:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
q = Ping.objects.filter(owner=check)
|
q = Ping.objects.filter(owner=check)
|
||||||
if n:
|
if n:
|
||||||
q = q.filter(n=n)
|
q = q.filter(n=n)
|
||||||
@ -328,9 +332,7 @@ def ping_details(request, code, n=None):
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def pause(request, code):
|
def pause(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user_id != request.team.user.id:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
check.status = "paused"
|
check.status = "paused"
|
||||||
check.save()
|
check.save()
|
||||||
@ -344,12 +346,8 @@ def pause(request, code):
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def remove_check(request, code):
|
def remove_check(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user != request.team.user:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
check.delete()
|
check.delete()
|
||||||
|
|
||||||
return redirect("hc-checks")
|
return redirect("hc-checks")
|
||||||
|
|
||||||
|
|
||||||
@ -371,11 +369,9 @@ def _get_events(check, limit):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def log(request, code):
|
def log(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user != request.team.user:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
limit = request.team.ping_log_limit
|
limit = check.user.profile.ping_log_limit
|
||||||
ctx = {
|
ctx = {
|
||||||
"check": check,
|
"check": check,
|
||||||
"events": _get_events(check, limit),
|
"events": _get_events(check, limit),
|
||||||
@ -388,11 +384,9 @@ def log(request, code):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def details(request, code):
|
def details(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user != request.team.user:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
channels = Channel.objects.filter(user=request.team.user)
|
channels = Channel.objects.filter(user=check.user)
|
||||||
channels = list(channels.order_by("created"))
|
channels = list(channels.order_by("created"))
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
@ -407,9 +401,7 @@ def details(request, code):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def status_single(request, code):
|
def status_single(request, code):
|
||||||
check = get_object_or_404(Check, code=code)
|
check = _get_check_for_user(request, code)
|
||||||
if check.user_id != request.team.user.id:
|
|
||||||
return HttpResponseForbidden()
|
|
||||||
|
|
||||||
status = check.get_status()
|
status = check.get_status()
|
||||||
events = _get_events(check, 20)
|
events = _get_events(check, 20)
|
||||||
|
@ -115,7 +115,12 @@
|
|||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a id="nav-email" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">
|
<a id="nav-email" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button">
|
||||||
{{ request.team }} <span class="caret"></span>
|
{% if check %}
|
||||||
|
{{ check.user.profile }}
|
||||||
|
{% else %}
|
||||||
|
{{ request.team }}
|
||||||
|
{% endif %}
|
||||||
|
<span class="caret"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
{% with teams=request.get_teams %}
|
{% with teams=request.get_teams %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user