hash otp
This commit is contained in:
parent
0d59a34e06
commit
2fe322241a
6 changed files with 127 additions and 27 deletions
|
|
@ -0,0 +1,99 @@
|
|||
# Generated by Django 5.1.4 on 2025-11-20 09:05
|
||||
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gooyal_oauth2', '0004_application_avatar'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='refreshtoken',
|
||||
unique_together=set(),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='application',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='application',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='grant',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='grant',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='refreshtoken',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='refreshtoken',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='resource',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='resource',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='scope',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='scope',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='application',
|
||||
name='uuid',
|
||||
field=models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='grant',
|
||||
name='uuid',
|
||||
field=models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='refreshtoken',
|
||||
name='uuid',
|
||||
field=models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='resource',
|
||||
name='uuid',
|
||||
field=models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='scope',
|
||||
name='uuid',
|
||||
field=models.UUIDField(db_index=True, default=uuid.uuid4, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -16,14 +16,14 @@ from django.conf import settings
|
|||
from django.db import models, router, transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from utils.models import BaseModel
|
||||
from .settings import oauth2_settings
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Resource(models.Model):
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
class Resource(BaseModel):
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
user = models.ForeignKey(
|
||||
|
|
@ -36,13 +36,12 @@ class Resource(models.Model):
|
|||
return self.name
|
||||
|
||||
|
||||
class Application(AbstractApplication):
|
||||
class Application(AbstractApplication, BaseModel):
|
||||
"""
|
||||
Application model for use with Django OAuth Toolkit that allows the scopes
|
||||
available to an application to be restricted on a per-application basis.
|
||||
"""
|
||||
id=None
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
id = None
|
||||
name = models.CharField(max_length=255, blank=False, unique=True)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
|
|
@ -74,14 +73,12 @@ class Application(AbstractApplication):
|
|||
allowed_scopes = self.allowed_scopes
|
||||
return Scope.objects.filter(name__in=allowed_scopes).order_by('name')
|
||||
|
||||
|
||||
|
||||
def allows_grant_type(self, *grant_types):
|
||||
# Assume, for this example, that self.authorization_grant_type is set to self.GRANT_AUTHORIZATION_CODE
|
||||
return bool(set([self.authorization_grant_type, self.GRANT_CLIENT_CREDENTIALS]) & set(grant_types))
|
||||
|
||||
|
||||
class Scope(models.Model):
|
||||
class Scope(BaseModel):
|
||||
"""
|
||||
Django model for an OAuth scope.
|
||||
"""
|
||||
|
|
@ -89,8 +86,6 @@ class Scope(models.Model):
|
|||
# NOTE: This is not used to limit access to the scope in any way - we want the
|
||||
# scope to be available to other applications in order to request access
|
||||
# to the resource it protects!
|
||||
id = None
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
application = models.ForeignKey(
|
||||
oauth2_settings.APPLICATION_MODEL,
|
||||
models.CASCADE,
|
||||
|
|
@ -177,17 +172,15 @@ class Scope(models.Model):
|
|||
return True
|
||||
|
||||
|
||||
class Grant(AbstractGrant):
|
||||
class Grant(AbstractGrant, BaseModel):
|
||||
id = None
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
application = models.ForeignKey(
|
||||
oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE, related_name='grants'
|
||||
)
|
||||
|
||||
|
||||
class RefreshToken(AbstractRefreshToken):
|
||||
class RefreshToken(BaseModel, AbstractRefreshToken):
|
||||
id = None
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
application = models.ForeignKey(
|
||||
oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE, related_name='refresh_tokens')
|
||||
|
||||
|
|
@ -215,7 +208,6 @@ class RefreshToken(AbstractRefreshToken):
|
|||
self.save()
|
||||
|
||||
|
||||
|
||||
class AccessToken(AbstractAccessToken):
|
||||
id = None
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
|
||||
|
|
@ -240,7 +232,7 @@ def clear_expired():
|
|||
flat_queryset = queryset.values_list("pk", flat=True)[:CLEAR_EXPIRED_TOKENS_BATCH_SIZE]
|
||||
batch_length = flat_queryset.count()
|
||||
queryset.model.objects.filter(pk__in=list(flat_queryset)).delete()
|
||||
logger.debug(f"{batch_length} tokens deleted, {current_no-batch_length} left")
|
||||
logger.debug(f"{batch_length} tokens deleted, {current_no - batch_length} left")
|
||||
queryset = queryset.model.objects.filter(query)
|
||||
time.sleep(CLEAR_EXPIRED_TOKENS_BATCH_INTERVAL)
|
||||
current_no = queryset.count()
|
||||
|
|
@ -298,4 +290,3 @@ def clear_expired():
|
|||
|
||||
grants_deleted_no = batch_delete(grants, grants_query)
|
||||
logger.info("%s Expired grant tokens deleted", grants_deleted_no)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,3 +31,9 @@ class ApplicationViewSet(ReadOnlyModelViewSet):
|
|||
else:
|
||||
raise Http404()
|
||||
|
||||
# @action(detail=True, permission_classes=[AllowAny])
|
||||
# def tokens(self, request, pk=None):
|
||||
# app: Application = self.get_object()
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
MAX_OTP_TRY = 3
|
||||
DEVELOPMENT_PHONE_NUMBERS = ['+989999999999', '+989999999998']
|
||||
DEVELOPMENT_PHONE_NUMBERS = []
|
||||
MAX_OTP_VALID_DURATION = 120
|
||||
|
||||
class GenderChoices(models.TextChoices):
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ class User(AbstractUser):
|
|||
|
||||
self.otp_expire = timezone.now() + timedelta(seconds=MAX_OTP_VALID_DURATION)
|
||||
self.otp_try = 0
|
||||
self.save()
|
||||
|
||||
def set_ott(self):
|
||||
self.ott = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
|
||||
|
|
@ -180,18 +181,22 @@ class User(AbstractUser):
|
|||
|
||||
def check_otp(self, otp):
|
||||
if self.otp_try <= MAX_OTP_TRY:
|
||||
result = otp and check_password(self.otp, otp) and self.otp_is_valid()
|
||||
try:
|
||||
result = otp and check_password(otp, self.otp) and self.otp_is_valid()
|
||||
except Exception as e:
|
||||
result = False
|
||||
|
||||
if result:
|
||||
self.otp = None
|
||||
self.date_joined = timezone.now()
|
||||
if not self.date_joined:
|
||||
self.date_joined = timezone.now()
|
||||
else:
|
||||
self.otp_try += 1
|
||||
|
||||
self.save()
|
||||
else:
|
||||
self.otp = None
|
||||
result = False
|
||||
|
||||
self.save()
|
||||
|
||||
return result
|
||||
|
||||
def check_ott(self, ott: str):
|
||||
|
|
|
|||
|
|
@ -73,13 +73,12 @@ class RequestOTPSerializer(serializers.ModelSerializer):
|
|||
try:
|
||||
user.set_otp()
|
||||
except Exception as e:
|
||||
raise UnprocessableEntity()
|
||||
|
||||
user.save()
|
||||
raise UnprocessableEntity('otp expire time not reached')
|
||||
|
||||
user.send_otp()
|
||||
|
||||
else:
|
||||
raise UnprocessableEntity()
|
||||
raise UnprocessableEntity('otp expire time not reached yet')
|
||||
|
||||
self.instance = user
|
||||
return user
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue