Repository: nautobot/nautobot

Issue:
Logout throws Validation Error when using `next` branch 
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Nautobot version (Docker tag too if applicable): v2.2.0a1
* Python version: 3.8
* Database platform, version: Postgres
* Middleware(s):

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
This is applicable when using the `next` branch with version `v2.2.0a1`.
### Steps to Reproduce
1. Login with a User
2. Logout
3.

<!-- What did you expect to happen? -->
### Expected Behavior
Logout successfully 

<!-- What happened instead? -->
### Observed Behavior
A `ValidationError` is thrown at `/logout/` with message `['“4ci8je1rmskkfei3g8avd9mt2da2bft5” is not a valid UUID.']` when I use the `next` branch.
Logout throws Validation Error when using `next` branch 
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Nautobot version (Docker tag too if applicable): v2.2.0a1
* Python version: 3.8
* Database platform, version: Postgres
* Middleware(s):

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
This is applicable when using the `next` branch with version `v2.2.0a1`.
### Steps to Reproduce
1. Login with a User
2. Logout
3.

<!-- What did you expect to happen? -->
### Expected Behavior
Logout successfully 

<!-- What happened instead? -->
### Observed Behavior
A `ValidationError` is thrown at `/logout/` with message `['“4ci8je1rmskkfei3g8avd9mt2da2bft5” is not a valid UUID.']` when I use the `next` branch.


Discussion:
Thanks for filing the issue! We actually just noticed this bug yesterday on the core team. :-) 

The issue is in the `_handle_deleted_object` signal, which is being triggered when the user logs out and their `session` DB record gets deleted. This signal is missing logic to handle the case where the deleted object has a PK that isn't of type UUID. A first pass fix is something like:

```diff
diff --git a/nautobot/extras/signals.py b/nautobot/extras/signals.py
index 86ad2aca8..17a31217c 100644
--- a/nautobot/extras/signals.py
+++ b/nautobot/extras/signals.py
@@ -20,6 +20,7 @@ from django_prometheus.models import model_deletes, model_inserts, model_updates
 
 from nautobot.core.celery import app, import_jobs_as_celery_tasks
 from nautobot.core.utils.config import get_settings_or_config
+from nautobot.core.utils.data import is_uuid
 from nautobot.extras.choices import JobResultStatusChoices, ObjectChangeActionChoices
 from nautobot.extras.constants import CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
 from nautobot.extras.models import (
@@ -165,6 +166,10 @@ def _handle_deleted_object(sender, instance, **kwargs):
     if change_context_state.get() is None:
         return
 
+    if not is_uuid(instance.pk):
+        # Probably some system object
+        return
+
     associations = ContactAssociation.objects.filter(
         associated_object_type=ContentType.objects.get_for_model(type(instance)), associated_object_id=instance.pk
     )
```

but we're having some discussions about whether there may be a more elegant way to fix it.
Thanks for filing the issue! We actually just noticed this bug yesterday on the core team. :-) 

The issue is in the `_handle_deleted_object` signal, which is being triggered when the user logs out and their `session` DB record gets deleted. This signal is missing logic to handle the case where the deleted object has a PK that isn't of type UUID. A first pass fix is something like:

```diff
diff --git a/nautobot/extras/signals.py b/nautobot/extras/signals.py
index 86ad2aca8..17a31217c 100644
--- a/nautobot/extras/signals.py
+++ b/nautobot/extras/signals.py
@@ -20,6 +20,7 @@ from django_prometheus.models import model_deletes, model_inserts, model_updates
 
 from nautobot.core.celery import app, import_jobs_as_celery_tasks
 from nautobot.core.utils.config import get_settings_or_config
+from nautobot.core.utils.data import is_uuid
 from nautobot.extras.choices import JobResultStatusChoices, ObjectChangeActionChoices
 from nautobot.extras.constants import CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
 from nautobot.extras.models import (
@@ -165,6 +166,10 @@ def _handle_deleted_object(sender, instance, **kwargs):
     if change_context_state.get() is None:
         return
 
+    if not is_uuid(instance.pk):
+        # Probably some system object
+        return
+
     associations = ContactAssociation.objects.filter(
         associated_object_type=ContentType.objects.get_for_model(type(instance)), associated_object_id=instance.pk
     )
```

but we're having some discussions about whether there may be a more elegant way to fix it.

Resolving patch:
diff --git a/nautobot/extras/signals.py b/nautobot/extras/signals.py
--- a/nautobot/extras/signals.py
+++ b/nautobot/extras/signals.py
@@ -20,6 +20,7 @@
 from django_prometheus.models import model_deletes, model_inserts, model_updates
 
 from nautobot.core.celery import app, import_jobs_as_celery_tasks
+from nautobot.core.models import BaseModel
 from nautobot.core.utils.config import get_settings_or_config
 from nautobot.core.utils.logging import sanitize
 from nautobot.extras.choices import JobResultStatusChoices, ObjectChangeActionChoices
@@ -167,10 +168,12 @@ def _handle_deleted_object(sender, instance, **kwargs):
     if change_context_state.get() is None:
         return
 
-    associations = ContactAssociation.objects.filter(
-        associated_object_type=ContentType.objects.get_for_model(type(instance)), associated_object_id=instance.pk
-    )
-    associations.delete()
+    if isinstance(instance, BaseModel):
+        associations = ContactAssociation.objects.filter(
+            associated_object_type=ContentType.objects.get_for_model(type(instance)), associated_object_id=instance.pk
+        )
+        associations.delete()
+
     if hasattr(instance, "notes") and isinstance(instance.notes, NotesQuerySet):
         notes = instance.notes
         notes.delete()


Test patch: