diff --git a/cookiecutter.json b/cookiecutter.json index fd5bd0f..4b483bc 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -3,6 +3,10 @@ "project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_')|replace('.', '_')|trim() }}", "python_version": "3.11.1", "_copy_without_render": [ - "*.html" + "*.html", + "*/activation*.txt" + ], + "_extensions": [ + "cookiecutter.extensions.RandomStringExtension" ] } diff --git a/{{cookiecutter.project_slug}}/src/common/forms.py b/{{cookiecutter.project_slug}}/src/common/forms.py new file mode 100644 index 0000000..b63633f --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/forms.py @@ -0,0 +1,8 @@ +import django_registration.forms + +from common.models import User + + +class RegistrationForm(django_registration.forms.RegistrationForm): + class Meta(django_registration.forms.RegistrationForm.Meta): + model = User diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_complete.html b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_complete.html new file mode 100644 index 0000000..8f609b1 --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_complete.html @@ -0,0 +1,7 @@ +{% extends "common/base.html" %} + +{% block content %} +

Activation réussie

+

Votre compte est désormais actif.

+

Se connecter

+{% endblock %} diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_body.txt b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_body.txt new file mode 100644 index 0000000..e76e294 --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_body.txt @@ -0,0 +1,2 @@ +Voici votre clé d'activation : https://{{ site.domain }}{% url "django_registration_activate" activation_key=activation_key %} +Elle est valable pendant {{ expiration_days }} jours. diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_subject.txt b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_subject.txt new file mode 100644 index 0000000..ac61dee --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_email_subject.txt @@ -0,0 +1 @@ +[{{cookiecutter.project_name}}] Activation de compte diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_failed.html b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_failed.html new file mode 100644 index 0000000..8cdb98b --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/activation_failed.html @@ -0,0 +1,8 @@ +{% extends "common/base.html" %} + +{% block content %} +

Erreur d'activation

+

+ {{ activation_error }} +

+{% endblock %} diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_closed.html b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_closed.html new file mode 100644 index 0000000..7a92514 --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_closed.html @@ -0,0 +1,6 @@ +{% extends "common/base.html" %} + +{% block content %} +

Inscriptions fermées

+

Les inscriptions sont désactivées.

+{% endblock %} diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_complete.html b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_complete.html new file mode 100644 index 0000000..19209d9 --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_complete.html @@ -0,0 +1,6 @@ +{% extends "common/base.html" %} + +{% block content %} +

Inscription réussie

+

Un e-mail permettant d'activer votre compte vous a été envoyé.

+{% endblock %} diff --git a/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_form.html b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_form.html new file mode 100644 index 0000000..0422e19 --- /dev/null +++ b/{{cookiecutter.project_slug}}/src/common/templates/django_registration/registration_form.html @@ -0,0 +1,10 @@ +{% extends "common/base.html" %} + +{% block content %} +

Inscription

+
+ {% csrf_token %} + {{ form }} + +
+{% endblock %} diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/settings.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/settings.py index 2db2b0f..79a1bab 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/settings.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/settings.py @@ -14,14 +14,19 @@ CONTRIB_DIR = PROJECT_ROOT / "contrib" env = environ.Env( DEBUG=(bool, False), - SECRET_KEY=str, + SECRET_KEY=(str, "{{ random_ascii_string(50, punctuation=True) }}"), ALLOWED_HOSTS=(list, []), DEBUG_TOOLBAR=(bool, True), STATIC_ROOT=(Path, BASE_DIR / "public" / "static"), LOG_LEVEL=(str, "DEBUG"), LOG_FORMAT=(str, "default"), APP_DATA=(Path, PROJECT_ROOT / "data"), - DATABASE_URL=str, + DATABASE_URL=(str, "sqlite:////app/db/db.sqlite3"), + REGISTRATION_OPEN=(bool, True), + MAILGUN_API_KEY=(str, ""), + MAILGUN_SENDER_DOMAIN=(str, ""), + MAILGUN_SENDER_ADDRESS=(str, ""), + CSRF_TRUSTED_ORIGINS=(list, ["http://localhost:8000"]), ) env_file = os.getenv("ENV_FILE", None) @@ -55,7 +60,9 @@ EXTERNAL_APPS = [ "django_cleanup.apps.CleanupConfig", # should be last: https://pypi.org/project/django-cleanup/ ] if DEBUG_TOOLBAR: - EXTERNAL_APPS.append("debug_toolbar") + EXTERNAL_APPS.insert(-2, "debug_toolbar") +if DEBUG: + EXTERNAL_APPS.insert(-2, "django_browser_reload") CUSTOM_APPS = [ "whitenoise.runserver_nostatic", # should be first @@ -77,6 +84,8 @@ MIDDLEWARE = [ ] if DEBUG_TOOLBAR: MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware") +if DEBUG: + MIDDLEWARE.append("django_browser_reload.middleware.BrowserReloadMiddleware") ROOT_URLCONF = "{{cookiecutter.project_slug}}.urls" @@ -204,3 +213,40 @@ LOGIN_URL = "/admin/login" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" AUTH_USER_MODEL = "common.User" + +ACCOUNT_ACTIVATION_DAYS = 2 +REGISTRATION_OPEN = env("REGISTRATION_OPEN") + +ANYMAIL = { + "MAILGUN_API_KEY": env("MAILGUN_API_KEY"), + "MAILGUN_SENDER_DOMAIN": env("MAILGUN_SENDER_DOMAIN"), +} +EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" +DEFAULT_FROM_EMAIL = env("MAILGUN_SENDER_ADDRESS") +SERVER_EMAIL = env("MAILGUN_SENDER_ADDRESS") + +if DEBUG: + EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" + +APP = { + "build": { + "date": "latest-date", + "commit": "latest-commit", + "describe": "latest-describe", + } +} +try: + with open("/app/git/build-date") as f: + APP["build"]["date"] = f.read().strip() +except Exception: # noqa: S110 + pass +try: + with open("/app/git/git-commit") as f: + APP["build"]["commit"] = f.read().strip() +except Exception: # noqa: S110 + pass +try: + with open("/app/git/git-describe") as f: + APP["build"]["describe"] = f.read().strip() +except Exception: # noqa: S110 + pass diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/urls.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/urls.py index 81e595f..7b05a0a 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/urls.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.project_slug}}/urls.py @@ -18,11 +18,20 @@ from django.conf.urls.static import static from django.contrib import admin from django.contrib.auth import logout from django.urls import include, path +from django_registration.backends.activation.views import RegistrationView +from common.forms import RegistrationForm from common.views import hello_world urlpatterns = [ path("logout/", logout, {"next_page": settings.LOGOUT_REDIRECT_URL}, name="logout"), + path( + "accounts/register/", + RegistrationView.as_view(form_class=RegistrationForm), + name="django_registration_register", + ), + path("accounts/", include("django_registration.backends.activation.urls")), + path("accounts/", include("django.contrib.auth.urls")), path("admin/", admin.site.urls), path("", hello_world, name="hello_world"), ] @@ -31,3 +40,6 @@ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG_TOOLBAR: urlpatterns.insert(0, path("__debug__/", include("debug_toolbar.urls"))) + +if settings.DEBUG: + urlpatterns.insert(0, path("__reload__/", include("django_browser_reload.urls")))