mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Add signals for customer account creation and sign in (#3470)
This commit is contained in:
@@ -61,7 +61,7 @@ Backend
|
|||||||
item_formsets, order_search_filter_q, order_search_forms
|
item_formsets, order_search_filter_q, order_search_forms
|
||||||
|
|
||||||
.. automodule:: pretix.base.signals
|
.. automodule:: pretix.base.signals
|
||||||
:members: logentry_display, logentry_object_link, requiredaction_display, timeline_events, orderposition_blocked_display
|
:members: logentry_display, logentry_object_link, requiredaction_display, timeline_events, orderposition_blocked_display, customer_created, customer_signed_in
|
||||||
|
|
||||||
Vouchers
|
Vouchers
|
||||||
""""""""
|
""""""""
|
||||||
|
|||||||
@@ -787,3 +787,23 @@ return a dictionary mapping names of attributes in the settings store to DRF ser
|
|||||||
|
|
||||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
customer_created = GlobalSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``customer``
|
||||||
|
|
||||||
|
This signal is sent out every time a customer account is created. The ``customer``
|
||||||
|
object is given as the first argument.
|
||||||
|
|
||||||
|
The ``sender`` keyword argument will contain the organizer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
customer_signed_in = GlobalSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``customer``
|
||||||
|
|
||||||
|
This signal is sent out every time a customer signs in. The ``customer`` object
|
||||||
|
is given as the first argument.
|
||||||
|
|
||||||
|
The ``sender`` keyword argument will contain the organizer.
|
||||||
|
"""
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ from pretix.base.customersso.oidc import (
|
|||||||
from pretix.base.models import Customer, InvoiceAddress, Order, OrderPosition
|
from pretix.base.models import Customer, InvoiceAddress, Order, OrderPosition
|
||||||
from pretix.base.services.mail import mail
|
from pretix.base.services.mail import mail
|
||||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||||
|
from pretix.base.signals import customer_created, customer_signed_in
|
||||||
from pretix.helpers.compat import CompatDeleteView
|
from pretix.helpers.compat import CompatDeleteView
|
||||||
from pretix.helpers.http import redirect_to_url
|
from pretix.helpers.http import redirect_to_url
|
||||||
from pretix.multidomain.models import KnownDomain
|
from pretix.multidomain.models import KnownDomain
|
||||||
@@ -151,7 +152,9 @@ class LoginView(RedirectBackMixin, FormView):
|
|||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
"""Security check complete. Log the user in."""
|
"""Security check complete. Log the user in."""
|
||||||
customer_login(self.request, form.get_customer())
|
customer = form.get_customer()
|
||||||
|
customer_login(self.request, customer)
|
||||||
|
customer_signed_in.send(customer.organizer, customer=customer)
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +240,8 @@ class RegistrationView(RedirectBackMixin, FormView):
|
|||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
form.create()
|
customer = form.create()
|
||||||
|
customer_created.send(customer.organizer, customer=customer)
|
||||||
messages.success(
|
messages.success(
|
||||||
self.request,
|
self.request,
|
||||||
_('Your account has been created. Please follow the link in the email we sent you to activate your '
|
_('Your account has been created. Please follow the link in the email we sent you to activate your '
|
||||||
@@ -756,6 +760,7 @@ class SSOLoginReturnView(RedirectBackMixin, View):
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
customer.save(force_insert=True)
|
customer.save(force_insert=True)
|
||||||
|
customer_created.send(customer.organizer, customer=customer)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
# This might either be a race condition or the email address is taken
|
# This might either be a race condition or the email address is taken
|
||||||
# by a different customer account
|
# by a different customer account
|
||||||
@@ -819,6 +824,7 @@ class SSOLoginReturnView(RedirectBackMixin, View):
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
customer_login(self.request, customer)
|
customer_login(self.request, customer)
|
||||||
|
customer_signed_in.send(customer.organizer, customer=customer)
|
||||||
return redirect_to_url(self.get_success_url(redirect_to))
|
return redirect_to_url(self.get_success_url(redirect_to))
|
||||||
|
|
||||||
def _fail(self, message, popup_origin):
|
def _fail(self, message, popup_origin):
|
||||||
|
|||||||
@@ -95,8 +95,12 @@ def test_native_disabled(env, client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_register(env, client):
|
def test_org_register(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_created
|
||||||
|
mocker.patch('pretix.base.signals.customer_created.send')
|
||||||
|
|
||||||
signer = signing.TimestampSigner(salt='customer-registration-captcha-127.0.0.1')
|
signer = signing.TimestampSigner(salt='customer-registration-captcha-127.0.0.1')
|
||||||
|
|
||||||
r = client.post('/bigevents/account/register', {
|
r = client.post('/bigevents/account/register', {
|
||||||
'email': 'john@example.org',
|
'email': 'john@example.org',
|
||||||
'name_parts_0': 'John Doe',
|
'name_parts_0': 'John Doe',
|
||||||
@@ -109,6 +113,7 @@ def test_org_register(env, client):
|
|||||||
customer = env[0].customers.get(email='john@example.org')
|
customer = env[0].customers.get(email='john@example.org')
|
||||||
assert not customer.is_verified
|
assert not customer.is_verified
|
||||||
assert customer.is_active
|
assert customer.is_active
|
||||||
|
customer_created.send.assert_called_once_with(customer.organizer, customer=customer)
|
||||||
|
|
||||||
r = client.post(
|
r = client.post(
|
||||||
f'/bigevents/account/activate?id={customer.identifier}&token={TokenGenerator().make_token(customer)}', {
|
f'/bigevents/account/activate?id={customer.identifier}&token={TokenGenerator().make_token(customer)}', {
|
||||||
@@ -123,7 +128,10 @@ def test_org_register(env, client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_register_duplicate_email(env, client):
|
def test_org_register_duplicate_email(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_created
|
||||||
|
mocker.patch('pretix.base.signals.customer_created.send')
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
env[0].customers.create(email='john@example.org')
|
env[0].customers.create(email='john@example.org')
|
||||||
r = client.post('/bigevents/account/register', {
|
r = client.post('/bigevents/account/register', {
|
||||||
@@ -132,6 +140,7 @@ def test_org_register_duplicate_email(env, client):
|
|||||||
})
|
})
|
||||||
assert b'already registered' in r.content
|
assert b'already registered' in r.content
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
customer_created.send.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -167,7 +176,11 @@ def test_org_activate_invalid_token(env, client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_login_logout(env, client):
|
def test_org_login_logout(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
|
customer = None
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
customer = env[0].customers.create(email='john@example.org', is_verified=True)
|
customer = env[0].customers.create(email='john@example.org', is_verified=True)
|
||||||
customer.set_password('foo')
|
customer.set_password('foo')
|
||||||
@@ -179,6 +192,8 @@ def test_org_login_logout(env, client):
|
|||||||
})
|
})
|
||||||
assert r.status_code == 302
|
assert r.status_code == 302
|
||||||
|
|
||||||
|
customer_signed_in.send.assert_called_once_with(customer.organizer, customer=customer)
|
||||||
|
|
||||||
r = client.get('/bigevents/account/')
|
r = client.get('/bigevents/account/')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
@@ -190,7 +205,10 @@ def test_org_login_logout(env, client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_login_invalid_password(env, client):
|
def test_org_login_invalid_password(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
customer = env[0].customers.create(email='john@example.org', is_verified=True)
|
customer = env[0].customers.create(email='john@example.org', is_verified=True)
|
||||||
customer.set_password('foo')
|
customer.set_password('foo')
|
||||||
@@ -202,10 +220,15 @@ def test_org_login_invalid_password(env, client):
|
|||||||
})
|
})
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert b'alert-danger' in r.content
|
assert b'alert-danger' in r.content
|
||||||
|
customer_signed_in.send.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_login_not_verified(env, client):
|
def test_org_login_not_verified(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
|
customer = None
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
customer = env[0].customers.create(email='john@example.org', is_verified=False)
|
customer = env[0].customers.create(email='john@example.org', is_verified=False)
|
||||||
customer.set_password('foo')
|
customer.set_password('foo')
|
||||||
@@ -217,10 +240,14 @@ def test_org_login_not_verified(env, client):
|
|||||||
})
|
})
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert b'alert-danger' in r.content
|
assert b'alert-danger' in r.content
|
||||||
|
customer_signed_in.send.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_login_not_active(env, client):
|
def test_org_login_not_active(env, client, mocker):
|
||||||
|
from pretix.base.signals import customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
customer = env[0].customers.create(email='john@example.org', is_verified=True, is_active=False)
|
customer = env[0].customers.create(email='john@example.org', is_verified=True, is_active=False)
|
||||||
customer.set_password('foo')
|
customer.set_password('foo')
|
||||||
@@ -232,6 +259,7 @@ def test_org_login_not_active(env, client):
|
|||||||
})
|
})
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert b'alert-danger' in r.content
|
assert b'alert-danger' in r.content
|
||||||
|
customer_signed_in.send.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -309,12 +337,18 @@ def _sso_login(client, provider, email='test@example.org', popup_origin=None, ex
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_sso_login_new_customer(env, client, provider):
|
def test_org_sso_login_new_customer(env, client, provider, mocker):
|
||||||
|
from pretix.base.signals import customer_created, customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_created.send')
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
_sso_login(client, provider)
|
_sso_login(client, provider)
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
c = Customer.objects.get(provider=provider)
|
c = Customer.objects.get(provider=provider)
|
||||||
assert c.external_identifier == "abcdf"
|
assert c.external_identifier == "abcdf"
|
||||||
|
customer_created.send.assert_called_once_with(c.organizer, customer=c)
|
||||||
|
customer_signed_in.send.assert_called_once_with(c.organizer, customer=c)
|
||||||
|
|
||||||
r = client.get('/bigevents/account/')
|
r = client.get('/bigevents/account/')
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
@@ -352,10 +386,15 @@ def test_org_sso_login_new_customer_popup_invalid_origin(env, client, provider):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_org_sso_login_returning_customer_new_email(env, client, provider):
|
def test_org_sso_login_returning_customer_new_email(env, client, provider, mocker):
|
||||||
|
from pretix.base.signals import customer_signed_in
|
||||||
|
mocker.patch('pretix.base.signals.customer_signed_in.send')
|
||||||
|
|
||||||
_sso_login(client, provider)
|
_sso_login(client, provider)
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
c = Customer.objects.get(provider=provider)
|
c = Customer.objects.get(provider=provider)
|
||||||
|
customer_signed_in.send.assert_called_once_with(c.organizer, customer=c)
|
||||||
|
customer_signed_in.send.reset_mock()
|
||||||
|
|
||||||
r = client.get('/bigevents/account/logout')
|
r = client.get('/bigevents/account/logout')
|
||||||
assert r.status_code == 302
|
assert r.status_code == 302
|
||||||
@@ -363,6 +402,7 @@ def test_org_sso_login_returning_customer_new_email(env, client, provider):
|
|||||||
_sso_login(client, provider, 'new@example.net')
|
_sso_login(client, provider, 'new@example.net')
|
||||||
c.refresh_from_db()
|
c.refresh_from_db()
|
||||||
assert c.email == "new@example.net"
|
assert c.email == "new@example.net"
|
||||||
|
customer_signed_in.send.assert_called_once_with(c.organizer, customer=c)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db(transaction=True)
|
@pytest.mark.django_db(transaction=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user