Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
TREBLLE_PROJECT_ID='add project id without quote'
TREBLLE_API_KEY='add api key without quote'
SECRET_KEY="add django secret key without quote"
9 changes: 9 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ name = "pypi"
django = "*"
treblle = "*"
python-decouple = "*"
pyjwt = "*"
black = "*"
django-cors-headers = "==1.1.0"
djangorestframework = "*"
djoser = "*"
pandas = "*"
install = "*"
djangorestframework-simplejwt = "*"
isort = "*"

[dev-packages]

Expand Down
382 changes: 378 additions & 4 deletions Pipfile.lock

Large diffs are not rendered by default.

32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,34 @@ pipenv shell
pipenv install
```
- Create a copy of `.env.example` and rename to `.env` then fill in the values
>- find the treblle keys on the treblle dashboard
>- find the treblle keys on the treblle dashboard

- Create admin user with:
> whilst in project directory
```shell
python manage.py shell

>>> from authme.models import CustomUser

>>> CustomUser.objects.create_user(email="youremail@example.com",username="johnDoe707", password="strongpassword", is_staff=True, is_superuser=True)
```

# Testing API

Postman Docs: [click here📬](https://documenter.getpostman.com/view/16596786/2s93zFXKTM)

Swagger Docs:

- use this to generate datetime object to fill into respective fields
```python
from datetime import datetime

t4 = datetime(year = 2018, month = 7, day = 12, hour = 7, minute = 9, second = 33)
t5 = datetime(year = 2018, month = 7, day = 14, hour = 5, minute = 55, second = 13)
t6 = t5 - t4


print("t4 =", t4)
print("t5 =", t5)
print("t6 =", t6)
```
Empty file added authme/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions authme/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions authme/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AuthmeConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "authme"
22 changes: 22 additions & 0 deletions authme/backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend


class EmailBackend(ModelBackend):
def authenticate(self, request, email=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=email)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None

def get_user(self, user_id):
UserModel = get_user_model()
try:
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
120 changes: 120 additions & 0 deletions authme/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Generated by Django 4.2.3 on 2023-07-06 03:21

import uuid

import django.utils.timezone
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="CustomUser",
fields=[
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=False, 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",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
(
"id",
models.UUIDField(
default=uuid.uuid4,
primary_key=True,
serialize=False,
unique=True,
),
),
("created", models.DateTimeField(auto_now_add=True)),
("last_updated", models.DateTimeField(auto_now=True)),
(
"email",
models.EmailField(
max_length=254, unique=True, verbose_name="email address"
),
),
(
"username",
models.CharField(
max_length=150, unique=True, verbose_name="username"
),
),
(
"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={
"verbose_name": "user",
"verbose_name_plural": "users",
},
),
]
19 changes: 19 additions & 0 deletions authme/migrations/0002_alter_customuser_last_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.2.3 on 2023-07-06 03:24

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("authme", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name="customuser",
name="last_login",
field=models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
]
Empty file added authme/migrations/__init__.py
Empty file.
47 changes: 47 additions & 0 deletions authme/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from utils.models import TrackObjectStateMixin


class CustomUserManager(BaseUserManager):
def create_user(
self,
email,
password=None,
username: str = None,
is_staff: bool = False,
is_superuser: bool = False,
**extra_fields
):
if not email:
raise ValueError("The Email field must be set")

email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.username = username
user.is_active = True
user.is_staff = is_staff
user.is_superuser = is_superuser
user.save(using=self._db)
return user


class CustomUser(TrackObjectStateMixin, AbstractUser):
email = models.EmailField(_("email address"), unique=True)
username = models.CharField(_("username"), max_length=150, unique=True)
# username = None

USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]

objects = CustomUserManager()

class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")

def __str__(self):
return self.email
25 changes: 25 additions & 0 deletions authme/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from rest_framework.permissions import BasePermission


class IsAdminUserOrReadOnly(BasePermission):
def has_permission(self, request, view):
if request.method == "POST":
return request.user.is_superuser
if request.method == "PUT":
return request.user.is_superuser
if request.method == "DELETE":
return request.user.is_superuser
return True


class ProtectAllMethods(BasePermission):
def has_permission(self, request, view):
if request.method == "GET":
return request.user.is_superuser
if request.method == "POST":
return request.user.is_superuser
if request.method == "PUT":
return request.user.is_superuser
if request.method == "DELETE":
return request.user.is_superuser
return True
80 changes: 80 additions & 0 deletions authme/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from django.contrib.auth import authenticate
from rest_framework import serializers
from rest_framework_simplejwt.tokens import RefreshToken

from .models import CustomUser


class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ["email"]


class RegisterSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True, required=True, min_length=8)
password2 = serializers.CharField(write_only=True, required=True, min_length=8)

class Meta:
model = CustomUser
fields = ["email", "username", "password1", "password2"]

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

def create(self, validated_data):
user = CustomUser.objects.create_user(
username=validated_data["username"],
email=validated_data["email"],
password=validated_data["password1"],
)
return user


# class LoginSerializer(serializers.Serializer):
# email = serializers.EmailField()
# password = serializers.CharField(write_only=True, min_length=8)

# def validate(self, data):
# email = data.get('email')
# password = data.get('password')

# if email and password:
# user = authenticate(email=email, password=password)
# if user:
# if not user.is_active:
# raise serializers.ValidationError('User account is disabled.')
# data['user'] = user
# else:
# raise serializers.ValidationError('Unable to log in with provided credentials.')
# else:
# raise serializers.ValidationError('Must include "email" and "password" fields.')

# return data

# class TokenSerializer(serializers.Serializer):
# refresh = serializers.CharField()
# access = serializers.CharField()


class UserDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
exclude = [
"password",
# "is_staff",
# "is_superuser",
"groups",
"user_permissions",
]
read_only_fields = [
"email",
"last_updated",
"created",
"uuid",
"date_joined",
"is_active",
"last_login",
]
3 changes: 3 additions & 0 deletions authme/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.
Loading