Base SMS integration
This commit is contained in:
parent
c75e3c56eb
commit
4edbf8a922
10 changed files with 105 additions and 3 deletions
|
@ -3,6 +3,9 @@ from django.conf import settings
|
||||||
from geopy.geocoders import Nominatim
|
from geopy.geocoders import Nominatim
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
import string
|
||||||
|
|
||||||
|
from random import SystemRandom
|
||||||
|
|
||||||
def name_to_coords(name):
|
def name_to_coords(name):
|
||||||
geocoder = Nominatim(user_agent="JourneyJoker.at")
|
geocoder = Nominatim(user_agent="JourneyJoker.at")
|
||||||
|
@ -16,3 +19,7 @@ def profile_to_coords(profile):
|
||||||
|
|
||||||
def upload_path(instance, filename):
|
def upload_path(instance, filename):
|
||||||
return f'userfiles/{instance.user.id}/{uuid.uuid4()}/{filename}'
|
return f'userfiles/{instance.user.id}/{uuid.uuid4()}/{filename}'
|
||||||
|
|
||||||
|
def generate_token(length=6, characters=string.digits):
|
||||||
|
return "".join([SystemRandom().choice(characters) for _ in range(length)])
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.utils import timezone
|
||||||
|
|
||||||
from django_countries.fields import CountryField
|
from django_countries.fields import CountryField
|
||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
|
from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
from .helpers import profile_to_coords, upload_path
|
from .helpers import profile_to_coords, upload_path
|
||||||
|
|
||||||
|
@ -62,6 +63,16 @@ class User(AbstractBaseUser):
|
||||||
has_module_perms = has_permission
|
has_module_perms = has_permission
|
||||||
has_perm = has_permission
|
has_perm = has_permission
|
||||||
|
|
||||||
|
@property
|
||||||
|
def phone(self):
|
||||||
|
try:
|
||||||
|
return self.clientprofile.phone
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
return self.partnerprofile.phone
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
class AddressMixin(models.Model):
|
class AddressMixin(models.Model):
|
||||||
street = models.CharField("Straße", max_length=64)
|
street = models.CharField("Straße", max_length=64)
|
||||||
city = models.CharField("Stadt", max_length=64)
|
city = models.CharField("Stadt", max_length=64)
|
||||||
|
@ -110,7 +121,7 @@ class PersonMixin(models.Model):
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
class Profile(PersonMixin, AddressMixin, PhoneMixin):
|
class Profile(PersonMixin, AddressMixin, PhoneMixin):
|
||||||
user = models.OneToOneField(User, models.CASCADE)
|
user = models.OneToOneField(get_user_model(), models.CASCADE)
|
||||||
verified = models.BooleanField(default=False)
|
verified = models.BooleanField(default=False)
|
||||||
enabled = models.BooleanField(default=True)
|
enabled = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
@ -125,3 +136,16 @@ class Profile(PersonMixin, AddressMixin, PhoneMixin):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
class TwoFactor(PolymorphicModel):
|
||||||
|
user = models.ForeignKey(User, models.CASCADE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def initiate(cls, user):
|
||||||
|
raise NotImplementedError("%s does not implement initiate()" % cls.__name__)
|
||||||
|
|
||||||
|
def send_token(self, description=""):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def validate_token(self, token):
|
||||||
|
raise NotImplementedError("%s does not implement validate_token()" % cls.__name__)
|
|
@ -19,4 +19,5 @@ staticmap
|
||||||
django-mathfilters
|
django-mathfilters
|
||||||
fast-luhn
|
fast-luhn
|
||||||
kumisms
|
kumisms
|
||||||
|
django-filtersignals
|
||||||
git+https://kumig.it/kumisystems/PyInvoice
|
git+https://kumig.it/kumisystems/PyInvoice
|
0
sms/__init__.py
Normal file
0
sms/__init__.py
Normal file
3
sms/admin.py
Normal file
3
sms/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
sms/apps.py
Normal file
6
sms/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class SmsConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'sms'
|
14
sms/functions.py
Normal file
14
sms/functions.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import kumisms
|
||||||
|
|
||||||
|
from dbsettings.functions import getValue
|
||||||
|
|
||||||
|
def sendMessage(recipients: list, content: str, api_key=None):
|
||||||
|
api_key = api_key or getValue("kumisms.api.key")
|
||||||
|
gateway = kumisms.KumiSMS(api_key)
|
||||||
|
|
||||||
|
for recipient in recipients:
|
||||||
|
gateway.send(recipient, content)
|
||||||
|
|
||||||
|
def sendMessageToUsers(users: list, content: str, api_key=None):
|
||||||
|
recipients = [user.phone for user in users]
|
||||||
|
return sendMessage(recipients, content, api_key)
|
41
sms/models.py
Normal file
41
sms/models.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from localauth.models import TwoFactor
|
||||||
|
from localauth.helpers import generate_token
|
||||||
|
|
||||||
|
from dbsettings.functions import getValue
|
||||||
|
|
||||||
|
from .functions import sendMessage
|
||||||
|
|
||||||
|
class SMSTwoFactor(TwoFactor):
|
||||||
|
@classmethod
|
||||||
|
def initiate(cls, user):
|
||||||
|
if user.phone:
|
||||||
|
cls.objects.get_or_create(user=user)
|
||||||
|
|
||||||
|
def send_token(self, description="%s"):
|
||||||
|
token = SMSTwoFactorToken.objects.create(user=self)
|
||||||
|
sendMessageToUsers([user], description % token)
|
||||||
|
|
||||||
|
def validate_token(self, token):
|
||||||
|
tokens = SMSTwoFactorToken.objects.filter(
|
||||||
|
user=self,
|
||||||
|
token=token,
|
||||||
|
used=False,
|
||||||
|
created__gte=timezone.now() - timedelta(seconds=getValue("sms.token.maxage", 300))
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if tokens:
|
||||||
|
tokens.update(used=True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
class SMSTwoFactorToken(models.Model):
|
||||||
|
user = models.ForeignKey(SMSTwoFactor, models.CASCADE)
|
||||||
|
token = models.CharField(max_length=256, default=generate_token)
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
used = models.BooleanField(default=False)
|
3
sms/tests.py
Normal file
3
sms/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
sms/views.py
Normal file
3
sms/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
Loading…
Reference in a new issue