Fixed OTP recognition
Added balance check to SMS providers
This commit is contained in:
parent
6a1b3843df
commit
f4aab6ee57
13 changed files with 109 additions and 15 deletions
|
@ -21,7 +21,11 @@ class BaseSMSProvider:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def get_edit_url(self):
|
def get_edit_url(self):
|
||||||
return
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_balance(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def sendSMS(self, recipients: Union[str, list], message: str):
|
def sendSMS(self, recipients: Union[str, list], message: str):
|
||||||
'''Send an SMS message to one or more recipients
|
'''Send an SMS message to one or more recipients
|
||||||
|
|
|
@ -18,20 +18,21 @@ for module in settings.EXPEPHALON_MODULES:
|
||||||
except (AttributeError, ModuleNotFoundError):
|
except (AttributeError, ModuleNotFoundError):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def get_sms_provider_by_name(name):
|
def get_sms_provider_by_name(name, active=False):
|
||||||
for provider in providers:
|
for provider in providers:
|
||||||
if provider.name == name:
|
if provider.get_name == name and (provider.is_active or not active):
|
||||||
return provider
|
return provider
|
||||||
|
|
||||||
def get_default_sms_provider_name():
|
def get_default_sms_provider_name():
|
||||||
return getValue("core.sms.default", False)
|
return getValue("core.sms.default", False)
|
||||||
|
|
||||||
def get_default_sms_provider():
|
def get_default_sms_provider():
|
||||||
name = get_default_sms_provider_name()
|
provider = get_sms_provider_by_name(get_default_sms_provider_name(), True)
|
||||||
if name:
|
if provider:
|
||||||
for provider in providers:
|
return provider
|
||||||
if provider.name == name and provider.is_active:
|
|
||||||
return provider
|
|
||||||
for provider in providers:
|
for provider in providers:
|
||||||
if provider.is_active:
|
if provider.is_active:
|
||||||
return provider
|
return provider
|
||||||
|
|
||||||
|
raise RuntimeError("No SMS provider is currently active")
|
0
kumisms/__init__.py
Normal file
0
kumisms/__init__.py
Normal file
3
kumisms/admin.py
Normal file
3
kumisms/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
kumisms/apps.py
Normal file
5
kumisms/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class KumismsConfig(AppConfig):
|
||||||
|
name = 'kumisms'
|
3
kumisms/models.py
Normal file
3
kumisms/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
70
kumisms/sms.py
Normal file
70
kumisms/sms.py
Normal file
|
@ -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()]
|
3
kumisms/tests.py
Normal file
3
kumisms/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
kumisms/views.py
Normal file
3
kumisms/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -12,7 +12,7 @@ import json
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
class PlaySMSServer(Model, BaseSMSProvider):
|
class PlaySMSServer(Model, BaseSMSProvider):
|
||||||
name = CharField(max_length=255)
|
name = CharField(max_length=255, unique=True)
|
||||||
logo = CharField(max_length=255)
|
logo = CharField(max_length=255)
|
||||||
https = BooleanField(default=True)
|
https = BooleanField(default=True)
|
||||||
host = CharField(max_length=255)
|
host = CharField(max_length=255)
|
||||||
|
@ -23,6 +23,10 @@ class PlaySMSServer(Model, BaseSMSProvider):
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getError(status):
|
def getError(status):
|
||||||
if status["error_string"]:
|
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))
|
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)
|
response = urlopen(url)
|
||||||
|
|
||||||
status = json.loads(response.read().decode())
|
status = json.loads(response.read().decode())
|
||||||
print(status)
|
|
||||||
|
|
||||||
error = PlaySMSServer.getError(status)
|
error = PlaySMSServer.getError(status)
|
||||||
|
|
||||||
|
|
|
@ -23,4 +23,4 @@ class OTPToken(Model):
|
||||||
|
|
||||||
provider = get_default_sms_provider()
|
provider = get_default_sms_provider()
|
||||||
|
|
||||||
provider.sendSMS(number, text)
|
provider.sendSMS(str(number), text)
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="mx-auto app-login-box col-sm-12 col-md-10 col-lg-9">
|
<div class="mx-auto app-login-box col-sm-12 col-md-10 col-lg-9">
|
||||||
<div class="app-logo"></div>
|
<div class="app-logo"></div>
|
||||||
<h4 class="mb-0">
|
<h4 class="mb-0">
|
||||||
<span class="d-block">Welcome back,</span>
|
<span class="d-block">Welcome back {{ request.user.first_name }},</span>
|
||||||
<span>Please select your Two-Factor Authentication provider</span></h4>
|
<span>Please select your Two-Factor Authentication provider</span></h4>
|
||||||
{% bootstrap_messages %}
|
{% bootstrap_messages %}
|
||||||
<div class="divider row"></div>
|
<div class="divider row"></div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="mx-auto app-login-box col-sm-12 col-md-10 col-lg-9">
|
<div class="mx-auto app-login-box col-sm-12 col-md-10 col-lg-9">
|
||||||
<div class="app-logo"></div>
|
<div class="app-logo"></div>
|
||||||
<h4 class="mb-0">
|
<h4 class="mb-0">
|
||||||
<span class="d-block">Welcome back,</span>
|
<span class="d-block">Welcome back {{ request.user.first_name }},</span>
|
||||||
<span>Please enter your OTP Token</span></h4>
|
<span>Please enter your OTP Token</span></h4>
|
||||||
{% bootstrap_messages %}
|
{% bootstrap_messages %}
|
||||||
<div class="divider row"></div>
|
<div class="divider row"></div>
|
||||||
|
|
Loading…
Reference in a new issue