✨(backend) allow to create a new user in a marketing system
We want to create a new user in a marketing system to create a dedicated onboarding for each of them. The marketing service is implemented in the django-lasuite library and it is possible to pick the backend we want or implement a new one following the documentation on this library.
This commit is contained in:
@@ -11,6 +11,7 @@ and this project adheres to
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- ⚡️(frontend) export html #1669
|
- ⚡️(frontend) export html #1669
|
||||||
|
- ✨(backend) allow to create a new user in a marketing system
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Here we describe all environment variables that can be set for the docs applicat
|
|||||||
These are the environment variables you can set for the `impress-backend` container.
|
These are the environment variables you can set for the `impress-backend` container.
|
||||||
|
|
||||||
| Option | Description | default |
|
| Option | Description | default |
|
||||||
|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|
|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||||
| AI_ALLOW_REACH_FROM | Users that can use AI must be this level. options are "public", "authenticated", "restricted" | authenticated |
|
| AI_ALLOW_REACH_FROM | Users that can use AI must be this level. options are "public", "authenticated", "restricted" | authenticated |
|
||||||
| AI_API_KEY | AI key to be used for AI Base url | |
|
| AI_API_KEY | AI key to be used for AI Base url | |
|
||||||
| AI_BASE_URL | OpenAI compatible AI base url | |
|
| AI_BASE_URL | OpenAI compatible AI base url | |
|
||||||
@@ -63,6 +63,8 @@ These are the environment variables you can set for the `impress-backend` contai
|
|||||||
| FRONTEND_HOMEPAGE_FEATURE_ENABLED | Frontend feature flag to display the homepage | false |
|
| FRONTEND_HOMEPAGE_FEATURE_ENABLED | Frontend feature flag to display the homepage | false |
|
||||||
| FRONTEND_THEME | Frontend theme to use | |
|
| FRONTEND_THEME | Frontend theme to use | |
|
||||||
| LANGUAGE_CODE | Default language | en-us |
|
| LANGUAGE_CODE | Default language | en-us |
|
||||||
|
| LASUITE_MARKETING_BACKEND | Backend used when SIGNUP_NEW_USER_TO_MARKETING_EMAIL is True. See https://github.com/suitenumerique/django-lasuite/blob/main/documentation/how-to-use-marketing-backend.md | lasuite.marketing.backends.dummy.DummyBackend |
|
||||||
|
| LASUITE_MARKETING_PARAMETERS | The parameters to configure LASUITE_MARKETING_BACKEND. See https://github.com/suitenumerique/django-lasuite/blob/main/documentation/how-to-use-marketing-backend.md | {} |
|
||||||
| LOGGING_LEVEL_LOGGERS_APP | Application logging level. options are "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL" | INFO |
|
| LOGGING_LEVEL_LOGGERS_APP | Application logging level. options are "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL" | INFO |
|
||||||
| LOGGING_LEVEL_LOGGERS_ROOT | Default logging level. options are "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL" | INFO |
|
| LOGGING_LEVEL_LOGGERS_ROOT | Default logging level. options are "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL" | INFO |
|
||||||
| LOGIN_REDIRECT_URL | Login redirect url | |
|
| LOGIN_REDIRECT_URL | Login redirect url | |
|
||||||
@@ -95,6 +97,7 @@ These are the environment variables you can set for the `impress-backend` contai
|
|||||||
| REDIS_URL | Cache url | redis://redis:6379/1 |
|
| REDIS_URL | Cache url | redis://redis:6379/1 |
|
||||||
| SENTRY_DSN | Sentry host | |
|
| SENTRY_DSN | Sentry host | |
|
||||||
| SESSION_COOKIE_AGE | duration of the cookie session | 60*60*12 |
|
| SESSION_COOKIE_AGE | duration of the cookie session | 60*60*12 |
|
||||||
|
| SIGNUP_NEW_USER_TO_MARKETING_EMAIL | Register new user to the marketing onboarding. If True, see env LASUITE_MARKETING_* system | False
|
||||||
| SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK | | false |
|
| SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK | | false |
|
||||||
| STORAGES_STATICFILES_BACKEND | | whitenoise.storage.CompressedManifestStaticFilesStorage |
|
| STORAGES_STATICFILES_BACKEND | | whitenoise.storage.CompressedManifestStaticFilesStorage |
|
||||||
| THEME_CUSTOMIZATION_CACHE_TIMEOUT | Cache duration for the customization settings | 86400 |
|
| THEME_CUSTOMIZATION_CACHE_TIMEOUT | Cache duration for the customization settings | 86400 |
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import os
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
|
|
||||||
|
from lasuite.marketing.tasks import create_or_update_contact
|
||||||
from lasuite.oidc_login.backends import (
|
from lasuite.oidc_login.backends import (
|
||||||
OIDCAuthenticationBackend as LaSuiteOIDCAuthenticationBackend,
|
OIDCAuthenticationBackend as LaSuiteOIDCAuthenticationBackend,
|
||||||
)
|
)
|
||||||
@@ -57,3 +58,22 @@ class OIDCAuthenticationBackend(LaSuiteOIDCAuthenticationBackend):
|
|||||||
return self.UserModel.objects.get_user_by_sub_or_email(sub, email)
|
return self.UserModel.objects.get_user_by_sub_or_email(sub, email)
|
||||||
except DuplicateEmailError as err:
|
except DuplicateEmailError as err:
|
||||||
raise SuspiciousOperation(err.message) from err
|
raise SuspiciousOperation(err.message) from err
|
||||||
|
|
||||||
|
def post_get_or_create_user(self, user, claims, is_new_user):
|
||||||
|
"""
|
||||||
|
Post-processing after user creation or retrieval.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (User): The user instance.
|
||||||
|
claims (dict): The claims dictionary.
|
||||||
|
is_new_user (bool): Indicates if the user was newly created.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- None
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if is_new_user and settings.SIGNUP_NEW_USER_TO_MARKETING_EMAIL:
|
||||||
|
create_or_update_contact.delay(
|
||||||
|
email=user.email, attributes={"DOCS_SOURCE": ["SIGNIN"]}
|
||||||
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
@@ -12,7 +13,10 @@ from cryptography.fernet import Fernet
|
|||||||
from lasuite.oidc_login.backends import get_oidc_refresh_token
|
from lasuite.oidc_login.backends import get_oidc_refresh_token
|
||||||
|
|
||||||
from core import models
|
from core import models
|
||||||
from core.authentication.backends import OIDCAuthenticationBackend
|
from core.authentication.backends import (
|
||||||
|
OIDCAuthenticationBackend,
|
||||||
|
create_or_update_contact,
|
||||||
|
)
|
||||||
from core.factories import UserFactory
|
from core.factories import UserFactory
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
@@ -509,3 +513,79 @@ def test_authentication_session_tokens(
|
|||||||
assert user is not None
|
assert user is not None
|
||||||
assert request.session["oidc_access_token"] == "test-access-token"
|
assert request.session["oidc_access_token"] == "test-access-token"
|
||||||
assert get_oidc_refresh_token(request.session) == "test-refresh-token"
|
assert get_oidc_refresh_token(request.session) == "test-refresh-token"
|
||||||
|
|
||||||
|
|
||||||
|
def test_authentication_post_get_or_create_user_new_user_to_marketing_email(settings):
|
||||||
|
"""
|
||||||
|
New user and SIGNUP_NEW_USER_TO_MARKETING_EMAIL enabled should create a contact
|
||||||
|
in the marketing backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = UserFactory()
|
||||||
|
settings.SIGNUP_NEW_USER_TO_MARKETING_EMAIL = True
|
||||||
|
|
||||||
|
klass = OIDCAuthenticationBackend()
|
||||||
|
with mock.patch.object(
|
||||||
|
create_or_update_contact, "delay"
|
||||||
|
) as mock_create_or_update_contact:
|
||||||
|
klass.post_get_or_create_user(user, {}, True)
|
||||||
|
mock_create_or_update_contact.assert_called_once_with(
|
||||||
|
email=user.email, attributes={"DOCS_SOURCE": ["SIGNIN"]}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_authentication_post_get_or_create_user_new_user_to_marketing_email_disabled(
|
||||||
|
settings,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
New user and SIGNUP_NEW_USER_TO_MARKETING_EMAIL disabled should not create a contact
|
||||||
|
in the marketing backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = UserFactory()
|
||||||
|
settings.SIGNUP_NEW_USER_TO_MARKETING_EMAIL = False
|
||||||
|
|
||||||
|
klass = OIDCAuthenticationBackend()
|
||||||
|
with mock.patch.object(
|
||||||
|
create_or_update_contact, "delay"
|
||||||
|
) as mock_create_or_update_contact:
|
||||||
|
klass.post_get_or_create_user(user, {}, True)
|
||||||
|
mock_create_or_update_contact.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_authentication_post_get_or_create_user_existing_user_to_marketing_email(
|
||||||
|
settings,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Existing user and SIGNUP_NEW_USER_TO_MARKETING_EMAIL enabled should not create a contact
|
||||||
|
in the marketing backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = UserFactory()
|
||||||
|
settings.SIGNUP_NEW_USER_TO_MARKETING_EMAIL = True
|
||||||
|
|
||||||
|
klass = OIDCAuthenticationBackend()
|
||||||
|
with mock.patch.object(
|
||||||
|
create_or_update_contact, "delay"
|
||||||
|
) as mock_create_or_update_contact:
|
||||||
|
klass.post_get_or_create_user(user, {}, False)
|
||||||
|
mock_create_or_update_contact.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_authentication_post_get_or_create_user_existing_user_to_marketing_email_disabled(
|
||||||
|
settings,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Existing user and SIGNUP_NEW_USER_TO_MARKETING_EMAIL disabled should not create a contact
|
||||||
|
in the marketing backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = UserFactory()
|
||||||
|
settings.SIGNUP_NEW_USER_TO_MARKETING_EMAIL = False
|
||||||
|
|
||||||
|
klass = OIDCAuthenticationBackend()
|
||||||
|
with mock.patch.object(
|
||||||
|
create_or_update_contact, "delay"
|
||||||
|
) as mock_create_or_update_contact:
|
||||||
|
klass.post_get_or_create_user(user, {}, False)
|
||||||
|
mock_create_or_update_contact.assert_not_called()
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ class Base(Configuration):
|
|||||||
# OIDC third party
|
# OIDC third party
|
||||||
"mozilla_django_oidc",
|
"mozilla_django_oidc",
|
||||||
"lasuite.malware_detection",
|
"lasuite.malware_detection",
|
||||||
|
"lasuite.marketing",
|
||||||
"csp",
|
"csp",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -808,6 +809,30 @@ class Base(Configuration):
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Marketing and communication settings
|
||||||
|
SIGNUP_NEW_USER_TO_MARKETING_EMAIL = values.BooleanValue(
|
||||||
|
False,
|
||||||
|
environ_name="SIGNUP_NEW_USER_TO_MARKETING_EMAIL",
|
||||||
|
environ_prefix=None,
|
||||||
|
help_text=(
|
||||||
|
"When enabled, new users are automatically added to mailing list "
|
||||||
|
"for product updates, marketing communications, and customized emails. "
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
LASUITE_MARKETING = {
|
||||||
|
"BACKEND": values.Value(
|
||||||
|
"lasuite.marketing.backends.dummy.DummyBackend",
|
||||||
|
environ_name="LASUITE_MARKETING_BACKEND",
|
||||||
|
environ_prefix=None,
|
||||||
|
),
|
||||||
|
"PARAMETERS": values.DictValue(
|
||||||
|
default={},
|
||||||
|
environ_name="LASUITE_MARKETING_PARAMETERS",
|
||||||
|
environ_prefix=None,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@property
|
@property
|
||||||
def ENVIRONMENT(self):
|
def ENVIRONMENT(self):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ dependencies = [
|
|||||||
"django-countries==8.1.0",
|
"django-countries==8.1.0",
|
||||||
"django-csp==4.0",
|
"django-csp==4.0",
|
||||||
"django-filter==25.2",
|
"django-filter==25.2",
|
||||||
"django-lasuite[all]==0.0.18",
|
"django-lasuite[all]==0.0.22",
|
||||||
"django-parler==2.3",
|
"django-parler==2.3",
|
||||||
"django-redis==6.0.0",
|
"django-redis==6.0.0",
|
||||||
"django-storages[s3]==1.14.6",
|
"django-storages[s3]==1.14.6",
|
||||||
|
|||||||
Reference in New Issue
Block a user