Compare commits

...
9 changed files with 67 additions and 13 deletions
+11 -1
View File
@@ -553,13 +553,23 @@ class TeamInviteSerializer(serializers.ModelSerializer):
class TeamAPITokenSerializer(serializers.ModelSerializer):
active = serializers.BooleanField(default=True, read_only=True)
sales_channel = serializers.SlugRelatedField(
slug_field="identifier",
queryset=SalesChannel.objects.none(),
required=False,
allow_empty=True,
)
class Meta:
model = TeamAPIToken
fields = (
'id', 'name', 'active'
'id', 'name', 'active', 'sales_channel'
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['sales_channel'].queryset = self.context['organizer'].organizer.sales_channels.all() if 'organizer' in self.context else SalesChannel.objects.none()
class TeamMemberSerializer(serializers.ModelSerializer):
class Meta:
+16 -1
View File
@@ -28,6 +28,7 @@ from django.contrib.auth.hashers import make_password
from django.db import transaction
from django.db.models import OuterRef, Q, Subquery, Sum
from django.db.models.functions import Coalesce
from django.http.response import Http404
from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django.utils.timezone import now
@@ -467,7 +468,7 @@ class TeamInviteViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnlyMo
serializer.save(team=self.team)
class TeamAPITokenViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnlyModelViewSet):
class TeamAPITokenViewSet(viewsets.ModelViewSet):
serializer_class = TeamAPITokenSerializer
queryset = TeamAPIToken.objects.none()
permission = 'organizer.teams:write'
@@ -506,6 +507,20 @@ class TeamAPITokenViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnly
self.team.log_action(
'pretix.team.token.created', auth=self.request.auth, user=self.request.user, data={
'name': instance.name,
'sales_channel': instance.sales_channel,
'id': instance.pk
}
)
@transaction.atomic()
def perform_update(self, serializer):
if not self.team.active:
raise Http404()
instance = serializer.save(team=self.team)
self.team.log_action(
'pretix.team.token.changed', auth=self.request.auth, user=self.request.user, data={
'name': instance.name,
'sales_channel': instance.sales_channel,
'id': instance.pk
}
)
+1
View File
@@ -178,6 +178,7 @@ class Device(LoggedModel):
info = models.JSONField(
null=True, blank=True,
)
sales_channel = models.ForeignKey("SalesChannel", on_delete=models.SET_NULL, null=True, blank=True)
objects = ScopedManager(organizer='organizer')
+3
View File
@@ -535,11 +535,14 @@ class TeamAPIToken(models.Model):
:type active: bool
:param token: The secret required to submit to the API
:type token: str
:param sales_channel: Default value for sales channel on API calls with this token
:type sales_channel: SalesChannel
"""
team = models.ForeignKey(Team, related_name="tokens", on_delete=models.CASCADE)
name = models.CharField(max_length=190)
active = models.BooleanField(default=True)
token = models.CharField(default=generate_api_token, max_length=64)
sales_channel = models.ForeignKey("SalesChannel", on_delete=models.CASCADE, null=True, blank=True)
def get_event_permission_set(self, organizer, event) -> set:
"""
+4 -2
View File
@@ -489,6 +489,7 @@ class DeviceForm(forms.ModelForm):
help_text=self.fields['security_profile'].help_text,
choices=[(k, v.verbose_name) for k, v in get_all_security_profiles().items()],
)
self.fields["sales_channel"].queryset = organizer.sales_channels.all()
def clean(self):
d = super().clean()
@@ -499,7 +500,7 @@ class DeviceForm(forms.ModelForm):
class Meta:
model = Device
fields = ['name', 'all_events', 'limit_events', 'security_profile', 'gate']
fields = ['name', 'all_events', 'limit_events', 'security_profile', 'gate', 'sales_channel']
widgets = {
'limit_events': forms.CheckboxSelectMultiple(attrs={
'data-inverse-dependency': '#id_all_events',
@@ -507,7 +508,8 @@ class DeviceForm(forms.ModelForm):
}),
}
field_classes = {
'limit_events': SafeEventMultipleChoiceField
'limit_events': SafeEventMultipleChoiceField,
"sales_channel": SafeModelChoiceField,
}
@@ -24,6 +24,7 @@
<legend>{% trans "Advanced settings" %}</legend>
{% bootstrap_field form.security_profile layout="control" %}
{% bootstrap_field form.gate layout="control" %}
{% bootstrap_field form.sales_channel layout="control" %}
</fieldset>
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
@@ -98,6 +98,7 @@
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Sales channel" %}</th>
<th width="150"></th>
</tr>
</thead>
@@ -113,6 +114,13 @@
</del>
{% endif %}
</td>
<td class="text-muted">
{% if t.sales_channel %}
{{ t.sales_channel }}
{% else %}
-
{% endif %}
</td>
<td class="text-right flip">
{% if t.active %}
<button type="submit" name="remove-token" value="{{ t.id }}"
@@ -129,6 +137,9 @@
<td>
{% bootstrap_field add_token_form.name layout='inline' %}<br>
</td>
<td>
{% bootstrap_field add_token_form.sales_channel layout='inline' %}<br>
</td>
<td class="text-right flip">
<button type="submit" class="btn btn-primary btn-sm btn-block">
<i class="fa fa-plus"></i> {% trans "Add" %}
@@ -7,10 +7,10 @@
<p>
{% trans "The list below shows all teams that exist within this organizer." %}
</p>
<div class="panel panel-default">
<div class="panel-heading">
<details class="panel panel-default" open data-stateful="organizers_teams_filter">
<summary class="panel-heading">
<h3 class="panel-title">{% trans "Filter" %}</h3>
</div>
</summary>
<form class="panel-body filter-form" action="" method="get">
<div class="row">
<div class="col-xs-12">
@@ -24,7 +24,7 @@
</button>
</div>
</form>
</div>
</details>
<a href="{% url "control:organizer.team.add" organizer=request.organizer.slug %}" class="btn btn-default">
<span class="fa fa-plus"></span>
{% trans "Create a new team" %}
@@ -65,11 +65,11 @@
</td>
<td class="text-right flip">
<a href="{% url "control:organizer.team" organizer=request.organizer.slug team=t.id %}"
class="btn btn-default btn-sm"><i class="fa fa-list"></i></a>
class="btn btn-default btn-sm" title="{% trans "Team members" %}"><i class="fa fa-list"></i></a>
<a href="{% url "control:organizer.team.edit" organizer=request.organizer.slug team=t.id %}"
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
class="btn btn-default btn-sm" title="{% trans "Edit" %}"><i class="fa fa-edit"></i></a>
<a href="{% url "control:organizer.team.delete" organizer=request.organizer.slug team=t.id %}"
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
class="btn btn-danger btn-sm" title="{% trans "Delete" %}"><i class="fa fa-trash"></i></a>
</td>
</tr>
{% endfor %}
+13 -2
View File
@@ -40,6 +40,8 @@ from collections import Counter
from datetime import time, timedelta
from decimal import Decimal
from hashlib import sha1
from django_scopes.forms import SafeModelChoiceField
from itertools import groupby
from json import JSONDecodeError
@@ -180,6 +182,11 @@ class InviteForm(forms.Form):
class TokenForm(forms.Form):
name = forms.CharField(required=False, label=_('Token name'))
sales_channel = SafeModelChoiceField(required=False, label=_('Sales channel'), queryset=SalesChannel.objects.none())
def __init__(self, organizer, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["sales_channel"].queryset = organizer.sales_channels.all()
class OrganizerDetailViewMixin:
@@ -1019,7 +1026,7 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
@cached_property
def add_token_form(self):
return TokenForm(data=(self.request.POST
if self.request.method == "POST" and "name" in self.request.POST else None))
if self.request.method == "POST" and "name" in self.request.POST else None), organizer=self.request.organizer)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
@@ -1164,10 +1171,14 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
return redirect(self.get_success_url())
elif "name" in self.request.POST and self.add_token_form.is_valid() and self.add_token_form.has_changed():
token = self.object.tokens.create(name=self.add_token_form.cleaned_data['name'])
token = self.object.tokens.create(
name=self.add_token_form.cleaned_data['name'],
sales_channel=self.add_token_form.cleaned_data['sales_channel']
)
self.object.log_action(
'pretix.team.token.created', user=self.request.user, data={
'name': self.add_token_form.cleaned_data['name'],
'sales_channel': self.add_token_form.cleaned_data['sales_channel'],
'id': token.pk
}
)