Organizer-level plugins (#5305)

* Add version notes to the docs

* Adapt signal handling

* Add UI

* Add API

* API and tests

* Fix registry

* Update doc/development/api/plugins.rst

Co-authored-by: Felix Rindt <felix@rindt.me>

* Fix failing tests

* Apply suggestions from code review

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Update src/pretix/control/templates/pretixcontrol/organizers/plugin_events.html

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

* Update src/pretix/control/templates/pretixcontrol/organizers/plugins.html

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

* Update src/pretix/control/templates/pretixcontrol/organizers/plugins.html

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

* Update src/pretix/control/navigation.py

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

* Update src/pretix/control/urls.py

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

* Apply suggestion from @wiffbi

* REbase migration

* Fix review note

* Fix test cases

* Remove plugin from all events if disabled on org level

* Update doc/development/api/plugins.rst

* Unify registries

* Rebase migration

---------

Co-authored-by: Felix Rindt <felix@rindt.me>
Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: luelista <weller@rami.io>
This commit is contained in:
Raphael Michel
2025-08-19 11:33:34 +02:00
committed by GitHub
parent 56964b6764
commit a51a6123f5
50 changed files with 1623 additions and 192 deletions

View File

@@ -380,3 +380,76 @@ class OrganizerTest(SoupTest):
assert doc.select('.alert-danger')
with scopes_disabled():
assert self.orga1.sales_channels.filter(identifier="web").exists()
def test_plugins(self):
doc = self.get_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug)
self.assertIn("Stripe", doc.select(".form-plugins")[0].text)
self.assertIn("Enable", doc.select("[name=\"plugin:tests.testdummyorga\"]")[0].text)
self.assertIn("Enable", doc.select("[name=\"plugin:tests.testdummyhybrid\"]")[0].text)
assert not doc.select("[name=\"plugin:pretix.plugins.stripe\"]")
assert not doc.select("[name=\"plugin:tests.testdummy\"]")
assert not doc.select("[name=\"plugin:tests.testdummyrestricted\"]")
assert not doc.select("[name=\"plugin:tests.testdummyorgarestricted\"]")
assert not doc.select("[name=\"plugin:tests.testdummyhidden\"]")
doc = self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummyorga': 'enable'})
self.assertIn("Disable", doc.select("[name=\"plugin:tests.testdummyorga\"]")[0].text)
doc = self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummyhybrid': 'enable'})
self.assertIn("Events with plugin testdummyhybrid", doc.select("h1")[0].text)
self.orga1.refresh_from_db()
assert "tests.testdummyhybrid" in self.orga1.get_plugins()
doc = self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummyhybrid': 'disable'})
self.assertIn("Enable", doc.select("[name=\"plugin:tests.testdummyhybrid\"]")[0].text)
self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummy': 'enable'})
self.orga1.refresh_from_db()
assert "tests.testdummy" not in self.orga1.get_plugins()
self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummyorgarestricted': 'enable'})
self.orga1.refresh_from_db()
assert "testdummyorgarestricted" not in self.orga1.get_plugins()
self.orga1.settings.allowed_restricted_plugins = ["tests.testdummyorgarestricted"]
self.post_doc('/control/organizer/%s/settings/plugins' % self.orga1.slug,
{'plugin:tests.testdummyorgarestricted': 'enable'})
self.orga1.refresh_from_db()
assert "tests.testdummyorgarestricted" in self.orga1.get_plugins()
def test_plugin_events(self):
resp = self.client.get('/control/organizer/%s/settings/plugins/tests.testdummyorga/events' % self.orga1.slug)
assert resp.status_code == 404
assert b"only be enabled for the entire organizer account" in resp.content
resp = self.client.get(
'/control/organizer/%s/settings/plugins/tests.testdummyrestricted/events' % self.orga1.slug)
assert resp.status_code == 404
assert b"currently not allowed" in resp.content
resp = self.client.get('/control/organizer/%s/settings/plugins/tests.testdummyhybrid/events' % self.orga1.slug)
assert resp.status_code == 404
assert b"currently not active on the organizer" in resp.content
resp = self.client.get('/control/organizer/%s/settings/plugins/pretix.plugins.stripe/events' % self.orga1.slug)
assert resp.status_code == 200
resp = self.client.post('/control/organizer/%s/settings/plugins/pretix.plugins.stripe/events' % self.orga1.slug,
{'events': self.event1.pk})
assert resp.status_code == 302
self.event1.refresh_from_db()
assert 'pretix.plugins.stripe' in self.event1.get_plugins()
assert 'pretix.plugins.banktransfer' in self.event1.get_plugins()
resp = self.client.post('/control/organizer/%s/settings/plugins/pretix.plugins.banktransfer/events' % self.orga1.slug,
{})
assert resp.status_code == 302
self.event1.refresh_from_db()
assert 'pretix.plugins.banktransfer' not in self.event1.get_plugins()
assert 'pretix.plugins.stripe' in self.event1.get_plugins()