Tag Assignment - organization OTP
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import typing
|
import typing
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
from apps.authentication.api.v1.serializers.jwt import CustomizedTokenObtainPairSerializer
|
from apps.authentication.api.v1.serializers.jwt import CustomizedTokenObtainPairSerializer
|
||||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||||
from rest_framework.decorators import action, permission_classes
|
from rest_framework.decorators import action, permission_classes
|
||||||
@@ -26,7 +26,10 @@ from apps.authentication.models import (
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from common.tools import CustomOperations
|
from common.tools import CustomOperations
|
||||||
|
from django.core.cache import cache
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
from common.sms import send_sms
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
class CustomizedTokenObtainPairView(TokenObtainPairView):
|
class CustomizedTokenObtainPairView(TokenObtainPairView):
|
||||||
@@ -138,6 +141,20 @@ class UserViewSet(ModelViewSet):
|
|||||||
else:
|
else:
|
||||||
return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)
|
return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
@action(
|
||||||
|
methods=['get'],
|
||||||
|
detail=False,
|
||||||
|
url_name='profile',
|
||||||
|
url_path='profile',
|
||||||
|
name='profile',
|
||||||
|
permission_classes=[AllowAny]
|
||||||
|
)
|
||||||
|
def profile(self, request):
|
||||||
|
serializer = authorize_view.UserRelationSerializer(
|
||||||
|
authorize_view.UserRelations.objects.get(user=request.user)
|
||||||
|
)
|
||||||
|
return Response(serializer.data, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class CityViewSet(ModelViewSet):
|
class CityViewSet(ModelViewSet):
|
||||||
""" Crud operations for city model """ #
|
""" Crud operations for city model """ #
|
||||||
@@ -195,3 +212,76 @@ class BankAccountViewSet(ModelViewSet):
|
|||||||
""" Crud operations for bank account model """ #
|
""" Crud operations for bank account model """ #
|
||||||
queryset = BankAccountInformation.objects.all()
|
queryset = BankAccountInformation.objects.all()
|
||||||
serializer_class = BankAccountSerializer
|
serializer_class = BankAccountSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralOTPViewSet(ModelViewSet):
|
||||||
|
""" general OTP user authorization """
|
||||||
|
|
||||||
|
user_relations_queryset = authorize_view.UserRelations.objects.all()
|
||||||
|
organization_queryset = Organization.objects.all()
|
||||||
|
user_queryset = User.objects.all()
|
||||||
|
user_serializer = UserSerializer
|
||||||
|
organization_serializer = OrganizationSerializer
|
||||||
|
user_relations_serializer = authorize_view.UserRelationSerializer
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_user_mobile(cls, data: dict) -> typing.Any:
|
||||||
|
""" find user mobile in multiple modes like from organization """
|
||||||
|
|
||||||
|
if data['get_mobile_type'] == 'organization':
|
||||||
|
# get user mobile by his/her organization
|
||||||
|
user_mobile = cls.user_relations_queryset.filter(
|
||||||
|
organization_id=int(data['object_id']),
|
||||||
|
role__role_name='Management').first().user.mobile
|
||||||
|
return user_mobile
|
||||||
|
|
||||||
|
if data['get_mobile_type'] == 'general':
|
||||||
|
return data['mobile']
|
||||||
|
|
||||||
|
@action(
|
||||||
|
methods=['post'],
|
||||||
|
detail=False,
|
||||||
|
url_path='send_otp',
|
||||||
|
url_name='send_otp',
|
||||||
|
name='send_otp'
|
||||||
|
)
|
||||||
|
@transaction.atomic
|
||||||
|
def send_otp(self, request):
|
||||||
|
"""
|
||||||
|
This module is for sending otp in whole project and different parts
|
||||||
|
like send otp code to user by organization or by general user mobile
|
||||||
|
"""
|
||||||
|
|
||||||
|
mobile = self.get_user_mobile(
|
||||||
|
data=request.data
|
||||||
|
)
|
||||||
|
|
||||||
|
# generate random integer and message for otp code
|
||||||
|
random_number = random.randint(10000, 99999)
|
||||||
|
message = f'کد احراز شما : {random_number}' # noqa
|
||||||
|
|
||||||
|
# caching code
|
||||||
|
if 'timeout' in request.data.keys():
|
||||||
|
cache.set(f"{random_number}", str(random_number), timeout=60 * int(request.data['timeout']))
|
||||||
|
else:
|
||||||
|
cache.set(f"{random_number}", str(random_number), timeout=60 * 3)
|
||||||
|
|
||||||
|
sms_response = send_sms(mobile=mobile, message=message)
|
||||||
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@action(
|
||||||
|
methods=['post'],
|
||||||
|
detail=False,
|
||||||
|
url_name='check_otp',
|
||||||
|
url_path='check_otp',
|
||||||
|
name='check_otp'
|
||||||
|
)
|
||||||
|
def check_otp(self, request):
|
||||||
|
""" Check sent otp code to user """
|
||||||
|
|
||||||
|
entered_code = request.data['code']
|
||||||
|
cached_code = cache.get(entered_code)
|
||||||
|
|
||||||
|
if entered_code == cached_code:
|
||||||
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
return Response(status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ from .api import (
|
|||||||
CityViewSet,
|
CityViewSet,
|
||||||
ProvinceViewSet,
|
ProvinceViewSet,
|
||||||
OrganizationViewSet,
|
OrganizationViewSet,
|
||||||
OrganizationTypeViewSet
|
OrganizationTypeViewSet,
|
||||||
|
GeneralOTPViewSet
|
||||||
)
|
)
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
@@ -21,6 +22,7 @@ router.register(r'city', CityViewSet, basename='city')
|
|||||||
router.register(r'province', ProvinceViewSet, basename='province')
|
router.register(r'province', ProvinceViewSet, basename='province')
|
||||||
router.register(r'organization', OrganizationViewSet, basename='organization')
|
router.register(r'organization', OrganizationViewSet, basename='organization')
|
||||||
router.register(r'organization-type', OrganizationTypeViewSet, basename='organization_type')
|
router.register(r'organization-type', OrganizationTypeViewSet, basename='organization_type')
|
||||||
|
router.register(r'otp', GeneralOTPViewSet, basename='otp')
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('login/', CustomizedTokenObtainPairView.as_view(), name='token_obtain_pair'),
|
path('login/', CustomizedTokenObtainPairView.as_view(), name='token_obtain_pair'),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from apps.core.models import BaseModel
|
|||||||
from crum import get_current_user
|
from crum import get_current_user
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from jdatetime import datetime
|
from jdatetime import datetime
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
class Tag(BaseModel):
|
class Tag(BaseModel):
|
||||||
@@ -85,6 +86,7 @@ class TagAssignment(BaseModel):
|
|||||||
)[3] + str(
|
)[3] + str(
|
||||||
datetime.now().month
|
datetime.now().month
|
||||||
)
|
)
|
||||||
|
self.serial_random_part = random.randint(1000, 9999)
|
||||||
if not self.serial:
|
if not self.serial:
|
||||||
self.serial = f"" \
|
self.serial = f"" \
|
||||||
f"{self.serial_sender_part}" \
|
f"{self.serial_sender_part}" \
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from django.db import transaction
|
|||||||
from rest_framework.exceptions import APIException
|
from rest_framework.exceptions import APIException
|
||||||
from apps.tag import permissions as tag_permissions
|
from apps.tag import permissions as tag_permissions
|
||||||
from apps.authorization import models as authorize_models
|
from apps.authorization import models as authorize_models
|
||||||
|
from apps.authentication.api.v1.api import GeneralOTPViewSet
|
||||||
from apps.tag.tools import tag_code_serial_scanning
|
from apps.tag.tools import tag_code_serial_scanning
|
||||||
from apps.tag import exceptions as tag_exceptions
|
from apps.tag import exceptions as tag_exceptions
|
||||||
from common.helpers import detect_file_extension
|
from common.helpers import detect_file_extension
|
||||||
@@ -110,6 +111,7 @@ class TagViewSet(viewsets.ModelViewSet):
|
|||||||
class TagAssignmentViewSet(viewsets.ModelViewSet):
|
class TagAssignmentViewSet(viewsets.ModelViewSet):
|
||||||
""" assignment of tags """
|
""" assignment of tags """
|
||||||
queryset = tag_models.TagAssignment.objects.all()
|
queryset = tag_models.TagAssignment.objects.all()
|
||||||
|
user_relations_queryset = authorize_models.UserRelations.objects.all()
|
||||||
serializer_class = TagAssignmentSerializer
|
serializer_class = TagAssignmentSerializer
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
@@ -120,6 +122,12 @@ class TagAssignmentViewSet(viewsets.ModelViewSet):
|
|||||||
if serializer.is_valid(raise_exception=True):
|
if serializer.is_valid(raise_exception=True):
|
||||||
tag_assignment = serializer.save()
|
tag_assignment = serializer.save()
|
||||||
|
|
||||||
|
# get assigner organization code
|
||||||
|
assigner_organization_code = self.user_relations_queryset.get(
|
||||||
|
user=request.user).organization.type.code # noqa
|
||||||
|
tag_assignment.serial_sender_part = assigner_organization_code # noqa
|
||||||
|
tag_assignment.save()
|
||||||
|
|
||||||
# get tags by species number like: 2 tags of species code 4
|
# get tags by species number like: 2 tags of species code 4
|
||||||
tags_to_allocate = request.data['allocated_tags']
|
tags_to_allocate = request.data['allocated_tags']
|
||||||
for tag in tags_to_allocate:
|
for tag in tags_to_allocate:
|
||||||
@@ -140,7 +148,7 @@ class TagAssignmentViewSet(viewsets.ModelViewSet):
|
|||||||
status='W',
|
status='W',
|
||||||
species_code=tag['species_code']
|
species_code=tag['species_code']
|
||||||
).save() # noqa
|
).save() # noqa
|
||||||
tag_to_allocate.status = 'W' # change tag status from free to waiting
|
tag_to_allocate.status = ' ' # change tag status from free to waiting
|
||||||
tag_to_allocate.save()
|
tag_to_allocate.save()
|
||||||
|
|
||||||
return Response(serializer.data, status.HTTP_201_CREATED)
|
return Response(serializer.data, status.HTTP_201_CREATED)
|
||||||
@@ -207,6 +215,29 @@ class TagAssignmentViewSet(viewsets.ModelViewSet):
|
|||||||
allocated_tag.delete()
|
allocated_tag.delete()
|
||||||
return Response(status.HTTP_200_OK)
|
return Response(status.HTTP_200_OK)
|
||||||
|
|
||||||
|
@action(
|
||||||
|
methods=['post'],
|
||||||
|
detail=False,
|
||||||
|
url_path='otp_verification',
|
||||||
|
url_name='otp_verification',
|
||||||
|
name='otp_verification'
|
||||||
|
)
|
||||||
|
def otp_verification(self, request):
|
||||||
|
""" OTP verification for organization """
|
||||||
|
|
||||||
|
if request.data['type'] == 'send':
|
||||||
|
otp_response = GeneralOTPViewSet().send_otp(request)
|
||||||
|
if otp_response.status_code == 200:
|
||||||
|
return Response(otp_response.status_code, status=status.HTTP_200_OK)
|
||||||
|
else:
|
||||||
|
return Response(otp_response.status_code, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
if request.data['type'] == 'check':
|
||||||
|
check_response = GeneralOTPViewSet().check_otp(request)
|
||||||
|
if check_response.status_code == 200:
|
||||||
|
return Response(check_response.status_code, status=status.HTTP_200_OK)
|
||||||
|
else:
|
||||||
|
return Response(check_response.status_code, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
@action(
|
@action(
|
||||||
methods=['put'],
|
methods=['put'],
|
||||||
detail=True,
|
detail=True,
|
||||||
|
|||||||
21
common/sms.py
Normal file
21
common/sms.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import typing
|
||||||
|
import requests
|
||||||
|
|
||||||
|
USERNAME_SMS = 'hamedan' # noqa # Sahand Sms username
|
||||||
|
PASSWORD_SMS = 'hamedan12345' # noqa # Sahand sms password
|
||||||
|
|
||||||
|
|
||||||
|
def send_sms(mobile: str = None, message: str = None) -> typing.Any:
|
||||||
|
""" send sms to a number with custom message """
|
||||||
|
|
||||||
|
url = f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?" \
|
||||||
|
f"username={USERNAME_SMS}&password={PASSWORD_SMS}" \
|
||||||
|
f"&from=30002501&to={mobile}&message={message}"
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||||
|
response = requests.request('GET', url, headers=headers)
|
||||||
|
print(response)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
send_sms(mobile="09389657326", message="12345")
|
||||||
Reference in New Issue
Block a user