forked from GithubBackups/healthchecks
SMS numbers can be annotated with labels. Fixes #155
This commit is contained in:
parent
5551a1cfd7
commit
cf6882edd3
@ -161,6 +161,7 @@ class ChannelsAdmin(admin.ModelAdmin):
|
||||
list_display = ("id", "code", "email", "formatted_kind", "value",
|
||||
"num_notifications")
|
||||
list_filter = ("kind", )
|
||||
raw_id_fields = ("user", "checks", )
|
||||
|
||||
def email(self, obj):
|
||||
return obj.user.email if obj.user else None
|
||||
|
@ -463,6 +463,21 @@ class Channel(models.Model):
|
||||
def latest_notification(self):
|
||||
return Notification.objects.filter(channel=self).latest()
|
||||
|
||||
@property
|
||||
def sms_number(self):
|
||||
assert self.kind == "sms"
|
||||
if self.value.startswith("{"):
|
||||
doc = json.loads(self.value)
|
||||
return doc["value"]
|
||||
return self.value
|
||||
|
||||
@property
|
||||
def sms_label(self):
|
||||
assert self.kind == "sms"
|
||||
if self.value.startswith("{"):
|
||||
doc = json.loads(self.value)
|
||||
return doc["label"]
|
||||
|
||||
|
||||
class Notification(models.Model):
|
||||
class Meta:
|
||||
|
@ -477,6 +477,21 @@ class NotifyTestCase(BaseTestCase):
|
||||
self.profile.refresh_from_db()
|
||||
self.assertEqual(self.profile.sms_sent, 1)
|
||||
|
||||
@patch("hc.api.transports.requests.request")
|
||||
def test_sms_handles_json_value(self, mock_post):
|
||||
value = {"label": "foo", "value": "+1234567890"}
|
||||
self._setup_data("sms", json.dumps(value))
|
||||
self.check.last_ping = now() - td(hours=2)
|
||||
|
||||
mock_post.return_value.status_code = 200
|
||||
|
||||
self.channel.notify(self.check)
|
||||
assert Notification.objects.count() == 1
|
||||
|
||||
args, kwargs = mock_post.call_args
|
||||
payload = kwargs["data"]
|
||||
self.assertEqual(payload["To"], "+1234567890")
|
||||
|
||||
@patch("hc.api.transports.requests.request")
|
||||
def test_sms_limit(self, mock_post):
|
||||
# At limit already:
|
||||
|
@ -369,7 +369,7 @@ class Sms(HttpTransport):
|
||||
|
||||
data = {
|
||||
'From': settings.TWILIO_FROM,
|
||||
'To': self.channel.value,
|
||||
'To': self.channel.sms_number,
|
||||
'Body': text,
|
||||
}
|
||||
|
||||
|
@ -105,4 +105,5 @@ phone_validator = RegexValidator(regex='^\+\d{5,15}$',
|
||||
|
||||
class AddSmsForm(forms.Form):
|
||||
error_css_class = "has-error"
|
||||
label = forms.CharField(max_length=100, required=False)
|
||||
value = forms.CharField(max_length=16, validators=[phone_validator])
|
||||
|
@ -22,7 +22,7 @@ class AddSmsTestCase(BaseTestCase):
|
||||
self.assertContains(r, "upgrade to a")
|
||||
|
||||
def test_it_creates_channel(self):
|
||||
form = {"value": "+1234567890"}
|
||||
form = {"label": "My Phone", "value": "+1234567890"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
@ -30,7 +30,8 @@ class AddSmsTestCase(BaseTestCase):
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.kind, "sms")
|
||||
self.assertEqual(c.value, "+1234567890")
|
||||
self.assertEqual(c.sms_number, "+1234567890")
|
||||
self.assertEqual(c.sms_label, "My Phone")
|
||||
|
||||
def test_it_rejects_bad_number(self):
|
||||
form = {"value": "not a phone number address"}
|
||||
@ -46,7 +47,7 @@ class AddSmsTestCase(BaseTestCase):
|
||||
self.client.post(self.url, form)
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.value, "+1234567890")
|
||||
self.assertEqual(c.sms_number, "+1234567890")
|
||||
|
||||
@override_settings(TWILIO_AUTH=None)
|
||||
def test_it_requires_credentials(self):
|
||||
|
@ -74,3 +74,14 @@ class ChannelsTestCase(BaseTestCase):
|
||||
r = self.client.get("/integrations/")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertContains(r, "(unconfirmed)")
|
||||
|
||||
def test_it_shows_sms_label(self):
|
||||
ch = Channel(kind="sms", user=self.alice)
|
||||
ch.value = json.dumps({"value": "+123", "label": "My Phone"})
|
||||
ch.save()
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get("/integrations/")
|
||||
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertContains(r, "My Phone (+123)")
|
||||
|
@ -896,7 +896,10 @@ def add_sms(request):
|
||||
form = AddSmsForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(user=request.team.user, kind="sms")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.value = json.dumps({
|
||||
"label": form.cleaned_data["label"],
|
||||
"value": form.cleaned_data["value"]
|
||||
})
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
|
@ -102,6 +102,12 @@
|
||||
{{ ch.hipchat_webhook_url }}
|
||||
{% elif ch.kind == "zendesk" %}
|
||||
{{ ch.zendesk_subdomain }}.zendesk.com
|
||||
{% elif ch.kind == "sms" %}
|
||||
{% if ch.sms_label %}
|
||||
{{ ch.sms_label }} ({{ ch.sms_number }})
|
||||
{% else %}
|
||||
{{ ch.sms_number }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ ch.value }}
|
||||
{% endif %}
|
||||
|
@ -9,14 +9,17 @@
|
||||
<div class="col-sm-12">
|
||||
<h1>SMS</h1>
|
||||
|
||||
<p>Get a SMS message to your specified number when check goes down.</p>
|
||||
<p>
|
||||
Get a SMS message to the specified phone number when a
|
||||
check goes down.
|
||||
</p>
|
||||
|
||||
{% if show_pricing and profile.sms_limit == 0 %}
|
||||
<p class="alert alert-success">
|
||||
<strong>Paid plan required.</strong>
|
||||
SMS messaging is not available on the free plan–sending the messages
|
||||
costs too much! Please upgrade to a
|
||||
<a href="{% url 'hc-pricing' %}">paid plan</a> to enable SMS messaging.
|
||||
cost too much! Please upgrade to a
|
||||
<a href="{% url 'hc-billing' %}">paid plan</a> to enable SMS messaging.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@ -24,6 +27,29 @@
|
||||
|
||||
<form method="post" class="form-horizontal" action="{% url 'hc-add-sms' %}">
|
||||
{% csrf_token %}
|
||||
<div class="form-group {{ form.label.css_classes }}">
|
||||
<label for="id_label" class="col-sm-2 control-label">Label</label>
|
||||
<div class="col-sm-6">
|
||||
<input
|
||||
id="id_label"
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="label"
|
||||
placeholder="Alice's Phone"
|
||||
value="{{ form.label.value|default:"" }}">
|
||||
|
||||
{% if form.label.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.label.errors|join:"" }}
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="help-block">
|
||||
Optional. If you add multiple phone numbers,
|
||||
the labels will help you tell them apart.
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="id_number" class="col-sm-2 control-label">Phone Number</label>
|
||||
<div class="col-sm-3">
|
||||
@ -39,6 +65,11 @@
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="help-block">
|
||||
Make sure the phone number starts with "+" and has the
|
||||
country code.
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user