Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
feat(apps/users): add the initial users app
Browse files Browse the repository at this point in the history
  • Loading branch information
bitterteriyaki committed Sep 30, 2023
1 parent 8725e46 commit 41be42f
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 1 deletion.
8 changes: 8 additions & 0 deletions apps/users/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig

default_app_config = "apps.users.UsersConfig"


class UsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.users"
34 changes: 34 additions & 0 deletions apps/users/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django.contrib.admin import register
from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin
from django.utils.translation import gettext_lazy as _

from apps.users.models import User


@register(User)
class UserAdmin(DefaultUserAdmin):
list_display = ("username", "email", "is_staff", "is_active")
fieldsets = [
(_("Personal info"), {"fields": ("username", "email", "password")}),
(
_("Permissions"),
{
"fields": (
"user_permissions",
"groups",
"is_active",
"is_staff",
"is_superuser",
)
}
),
]
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("username", "email", "password1", "password2"),
},
),
)
37 changes: 37 additions & 0 deletions apps/users/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from typing import TYPE_CHECKING, Any

from django.contrib.auth.models import BaseUserManager

if TYPE_CHECKING:
from apps.users.models import User
else:
User = Any


class UserManager(BaseUserManager[User]):
def _create_user(
self,
username: str,
email: str,
password: str,
**fields: bool,
) -> User:
email = self.normalize_email(email)
user = self.model(username=username, email=email, **fields)

user.set_password(password)
user.save()

return user

def create_user(self, username: str, email: str, password: str, **fields: bool) -> User:
fields.setdefault("is_staff", False)
fields.setdefault("is_superuser", False)

return self._create_user(username, email, password, **fields)

def create_superuser(self, username: str, email: str, password: str, **fields: bool) -> User:
fields["is_staff"] = True
fields["is_superuser"] = True

return self._create_user(username, email, password, **fields)
87 changes: 87 additions & 0 deletions apps/users/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Generated by Django 4.2.5 on 2023-09-30 02:51

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="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",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"email",
models.EmailField(
db_index=True, max_length=256, unique=True
),
),
(
"username",
models.CharField(
db_index=True, max_length=128, unique=True
),
),
("is_active", models.BooleanField(default=True)),
("is_staff", models.BooleanField(default=False)),
(
"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={
"db_table": "users",
},
),
]
Empty file.
33 changes: 33 additions & 0 deletions apps/users/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db.models import EmailField, CharField, BooleanField

from core.models import TimestampedModel
from apps.users.managers import UserManager


class User(AbstractBaseUser, PermissionsMixin, TimestampedModel):
"""Represents an user."""

email = EmailField(db_index=True, max_length=256, unique=True)
username = CharField(db_index=True, max_length=128, unique=True)

# When a user no longer wishes to use our platform, they may try to
# delete there account. That's a problem for us because the data we
# collect is valuable to us and we don't want to delete it. To solve
# this problem, we will simply offer users a way to deactivate their
# account instead of letting them delete it. That way they won't
# show up on the site anymore, but we can still analyze the data.
is_active = BooleanField(default=True)

# Designates whether the user can log into the admin site.
is_staff = BooleanField(default=False)

# Telling Django that the email field should be used for
# authentication instead of the username field.
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]

objects = UserManager()

class Meta:
db_table = "users"
15 changes: 15 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.db.models import Model, DateTimeField


class TimestampedModel(Model):
created_at = DateTimeField(auto_now_add=True)
updated_at = DateTimeField(auto_now=True)

class Meta:
abstract = True

# By default, any model that inherits from this class should be
# ordered in reverse-chronological order. We can override this
# on a per-model basis as needed, but reverse-chronological is a
# good default ordering for most models.
ordering = ["-created_at", "-updated_at"]
9 changes: 8 additions & 1 deletion server/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@
"bootstrap5",
]

LOCAL_APPS: List[str] = []
LOCAL_APPS = [
"apps.users"
]

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

Expand Down Expand Up @@ -137,6 +139,11 @@

LOGIN_URL = "login"

# The model to use to represent an user.
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-user-model

AUTH_USER_MODEL = "users.User"

#####################
# Django Guardian #
#####################
Expand Down
3 changes: 3 additions & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
{{ user.username }}
</a>
<ul class="dropdown-menu">
{% if user.is_staff %}
<li><a href="{% url 'admin:index' %}" class="dropdown-item">Admin</a></li>
{% endif %}
<li><a href="#" class="dropdown-item">You profile</a></li>
<li><hr class="dropdown-divider"></li>
<li>
Expand Down

0 comments on commit 41be42f

Please sign in to comment.