Repository: pretix/pretix

Issue:
Internal Server Error When Trying to Change Add-On Products Without Login
When trying to change addon products without an active login session (click link from mail, try to change products) the following error occurs and the internal server error page is being displayed.

It works when the user is logged in.

version 4.8.0

```
ERROR 2022-05-16 10:03:08,504 django.request log Internal Server Error: /foo/bar/change
Traceback (most recent call last):
  File "/home/pretix/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/decorators/clickjacking.py", line 50, in wrapped_view
    resp = view_func(*args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1189, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/robots.py", line 41, in dispatch
    resp = super().dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 159, in get
    context = self.get_context_data(**kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1210, in get_context_data
    ctx['positions'] = self.positions
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1258, in positions
    self.request.customer.usable_memberships(
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/functional.py", line 247, in inner
    return func(self._wrapped, *args)
AttributeError: 'NoneType' object has no attribute 'usable_memberships'
```

settings for that use-case:

![image](https://user-images.githubusercontent.com/5830192/168570559-caa06021-d1ef-4342-8ee9-cd0a2c6e1868.png)

Internal Server Error When Trying to Change Add-On Products Without Login
When trying to change addon products without an active login session (click link from mail, try to change products) the following error occurs and the internal server error page is being displayed.

It works when the user is logged in.

version 4.8.0

```
ERROR 2022-05-16 10:03:08,504 django.request log Internal Server Error: /foo/bar/change
Traceback (most recent call last):
  File "/home/pretix/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/decorators/clickjacking.py", line 50, in wrapped_view
    resp = view_func(*args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1189, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/robots.py", line 41, in dispatch
    resp = super().dispatch(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 159, in get
    context = self.get_context_data(**kwargs)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1210, in get_context_data
    ctx['positions'] = self.positions
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/pretix/venv/lib/python3.8/site-packages/pretix/presale/views/order.py", line 1258, in positions
    self.request.customer.usable_memberships(
  File "/home/pretix/venv/lib/python3.8/site-packages/django/utils/functional.py", line 247, in inner
    return func(self._wrapped, *args)
AttributeError: 'NoneType' object has no attribute 'usable_memberships'
```

settings for that use-case:

![image](https://user-images.githubusercontent.com/5830192/168570559-caa06021-d1ef-4342-8ee9-cd0a2c6e1868.png)



Discussion:
Happens for me without add-on products in my order, and for some users, even if they already have add-on products in their orders. So "no add-on products" is not the cause here.
Happens for me without add-on products in my order, and for some users, even if they already have add-on products in their orders. So "no add-on products" is not the cause here.

Resolving patch:
diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py
--- a/src/pretix/presale/views/order.py
+++ b/src/pretix/presale/views/order.py
@@ -1255,7 +1255,7 @@ def positions(self):
                             allow_addons=True,
                             quota_cache=quota_cache,
                             memberships=(
-                                self.request.customer.usable_memberships(
+                                self.order.customer.usable_memberships(
                                     for_event=p.subevent or self.request.event,
                                     testmode=self.order.testmode
                                 )


Test patch: