Skip to content

Commit

Permalink
repo init
Browse files Browse the repository at this point in the history
  • Loading branch information
eknvarli authored Mar 17, 2024
1 parent 0d053d7 commit dd39d2c
Show file tree
Hide file tree
Showing 31 changed files with 678 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
django = "*"
djangorestframework = "*"
django-environ = "*"
requests = "*"

[dev-packages]

[requires]
python_version = "3.10"
python_full_version = "3.10.12"
202 changes: 202 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added core/__init__.py
Empty file.
Binary file added core/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/admin.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/apps.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/models.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/serializers.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/utils.cpython-310.pyc
Binary file not shown.
Binary file added core/__pycache__/views.cpython-310.pyc
Binary file not shown.
5 changes: 5 additions & 0 deletions core/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin
from core.models import UserModel

# Register your models here.
admin.site.register(UserModel)
6 changes: 6 additions & 0 deletions core/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class CoreConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'core'
39 changes: 39 additions & 0 deletions core/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 5.0.3 on 2024-03-17 01:08

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]

operations = [
migrations.CreateModel(
name='UserModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('phone_number', models.CharField(max_length=10, unique=True, validators=[django.core.validators.RegexValidator(message='Phone number must be 10 digits only.', regex='^\\d{10}')])),
('email', models.EmailField(blank=True, max_length=50, null=True, validators=[django.core.validators.EmailValidator()])),
('otp', models.CharField(max_length=6)),
('otp_expiry', models.DateTimeField(blank=True, null=True)),
('max_otp_try', models.CharField(default=3, max_length=2)),
('otp_max_out', models.DateTimeField(blank=True, null=True)),
('is_active', models.BooleanField(default=False)),
('is_staff', models.BooleanField(default=False)),
('user_registered_at', models.DateTimeField(auto_now_add=True)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'abstract': False,
},
),
]
Empty file added core/migrations/__init__.py
Empty file.
Binary file not shown.
Binary file added core/migrations/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
50 changes: 50 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.db import models
from django.conf import settings
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin
)
from django.core.validators import RegexValidator, validate_email

phone_regex = RegexValidator(
regex=r"^\d{10}", message="Phone number must be 10 digits only."
)


class UserManager(BaseUserManager):
def create_user(self, phone_number, password=None):
if not phone_number:
raise ValueError("Phone number is required.")
user = self.model(phone_number=phone_number)
user.set_password(password)
user.save(using=self._db)
return user

def create_superuser(self, phone_number, password):
user = self.create_user(phone_number, password)
user.is_staff = True
user.is_active = True
user.is_superuser = True
user.save(using=self._db)
return user


class UserModel(AbstractBaseUser, PermissionsMixin):
phone_number = models.CharField(validators=[phone_regex], unique=True, max_length=10, blank=False, null=False)
email = models.EmailField(max_length=50, blank=True, null=True, validators=[validate_email])
otp = models.CharField(max_length=6)
otp_expiry = models.DateTimeField(blank=True, null=True)
max_otp_try = models.CharField(max_length=2, default=settings.MAX_OTP_TRY)
otp_max_out = models.DateTimeField(blank=True, null=True)

is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
user_registered_at = models.DateTimeField(auto_now_add=True)

USERNAME_FIELD = 'phone_number'

objects = UserManager()

def __str__(self):
return self.phone_number
56 changes: 56 additions & 0 deletions core/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from datetime import datetime, timedelta
import random
from django.conf import settings
from rest_framework import serializers
from core.utils import send_otp


from core.models import UserModel


class UserSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(
write_only=True,
min_length=settings.MIN_PASSWORD_LENGTH,
error_messages={
'min_length': f'Password must be longer than {settings.MIN_PASSWORD_LENGTH} characters.'
}
)

password2 = serializers.CharField(
write_only=True,
min_length=settings.MIN_PASSWORD_LENGTH,
error_messages={
'min_length': f'Password must be longer than {settings.MIN_PASSWORD_LENGTH} characters.'
}
)

class Meta:
model = UserModel
fields = (
'phone_number',
'email',
'password1',
'password2',
)

def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError("Passwords do not match.")
return data

def create(self, validated_data):
otp = random.randint(1000, 9999)
otp_expiry = datetime.now() + timedelta(minutes=10)

user = UserModel(
phone_number=validated_data['phone_number'],
email=validated_data['email'],
otp=otp,
otp_expiry=otp_expiry,
max_otp_try=settings.MAX_OTP_TRY
)
user.set_password(validated_data['password1'])
user.save()
send_otp(validated_data['phone_number'], otp)
return user
3 changes: 3 additions & 0 deletions core/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
11 changes: 11 additions & 0 deletions core/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import requests
from django.conf import settings

def send_otp(mobile, otp):
url = f'https://2factor.in/API/V1/{settings.SMS_API_KEY}/SMS/{mobile}/{otp}/Your OTP is'
payload = ''
headers = {'Content-Type': 'application/x-www-form-urlencoded'}

response = requests.get(url, data=payload, headers=headers)

return bool(response.ok)
Loading

0 comments on commit dd39d2c

Please sign in to comment.