Browse Source

Implement alternative ping URLs, WIP

pull/563/head
Pēteris Caune 3 years ago
parent
commit
5b9008e321
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
20 changed files with 182 additions and 18 deletions
  1. +23
    -0
      hc/accounts/migrations/0045_auto_20210908_1257.py
  2. +11
    -2
      hc/accounts/models.py
  3. +1
    -0
      hc/accounts/tests/test_signup.py
  4. +2
    -1
      hc/accounts/views.py
  5. +22
    -0
      hc/api/migrations/0079_auto_20210907_0918.py
  6. +19
    -0
      hc/api/migrations/0080_fill_slug.py
  7. +25
    -2
      hc/api/models.py
  8. +2
    -0
      hc/api/tests/test_create_check.py
  9. +5
    -3
      hc/api/tests/test_get_check.py
  10. +1
    -0
      hc/api/tests/test_update_check.py
  11. +1
    -0
      hc/api/urls.py
  12. +6
    -1
      hc/api/views.py
  13. +2
    -0
      hc/front/tests/test_copy.py
  14. +1
    -0
      hc/front/tests/test_update_name.py
  15. +6
    -2
      hc/front/views.py
  16. +10
    -2
      static/css/my_checks_desktop.css
  17. +10
    -2
      templates/accounts/project.html
  18. +10
    -0
      templates/docs/api.html
  19. +10
    -0
      templates/docs/api.md
  20. +15
    -3
      templates/front/my_checks_desktop.html

+ 23
- 0
hc/accounts/migrations/0045_auto_20210908_1257.py View File

@ -0,0 +1,23 @@
# Generated by Django 3.2.6 on 2021-09-08 12:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0044_auto_20210730_0942'),
]
operations = [
migrations.AddField(
model_name='project',
name='ping_key',
field=models.CharField(blank=True, max_length=128, null=True, unique=True),
),
migrations.AddField(
model_name='project',
name='show_slugs',
field=models.BooleanField(default=False),
),
]

+ 11
- 2
hc/accounts/models.py View File

@ -322,6 +322,8 @@ class Project(models.Model):
api_key = models.CharField(max_length=128, blank=True, db_index=True)
api_key_readonly = models.CharField(max_length=128, blank=True, db_index=True)
badge_key = models.CharField(max_length=150, unique=True)
ping_key = models.CharField(max_length=128, blank=True, null=True, unique=True)
show_slugs = models.BooleanField(default=False)
def __str__(self):
return self.name or self.owner.email
@ -337,8 +339,15 @@ class Project(models.Model):
return self.owner_profile.num_checks_available()
def set_api_keys(self):
self.api_key = token_urlsafe(nbytes=24)
self.api_key_readonly = token_urlsafe(nbytes=24)
def pick(nbytes=24):
while True:
candidate = token_urlsafe(nbytes)
if candidate[0] not in "-_" and candidate[-1] not in "-_":
return candidate
self.api_key = pick()
self.api_key_readonly = pick()
self.ping_key = pick(16)
self.save()
def invite_suggestions(self):


+ 1
- 0
hc/accounts/tests/test_signup.py View File

@ -39,6 +39,7 @@ class SignupTestCase(TestCase):
# And check should be associated with the new user
check = Check.objects.get()
self.assertEqual(check.name, "My First Check")
self.assertEqual(check.slug, "my-first-check")
self.assertEqual(check.project, project)
# A channel should have been created


+ 2
- 1
hc/accounts/views.py View File

@ -79,7 +79,7 @@ def _make_user(email, tz=None, with_project=True):
project.save()
check = Check(project=project)
check.name = "My First Check"
check.set_name_slug("My First Check")
check.save()
channel = Channel(project=project)
@ -336,6 +336,7 @@ def project(request, code):
project.api_key = ""
project.api_key_readonly = ""
project.ping_key = None
project.save()
ctx["api_keys_revoked"] = True


+ 22
- 0
hc/api/migrations/0079_auto_20210907_0918.py View File

@ -0,0 +1,22 @@
# Generated by Django 3.2.6 on 2021-09-07 09:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0078_sms_values'),
]
operations = [
migrations.AddField(
model_name='check',
name='slug',
field=models.CharField(blank=True, max_length=100),
),
migrations.AddIndex(
model_name='check',
index=models.Index(fields=['project_id', 'slug'], name='api_check_project_slug'),
),
]

+ 19
- 0
hc/api/migrations/0080_fill_slug.py View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.6 on 2021-09-07 09:19
from django.db import migrations
from django.utils.text import slugify
def fill_slug(apps, schema_editor):
Check = apps.get_model("api", "CHeck")
for c in Check.objects.exclude(name="").only("name"):
Check.objects.filter(id=c.id).update(slug=slugify(c.name))
class Migration(migrations.Migration):
dependencies = [
("api", "0079_auto_20210907_0918"),
]
operations = [migrations.RunPython(fill_slug, migrations.RunPython.noop)]

+ 25
- 2
hc/api/models.py View File

@ -12,6 +12,7 @@ from django.core.signing import TimestampSigner
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from hc.accounts.models import Project
from hc.api import transports
from hc.lib import emails
@ -68,6 +69,7 @@ def isostring(dt):
class Check(models.Model):
name = models.CharField(max_length=100, blank=True)
slug = models.CharField(max_length=100, blank=True)
tags = models.CharField(max_length=500, blank=True)
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
desc = models.TextField(blank=True)
@ -100,7 +102,8 @@ class Check(models.Model):
fields=["alert_after"],
name="api_check_aa_not_down",
condition=~models.Q(status="down"),
)
),
models.Index(fields=["project_id", "slug"], name="api_check_project_slug"),
]
def __str__(self):
@ -112,8 +115,23 @@ class Check(models.Model):
return str(self.code)
def relative_url(self):
if self.project.show_slugs:
if not self.slug:
return None
key = self.project.ping_key
# If ping_key is not set, use dummy placeholder
if key is None:
key = "{ping_key}"
return key + "/" + self.slug
return str(self.code)
def url(self):
return settings.PING_ENDPOINT + str(self.code)
s = self.relative_url()
if s:
return settings.PING_ENDPOINT + s
def details_url(self):
return settings.SITE_ROOT + reverse("hc-details", args=[self.code])
@ -128,6 +146,10 @@ class Check(models.Model):
if self.last_duration and self.last_duration < MAX_DELTA:
return self.last_duration
def set_name_slug(self, name):
self.name = name
self.slug = slugify(name)
def get_grace_start(self, with_started=True):
""" Return the datetime when the grace period starts.
@ -224,6 +246,7 @@ class Check(models.Model):
result = {
"name": self.name,
"slug": self.slug,
"tags": self.tags,
"desc": self.desc,
"grace": int(self.grace.total_seconds()),


+ 2
- 0
hc/api/tests/test_create_check.py View File

@ -28,6 +28,7 @@ class CreateCheckTestCase(BaseTestCase):
doc = r.json()
assert "ping_url" in doc
self.assertEqual(doc["name"], "Foo")
self.assertEqual(doc["slug"], "foo")
self.assertEqual(doc["tags"], "bar,baz")
self.assertEqual(doc["last_ping"], None)
self.assertEqual(doc["n_pings"], 0)
@ -38,6 +39,7 @@ class CreateCheckTestCase(BaseTestCase):
check = Check.objects.get()
self.assertEqual(check.name, "Foo")
self.assertEqual(check.slug, "foo")
self.assertEqual(check.tags, "bar,baz")
self.assertEqual(check.methods, "")
self.assertEqual(check.timeout.total_seconds(), 3600)


+ 5
- 3
hc/api/tests/test_get_check.py View File

@ -11,7 +11,8 @@ class GetCheckTestCase(BaseTestCase):
self.now = now().replace(microsecond=0)
self.a1 = Check(project=self.project, name="Alice 1")
self.a1 = Check(project=self.project)
self.a1.set_name_slug("Alice 1")
self.a1.timeout = td(seconds=3600)
self.a1.grace = td(seconds=900)
self.a1.n_pings = 0
@ -33,8 +34,9 @@ class GetCheckTestCase(BaseTestCase):
self.assertEqual(r["Access-Control-Allow-Origin"], "*")
doc = r.json()
self.assertEqual(len(doc), 15)
self.assertEqual(len(doc), 16)
self.assertEqual(doc["slug"], "alice-1")
self.assertEqual(doc["timeout"], 3600)
self.assertEqual(doc["grace"], 900)
self.assertEqual(doc["ping_url"], self.a1.url())
@ -61,7 +63,7 @@ class GetCheckTestCase(BaseTestCase):
self.assertEqual(r["Access-Control-Allow-Origin"], "*")
doc = r.json()
self.assertEqual(len(doc), 15)
self.assertEqual(len(doc), 16)
self.assertEqual(doc["timeout"], 3600)
self.assertEqual(doc["grace"], 900)


+ 1
- 0
hc/api/tests/test_update_check.py View File

@ -38,6 +38,7 @@ class UpdateCheckTestCase(BaseTestCase):
doc = r.json()
assert "ping_url" in doc
self.assertEqual(doc["name"], "Foo")
self.assertEqual(doc["slug"], "foo")
self.assertEqual(doc["tags"], "bar,baz")
self.assertEqual(doc["desc"], "My description")
self.assertEqual(doc["n_pings"], 0)


+ 1
- 0
hc/api/urls.py View File

@ -33,6 +33,7 @@ urlpatterns = [
path("ping/<uuid:code>/fail", views.ping, {"action": "fail"}, name="hc-fail"),
path("ping/<uuid:code>/start", views.ping, {"action": "start"}, name="hc-start"),
path("ping/<uuid:code>/<int:exitstatus>", views.ping),
path("ping/<slug:ping_key>/<slug:slug>", views.ping_by_slug),
path("api/v1/checks/", views.checks),
path("api/v1/checks/<uuid:code>", views.single, name="hc-api-single"),
path("api/v1/checks/<sha1:unique_key>", views.get_check_by_unique_key),


+ 6
- 1
hc/api/views.py View File

@ -55,6 +55,11 @@ def ping(request, code, action="success", exitstatus=None):
return response
def ping_by_slug(request, ping_key, slug, action="success", exitstatus=None):
check = get_object_or_404(Check, slug=slug, project__ping_key=ping_key)
return ping(request, check.code, action, exitstatus)
def _lookup(project, spec):
unique_fields = spec.get("unique", [])
if unique_fields:
@ -108,7 +113,7 @@ def _update(check, spec):
need_save = True
if "name" in spec and check.name != spec["name"]:
check.name = spec["name"]
check.set_name_slug(spec["name"])
need_save = True
if "tags" in spec and check.tags != spec["tags"]:


+ 2
- 0
hc/front/tests/test_copy.py View File

@ -7,6 +7,7 @@ class CopyCheckTestCase(BaseTestCase):
super().setUp()
self.check = Check(project=self.project)
self.check.name = "Foo"
self.check.slug = "foo"
self.check.subject = "success-keyword"
self.check.subject_fail = "failure-keyword"
self.check.methods = "POST"
@ -21,6 +22,7 @@ class CopyCheckTestCase(BaseTestCase):
self.assertContains(r, "This is a brand new check")
copy = Check.objects.get(name="Foo (copy)")
self.assertEqual(copy.slug, "foo-copy")
self.assertEqual(copy.subject, "success-keyword")
self.assertEqual(copy.subject_fail, "failure-keyword")
self.assertEqual(copy.methods, "POST")


+ 1
- 0
hc/front/tests/test_update_name.py View File

@ -17,6 +17,7 @@ class UpdateNameTestCase(BaseTestCase):
self.check.refresh_from_db()
self.assertEqual(self.check.name, "Alice Was Here")
self.assertEqual(self.check.slug, "alice-was-here")
def test_team_access_works(self):
payload = {"name": "Bob Was Here"}


+ 6
- 2
hc/front/views.py View File

@ -174,6 +174,10 @@ def my_checks(request, code):
request.profile.sort = request.GET["sort"]
request.profile.save()
if request.GET.get("urls") in ("uuid", "slug") and rw:
project.show_slugs = request.GET["urls"] == "slug"
project.save()
if request.session.get("last_project_id") != project.id:
request.session["last_project_id"] = project.id
@ -402,7 +406,7 @@ def update_name(request, code):
form = forms.NameTagsForm(request.POST)
if form.is_valid():
check.name = form.cleaned_data["name"]
check.set_name_slug(form.cleaned_data["name"])
check.tags = form.cleaned_data["tags"]
check.desc = form.cleaned_data["desc"]
check.save()
@ -694,7 +698,7 @@ def copy(request, code):
new_name = check.name[:90] + "... (copy)"
copied = Check(project=check.project)
copied.name = new_name
copied.set_name_slug(new_name)
copied.desc, copied.tags = check.desc, check.tags
copied.subject, copied.subject_fail = check.subject, check.subject_fail
copied.methods = check.methods


+ 10
- 2
static/css/my_checks_desktop.css View File

@ -6,7 +6,7 @@
background-color: var(--table-bg-hover);
}
.my-checks-name.unnamed {
.my-checks-name.unnamed, .url span.unavailable {
color: var(--text-muted);
font-style: italic;
}
@ -132,7 +132,7 @@ tr:hover .copy-link {
white-space: nowrap;
}
#checks-table .btn {
#checks-table td .btn {
border-color: transparent;
background-color: transparent;
font-size: 20px;
@ -159,3 +159,11 @@ tr:hover .copy-link {
color: #FFF;
outline: none;
}
#url-style-switcher a {
color: var(--text-muted);
}
#url-style-switcher a.active {
text-decoration: underline;
}

+ 10
- 2
templates/accounts/project.html View File

@ -89,9 +89,17 @@
API key (read-only): <br />
<pre>{{ project.api_key_readonly }}</pre>
</p>
<p>Related links:</p>
{% endif %}
{% if project.ping_key %}
<p>
Ping key: <br />
<pre>{{ project.ping_key }}</pre>
</p>
{% endif %}
<p>See also:</p>
<ul>
<li><a href="{% url 'hc-serve-doc' 'api' %}">API documentation</a></li>
{% if project.api_key_readonly %}
{% if enable_prometheus %}
<li>
<a href="{% url 'hc-metrics' project.code project.api_key_readonly %}">Prometheus metrics endpoint</a>
@ -101,8 +109,8 @@
<a href="{{ project.dashboard_url }}">Read-only dashboard</a>
(<a href="https://github.com/healthchecks/dashboard/#security">security considerations</a>)
</li>
{% endif %}
</ul>
{% endif %}
<button
data-toggle="modal"
data-target="#revoke-api-key-modal"


+ 10
- 0
templates/docs/api.html View File

@ -116,6 +116,7 @@ specified value.</p>
<span class="nt">&quot;checks&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Filesystem Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;filesystem-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;backup fs&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs incremental backup every hour&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">600</span><span class="p">,</span>
@ -133,6 +134,7 @@ specified value.</p>
<span class="p">},</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Database Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;database-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;production db&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs ~/db-backup.sh&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">1200</span><span class="p">,</span>
@ -165,6 +167,7 @@ and <a href="#list-flips">Get a list of check's status changes</a> API calls.</p
<span class="nt">&quot;checks&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Filesystem Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;filesystem-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;backup fs&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs incremental backup every hour&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">600</span><span class="p">,</span>
@ -179,6 +182,7 @@ and <a href="#list-flips">Get a list of check's status changes</a> API calls.</p
<span class="p">},</span>
<span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Database Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;database-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;production db&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs ~/db-backup.sh&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">1200</span><span class="p">,</span>
@ -220,6 +224,7 @@ using the read-only API key) as an identifier.</p>
<h3>Example Response</h3>
<div class="highlight"><pre><span></span><code><span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Database Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;database-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;production db&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs ~/db-backup.sh&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">1200</span><span class="p">,</span>
@ -249,6 +254,7 @@ API responses, the client can easily construct these URLs themselves <em>if</em>
check's unique UUID.</p>
<div class="highlight"><pre><span></span><code><span class="p">{</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Database Backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;database-backup&quot;</span><span class="p">,</span>
<span class="nt">&quot;tags&quot;</span><span class="p">:</span> <span class="s2">&quot;production db&quot;</span><span class="p">,</span>
<span class="nt">&quot;desc&quot;</span><span class="p">:</span> <span class="s2">&quot;Runs ~/db-backup.sh&quot;</span><span class="p">,</span>
<span class="nt">&quot;grace&quot;</span><span class="p">:</span> <span class="mi">1200</span><span class="p">,</span>
@ -416,6 +422,7 @@ the limit is 20 checks per account.</dd>
<span class="nt">&quot;last_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;n_pings&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;next_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;manual_resume&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;methods&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">,</span>
@ -558,6 +565,7 @@ field values.</dd>
<span class="nt">&quot;last_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;n_pings&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;next_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;manual_resume&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;methods&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">,</span>
@ -602,6 +610,7 @@ header is sometimes required by some network proxies and web servers.</p>
<span class="nt">&quot;last_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;n_pings&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;next_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;manual_resume&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;methods&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">,</span>
@ -643,6 +652,7 @@ check that was just deleted.</p>
<span class="nt">&quot;last_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;n_pings&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;Backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;slug&quot;</span><span class="p">:</span> <span class="s2">&quot;backups&quot;</span><span class="p">,</span>
<span class="nt">&quot;next_ping&quot;</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="nt">&quot;manual_resume&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;methods&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">,</span>


+ 10
- 0
templates/docs/api.md View File

@ -97,6 +97,7 @@ curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/
"checks": [
{
"name": "Filesystem Backup",
"slug": "filesystem-backup",
"tags": "backup fs",
"desc": "Runs incremental backup every hour",
"grace": 600,
@ -114,6 +115,7 @@ curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/
},
{
"name": "Database Backup",
"slug": "database-backup",
"tags": "production db",
"desc": "Runs ~/db-backup.sh",
"grace": 1200,
@ -150,6 +152,7 @@ Example:
"checks": [
{
"name": "Filesystem Backup",
"slug": "filesystem-backup",
"tags": "backup fs",
"desc": "Runs incremental backup every hour",
"grace": 600,
@ -164,6 +167,7 @@ Example:
},
{
"name": "Database Backup",
"slug": "database-backup",
"tags": "production db",
"desc": "Runs ~/db-backup.sh",
"grace": 1200,
@ -215,6 +219,7 @@ curl --header "X-Api-Key: your-api-key" SITE_ROOT/api/v1/checks/<uuid>
```json
{
"name": "Database Backup",
"slug": "database-backup",
"tags": "production db",
"desc": "Runs ~/db-backup.sh",
"grace": 1200,
@ -249,6 +254,7 @@ check's unique UUID.
```json
{
"name": "Database Backup",
"slug": "database-backup",
"tags": "production db",
"desc": "Runs ~/db-backup.sh",
"grace": 1200,
@ -456,6 +462,7 @@ curl SITE_ROOT/api/v1/checks/ \
"last_ping": null,
"n_pings": 0,
"name": "Backups",
"slug": "backups",
"next_ping": null,
"manual_resume": false,
"methods": "",
@ -636,6 +643,7 @@ curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
"last_ping": null,
"n_pings": 0,
"name": "Backups",
"slug": "backups",
"next_ping": null,
"manual_resume": false,
"methods": "",
@ -692,6 +700,7 @@ header is sometimes required by some network proxies and web servers.
"last_ping": null,
"n_pings": 0,
"name": "Backups",
"slug": "backups",
"next_ping": null,
"manual_resume": false,
"methods": "",
@ -744,6 +753,7 @@ curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc \
"last_ping": null,
"n_pings": 0,
"name": "Backups",
"slug": "backups",
"next_ping": null,
"manual_resume": false,
"methods": "",


+ 15
- 3
templates/front/my_checks_desktop.html View File

@ -22,8 +22,16 @@
{% endif %}
</th>
<th class="hidden-xs hidden-sm">
<span class="visible-lg">Ping URL</span>
<span class="visible-md">Code</span>
<span class="visible-lg-inline">
Ping URL
</span>
<span class="visible-md-inline">{{ project.show_slugs|yesno:"Key/Slug,UUID" }}</span>
{% if rw %}
<small id="url-style-switcher">
<a href="?urls=uuid" {% if not project.show_slugs %}class="active"{% endif %}>uuid</a>
<a href="?urls=slug" {% if project.show_slugs %}class="active"{% endif %}>slug</a>
</small>
{% endif %}
</th>
<th class="th-integrations hidden-xs">Integrations</th>
<th class="th-period hidden-xs">
@ -73,12 +81,16 @@
</div>
</td>
<td class="hidden-xs hidden-sm url">
{% if project.show_slugs and not check.slug %}
<span class="unavailable">unavailable, set name first</span>
{% else %}
<span class="my-checks-url">
<span class="base hidden-md">{{ ping_endpoint }}</span>{{ check.code }}
<span class="base hidden-md">{{ ping_endpoint }}</span>{{ check.relative_url }}
</span>
<button class="copy-link" data-clipboard-text="{{ check.url }}">
copy
</button>
{% endif %}
</td>
<td class="hidden-xs">
{% if channels|length <= 10 %}


Loading…
Cancel
Save