-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added accounts and login features (#29)
* Added accounts and login features * Add tests and update requirements for Postgres binary * Run pre-commit hooks on all files Signed-off-by: Nishant Nayak <nishantnayak2001@gmail.com> * Made ui changes to forms * Update DaisyUI to 4.x and fix some styles Signed-off-by: Nishant Nayak <nishantnayak2001@gmail.com> * Update Dockerfiles and Shell scripts according to linters Signed-off-by: Nishant Nayak <nishantnayak2001@gmail.com> --------- Signed-off-by: Nishant Nayak <nishantnayak2001@gmail.com> Co-authored-by: Nishant Nayak <nishantnayak2001@gmail.com>
- Loading branch information
1 parent
ce37ba4
commit 1e7f0ca
Showing
25 changed files
with
736 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from django.contrib import admin | ||
from django.contrib.auth.admin import UserAdmin | ||
|
||
from .models import User | ||
|
||
# Register your models here. | ||
|
||
|
||
class CorpusUserAdmin(UserAdmin): | ||
fieldsets = ( | ||
(None, {"fields": ("email", "password")}), | ||
( | ||
"Personal Info", | ||
{"fields": ("first_name", "last_name", "phone_no", "gender")}, | ||
), | ||
( | ||
"Permissions", | ||
{ | ||
"fields": ( | ||
"is_active", | ||
"is_staff", | ||
"is_superuser", | ||
"groups", | ||
"user_permissions", | ||
) | ||
}, | ||
), | ||
("Important dates", {"fields": ("last_login", "date_joined")}), | ||
) | ||
add_fieldsets = ( | ||
( | ||
None, | ||
{ | ||
"classes": ("wide",), | ||
"fields": ( | ||
"email", | ||
"first_name", | ||
"last_name", | ||
"phone_no", | ||
"gender", | ||
"password1", | ||
"password2", | ||
), | ||
}, | ||
), | ||
) | ||
list_display = ("email", "first_name", "last_name", "phone_no", "gender") | ||
search_fields = ("email", "first_name", "last_name", "phone_no") | ||
ordering = ("email",) | ||
|
||
|
||
admin.site.register(User, CorpusUserAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class AccountsConfig(AppConfig): | ||
default_auto_field = "django.db.models.BigAutoField" | ||
name = "accounts" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 CorpusAuthBackend(ModelBackend): | ||
def authenticate(self, request, username=None, password=None, **kwargs): | ||
UserModel = get_user_model() | ||
try: | ||
user = UserModel.objects.get(email=username) | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from django import forms | ||
from django.contrib.auth.forms import AuthenticationForm | ||
from django.contrib.auth.forms import UserChangeForm | ||
from django.contrib.auth.forms import UserCreationForm | ||
|
||
from .models import GENDERS | ||
from .models import User | ||
|
||
|
||
class CorpusCreationForm(UserCreationForm): | ||
phone_no = forms.CharField(required=True, max_length=10) | ||
gender = forms.ChoiceField(choices=GENDERS, required=True) | ||
first_name = forms.CharField(max_length=30, required=True, help_text="Required.") | ||
|
||
error_css_class = "text-sm text-error" | ||
|
||
class Meta: | ||
model = User | ||
fields = [ | ||
"first_name", | ||
"last_name", | ||
"phone_no", | ||
"gender", | ||
"email", | ||
"password1", | ||
"password2", | ||
] | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(CorpusCreationForm, self).__init__(*args, **kwargs) | ||
for visible in self.visible_fields(): | ||
visible.field.widget.attrs[ | ||
"class" | ||
] = "mt-1 block w-full rounded-md border-base-800 text-black shadow-sm focus:border-primary focus:ring focus:ring-primary-200 focus:ring-opacity-50" # noqa: E501 | ||
|
||
|
||
class CorpusChangeForm(UserChangeForm): | ||
phone_no = forms.CharField(required=True) | ||
gender = forms.ChoiceField(choices=GENDERS, required=True) | ||
|
||
class Meta: | ||
model = User | ||
fields = [ | ||
"first_name", | ||
"last_name", | ||
"phone_no", | ||
"gender", | ||
"email", | ||
] | ||
|
||
|
||
class CorpusLoginForm(AuthenticationForm): | ||
def __init__(self, *args, **kwargs): | ||
super(CorpusLoginForm, self).__init__(*args, **kwargs) | ||
for visible in self.visible_fields(): | ||
visible.field.widget.attrs[ | ||
"class" | ||
] = "mt-1 block w-full rounded-md border-base-800 text-black shadow-sm focus:border-primary focus:ring focus:ring-primary-200 focus:ring-opacity-50" # noqa: E501 | ||
|
||
def clean_username(self): | ||
username = self.cleaned_data.get("username") | ||
if username: | ||
username = username.lower() | ||
return username |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# Generated by Django 4.2.4 on 2023-09-07 15:06 | ||
import django.utils.timezone | ||
from django.db import migrations | ||
from django.db import models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
("auth", "0012_alter_user_first_name_max_length"), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="User", | ||
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", | ||
), | ||
), | ||
( | ||
"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" | ||
), | ||
), | ||
("phone_no", models.CharField(max_length=13, unique=True)), | ||
( | ||
"gender", | ||
models.CharField( | ||
choices=[ | ||
("M", "Male"), | ||
("F", "Female"), | ||
("O", "Other"), | ||
("N", "Prefer not to disclose"), | ||
], | ||
max_length=1, | ||
), | ||
), | ||
("email", models.EmailField(max_length=254, unique=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={ | ||
"verbose_name": "user", | ||
"verbose_name_plural": "users", | ||
"abstract": False, | ||
}, | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from django.contrib.auth.base_user import BaseUserManager | ||
from django.contrib.auth.models import AbstractUser | ||
from django.db import models | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
# Create your models here. | ||
|
||
GENDERS = [ | ||
("M", "Male"), | ||
("F", "Female"), | ||
("O", "Other"), | ||
("N", "Prefer not to disclose"), | ||
] | ||
|
||
|
||
class UserManager(BaseUserManager): | ||
def create_user(self, email, password, **kwargs): | ||
if not email: | ||
raise ValueError(_("Email must be set.")) | ||
|
||
email = self.normalize_email(email) | ||
user = self.model(email=email, **kwargs) | ||
user.set_password(password) | ||
user.save() | ||
return user | ||
|
||
def create_superuser(self, email, password, **kwargs): | ||
kwargs.setdefault("is_staff", True) | ||
kwargs.setdefault("is_superuser", True) | ||
kwargs.setdefault("is_active", True) | ||
|
||
if kwargs.get("is_staff") is not True: | ||
raise ValueError(_("Superuser must have is_staff=True.")) | ||
if kwargs.get("is_superuser") is not True: | ||
raise ValueError(_("Superuser must have is_superuser=True.")) | ||
return self.create_user(email, password, **kwargs) | ||
|
||
def users(self): | ||
return self.filter(is_active=True) | ||
|
||
|
||
class User(AbstractUser): | ||
username = None | ||
phone_no = models.CharField(max_length=13, unique=True, blank=False, null=False) | ||
gender = models.CharField(max_length=1, choices=GENDERS, blank=False, null=False) | ||
email = models.EmailField(unique=True, blank=False, null=False) | ||
|
||
USERNAME_FIELD = "email" | ||
REQUIRED_FIELDS = [] | ||
|
||
objects = UserManager() | ||
|
||
def __str__(self): | ||
return f"{self.first_name} {self.last_name}" |
Oops, something went wrong.