sms: factorize OVH and SMSFactor connectors (#81143)
This commit is contained in:
parent
62e452c31e
commit
aed4c44107
|
@ -2,25 +2,19 @@ import hashlib
|
|||
import json
|
||||
import random
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from passerelle.base.models import SkipJob
|
||||
from passerelle.sms.models import SMSResource
|
||||
from passerelle.sms.models import TrackCreditSMSResource
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
|
||||
|
||||
class OVHSMSGateway(SMSResource):
|
||||
class OVHSMSGateway(TrackCreditSMSResource):
|
||||
documentation_url = (
|
||||
'https://doc-publik.entrouvert.com/admin-fonctionnel/les-tutos/configuration-envoi-sms/'
|
||||
)
|
||||
|
@ -83,17 +77,6 @@ class OVHSMSGateway(SMSResource):
|
|||
),
|
||||
)
|
||||
msg_class = models.IntegerField(choices=MESSAGES_CLASSES, default=1, verbose_name=_('Message class'))
|
||||
credit_threshold_alert = models.PositiveIntegerField(
|
||||
verbose_name=_('Credit alert threshold'), default=500
|
||||
)
|
||||
credit_left = models.PositiveIntegerField(verbose_name=_('Credit left'), default=0, editable=False)
|
||||
alert_emails = ArrayField(
|
||||
models.EmailField(blank=True),
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Email addresses list to send credit alerts to, separated by comma'),
|
||||
)
|
||||
credit_alert_timestamp = models.DateTimeField(null=True, editable=False)
|
||||
|
||||
TEST_DEFAULTS = {
|
||||
'create_kwargs': {
|
||||
|
@ -191,39 +174,15 @@ class OVHSMSGateway(SMSResource):
|
|||
self.save(update_credit=False)
|
||||
return credits_removed
|
||||
|
||||
def check_status(self):
|
||||
if self.uses_new_api:
|
||||
super().check_status()
|
||||
|
||||
def update_credit_left(self):
|
||||
result = self.request('get', endpoint='')
|
||||
self.credit_left = result['creditsLeft']
|
||||
self.save(update_credit=False)
|
||||
|
||||
def send_credit_alert_if_needed(self):
|
||||
if self.credit_left >= self.credit_threshold_alert:
|
||||
return
|
||||
if self.credit_alert_timestamp and self.credit_alert_timestamp > timezone.now() - timedelta(days=1):
|
||||
return # alerts are sent daily
|
||||
ctx = {
|
||||
'connector': self,
|
||||
'connector_url': urljoin(settings.SITE_BASE_URL, self.get_absolute_url()),
|
||||
}
|
||||
subject = render_to_string('ovh/credit_alert_subject.txt', ctx).strip()
|
||||
body = render_to_string('ovh/credit_alert_body.txt', ctx)
|
||||
html_body = render_to_string('ovh/credit_alert_body.html', ctx)
|
||||
send_mail(
|
||||
subject,
|
||||
body,
|
||||
settings.DEFAULT_FROM_EMAIL,
|
||||
self.alert_emails,
|
||||
html_message=html_body,
|
||||
)
|
||||
self.credit_alert_timestamp = timezone.now()
|
||||
self.save()
|
||||
self.logger.warning('credit is too low, alerts were sent to %s', self.alert_emails)
|
||||
|
||||
def check_status(self):
|
||||
if self.uses_new_api:
|
||||
self.update_credit_left()
|
||||
self.send_credit_alert_if_needed()
|
||||
|
||||
def save(self, *args, update_credit=True, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
if update_credit and self.uses_new_api:
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{% extends "emails/body_base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<p>{% trans "Hi," %}</p>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed with name=connector.title credit_left=connector.credit_left %}
|
||||
There are only {{ credit_left }} credits left for connector {{ name }}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed with account=connector.account %}
|
||||
Please add more credit as soon as possible for OVH account {{ account }}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
{% with _("View connector page") as button_label %}
|
||||
{% include "emails/button-link.html" with url=connector_url label=button_label %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
|
@ -1,17 +0,0 @@
|
|||
{% extends "emails/body_base.txt" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}{% autoescape off %}{% trans "Hi," %}
|
||||
|
||||
{% blocktrans trimmed with name=connector.title credit_left=connector.credit_left %}
|
||||
There are only {{ credit_left }} credits left for connector {{ name }}.
|
||||
{% endblocktrans %}
|
||||
|
||||
{% blocktrans trimmed with account=connector.account %}
|
||||
Please add more credit as soon as possible for OVH account {{ account }}.
|
||||
{% endblocktrans %}
|
||||
|
||||
{% trans "View connector page:" %} {{ connector_url }}
|
||||
|
||||
{% endautoescape %}
|
||||
{% endblock %}
|
|
@ -13,36 +13,19 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import datetime
|
||||
import logging
|
||||
import urllib.parse
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from passerelle.sms.models import SMSResource
|
||||
from passerelle.sms.models import TrackCreditSMSResource
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
|
||||
|
||||
class SMSFactorSMSGateway(SMSResource):
|
||||
class SMSFactorSMSGateway(TrackCreditSMSResource):
|
||||
auth_token = models.CharField(verbose_name=_('Auth Token'), max_length=255)
|
||||
credit_threshold_alert = models.PositiveIntegerField(
|
||||
verbose_name=_('Credit alert threshold'), default=500
|
||||
)
|
||||
credit_left = models.PositiveIntegerField(verbose_name=_('Credit left'), default=0, editable=False)
|
||||
alert_emails = ArrayField(
|
||||
models.EmailField(blank=True),
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Email addresses list to send credit alerts to, separated by comma'),
|
||||
)
|
||||
credit_alert_timestamp = models.DateTimeField(null=True, editable=False)
|
||||
|
||||
# unecessary field
|
||||
allow_premium_rate = None
|
||||
|
@ -173,36 +156,6 @@ class SMSFactorSMSGateway(SMSResource):
|
|||
try:
|
||||
# SMS Factor returns this as a string, for an unknown reason
|
||||
self.credit_left = int(result['credits'])
|
||||
self.save(update_fields=['credit_left'])
|
||||
except KeyError:
|
||||
self.logger.warning('Cannot retrieve credits for sms-factor connector: %s', result)
|
||||
else:
|
||||
self.save(update_fields=['credit_left'])
|
||||
|
||||
def send_credit_alert_if_needed(self):
|
||||
if self.credit_left >= self.credit_threshold_alert:
|
||||
return
|
||||
if self.credit_alert_timestamp and self.credit_alert_timestamp > timezone.now() - datetime.timedelta(
|
||||
days=1
|
||||
):
|
||||
return # alerts are sent daily
|
||||
ctx = {
|
||||
'connector': self,
|
||||
'connector_url': urllib.parse.urljoin(settings.SITE_BASE_URL, self.get_absolute_url()),
|
||||
}
|
||||
subject = render_to_string('smsfactor/credit_alert_subject.txt', ctx).strip()
|
||||
body = render_to_string('smsfactor/credit_alert_body.txt', ctx)
|
||||
html_body = render_to_string('smsfactor/credit_alert_body.html', ctx)
|
||||
send_mail(
|
||||
subject,
|
||||
body,
|
||||
settings.DEFAULT_FROM_EMAIL,
|
||||
self.alert_emails,
|
||||
html_message=html_body,
|
||||
)
|
||||
self.credit_alert_timestamp = timezone.now()
|
||||
self.save()
|
||||
self.logger.warning('credit is too low, alerts were sent to %s', self.alert_emails)
|
||||
|
||||
def check_status(self):
|
||||
self.update_credit_left()
|
||||
self.send_credit_alert_if_needed()
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
{% extends "emails/subject.txt" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block email-subject %}{% autoescape off %}{% blocktrans trimmed with credit_left=connector.credit_left %}
|
||||
SMS Factor alert: only {{ credit_left }} credits left
|
||||
{% endblocktrans %}{% endautoescape %}{% endblock %}
|
|
@ -13,13 +13,19 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
import urllib.parse
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.core.mail import send_mail
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import re_path, reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -256,3 +262,52 @@ class SMSLog(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return '%s %s %s' % (self.timestamp, self.appname, self.slug)
|
||||
|
||||
|
||||
class TrackCreditSMSResource(SMSResource):
|
||||
credit_threshold_alert = models.PositiveIntegerField(
|
||||
verbose_name=_('Credit alert threshold'), default=500
|
||||
)
|
||||
credit_left = models.PositiveIntegerField(verbose_name=_('Credit left'), default=0, editable=False)
|
||||
alert_emails = ArrayField(
|
||||
models.EmailField(blank=True),
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Email addresses list to send credit alerts to, separated by comma'),
|
||||
)
|
||||
credit_alert_timestamp = models.DateTimeField(null=True, editable=False)
|
||||
|
||||
def update_credit_left(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def send_credit_alert_if_needed(self):
|
||||
if self.credit_left >= self.credit_threshold_alert:
|
||||
return
|
||||
if self.credit_alert_timestamp and self.credit_alert_timestamp > timezone.now() - datetime.timedelta(
|
||||
days=1
|
||||
):
|
||||
return # alerts are sent daily
|
||||
ctx = {
|
||||
'connector': self,
|
||||
'connector_url': urllib.parse.urljoin(settings.SITE_BASE_URL, self.get_absolute_url()),
|
||||
}
|
||||
subject = render_to_string('sms/credit_alert_subject.txt', ctx).strip()
|
||||
body = render_to_string('sms/credit_alert_body.txt', ctx)
|
||||
html_body = render_to_string('sms/credit_alert_body.html', ctx)
|
||||
send_mail(
|
||||
subject,
|
||||
body,
|
||||
settings.DEFAULT_FROM_EMAIL,
|
||||
self.alert_emails,
|
||||
html_message=html_body,
|
||||
)
|
||||
self.credit_alert_timestamp = timezone.now()
|
||||
self.save()
|
||||
self.logger.warning('credit is too low, alerts were sent to %s', self.alert_emails)
|
||||
|
||||
def check_status(self):
|
||||
self.update_credit_left()
|
||||
self.send_credit_alert_if_needed()
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<p>
|
||||
{% blocktrans trimmed with account=connector.account %}
|
||||
Please add more credit as soon as possible for your SMS Factor account.
|
||||
Please add more credit as soon as possible for your account.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
|
@ -20,3 +20,4 @@
|
|||
{% include "emails/button-link.html" with url=connector_url label=button_label %}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
|
@ -7,11 +7,12 @@
|
|||
There are only {{ credit_left }} credits left for connector {{ name }}.
|
||||
{% endblocktrans %}
|
||||
|
||||
{% blocktrans trimmed with account=connector.account %}
|
||||
Please add more credit as soon as possible for your SMS Factor account.
|
||||
{% blocktrans trimmed %}
|
||||
Please add more credit as soon as possible for your account.
|
||||
{% endblocktrans %}
|
||||
|
||||
{% trans "View connector page:" %} {{ connector_url }}
|
||||
|
||||
{% endautoescape %}
|
||||
{% endblock %}
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block email-subject %}{% autoescape off %}{% blocktrans trimmed with credit_left=connector.credit_left %}
|
||||
OVH SMS alert: only {{ credit_left }} credits left
|
||||
SMS alert: only {{ credit_left }} credits left
|
||||
{% endblocktrans %}{% endautoescape %}{% endblock %}
|
|
@ -28,14 +28,18 @@ from passerelle.apps.ovh.models import OVHSMSGateway
|
|||
from passerelle.apps.sfr_dmc.models import SfrDmcGateway
|
||||
from passerelle.apps.smsfactor.models import SMSFactorSMSGateway
|
||||
from passerelle.base.models import AccessRight, ApiUser, Job, ResourceLog
|
||||
from passerelle.sms.models import SMSLog, SMSResource
|
||||
from passerelle.sms.models import SMSLog, SMSResource, TrackCreditSMSResource
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
from tests.test_manager import login
|
||||
from tests.utils import FakedResponse
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
klasses = SMSResource.__subclasses__()
|
||||
klasses = [
|
||||
klass
|
||||
for klass in SMSResource.__subclasses__() + TrackCreditSMSResource.__subclasses__()
|
||||
if not klass._meta.abstract
|
||||
]
|
||||
|
||||
|
||||
def test_clean_numbers():
|
||||
|
@ -526,9 +530,8 @@ def test_ovh_alert_emails(app, freezer, mailoutbox):
|
|||
|
||||
mail = mailoutbox[0]
|
||||
assert mail.recipients() == ['test@entrouvert.org']
|
||||
assert mail.subject == 'OVH SMS alert: only 99 credits left'
|
||||
assert mail.subject == 'SMS alert: only 99 credits left'
|
||||
for body in (mail.body, mail.alternatives[0][0]):
|
||||
assert connector.account in body
|
||||
assert connector.title in body
|
||||
assert 'http://localhost/ovh/test-ovh/' in body
|
||||
mailoutbox.clear()
|
||||
|
@ -810,7 +813,7 @@ def test_sms_factor_alert_emails(app, freezer, mailoutbox):
|
|||
|
||||
mail = mailoutbox[0]
|
||||
assert mail.recipients() == ['test@entrouvert.org']
|
||||
assert mail.subject == 'SMS Factor alert: only 99 credits left'
|
||||
assert mail.subject == 'SMS alert: only 99 credits left'
|
||||
for body in (mail.body, mail.alternatives[0][0]):
|
||||
assert 'SMS Factor' in body
|
||||
assert connector.title in body
|
||||
|
|
Loading…
Reference in New Issue