From f4aab6ee5723e4127bcc4766efc79c4098769884 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Sat, 23 May 2020 11:12:48 +0200 Subject: [PATCH] Fixed OTP recognition Added balance check to SMS providers --- core/classes/sms.py | 6 +- core/modules/sms.py | 17 +++--- kumisms/__init__.py | 0 kumisms/admin.py | 3 + kumisms/apps.py | 5 ++ kumisms/models.py | 3 + kumisms/sms.py | 70 ++++++++++++++++++++++++ kumisms/tests.py | 3 + kumisms/views.py | 3 + playsms/models.py | 8 ++- smsotp/models.py | 2 +- templates/backend/auth/otp_selector.html | 2 +- templates/backend/auth/otp_verifier.html | 2 +- 13 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 kumisms/__init__.py create mode 100644 kumisms/admin.py create mode 100644 kumisms/apps.py create mode 100644 kumisms/models.py create mode 100644 kumisms/sms.py create mode 100644 kumisms/tests.py create mode 100644 kumisms/views.py diff --git a/core/classes/sms.py b/core/classes/sms.py index eafc872..8ab8486 100644 --- a/core/classes/sms.py +++ b/core/classes/sms.py @@ -21,7 +21,11 @@ class BaseSMSProvider: @property def get_edit_url(self): - return + return False + + @property + def get_balance(self): + return False def sendSMS(self, recipients: Union[str, list], message: str): '''Send an SMS message to one or more recipients diff --git a/core/modules/sms.py b/core/modules/sms.py index 7aef123..0c076cf 100644 --- a/core/modules/sms.py +++ b/core/modules/sms.py @@ -18,20 +18,21 @@ for module in settings.EXPEPHALON_MODULES: except (AttributeError, ModuleNotFoundError): continue -def get_sms_provider_by_name(name): +def get_sms_provider_by_name(name, active=False): for provider in providers: - if provider.name == name: + if provider.get_name == name and (provider.is_active or not active): return provider def get_default_sms_provider_name(): return getValue("core.sms.default", False) def get_default_sms_provider(): - name = get_default_sms_provider_name() - if name: - for provider in providers: - if provider.name == name and provider.is_active: - return provider + provider = get_sms_provider_by_name(get_default_sms_provider_name(), True) + if provider: + return provider + for provider in providers: if provider.is_active: - return provider \ No newline at end of file + return provider + + raise RuntimeError("No SMS provider is currently active") \ No newline at end of file diff --git a/kumisms/__init__.py b/kumisms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kumisms/admin.py b/kumisms/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/kumisms/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/kumisms/apps.py b/kumisms/apps.py new file mode 100644 index 0000000..b6cfebc --- /dev/null +++ b/kumisms/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class KumismsConfig(AppConfig): + name = 'kumisms' diff --git a/kumisms/models.py b/kumisms/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/kumisms/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/kumisms/sms.py b/kumisms/sms.py new file mode 100644 index 0000000..0ef1c86 --- /dev/null +++ b/kumisms/sms.py @@ -0,0 +1,70 @@ +from core.classes.sms import BaseSMSProvider, SMSNotSent + +from dbsettings.functions import getValue + +from urllib.parse import urlencode +from urllib.request import urlopen, Request +from typing import Union + +import json + +# Create your models here. + +class KumiSMSServer(BaseSMSProvider): + @property + def is_active(self): + return bool(self.get_balance) + + @property + def get_name(self): + return "Kumi SMS" + + @property + def get_key(self): + return getValue("kumisms.apikey") + + @staticmethod + def getError(status): + if "error" in status.keys(): + return status["error"] + + def sendSMS(self, recipients: Union[str, list], message: str): + '''Send an SMS message to one or more recipients + + :param recipients: Recipient phone number as a string, or a list of multiple phone number strings + :param message: Message to be sent as a string + ''' + + if isinstance(recipients, str): + recipients = [recipients] + + url = 'https://kumisms.com/api/v1/send/' + + for recipient in recipients: + vars = {"key": self.get_key, "text": message, "recipient": recipient} + + request = Request(url, urlencode(vars).encode()) + response = urlopen(request) + + status = json.loads(response.read().decode()) + + error = KumiSMSServer.getError(status) + + if error: + raise SMSNotSent(f'An error occurred trying to send the SMS: {error}') + + @property + def get_balance(self): + url = 'https://kumisms.com/api/v1/balance/' + + vars = {"key": self.get_key} + + request = Request(url, urlencode(vars).encode()) + response = urlopen(request) + + status = json.loads(response.read().decode()) + + if not KumiSMSServer.getError(status): + return status["balance"] + +SMSPROVIDERS = [KumiSMSServer()] \ No newline at end of file diff --git a/kumisms/tests.py b/kumisms/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/kumisms/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/kumisms/views.py b/kumisms/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/kumisms/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/playsms/models.py b/playsms/models.py index a4cbe74..0b7b90f 100644 --- a/playsms/models.py +++ b/playsms/models.py @@ -12,7 +12,7 @@ import json # Create your models here. class PlaySMSServer(Model, BaseSMSProvider): - name = CharField(max_length=255) + name = CharField(max_length=255, unique=True) logo = CharField(max_length=255) https = BooleanField(default=True) host = CharField(max_length=255) @@ -23,6 +23,10 @@ class PlaySMSServer(Model, BaseSMSProvider): def is_active(self): return True + @property + def get_name(self): + return self.name + @staticmethod def getError(status): if status["error_string"]: @@ -45,11 +49,9 @@ class PlaySMSServer(Model, BaseSMSProvider): url = 'http%s://%s/index.php?app=ws&u=%s&h=%s&op=pv&to=%s&msg=%s' % ("s" if self.https else "", self.host, self.username, self.token, recipients, quote_plus(message)) - print(url) response = urlopen(url) status = json.loads(response.read().decode()) - print(status) error = PlaySMSServer.getError(status) diff --git a/smsotp/models.py b/smsotp/models.py index cfbcb88..59f80c9 100644 --- a/smsotp/models.py +++ b/smsotp/models.py @@ -23,4 +23,4 @@ class OTPToken(Model): provider = get_default_sms_provider() - provider.sendSMS(number, text) \ No newline at end of file + provider.sendSMS(str(number), text) \ No newline at end of file diff --git a/templates/backend/auth/otp_selector.html b/templates/backend/auth/otp_selector.html index 8d9387a..256c182 100644 --- a/templates/backend/auth/otp_selector.html +++ b/templates/backend/auth/otp_selector.html @@ -4,7 +4,7 @@

- Welcome back, + Welcome back {{ request.user.first_name }}, Please select your Two-Factor Authentication provider

{% bootstrap_messages %}
diff --git a/templates/backend/auth/otp_verifier.html b/templates/backend/auth/otp_verifier.html index 0a27c53..5cad949 100644 --- a/templates/backend/auth/otp_verifier.html +++ b/templates/backend/auth/otp_verifier.html @@ -4,7 +4,7 @@