mirror of
https://github.com/pretix/pretix.git
synced 2026-09-19 17:14:41 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09b10127b4 | ||
|
|
08f66fae3a | ||
|
|
cde6c301b2 | ||
|
|
ff3da7c8f6 | ||
|
|
403efcf38c | ||
|
|
71153ccdf4 | ||
|
|
4f343aac1f | ||
|
|
b4b5dd2ff3 | ||
|
|
4f0d5f0a64 |
@@ -0,0 +1,241 @@
|
||||
Event Meta Properties
|
||||
=====================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
An event meta property is used to to define meta information fields for its events.
|
||||
This information can be re-used, for example, in ticket layouts.
|
||||
|
||||
The event meta property resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Unique ID for this property
|
||||
name string Name of the property
|
||||
default string Value of the default option
|
||||
required boolean If ``true``, an event can only be taken live if the
|
||||
property is set. In event series, it's always optional
|
||||
to set a value for individual dates
|
||||
protected boolean If ``true``, the value for an event can only be changed
|
||||
by organizer-level administrators
|
||||
filter_public boolean If ``true``, this property will be shown to filter
|
||||
events in the public event list and calendar
|
||||
public_label string Public name of the property
|
||||
filter_allowed boolean If ``true``, this property will be shown to filter
|
||||
events or reports in the backend, and it can also be
|
||||
used for hidden filter parameters in the frontend
|
||||
choices list of objects List of JSON objects representing all permitted values
|
||||
for this property, or ``null`` for no limitation.
|
||||
Each choice object has a required internal name named
|
||||
``key`` and optional public name named ``label``
|
||||
consisting of a dictionary of i18n string translations
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/event_meta_properties/
|
||||
|
||||
Returns a list of all meta properties for the organizer.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/meta_properties/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Color",
|
||||
"default": "blue",
|
||||
"required": false,
|
||||
"protected": false,
|
||||
"filter_public": false,
|
||||
"public_label": {},
|
||||
"filter_allowed": true,
|
||||
"choices": [
|
||||
{
|
||||
"key": "blue",
|
||||
"label": {
|
||||
"en": "Blue"
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/event_meta_properties/(id)/
|
||||
|
||||
Returns information on one property, identified by its id.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/event_meta_properties/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Color",
|
||||
"default": "blue",
|
||||
"required": false,
|
||||
"protected": false,
|
||||
"filter_public": false,
|
||||
"public_label": {},
|
||||
"filter_allowed": true,
|
||||
"choices": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer
|
||||
:param id: The ``id`` field of the meta property to retrieve
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/event_meta_properties/
|
||||
|
||||
Creates a new meta property
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/event_meta_properties/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "ref-code",
|
||||
"default": "abcde",
|
||||
"required": true,
|
||||
"choices": null
|
||||
}
|
||||
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "reference",
|
||||
"default": "abcde",
|
||||
"required": true,
|
||||
"protected": false,
|
||||
"filter_public": false,
|
||||
"public_label": null,
|
||||
"filter_allowed": true,
|
||||
"choices": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The meta property could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/event_meta_properties/(id)/
|
||||
|
||||
Update a meta property. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide
|
||||
all fields of the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the
|
||||
fields that you want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/event_meta_properties/2/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"required": false
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 3,
|
||||
"name": "reference",
|
||||
"default": "abcde",
|
||||
"required": false,
|
||||
"protected": false,
|
||||
"filter_public": false,
|
||||
"public_label": null,
|
||||
"filter_allowed": true,
|
||||
"choices": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer
|
||||
:param id: The ``id`` field of the meta property to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The property could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/event_meta_properties/(id)/
|
||||
|
||||
Delete a meta property.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/event_meta_properties/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer
|
||||
:param id: The ``id`` field of the meta property to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource.
|
||||
@@ -12,6 +12,7 @@ at :ref:`plugin-docs`.
|
||||
organizers
|
||||
events
|
||||
subevents
|
||||
event_meta_properties
|
||||
taxrules
|
||||
categories
|
||||
items
|
||||
|
||||
@@ -40,9 +40,10 @@ from pretix.api.serializers.settings import SettingsSerializer
|
||||
from pretix.base.auth import get_auth_backends
|
||||
from pretix.base.i18n import get_language_without_region
|
||||
from pretix.base.models import (
|
||||
Customer, Device, GiftCard, GiftCardAcceptance, GiftCardTransaction,
|
||||
Membership, MembershipType, OrderPosition, Organizer, ReusableMedium,
|
||||
SalesChannel, SeatingPlan, Team, TeamAPIToken, TeamInvite, User,
|
||||
Customer, Device, EventMetaProperty, GiftCard, GiftCardAcceptance,
|
||||
GiftCardTransaction, Membership, MembershipType, OrderPosition, Organizer,
|
||||
ReusableMedium, SalesChannel, SeatingPlan, Team, TeamAPIToken, TeamInvite,
|
||||
User,
|
||||
)
|
||||
from pretix.base.models.seating import SeatingPlanLayoutValidator
|
||||
from pretix.base.permissions import (
|
||||
@@ -640,3 +641,62 @@ class OrganizerSettingsSerializer(SettingsSerializer):
|
||||
)
|
||||
# TODO: make sure pub is always correct
|
||||
return 'pub/' + fname
|
||||
|
||||
|
||||
class KeyLabelObjectListField(serializers.Field):
|
||||
|
||||
def to_representation(self, value):
|
||||
# django added unneccessary keys DELETE, ORDER through formsets, filter them here for backwards compat
|
||||
def strip_unknown_keys(v):
|
||||
return {k: v[k] for k in v.keys() if k in ("key", "label")}
|
||||
return [strip_unknown_keys(v) for v in value]
|
||||
|
||||
def to_internal_value(self, data):
|
||||
if data is None:
|
||||
return data
|
||||
if not isinstance(data, list):
|
||||
raise ValidationError("Choices need to be a list or null.")
|
||||
if not data:
|
||||
# empty list
|
||||
return None
|
||||
|
||||
if any([not isinstance(choice, dict) for choice in data]):
|
||||
raise ValidationError("Choices need to contain only objects.")
|
||||
|
||||
required_keys = {"key"}
|
||||
allowed_keys = {"key", "label"}
|
||||
if not all([required_keys <= set(choice.keys()) <= allowed_keys for choice in data]):
|
||||
raise ValidationError("Each choice must contain a key and optionally a label.")
|
||||
|
||||
choice_keys = [choice.get("key") for choice in data]
|
||||
if len(set(choice_keys)) < len(choice_keys):
|
||||
raise ValidationError("Each choice must have a unique key.")
|
||||
return data
|
||||
|
||||
|
||||
class EventMetaPropertiesSerializer(I18nAwareModelSerializer):
|
||||
choices = KeyLabelObjectListField(allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = EventMetaProperty
|
||||
fields = (
|
||||
'id', 'name', 'default', 'required', 'protected', 'filter_public', 'public_label', 'filter_allowed',
|
||||
'choices'
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
full_data = self.to_internal_value(self.to_representation(self.instance)) if self.instance else {}
|
||||
full_data.update(data)
|
||||
|
||||
choices = full_data.get("choices")
|
||||
default = full_data.get("default")
|
||||
if choices and default:
|
||||
choice_keys = [c.get("key") for c in choices]
|
||||
if default not in choice_keys:
|
||||
raise ValidationError("You cannot set a default value that is not a valid value.")
|
||||
|
||||
if not choices and "choices" in data:
|
||||
# normalize empty dict to None
|
||||
data["choices"] = None
|
||||
return data
|
||||
|
||||
@@ -68,6 +68,7 @@ orga_router.register(r'scheduled_exports', exporters.ScheduledOrganizerExportVie
|
||||
orga_router.register(r'exporters', exporters.OrganizerExportersViewSet, basename='exporters')
|
||||
orga_router.register(r'transactions', order.OrganizerTransactionViewSet)
|
||||
orga_router.register(r'orderpositions', order.OrganizerOrderPositionViewSet, basename='orderpositions')
|
||||
orga_router.register(r'event_meta_properties', organizer.EventMetaPropertiesViewSet)
|
||||
|
||||
team_router = routers.DefaultRouter()
|
||||
team_router.register(r'members', organizer.TeamMemberViewSet)
|
||||
|
||||
@@ -44,15 +44,16 @@ from pretix.api.models import OAuthAccessToken
|
||||
from pretix.api.pagination import TotalOrderingFilter
|
||||
from pretix.api.serializers.organizer import (
|
||||
CustomerCreateSerializer, CustomerSerializer, DeviceSerializer,
|
||||
GiftCardSerializer, GiftCardTransactionSerializer, MembershipSerializer,
|
||||
EventMetaPropertiesSerializer, GiftCardSerializer,
|
||||
GiftCardTransactionSerializer, MembershipSerializer,
|
||||
MembershipTypeSerializer, OrganizerSerializer, OrganizerSettingsSerializer,
|
||||
SalesChannelSerializer, SeatingPlanSerializer, TeamAPITokenSerializer,
|
||||
TeamInviteSerializer, TeamMemberSerializer, TeamSerializer,
|
||||
)
|
||||
from pretix.base.models import (
|
||||
Customer, Device, Event, GiftCard, GiftCardTransaction, LogEntry,
|
||||
Membership, MembershipType, Organizer, SalesChannel, SeatingPlan, Team,
|
||||
TeamAPIToken, TeamInvite, User,
|
||||
Customer, Device, Event, EventMetaProperty, GiftCard, GiftCardTransaction,
|
||||
LogEntry, Membership, MembershipType, Organizer, SalesChannel, SeatingPlan,
|
||||
Team, TeamAPIToken, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.plugins import (
|
||||
PLUGIN_LEVEL_EVENT, PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID,
|
||||
@@ -846,3 +847,49 @@ class SalesChannelViewSet(viewsets.ModelViewSet):
|
||||
data={'id': instance.pk}
|
||||
)
|
||||
instance.delete()
|
||||
|
||||
|
||||
class EventMetaPropertiesViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = EventMetaPropertiesSerializer
|
||||
queryset = EventMetaProperty.objects.none()
|
||||
write_permission = 'organizer.settings.general:write'
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.organizer.meta_properties.all()
|
||||
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['organizer'] = self.request.organizer
|
||||
return ctx
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_destroy(self, instance):
|
||||
instance.log_action(
|
||||
'pretix.property.deleted',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'id': instance.pk}
|
||||
)
|
||||
instance.delete()
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_create(self, serializer):
|
||||
inst = serializer.save(organizer_id=self.request.organizer.pk)
|
||||
serializer.instance.log_action(
|
||||
'pretix.property.created',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=self.request.data,
|
||||
)
|
||||
return inst
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_update(self, serializer):
|
||||
inst = serializer.save(organizer_id=self.request.organizer.pk)
|
||||
serializer.instance.log_action(
|
||||
'pretix.property.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=self.request.data,
|
||||
)
|
||||
return inst
|
||||
|
||||
@@ -717,6 +717,10 @@ class CoreUserImpersonatedLogEntryType(UserImpersonatedLogEntryType):
|
||||
'pretix.organizer.export.schedule.failed': _('A scheduled export has failed: {reason}.'),
|
||||
'pretix.organizer.outgoingmails.retried': _('Failed emails have been scheduled to be retried.'),
|
||||
'pretix.organizer.outgoingmails.aborted': _('Queued emails have been aborted.'),
|
||||
'pretix.property.created': _('An organizer meta property has been created.'),
|
||||
'pretix.property.deleted': _('An organizer meta property has been deleted.'),
|
||||
'pretix.property.changed': _('An organizer meta property has been changed.'),
|
||||
'pretix.property.reordered': _('An organizer meta property has been reordered.'),
|
||||
'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'),
|
||||
'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'),
|
||||
'pretix.giftcards.acceptance.acceptor.invited': _('A new gift card acceptor has been invited.'),
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import pytest
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def event_meta_property(organizer):
|
||||
return organizer.meta_properties.create(
|
||||
name="Color",
|
||||
default="Red",
|
||||
required=False,
|
||||
choices=[
|
||||
{
|
||||
"key": "Red",
|
||||
"label": "Rot",
|
||||
"DELETE": False,
|
||||
"ORDER": 1,
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
TEST_TYPE_RES = {
|
||||
"name": "Color",
|
||||
"default": "Red",
|
||||
"required": False,
|
||||
"choices": [{"key": "Red", "label": "Rot"}],
|
||||
'filter_allowed': True,
|
||||
'filter_public': False,
|
||||
'protected': False,
|
||||
'public_label': None,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_meta_property_list(token_client, organizer, event_meta_property):
|
||||
res = dict(TEST_TYPE_RES)
|
||||
|
||||
resp = token_client.get('/api/v1/organizers/{}/event_meta_properties/'
|
||||
.format(organizer.slug))
|
||||
assert resp.status_code == 200
|
||||
event_meta_property.refresh_from_db()
|
||||
res["id"] = event_meta_property.pk
|
||||
assert res in resp.data['results']
|
||||
assert len(resp.data['results']) == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_meta_property_detail(token_client, organizer, event_meta_property):
|
||||
res = TEST_TYPE_RES
|
||||
resp = token_client.get('/api/v1/organizers/{}/event_meta_properties/{}/'
|
||||
.format(organizer.slug, event_meta_property.pk))
|
||||
assert resp.status_code == 200
|
||||
event_meta_property.refresh_from_db()
|
||||
res["id"] = event_meta_property.pk
|
||||
assert res == resp.data
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_meta_property_create(token_client, organizer):
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
|
||||
format='json',
|
||||
data={
|
||||
"name": "Color",
|
||||
"default": "Red",
|
||||
"required": False,
|
||||
"choices": ["Red", "Green", "Blue"]
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
|
||||
format='json',
|
||||
data={
|
||||
"name": "Color",
|
||||
"default": "Red",
|
||||
"required": False,
|
||||
"choices": {"key": "r", "label": "Red"},
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
choices = [
|
||||
{"key": "r", "label": "Red"},
|
||||
{"key": "g", "label": "Green"},
|
||||
{"key": "b", "label": "Blue"},
|
||||
]
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
|
||||
format='json',
|
||||
data={
|
||||
"name": "Color",
|
||||
"default": "k",
|
||||
"required": False,
|
||||
"choices": choices,
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/event_meta_properties/'.format(organizer.slug),
|
||||
format='json',
|
||||
data={
|
||||
"name": "Color",
|
||||
"default": "r",
|
||||
"required": False,
|
||||
"choices": choices,
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
with scopes_disabled():
|
||||
event_meta_property = organizer.meta_properties.get(id=resp.data['id'])
|
||||
assert event_meta_property.name == "Color"
|
||||
assert event_meta_property.default == "r"
|
||||
assert event_meta_property.choices == choices
|
||||
assert not event_meta_property.required
|
||||
assert len(organizer.meta_properties.all()) == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_meta_property_patch(token_client, organizer, event_meta_property):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/event_meta_properties/{}/'
|
||||
.format(organizer.slug, event_meta_property.pk),
|
||||
format='json',
|
||||
data={
|
||||
# existing default is not in choices
|
||||
"choices": [{'k': 'Black'}],
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/event_meta_properties/{}/'
|
||||
.format(organizer.slug, event_meta_property.pk),
|
||||
format='json',
|
||||
data={
|
||||
"choices": [],
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
event_meta_property.refresh_from_db()
|
||||
assert event_meta_property.choices is None
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/event_meta_properties/{}/'
|
||||
.format(organizer.slug, event_meta_property.pk),
|
||||
format='json',
|
||||
data={
|
||||
"required": True,
|
||||
"choices": None,
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
event_meta_property.refresh_from_db()
|
||||
assert event_meta_property.required
|
||||
assert event_meta_property.choices is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_meta_property_delete(token_client, organizer, event_meta_property):
|
||||
resp = token_client.delete(
|
||||
'/api/v1/organizers/{}/event_meta_properties/{}/'
|
||||
.format(organizer.slug, event_meta_property.pk),
|
||||
)
|
||||
assert resp.status_code == 204
|
||||
assert len(organizer.meta_properties.all()) == 0
|
||||
@@ -223,6 +223,8 @@ org_permission_sub_urls = [
|
||||
('post', 'organizer.customers:write', 'customers/1/anonymize/', 404),
|
||||
('put', 'organizer.customers:write', 'customers/1/', 404),
|
||||
('delete', 'organizer.customers:write', 'customers/1/', 404),
|
||||
('post', 'organizer.settings.general:write', 'event_meta_properties/', 400),
|
||||
('patch', 'organizer.settings.general:write', 'event_meta_properties/1/', 200),
|
||||
('get', 'organizer.customers:read', 'memberships/', 200),
|
||||
('post', 'organizer.customers:write', 'memberships/', 400),
|
||||
('get', 'organizer.customers:read', 'memberships/1/', 404),
|
||||
|
||||
Reference in New Issue
Block a user