Use new permissions, remove inconsistencies

This commit is contained in:
Raphael Michel
2026-01-12 18:30:39 +01:00
parent 2c8b545ed1
commit 18d3df4736
61 changed files with 1214 additions and 781 deletions

View File

@@ -1387,7 +1387,14 @@ def test_get_event_settings(token_client, organizer, event):
@pytest.mark.django_db
def test_patch_event_settings(token_client, organizer, event):
def test_patch_event_settings(token_client, organizer, event, team):
team.all_event_permissions = False
team.limit_event_permissions = {
"event.settings.general:write": True,
"event.settings.tax:write": True,
}
team.save()
organizer.settings.imprint_url = 'https://example.org'
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
@@ -1503,6 +1510,29 @@ def test_patch_event_settings(token_client, organizer, event):
event.settings.flush()
assert set(event.settings.locales) == set(locales)
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
{
'display_net_prices': True,
},
format='json'
)
assert resp.status_code == 200
event.settings.flush()
assert event.settings.display_net_prices
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
{
'invoice_address_asked': False,
},
format='json'
)
assert resp.status_code == 400
assert resp.data == {
'invoice_address_asked': ['Setting this field requires permission event.settings.invoicing:write']
}
@pytest.mark.django_db
def test_patch_event_settings_validation(token_client, organizer, event):

View File

@@ -59,7 +59,7 @@ event_urls = [
]
event_permission_sub_urls = [
('get', 'event.settings.general:write', 'settings/', 200),
('get', None, 'settings/', 200),
('patch', 'event.settings.general:write', 'settings/', 200),
('get', 'event.orders:read', 'revokedsecrets/', 200),
('get', 'event.orders:read', 'revokedsecrets/1/', 404),
@@ -118,12 +118,15 @@ event_permission_sub_urls = [
('delete', 'event.items:write', 'items/1/addons/1/', 404),
('get', None, 'subevents/', 200),
('get', None, 'subevents/1/', 404),
('post', 'event.subevents:write', 'subevents/', 400),
('patch', 'event.subevents:write', 'subevents/1/', 404),
('put', 'event.subevents:write', 'subevents/1/', 404),
('get', None, 'taxrules/', 200),
('get', None, 'taxrules/1/', 404),
('post', 'event.settings.general:write', 'taxrules/', 400),
('put', 'event.settings.general:write', 'taxrules/1/', 404),
('patch', 'event.settings.general:write', 'taxrules/1/', 404),
('delete', 'event.settings.general:write', 'taxrules/1/', 404),
('post', 'event.settings.tax:write', 'taxrules/', 400),
('put', 'event.settings.tax:write', 'taxrules/1/', 404),
('patch', 'event.settings.tax:write', 'taxrules/1/', 404),
('delete', 'event.settings.tax:write', 'taxrules/1/', 404),
('get', 'event.settings.general:write', 'sendmail_rules/', 200),
('get', 'event.settings.general:write', 'sendmail_rules/1/', 404),
('post', 'event.settings.general:write', 'sendmail_rules/', 400),
@@ -214,16 +217,16 @@ org_permission_sub_urls = [
('put', 'organizer.settings.general:write', 'webhooks/1/', 404),
('patch', 'organizer.settings.general:write', 'webhooks/1/', 404),
('delete', 'organizer.settings.general:write', 'webhooks/1/', 404),
('get', 'organizer.customers:write', 'customers/', 200),
('get', 'organizer.customers:read', 'customers/', 200),
('post', 'organizer.customers:write', 'customers/', 201),
('get', 'organizer.customers:write', 'customers/1/', 404),
('get', 'organizer.customers:read', 'customers/1/', 404),
('patch', 'organizer.customers:write', 'customers/1/', 404),
('post', 'organizer.customers:write', 'customers/1/anonymize/', 404),
('put', 'organizer.customers:write', 'customers/1/', 404),
('delete', 'organizer.customers:write', 'customers/1/', 404),
('get', 'organizer.customers:write', 'memberships/', 200),
('get', 'organizer.customers:read', 'memberships/', 200),
('post', 'organizer.customers:write', 'memberships/', 400),
('get', 'organizer.customers:write', 'memberships/1/', 404),
('get', 'organizer.customers:read', 'memberships/1/', 404),
('patch', 'organizer.customers:write', 'memberships/1/', 404),
('put', 'organizer.customers:write', 'memberships/1/', 404),
('delete', 'organizer.customers:write', 'memberships/1/', 404),
@@ -239,18 +242,18 @@ org_permission_sub_urls = [
('patch', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
('put', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
('delete', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
('get', 'organizer.giftcards:write', 'giftcards/', 200),
('get', 'organizer.giftcards:read', 'giftcards/', 200),
('post', 'organizer.giftcards:write', 'giftcards/', 400),
('get', 'organizer.giftcards:write', 'giftcards/1/', 404),
('get', 'organizer.giftcards:read', 'giftcards/1/', 404),
('put', 'organizer.giftcards:write', 'giftcards/1/', 404),
('patch', 'organizer.giftcards:write', 'giftcards/1/', 404),
('get', 'organizer.giftcards:write', 'giftcards/1/transactions/', 404),
('get', 'organizer.giftcards:write', 'giftcards/1/transactions/1/', 404),
('get', 'organizer.settings.general:write', 'devices/', 200),
('post', 'organizer.settings.general:write', 'devices/', 400),
('get', 'organizer.settings.general:write', 'devices/1/', 404),
('put', 'organizer.settings.general:write', 'devices/1/', 404),
('patch', 'organizer.settings.general:write', 'devices/1/', 404),
('get', 'organizer.giftcards:read', 'giftcards/1/transactions/', 404),
('get', 'organizer.giftcards:read', 'giftcards/1/transactions/1/', 404),
('get', 'organizer.devices:read', 'devices/', 200),
('post', 'organizer.devices:write', 'devices/', 400),
('get', 'organizer.devices:read', 'devices/1/', 404),
('put', 'organizer.devices:write', 'devices/1/', 404),
('patch', 'organizer.devices:write', 'devices/1/', 404),
('get', 'organizer.teams:write', 'teams/', 200),
('post', 'organizer.teams:write', 'teams/', 400),
('get', 'organizer.teams:write', 'teams/{team_id}/', 200),
@@ -266,7 +269,11 @@ org_permission_sub_urls = [
('get', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
('delete', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
('post', 'organizer.teams:write', 'teams/{team_id}/tokens/', 400),
('get', 'organizer.reusablemedia:read', 'reusablemedia/', 200),
('get', 'organizer.reusablemedia:read', 'reusablemedia/1/', 404),
('post', 'organizer.reusablemedia:write', 'reusablemedia/', 400),
('patch', 'organizer.reusablemedia:write', 'reusablemedia/1/', 404),
('put', 'organizer.reusablemedia:write', 'reusablemedia/1/', 404),
]

View File

@@ -119,7 +119,39 @@ def test_medium_list(token_client, organizer, event, medium):
@pytest.mark.django_db
def test_medium_detail(token_client, organizer, event, medium, giftcard, customer):
def test_medium_detail_permission_missing(token_client, organizer, event, medium, giftcard, customer, team):
team.all_organizer_permissions = False
team.limit_organizer_permissions = {
"organizer.reusablemedia:read": True,
}
team.save()
resp = token_client.get(
'/api/v1/organizers/{}/reusablemedia/{}/?expand=linked_giftcard'.format(
organizer.slug, medium.pk
)
)
assert resp.status_code == 403
assert "No permission to access gift card details." in str(resp.data)
resp = token_client.get(
'/api/v1/organizers/{}/reusablemedia/{}/?expand=customer'.format(
organizer.slug, medium.pk
)
)
assert resp.status_code == 403
assert "No permission to access customer details." in str(resp.data)
@pytest.mark.django_db
def test_medium_detail(token_client, organizer, event, medium, giftcard, customer, team):
team.all_organizer_permissions = False
team.limit_organizer_permissions = {
"organizer.reusablemedia:read": True,
"organizer.customers:read": True,
"organizer.giftcards:read": True,
}
team.save()
res = dict(TEST_MEDIUM_RES)
res["id"] = medium.pk
res["created"] = medium.created.isoformat().replace('+00:00', 'Z')
@@ -340,7 +372,16 @@ def test_medium_lookup_not_found(token_client, organizer, organizer2, medium):
@pytest.mark.django_db
def test_medium_lookup_autocreate(token_client, organizer):
def test_medium_lookup_autocreate(token_client, organizer, team):
team.all_organizer_permissions = False
team.limit_organizer_permissions = {
"organizer.reusablemedia:read": True,
"organizer.reusablemedia:write": True,
"organizer.customers:read": True,
"organizer.giftcards:read": True,
}
team.save()
# Disabled
resp = token_client.post(
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
@@ -386,7 +427,15 @@ def test_medium_lookup_autocreate(token_client, organizer):
@pytest.mark.django_db
def test_medium_autocreate_giftcard(token_client, organizer):
def test_medium_autocreate_giftcard(token_client, organizer, team):
team.all_organizer_permissions = False
team.limit_organizer_permissions = {
"organizer.reusablemedia:write": True,
"organizer.reusablemedia:read": True,
"organizer.customers:read": True,
"organizer.giftcards:read": True,
}
team.save()
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard = True
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency = 'USD'
resp = token_client.post(

View File

@@ -175,8 +175,6 @@ def test_team_update_legacy_add_perm(token_client, organizer, event, second_team
assert second_team.limit_event_permissions == {
"event.settings.general:write": True,
"event.settings.payment:write": True,
"event.settings.plugins:write": True,
"event.settings.email.sender:write": True,
"event.settings.tax:write": True,
"event.settings.invoicing:write": True,
"event.subevents:write": True,

View File

@@ -57,9 +57,9 @@ class ItemFormTest(SoupTest):
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
)
self.item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0, position=1)
t = Team.objects.create(organizer=self.orga1, all_event_permissions=True)
t.members.add(self.user)
t.limit_events.add(self.event1)
self.team = Team.objects.create(organizer=self.orga1, all_event_permissions=True)
self.team.members.add(self.user)
self.team.limit_events.add(self.event1)
self.client.login(email='dummy@dummy.dummy', password='dummy')
@@ -270,6 +270,14 @@ class QuestionsTest(ItemFormTest):
tbl = doc.select('.container-fluid table.table-bordered tbody')[0]
assert tbl.select('tr')[0].select('td')[0].text.strip() == '42'
# Test permission requirement
self.team.all_event_permissions = False
self.team.limit_event_permissions = {}
self.team.save()
doc = self.get_doc('/control/event/%s/%s/questions/%s/' % (self.orga1.slug, self.event1.slug, c.id))
assert not doc.select('.container-fluid table.table-bordered tbody')
assert doc.select('.empty-collection')
def test_set_dependency(self):
with scopes_disabled():
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)

View File

@@ -44,7 +44,7 @@ from pretix.base.models import Event, Order, Organizer, Team, User
@pytest.fixture
def env():
o = Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer'
@@ -308,29 +308,29 @@ event_permission_urls = [
("event.settings.general:write", "delete/", 200, HTTP_GET),
("event.settings.general:write", "dangerzone/", 200, HTTP_GET),
("event.settings.general:write", "settings/", 200, HTTP_GET),
("event.settings.general:write", "settings/plugins", 200, HTTP_GET),
("event.settings.general:write", "settings/payment", 200, HTTP_GET),
# ("event.settings.payment:write", "settings/payment", 200, HTTP_GET), GET allowed also with other permissions
("event.settings.payment:write", "settings/payment", 200, HTTP_POST),
("event.settings.payment:write", "settings/payment/banktransfer", 200, HTTP_GET),
("event.settings.general:write", "settings/tickets", 200, HTTP_GET),
("event.settings.general:write", "settings/email", 200, HTTP_GET),
("event.settings.general:write", "settings/email/setup", 200, HTTP_GET),
("event.settings.general:write", "settings/cancel", 200, HTTP_GET),
("event.settings.general:write", "settings/invoice", 200, HTTP_GET),
("event.settings.general:write", "settings/widget", 200, HTTP_GET),
("event.settings.general:write", "settings/invoice/preview", 200, HTTP_GET),
("event.settings.general:write", "settings/tax/", 200, HTTP_GET),
("event.settings.general:write", "settings/tax/1/", 404, HTTP_GET),
("event.settings.general:write", "settings/tax/add", 200, HTTP_GET),
("event.settings.general:write", "settings/tax/1/delete", 404, HTTP_GET),
("event.settings.general:write", "settings/tax/1/default", 404, HTTP_POST),
("event.settings.invoicing:write", "settings/invoice", 200, HTTP_GET),
("event.settings.invoicing:write", "settings/invoice/preview", 200, HTTP_GET),
("event.settings.tax:write", "settings/tax/", 200, HTTP_GET),
("event.settings.tax:write", "settings/tax/1/", 404, HTTP_GET),
("event.settings.tax:write", "settings/tax/add", 200, HTTP_GET),
("event.settings.tax:write", "settings/tax/1/delete", 404, HTTP_GET),
("event.settings.tax:write", "settings/tax/1/default", 404, HTTP_POST),
("event.settings.general:write", "comment/", 405, HTTP_GET),
# Lists are currently not access-controlled
# ("event.items:write", "items/", 200),
(None, "items/", 200, HTTP_GET),
("event.items:write", "items/add", 200, HTTP_GET),
("event.items:write", "items/1/up", 404, HTTP_POST),
("event.items:write", "items/1/down", 404, HTTP_POST),
("event.items:write", "items/reorder/2/", 400, HTTP_POST),
("event.items:write", "items/1/delete", 404, HTTP_GET),
# ("event.items:write", "categories/", 200),
(None, "categories/", 200, HTTP_GET),
# We don't have to create categories and similar objects
# for testing this, it is enough to test that a 404 error
# is returned instead of a 403 one.
@@ -340,29 +340,30 @@ event_permission_urls = [
("event.items:write", "categories/2/down", 404, HTTP_POST),
("event.items:write", "categories/reorder", 400, HTTP_POST),
("event.items:write", "categories/add", 200, HTTP_GET),
# ("event.items:write", "questions/", 200, HTTP_GET),
("event.items:write", "questions/2/", 404, HTTP_GET),
(None, "questions/", 200, HTTP_GET),
(None, "questions/2/", 404, HTTP_GET),
("event.items:write", "questions/2/delete", 404, HTTP_GET),
("event.items:write", "questions/reorder", 400, HTTP_POST),
("event.items:write", "questions/add", 200, HTTP_GET),
# ("event.items:write", "quotas/", 200, HTTP_GET),
(None, "quotas/", 200, HTTP_GET),
("event.items:write", "quotas/2/change", 404, HTTP_GET),
("event.items:write", "quotas/2/delete", 404, HTTP_GET),
("event.items:write", "quotas/add", 200, HTTP_GET),
# ("event.items:write", "discounts/", 200),
# We don't have to create categories and similar objects
# for testing this, it is enough to test that a 404 error
# is returned instead of a 403 one.
(None, "discounts/", 200, HTTP_GET),
("event.items:write", "discounts/2/", 404, HTTP_GET),
("event.items:write", "discounts/2/delete", 404, HTTP_GET),
("event.items:write", "discounts/2/up", 404, HTTP_POST),
("event.items:write", "discounts/2/down", 404, HTTP_POST),
("event.items:write", "discounts/reorder", 400, HTTP_POST),
("event.items:write", "discounts/add", 200, HTTP_GET),
("event.settings.general:write", "subevents/", 200, HTTP_GET),
("event.settings.general:write", "subevents/2/", 404, HTTP_GET),
("event.settings.general:write", "subevents/2/delete", 404, HTTP_GET),
("event.settings.general:write", "subevents/add", 200, HTTP_GET),
(None, "subevents/", 200, HTTP_GET),
("event.subevents:write", "subevents/2/", 404, HTTP_GET),
("event.subevents:write", "subevents/2/", 404, HTTP_POST),
("event.subevents:write", "subevents/2/delete", 404, HTTP_GET),
("event.subevents:write", "subevents/add", 200, HTTP_GET),
("event.subevents:write", "subevents/bulk_add", 200, HTTP_GET),
("event.subevents:write", "subevents/bulk_action", 302, HTTP_POST),
("event.subevents:write", "subevents/bulk_edit", 404, HTTP_POST),
("event.orders:read", "orders/overview/", 200, HTTP_GET),
("event.orders:read", "orders/export/", 200, HTTP_GET),
("event.orders:read", "orders/export/do", 302, HTTP_POST),
@@ -386,7 +387,7 @@ event_permission_urls = [
("event.orders:write", "orders/import/", 200, HTTP_GET),
("event.orders:write", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404, HTTP_GET),
("event.orders:read", "orders/FOO/answer/5/", 404, HTTP_GET),
("event.orders:write", "cancel/", 200, HTTP_GET),
("event:cancel", "cancel/", 200, HTTP_GET),
("event.vouchers:write", "vouchers/add", 200, HTTP_GET),
("event.vouchers:write", "vouchers/bulk_add", 200, HTTP_GET),
("event.vouchers:read", "vouchers/", 200, HTTP_GET),
@@ -422,6 +423,8 @@ def test_wrong_event_permission(perf_patch, client, env, perm, url, code, http_m
t = Team(
pk=2, organizer=env[2], all_events=True
)
if not perm:
pytest.skip()
t.all_event_permissions = False
t.limit_event_permissions.pop(perm, None)
t.save()
@@ -533,17 +536,17 @@ organizer_permission_urls = [
("organizer.settings.general:write", "organizer/dummy/settings/plugins/pretix.plugins.sendmail/events", 200),
("organizer.settings.general:write", "organizer/dummy/settings/email", 200),
("organizer.settings.general:write", "organizer/dummy/settings/email/setup", 200),
("organizer.settings.general:write", "organizer/dummy/devices", 200),
("organizer.settings.general:write", "organizer/dummy/devices/select2", 200),
("organizer.settings.general:write", "organizer/dummy/device/add", 200),
("organizer.settings.general:write", "organizer/dummy/device/1/edit", 404),
("organizer.settings.general:write", "organizer/dummy/device/1/connect", 404),
("organizer.settings.general:write", "organizer/dummy/device/1/revoke", 404),
("organizer.settings.general:write", "organizer/dummy/gates", 200),
("organizer.settings.general:write", "organizer/dummy/gates/select2", 200),
("organizer.settings.general:write", "organizer/dummy/gate/add", 200),
("organizer.settings.general:write", "organizer/dummy/gate/1/edit", 404),
("organizer.settings.general:write", "organizer/dummy/gate/1/delete", 404),
("organizer.devices:read", "organizer/dummy/devices", 200),
("organizer.devices:read", "organizer/dummy/devices/select2", 200),
("organizer.devices:write", "organizer/dummy/device/add", 200),
("organizer.devices:write", "organizer/dummy/device/1/edit", 404),
("organizer.devices:write", "organizer/dummy/device/1/connect", 404),
("organizer.devices:write", "organizer/dummy/device/1/revoke", 404),
("organizer.devices:read", "organizer/dummy/gates", 200),
("organizer.devices:read", "organizer/dummy/gates/select2", 200),
("organizer.devices:write", "organizer/dummy/gate/add", 200),
("organizer.devices:write", "organizer/dummy/gate/1/edit", 404),
("organizer.devices:write", "organizer/dummy/gate/1/delete", 404),
("organizer.settings.general:write", "organizer/dummy/properties", 200),
("organizer.settings.general:write", "organizer/dummy/property/add", 200),
("organizer.settings.general:write", "organizer/dummy/property/1/edit", 404),
@@ -560,12 +563,12 @@ organizer_permission_urls = [
("organizer.settings.general:write", "organizer/dummy/ssoprovider/add", 200),
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/edit", 404),
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/delete", 404),
("organizer.customers:write", "organizer/dummy/customers", 200),
("organizer.customers:read", "organizer/dummy/customers", 200),
("organizer.customers:write", "organizer/dummy/customer/ABC/edit", 404),
("organizer.customers:write", "organizer/dummy/customer/ABC/anonymize", 404),
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/add", 404),
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/1/edit", 404),
("organizer.customers:write", "organizer/dummy/customer/ABC/", 404),
("organizer.customers:read", "organizer/dummy/customer/ABC/", 404),
("organizer.reusablemedia:read", "organizer/dummy/reusable_media", 200),
("organizer.reusablemedia:write", "organizer/dummy/reusable_media/1/edit", 404),
("organizer.reusablemedia:read", "organizer/dummy/reusable_media/1/", 404),