diff --git a/doc/api/resources/customers.rst b/doc/api/resources/customers.rst index 17d5d9279..d9fd2c14f 100644 --- a/doc/api/resources/customers.rst +++ b/doc/api/resources/customers.rst @@ -26,10 +26,16 @@ date_joined datetime Date and time o locale string Preferred language of the customer last_modified datetime Date and time of modification of the record notes string Internal notes and comments (or ``null``) +password string Can only be set during creation of a new customer, will + not be included in any responses. ===================================== ========================== ======================================================= .. versionadded:: 4.0 +.. versionchanged:: 4.3 + + Passwords can now be set through the API during customer creation. + Endpoints --------- @@ -146,6 +152,7 @@ Endpoints { "email": "test@example.org", + "password": "verysecret", "send_email": true } diff --git a/src/pretix/api/serializers/organizer.py b/src/pretix/api/serializers/organizer.py index a4e5c7593..f181b0f06 100644 --- a/src/pretix/api/serializers/organizer.py +++ b/src/pretix/api/serializers/organizer.py @@ -77,10 +77,11 @@ class CustomerSerializer(I18nAwareModelSerializer): class CustomerCreateSerializer(CustomerSerializer): send_email = serializers.BooleanField(default=False, required=False, allow_null=True) + password = serializers.CharField(write_only=True, required=False, allow_null=True) class Meta: model = Customer - fields = CustomerSerializer.Meta.fields + ('send_email',) + fields = CustomerSerializer.Meta.fields + ('send_email', 'password') class MembershipTypeSerializer(I18nAwareModelSerializer): diff --git a/src/pretix/api/views/organizer.py b/src/pretix/api/views/organizer.py index 65b899e94..05b689826 100644 --- a/src/pretix/api/views/organizer.py +++ b/src/pretix/api/views/organizer.py @@ -515,8 +515,8 @@ class CustomerViewSet(viewsets.ModelViewSet): raise MethodNotAllowed("Customers cannot be deleted.") @transaction.atomic() - def perform_create(self, serializer, send_email=False): - customer = serializer.save(organizer=self.request.organizer, password=make_password(None)) + def perform_create(self, serializer, send_email=False, password=None): + customer = serializer.save(organizer=self.request.organizer, password=make_password(password)) serializer.instance.log_action( 'pretix.customer.created', user=self.request.user, @@ -530,7 +530,7 @@ class CustomerViewSet(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): serializer = CustomerCreateSerializer(data=request.data, context=self.get_serializer_context()) serializer.is_valid(raise_exception=True) - self.perform_create(serializer, send_email=serializer.validated_data.pop('send_email', False)) + self.perform_create(serializer, send_email=serializer.validated_data.pop('send_email', False), password=serializer.validated_data.pop('password', None)) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) diff --git a/src/tests/api/test_customers.py b/src/tests/api/test_customers.py index 233b6eebf..54a18cac5 100644 --- a/src/tests/api/test_customers.py +++ b/src/tests/api/test_customers.py @@ -82,6 +82,7 @@ def test_customer_create(token_client, organizer): data={ 'identifier': 'IGNORED', 'email': 'bar@example.com', + 'password': 'foobar', 'name_parts': { "_scheme": "given_family", 'given_name': 'John', @@ -99,6 +100,7 @@ def test_customer_create(token_client, organizer): assert customer.is_active assert customer.name == 'John Doe' assert customer.is_verified + assert customer.check_password('foobar') assert len(djmail.outbox) == 0