Skip to content

Commit

Permalink
✨(dashboard) Add user authentication system
Browse files Browse the repository at this point in the history
Introduced a new user model `DashboardUser` and related configurations for user management, authentication, and admin interface. Implemented user login functionality and protected menu options based on user authentication status.
  • Loading branch information
ssorin committed Nov 15, 2024
1 parent 5dea998 commit 9f29cc2
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 77 deletions.
4 changes: 3 additions & 1 deletion src/dashboard/apps/home/templates/home/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
{% load i18n %}

{% block content %}
<h2>{% trans "QualiCharge dashboard" %}</h2>
<h2>
{% trans "QualiCharge dashboard" %}
</h2>

{% include "home/cards/consentement.html" %}
{% endblock content %}
1 change: 1 addition & 0 deletions src/dashboard/apps/users/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Dashboard users app."""
13 changes: 13 additions & 0 deletions src/dashboard/apps/users/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Dashboard users admin."""

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import DashboardUser


@admin.register(DashboardUser)
class DashboardUserAdmin(UserAdmin):
"""Dashboard user admin based on UserAdmin."""

pass
10 changes: 10 additions & 0 deletions src/dashboard/apps/users/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Dashboard users app base config."""

from django.apps import AppConfig


class UsersConfig(AppConfig):
"""Users app config."""

default_auto_field = "django.db.models.BigAutoField"
name = "apps.users"
132 changes: 132 additions & 0 deletions src/dashboard/apps/users/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Generated by Django 5.1.3 on 2024-11-15 15:30

import django.contrib.auth.models
import django.contrib.auth.validators
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="DashboardUser",
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",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"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"
),
),
(
"email",
models.EmailField(
blank=True, max_length=254, verbose_name="email address"
),
),
(
"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"
),
),
(
"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,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
]
1 change: 1 addition & 0 deletions src/dashboard/apps/users/migrations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Dashboard users app migrations."""
14 changes: 14 additions & 0 deletions src/dashboard/apps/users/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Dashboard users models."""

from django.contrib.auth.models import AbstractUser


class DashboardUser(AbstractUser):
"""Represents a user in the Dashboard application, extending the AbstractUser model.
Designed to be used as part of the system's authentication and user
management functionality, incorporating the fields and methods provided by the
AbstractUser model in Django.
"""

pass
1 change: 1 addition & 0 deletions src/dashboard/apps/users/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Dashboard users app tests."""
30 changes: 30 additions & 0 deletions src/dashboard/apps/users/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Dashboard users models tests."""

import pytest
from django.contrib.auth import get_user_model


@pytest.mark.django_db
def test_create_user():
"""Tests the creation of a default user model."""
User = get_user_model()
user = User.objects.create_user(username="john", password="foo") # noqa: S106

assert user.username == "john"
assert user.is_active is True
assert user.is_staff is False
assert user.is_superuser is False


@pytest.mark.django_db
def test_create_superuser():
"""Tests the creation of a superuser with the user model."""
User = get_user_model()
admin_user = User.objects.create_superuser(
username="superadmin", password="foo" # noqa: S106
)

assert admin_user.username == "superadmin"
assert admin_user.is_active is True
assert admin_user.is_staff is True
assert admin_user.is_superuser is True
8 changes: 8 additions & 0 deletions src/dashboard/dashboard/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"widget_tweaks",
"dsfr",
"dashboard",
"apps",
"apps.users",
"apps.home",
]

Expand Down Expand Up @@ -141,3 +143,9 @@
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

# Authentication
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

AUTH_USER_MODEL = "users.DashboardUser"
3 changes: 3 additions & 0 deletions src/dashboard/dashboard/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

urlpatterns = [
path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
# apps
path("", include("apps.home.urls")),
# internationalization
path("i18n/", include("django.conf.urls.i18n")),
]
Binary file modified src/dashboard/locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
77 changes: 40 additions & 37 deletions src/dashboard/locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-14 16:32+0100\n"
"PO-Revision-Date: 2024-11-14 16:37+0100\n"
"POT-Creation-Date: 2024-11-15 15:18+0100\n"
"PO-Revision-Date: 2024-11-15 15:19+0100\n"
"Last-Translator: ssorin <[email protected]>\n"
"Language-Team: \n"
"Language: fr\n"
Expand All @@ -19,6 +19,14 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.5\n"

#: apps/home/templates/home/cards/consentement.html:12
msgid "Consent Management"
msgstr "Gestion du consentement"

#: apps/home/templates/home/index.html:7
msgid "QualiCharge dashboard"
msgstr "Tableau de bord QualiCharge"

#: dashboard/settings.py:124
msgid "French"
msgstr "Français"
Expand All @@ -27,84 +35,79 @@ msgstr "Français"
msgid "English"
msgstr "Anglais"

#: templates/404.html:7 templates/404.html:12
#: templates/404.html:7 templates/404.html:13
msgid "Page not found (Err 404)"
msgstr "Page non trouvée (Erreur 404)"

#: templates/404.html:15
#: templates/404.html:17
#, python-format
msgid ""
"\n"
" Sorry but this page does not exist.<br /> \n"
" You can return to the <a href=\"%(url_home)s\">home page.</"
"a>\n"
" "
" Sorry but this page does not exist.<br /> \n"
" You can return to the <a href=\"%(url_home)s\">home page.</a>\n"
" "
msgstr ""
"\n"
" Désolé, mais cette page n'existe pas.<br /> \n"
" Vous pouvez revenir à la <a href=\"%(url_home)s\">page "
"d'accueil.</a>\n"
" "
" Désolé, mais cette page n'existe pas.<br /> \n"
" Vous pouvez revenir à la <a href=\"%(url_home)s\">page d'accueil.</"
"a>\n"
" "

#: templates/500.html:7
msgid "Server Error (Err. 500)"
msgstr "Erreur du serveur (Err. 500)"

#: templates/500.html:12
#: templates/500.html:13
msgid "Server Error (Err 500)"
msgstr "Erreur du serveur (Err 500)"

#: templates/500.html:15
#: templates/500.html:17
#, python-format
msgid ""
"\n"
" Oops, It seems that the server has a problem.<br /> \n"
" You can try to return to the <a href=\"%(url_home)s\">home "
"page.</a>\n"
" "
" Oops, It seems that the server has a problem.<br />\n"
" You can try to return to the <a href=\"%(url_home)s\">home page.</"
"a>\n"
" "
msgstr ""
"\n"
" Oups, il semble que le serveur a un problème.<br /> \n"
" Vous pouvez essayer de revenir à la <a href=\"%(url_home)s"
"\">page d'accueil.</a>\n"
" "
" Oups, il semble que le serveur a un problème.<br /> \n"
" Vous pouvez essayer de revenir à la <a href=\"%(url_home)s\">page "
"d'accueil.</a>\n"
" "

#: templates/blocks/header.html:6
msgid "Home page"
msgstr "Accueil"

#: templates/blocks/header.html:28
#: templates/blocks/header.html:31
msgid "Display settings"
msgstr "Paramètres d'affichage"

#: templates/blocks/header.html:37
#: templates/blocks/header.html:50
msgid "Search"
msgstr "Recherche"

#: templates/blocks/header.html:44
#: templates/blocks/header.html:52
msgid "Menu"
msgstr "Menu"

#: templates/blocks/language_selector.html:10
#: templates/blocks/language_selector.html:15
msgid "Select language"
msgstr "Sélectionner la langue"

#: templates/blocks/main_menu.html:8
#: templates/blocks/logout.html:6
msgid "Log Out"
msgstr "Se déconnecter"

#: templates/blocks/main_menu.html:9
msgid "close"
msgstr "fermer"

#: templates/blocks/main_menu.html:10
#: templates/blocks/main_menu.html:13
msgid "Main menu"
msgstr "Menu principal"

#: templates/blocks/main_menu.html:21
#: templates/blocks/main_menu.html:25
msgid "Home"
msgstr "Accueil"

#: templates/home/cards/consentement.html:12
msgid "Consent Management"
msgstr "Gestion du consentement"

#: templates/home/index.html:6
msgid "QualiCharge dashboard"
msgstr "Tableau de bord QualiCharge"
Loading

0 comments on commit 9f29cc2

Please sign in to comment.