core: delete session when user is set to inactive
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		| @ -4,6 +4,8 @@ from json import loads | ||||
| from typing import Any, Optional | ||||
|  | ||||
| from django.contrib.auth import update_session_auth_hash | ||||
| from django.contrib.sessions.backends.cache import KEY_PREFIX | ||||
| from django.core.cache import cache | ||||
| from django.db.models.functions import ExtractHour | ||||
| from django.db.models.query import QuerySet | ||||
| from django.db.transaction import atomic | ||||
| @ -57,6 +59,7 @@ from authentik.core.models import ( | ||||
|     USER_ATTRIBUTE_SA, | ||||
|     USER_ATTRIBUTE_TOKEN_EXPIRING, | ||||
|     USER_PATH_SERVICE_ACCOUNT, | ||||
|     AuthenticatedSession, | ||||
|     Group, | ||||
|     Token, | ||||
|     TokenIntents, | ||||
| @ -561,3 +564,14 @@ class UserViewSet(UsedByMixin, ModelViewSet): | ||||
|                 ) | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|     def partial_update(self, request: Request, *args, **kwargs) -> Response: | ||||
|         response = super().partial_update(request, *args, **kwargs) | ||||
|         instance: User = self.get_object() | ||||
|         if not instance.is_active: | ||||
|             sessions = AuthenticatedSession.objects.filter(user=instance) | ||||
|             session_ids = sessions.values_list("session_key", flat=True) | ||||
|             cache.delete_many(f"{KEY_PREFIX}{session}" for session in session_ids) | ||||
|             sessions.delete() | ||||
|             LOGGER.debug("Deleted user's sessions", user=instance.username) | ||||
|         return response | ||||
|  | ||||
| @ -1,10 +1,12 @@ | ||||
| """Test Users API""" | ||||
| from json import loads | ||||
|  | ||||
| from django.contrib.sessions.backends.cache import KEY_PREFIX | ||||
| from django.core.cache import cache | ||||
| from django.urls.base import reverse | ||||
| from rest_framework.test import APITestCase | ||||
|  | ||||
| from authentik.core.models import User | ||||
| from authentik.core.models import AuthenticatedSession, User | ||||
| from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_tenant | ||||
| from authentik.flows.models import FlowDesignation | ||||
| from authentik.lib.config import CONFIG | ||||
| @ -257,3 +259,26 @@ class TestUsersAPI(APITestCase): | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         body = loads(response.content.decode()) | ||||
|         self.assertEqual(body["user"]["avatar"], "bar") | ||||
|  | ||||
|     def test_session_delete(self): | ||||
|         """Ensure sessions are deleted when a user is deactivated""" | ||||
|         user = create_test_admin_user() | ||||
|         session_id = generate_id() | ||||
|         AuthenticatedSession.objects.create( | ||||
|             user=user, | ||||
|             session_key=session_id, | ||||
|             last_ip="", | ||||
|         ) | ||||
|         cache.set(KEY_PREFIX + session_id, "foo") | ||||
|  | ||||
|         self.client.force_login(self.admin) | ||||
|         response = self.client.patch( | ||||
|             reverse("authentik_api:user-detail", kwargs={"pk": user.pk}), | ||||
|             data={ | ||||
|                 "is_active": False, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|  | ||||
|         self.assertIsNone(cache.get(KEY_PREFIX + session_id)) | ||||
|         self.assertFalse(AuthenticatedSession.objects.filter(session_key=session_id).exists()) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer