Allow to use custom domains for some but not all events (Z#23153875) (#4627)

* Allow to use custom domains for some but not all events

* Update src/pretix/multidomain/urlreverse.py

* Apply suggestions from code review

Co-authored-by: Mira <weller@rami.io>

* Logging for domain config changes

---------

Co-authored-by: Mira <weller@rami.io>
This commit is contained in:
Raphael Michel
2024-12-02 15:58:50 +01:00
committed by GitHub
parent e2753686ee
commit e99ee91573
20 changed files with 747 additions and 153 deletions

View File

@@ -1967,7 +1967,7 @@ def test_pdf_data(token_client, organizer, event, order, django_assert_max_num_q
assert not resp.data['positions'][0].get('pdf_data')
# order list
with django_assert_max_num_queries(31):
with django_assert_max_num_queries(32):
resp = token_client.get('/api/v1/organizers/{}/events/{}/orders/?pdf_data=true'.format(
organizer.slug, event.slug
))
@@ -1982,7 +1982,7 @@ def test_pdf_data(token_client, organizer, event, order, django_assert_max_num_q
assert not resp.data['results'][0]['positions'][0].get('pdf_data')
# position list
with django_assert_max_num_queries(34):
with django_assert_max_num_queries(35):
resp = token_client.get('/api/v1/organizers/{}/events/{}/orderpositions/?pdf_data=true'.format(
organizer.slug, event.slug
))

View File

@@ -40,16 +40,21 @@ def env():
@pytest.mark.django_db
def test_control_only_on_main_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_DOMAIN)
r = client.get('/control/login', HTTP_HOST='foobar')
assert r.status_code == 302
assert r['Location'] == 'http://example.com/control/login'
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1])
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1], mode=KnownDomain.MODE_EVENT_DOMAIN)
r = client.get('/control/login', HTTP_HOST='barfoo')
assert r.status_code == 302
assert r['Location'] == 'http://example.com/control/login'
KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
r = client.get('/control/login', HTTP_HOST='altfoo')
assert r.status_code == 302
assert r['Location'] == 'http://example.com/control/login'
@pytest.mark.django_db
def test_append_slash(env, client):
@@ -80,6 +85,15 @@ def test_event_on_custom_domain(env, client):
assert b'<meta property="og:title" content="MRMCD2015" />' in r.content
@pytest.mark.django_db
def test_event_on_org_alt_domain(env, client):
d = KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
r = client.get('/2015/', HTTP_HOST='foobar')
assert r.status_code == 200
assert b'<meta property="og:title" content="MRMCD2015" />' in r.content
@pytest.mark.django_db
def test_path_without_trailing_slash_on_org_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
@@ -95,6 +109,15 @@ def test_event_with_org_domain_on_main_domain(env, client):
assert r['Location'] == 'http://foobar/2015/'
@pytest.mark.django_db
def test_event_with_org_alt_domain_on_main_domain(env, client):
d = KnownDomain.objects.create(domainname='foobar', organizer=env[0])
d.event_assignments.create(event=env[1])
r = client.get('/mrmcd/2015/', HTTP_HOST='example.com')
assert r.status_code == 302
assert r['Location'] == 'http://foobar/2015/'
@pytest.mark.django_db
def test_event_with_custom_domain_on_main_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], event=env[1])
@@ -112,6 +135,40 @@ def test_event_with_custom_domain_on_org_domain(env, client):
assert r['Location'] == 'http://barfoo'
@pytest.mark.django_db
def test_event_with_custom_domain_on_org_alt_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1])
r = client.get('/2015/', HTTP_HOST='altfoo')
assert r.status_code == 302
assert r['Location'] == 'http://barfoo'
@pytest.mark.django_db
def test_event_with_org_alt_domain_on_org_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_DOMAIN)
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
r = client.get('/2015/', HTTP_HOST='foobar')
assert r.status_code == 302
assert r['Location'] == 'http://altfoo/2015/'
@pytest.mark.django_db
def test_event_without_org_alt_domain_on_org_alt_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
r = client.get('/', HTTP_HOST='foobar')
assert r.status_code == 302
assert r['Location'] == 'http://example.com/mrmcd/'
KnownDomain.objects.create(domainname='foobaz', organizer=env[0], mode=KnownDomain.MODE_ORG_DOMAIN)
r = client.get('/', HTTP_HOST='foobar')
assert r.status_code == 302
assert r['Location'] == 'http://foobaz/'
@pytest.mark.django_db
def test_organizer_with_org_domain_on_main_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
@@ -143,6 +200,10 @@ def test_unknown_event_on_org_domain(env, client):
r = client.get('/1234/', HTTP_HOST='foobar')
assert r.status_code == 404
KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
r = client.get('/1234/', HTTP_HOST='altfoo')
assert r.status_code == 404
@pytest.mark.django_db
def test_cookie_domain_on_org_domain(env, client):
@@ -153,6 +214,16 @@ def test_cookie_domain_on_org_domain(env, client):
assert r.client.cookies['pretix_session']['domain'] == ''
@pytest.mark.django_db
def test_cookie_domain_on_org_alt_domain(env, client):
d = KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
client.post('/2015/cart/add', HTTP_HOST='foobar')
r = client.get('/2015/', HTTP_HOST='foobar')
assert r.client.cookies['pretix_csrftoken']['domain'] == ''
assert r.client.cookies['pretix_session']['domain'] == ''
@pytest.mark.django_db
def test_cookie_domain_on_event_domain(env, client):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])

View File

@@ -62,6 +62,36 @@ def test_event_custom_domain_front_page(env):
assert rendered == 'http://foobar/2015/'
@pytest.mark.django_db
def test_event_custom_event_domain_front_page(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], event=env[1], mode=KnownDomain.MODE_EVENT_DOMAIN)
rendered = TEMPLATE_FRONT_PAGE.render(Context({
'event': env[1]
})).strip()
assert rendered == 'http://foobar/'
@pytest.mark.django_db
def test_event_custom_org_alt_domain_front_page(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_DOMAIN)
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
rendered = TEMPLATE_FRONT_PAGE.render(Context({
'event': env[1]
})).strip()
assert rendered == 'http://altfoo/2015/'
@pytest.mark.django_db
def test_event_custom_org_alt_domain_unassigned_front_page(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0], mode=KnownDomain.MODE_ORG_DOMAIN)
KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
rendered = TEMPLATE_FRONT_PAGE.render(Context({
'event': env[1]
})).strip()
assert rendered == 'http://foobar/2015/'
@pytest.mark.django_db
def test_event_main_domain_kwargs(env):
rendered = TEMPLATE_KWARGS.render(Context({

View File

@@ -37,7 +37,7 @@ def env():
organizer=o, name='MRMCD2015', slug='2015',
date_from=now()
)
event.get_cache().clear()
event.cache.clear()
return o, event
@@ -60,6 +60,16 @@ def test_event_org_domain_kwargs(env):
assert eventreverse(env[1], 'presale:event.checkout', {'step': 'payment'}) == 'http://foobar/2015/checkout/payment/'
@pytest.mark.django_db
def test_event_org_alt_domain_kwargs(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
assert eventreverse(env[1], 'presale:event.checkout', {'step': 'payment'}) == 'http://foobar/2015/checkout/payment/'
d.event_assignments.create(event=env[1])
with scopes_disabled():
assert eventreverse(Event.objects.get(pk=env[1].pk), 'presale:event.checkout', {'step': 'payment'}) == 'http://altfoo/2015/checkout/payment/'
@pytest.mark.django_db
def test_event_main_domain_kwargs(env):
assert eventreverse(env[1], 'presale:event.checkout', {'step': 'payment'}) == '/mrmcd/2015/checkout/payment/'
@@ -72,6 +82,15 @@ def test_event_org_domain_front_page(env):
assert eventreverse(env[0], 'presale:organizer.index') == 'http://foobar/'
@pytest.mark.django_db
def test_event_org_alt_domain_front_page(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
assert eventreverse(env[1], 'presale:event.index') == 'http://altfoo/2015/'
assert eventreverse(env[0], 'presale:organizer.index') == 'http://foobar/'
@pytest.mark.django_db
def test_event_custom_domain_front_page(env):
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1])
@@ -109,8 +128,8 @@ def test_event_org_domain_keep_scheme(env):
}
})
def test_event_main_domain_cache(env):
env[0].get_cache().clear()
with assert_num_queries(1):
env[0].cache.clear()
with assert_num_queries(2):
eventreverse(env[1], 'presale:event.index')
with assert_num_queries(0):
eventreverse(env[1], 'presale:event.index')
@@ -125,8 +144,8 @@ def test_event_main_domain_cache(env):
})
def test_event_org_domain_cache(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
env[0].get_cache().clear()
with assert_num_queries(1):
env[0].cache.clear()
with assert_num_queries(2):
eventreverse(env[1], 'presale:event.index')
with assert_num_queries(0):
eventreverse(env[1], 'presale:event.index')
@@ -142,13 +161,36 @@ def test_event_org_domain_cache(env):
def test_event_custom_domain_cache(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1])
env[0].get_cache().clear()
env[0].cache.clear()
with assert_num_queries(1):
eventreverse(env[1], 'presale:event.index')
with assert_num_queries(0):
eventreverse(env[1], 'presale:event.index')
@pytest.mark.django_db
@override_settings(CACHES={
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
})
@scopes_disabled()
def test_event_org_alt_domain_cache_clear(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
kd_alt = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
env[0].cache.clear()
with assert_num_queries(2):
eventreverse(env[1], 'presale:event.index')
kd_alt.event_assignments.create(event=env[1])
with assert_num_queries(2):
ev = Event.objects.get(pk=env[1].pk)
assert ev.pk == env[1].pk
assert ev.organizer == env[0]
with assert_num_queries(1):
eventreverse(ev, 'presale:event.index')
@pytest.mark.django_db
@override_settings(CACHES={
'default': {
@@ -160,14 +202,14 @@ def test_event_custom_domain_cache(env):
def test_event_org_domain_cache_clear(env):
kd = KnownDomain.objects.create(domainname='foobar', organizer=env[0])
env[0].cache.clear()
with assert_num_queries(1):
with assert_num_queries(2):
eventreverse(env[1], 'presale:event.index')
kd.delete()
with assert_num_queries(2):
ev = Event.objects.get(pk=env[1].pk)
assert ev.pk == env[1].pk
assert ev.organizer == env[0]
with assert_num_queries(1):
with assert_num_queries(2):
eventreverse(ev, 'presale:event.index')
@@ -190,7 +232,7 @@ def test_event_custom_domain_cache_clear(env):
ev = Event.objects.get(pk=env[1].pk)
assert ev.pk == env[1].pk
assert ev.organizer == env[0]
with assert_num_queries(1):
with assert_num_queries(2):
eventreverse(ev, 'presale:event.index')
@@ -210,3 +252,11 @@ def test_event_custom_domain_absolute(env):
def test_event_org_domain_absolute(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://foobar/2015/'
@pytest.mark.django_db
def test_event_org_alt_domain_absolute(env):
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://altfoo/2015/'

View File

@@ -378,6 +378,13 @@ def test_org_sso_login_new_customer_popup(env, client, provider):
_sso_login(client, provider, popup_origin="https://popuporigin")
@pytest.mark.django_db
def test_org_sso_login_new_customer_popup_org_alt_domain(env, client, provider):
d = KnownDomain.objects.create(organizer=env[0], domainname="popuporigin", mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
_sso_login(client, provider, popup_origin="https://popuporigin")
@pytest.mark.django_db
def test_org_sso_login_new_customer_popup_invalid_origin(env, client, provider):
KnownDomain.objects.create(organizer=env[0], event=env[1], domainname="popuporigin")
@@ -696,16 +703,21 @@ def client2():
return Client()
def _cross_domain_login(env, client, client2):
def _cross_domain_login(env, client, client2, org_alt=False):
with scopes_disabled():
customer = env[0].customers.create(email='john@example.org', is_verified=True)
customer.set_password('foo')
customer.save()
KnownDomain.objects.create(domainname='org.test', organizer=env[0])
KnownDomain.objects.create(domainname='event.test', organizer=env[0], event=env[1])
if org_alt:
d = KnownDomain.objects.create(domainname='event.test', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
d.event_assignments.create(event=env[1])
else:
KnownDomain.objects.create(domainname='event.test', organizer=env[0], event=env[1])
# Log in on org domain
r = client.post('/account/login?next=https://event.test/redeem&request_cross_domain_customer_auth=true', {
path = '/conf/' if org_alt else '/'
r = client.post(f'/account/login?next=https://event.test{path}redeem&request_cross_domain_customer_auth=true', {
'email': 'john@example.org',
'password': 'foo',
}, HTTP_HOST='org.test')
@@ -713,12 +725,12 @@ def _cross_domain_login(env, client, client2):
u = urlparse(r.headers['Location'])
assert u.netloc == 'event.test'
assert u.path == '/redeem'
assert u.path == path + 'redeem'
q = parse_qs(u.query)
assert 'cross_domain_customer_auth' in q
# Take session over to event domain
r = client2.get(f'/?{u.query}', HTTP_HOST='event.test')
r = client2.get(f'{path}?{u.query}', HTTP_HOST='event.test')
assert r.status_code == 200
assert b'john@example.org' in r.content
@@ -727,12 +739,27 @@ def _cross_domain_login(env, client, client2):
def test_cross_domain_login(env, client, client2):
_cross_domain_login(env, client, client2)
# Logged in on org domain
# Logged in on evnet domain
r = client.get('/', HTTP_HOST='event.test')
assert r.status_code == 200
assert b'john@example.org' in r.content
# Logged in on event domain
# Logged in on org domain
r = client2.get('/', HTTP_HOST='org.test')
assert r.status_code == 200
assert b'john@example.org' in r.content
@pytest.mark.django_db
def test_cross_domain_login_org_alt(env, client, client2):
_cross_domain_login(env, client, client2, org_alt=True)
# Logged in on org alt domain
r = client.get('/conf/', HTTP_HOST='event.test')
assert r.status_code == 200
assert b'john@example.org' in r.content
# Logged in on org domain
r = client2.get('/', HTTP_HOST='org.test')
assert r.status_code == 200
assert b'john@example.org' in r.content