# Which issue(s) this PR fixes
Solves the (rare) issue where a user could potentially have > 1
mobileapp auth token, leading to 500 errors when trying to interact w/
the authtoken (ex. disconnect a mobile app from a user's profile):
```shell
2023-03-07 10:12:13 source=engine:app google_trace_id=e14bf933d634068a48caf093ce43c7f5/5550677047491218352 logger=django.request Internal Server Error: /api/internal/v1/users/U6WJ3BRLM1TR7/unlink_backend
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/etc/app/apps/api/views/user.py", line 453, in unlink_backend
backend.unlink_user(user)
File "/etc/app/apps/mobile_app/backend.py", line 34, in unlink_user
token = MobileAppAuthToken.objects.get(user=user)
File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 439, in get
raise self.model.MultipleObjectsReturned(
apps.mobile_app.models.MobileAppAuthToken.MultipleObjectsReturned: get() returned more than one MobileAppAuthToken -- it returned 2!
```
## Checklist
- [x] Tests updated
- [ ] Documentation added (N/A)
- [x] `CHANGELOG.md` updated
29 lines
1 KiB
Python
29 lines
1 KiB
Python
from django.db import migrations, models
|
|
import django.db.models.deletion
|
|
|
|
|
|
def delete_user_duplicate_mobileappauthtokens(apps, _):
|
|
MobileAppAuthToken = apps.get_model('mobile_app', 'MobileAppAuthToken')
|
|
|
|
# start w/ the oldest mobile app auth tokens (ORDER BY id ASC)
|
|
# and if we find any newer tokens, delete the earlier ones (ie. `row` variable)
|
|
for row in MobileAppAuthToken.objects.all().order_by('id'):
|
|
if MobileAppAuthToken.objects.filter(user_id=row.user_id).count() > 1:
|
|
row.delete()
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('user_management', '0008_organization_is_grafana_incident_enabled'),
|
|
('mobile_app', '0001_initial'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.RunPython(delete_user_duplicate_mobileappauthtokens, migrations.RunPython.noop),
|
|
migrations.AlterField(
|
|
model_name='mobileappauthtoken',
|
|
name='user',
|
|
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='user_management.user'),
|
|
),
|
|
]
|