diff --git a/open_api_framework/admin.py b/open_api_framework/admin.py index af5c958..5bca0ad 100644 --- a/open_api_framework/admin.py +++ b/open_api_framework/admin.py @@ -1,10 +1,9 @@ -from importlib import import_module - -from django.conf import settings from django.contrib import admin from sessionprofile.models import SessionProfile +from open_api_framework.utils import get_session_store + @admin.register(SessionProfile) class SessionProfileAdmin(admin.ModelAdmin): @@ -13,7 +12,7 @@ class SessionProfileAdmin(admin.ModelAdmin): @property def SessionStore(self): - return import_module(settings.SESSION_ENGINE).SessionStore + return get_session_store() def get_queryset(self, request): qs = super().get_queryset(request) @@ -35,8 +34,7 @@ def delete_model(self, request, obj): def delete_queryset(self, request, queryset): - session_keys = list(queryset.values_list("session_key", flat=True)) - for session_key in session_keys: - self.SessionStore(session_key).flush() + for session_profile in queryset.iterator(): + self.SessionStore(session_profile.session_key).flush() super().delete_queryset(request, queryset) diff --git a/open_api_framework/conf/base.py b/open_api_framework/conf/base.py index c1ed56b..e39a95a 100644 --- a/open_api_framework/conf/base.py +++ b/open_api_framework/conf/base.py @@ -231,12 +231,14 @@ "mozilla_django_oidc_db", "log_outgoing_requests", "django_setup_configuration", + "sessionprofile", "open_api_framework", PROJECT_DIRNAME, ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "sessionprofile.middleware.SessionProfileMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", diff --git a/open_api_framework/utils.py b/open_api_framework/utils.py new file mode 100644 index 0000000..8d95d62 --- /dev/null +++ b/open_api_framework/utils.py @@ -0,0 +1,8 @@ +from importlib import import_module + +from django.conf import settings +from django.contrib.sessions.backends.base import SessionBase + + +def get_session_store() -> SessionBase: + return import_module(settings.SESSION_ENGINE).SessionStore diff --git a/tests/conftest.py b/tests/conftest.py index cfb7fff..3e3adab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,17 +1,6 @@ -from importlib import import_module +# import pytest -from django.conf import settings as django_settings -import pytest - - -@pytest.fixture -def cache_session_store(settings): - settings.SESSION_ENGINE = "django.contrib.sessions.backends.cache" - return import_module(django_settings.SESSION_ENGINE).SessionStore - - -@pytest.fixture -def db_session_store(settings): - settings.SESSION_ENGINE = "django.contrib.sessions.backends.db" - return import_module(django_settings.SESSION_ENGINE).SessionStore +# @pytest.fixture +# def some_fixture(request): +# return "foo" diff --git a/tests/factories.py b/tests/factories.py index 17d5a92..170ea43 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -1,11 +1,8 @@ -from importlib import import_module - -from django.conf import settings - -import factory import factory.fuzzy from sessionprofile.models import SessionProfile +from open_api_framework.utils import get_session_store + class SessionProfileFactory(factory.django.DjangoModelFactory): @@ -14,11 +11,7 @@ class SessionProfileFactory(factory.django.DjangoModelFactory): class Meta: model = SessionProfile - @classmethod - def create(cls, **kwargs): - SessionStore = import_module(settings.SESSION_ENGINE).SessionStore - - instance = super().create(**kwargs) - SessionStore(instance.session_key).save(True) - - return instance + @factory.post_generation + def session(self, create, extracted, **kwargs): + SessionStore = get_session_store() + SessionStore(self.session_key).save(True) diff --git a/tests/test_admin.py b/tests/test_admin.py index d888d18..e31d519 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,10 +1,14 @@ +from django.contrib.sessions.backends.cache import SessionStore as CachedSessionStore +from django.contrib.sessions.backends.db import SessionStore as DBSessionStore from django.contrib.sessions.models import Session +from django.test import override_settings from django.urls import reverse import pytest -from pytest_django.fixtures import admin_user from sessionprofile.models import SessionProfile +from open_api_framework.utils import get_session_store + from .factories import SessionProfileFactory @@ -25,9 +29,6 @@ def test_session_profile_sanity(client, admin_user, session_changelist_url): assert client.session.session_key == session.session_key -admin_user2 = admin_user - - def test_only_session_profile_of_user_shown( client, admin_user, django_user_model, session_changelist_url ): @@ -54,10 +55,44 @@ def test_only_session_profile_of_user_shown( other_user_session = SessionProfile.objects.get(user=other_admin) assert other_user_session.session_key not in response.content.decode() + # should only be able to access own page + change_url = reverse( + "admin:sessionprofile_sessionprofile_change", + args=[admin_user_session.session_key], + ) + response = client.get(change_url) + assert response.status_code == 200 -def test_delete_with_session_db_backend( - client, admin_user, session_changelist_url, db_session_store -): + change_url = reverse( + "admin:sessionprofile_sessionprofile_change", + args=[other_user_session.session_key], + ) + response = client.get(change_url) + assert response.status_code == 302 + assert response.url == reverse("admin:index") + + +def test_cant_delete_other_users_session(client, admin_user, django_user_model): + client.force_login(admin_user) + + other_admin = django_user_model.objects.create_superuser("garry") + + other_user_session = SessionProfileFactory(user=other_admin) + + delete_url = reverse( + "admin:sessionprofile_sessionprofile_delete", + args=[other_user_session.session_key], + ) + + response = client.post(delete_url, {"post": "yes"}) + assert response.status_code == 302 + + SessionStore = get_session_store() + + assert SessionStore().exists(other_user_session.session_key) + + +def test_delete_with_session_db_backend(client, admin_user, session_changelist_url): client.force_login(admin_user) session = SessionProfileFactory(user=admin_user) @@ -65,7 +100,7 @@ def test_delete_with_session_db_backend( assert SessionProfile.objects.count() == 1 # sesison created by login assert Session.objects.count() == 2 - assert db_session_store().exists(session.session_key) + assert DBSessionStore().exists(session.session_key) url = reverse("admin:sessionprofile_sessionprofile_delete", args=[session.pk]) @@ -76,19 +111,18 @@ def test_delete_with_session_db_backend( assert SessionProfile.objects.count() == 1 assert SessionProfile.objects.count() != session assert Session.objects.count() == 1 - assert not db_session_store().exists(session.session_key) + assert not DBSessionStore().exists(session.session_key) -def test_delete_with_session_cache_backend( - client, admin_user, session_changelist_url, cache_session_store -): +@override_settings(SESSION_ENGINE="django.contrib.sessions.backends.cache") +def test_delete_with_session_cache_backend(client, admin_user, session_changelist_url): client.force_login(admin_user) session = SessionProfileFactory(user=admin_user) assert SessionProfile.objects.count() == 1 assert Session.objects.count() == 0 - assert cache_session_store().exists(session.session_key) + assert CachedSessionStore().exists(session.session_key) url = reverse("admin:sessionprofile_sessionprofile_delete", args=[session.pk]) @@ -99,11 +133,11 @@ def test_delete_with_session_cache_backend( assert SessionProfile.objects.count() == 1 assert SessionProfile.objects.count() != session assert Session.objects.count() == 0 - assert not cache_session_store().exists(session.session_key) + assert not CachedSessionStore().exists(session.session_key) def test_delete_action_with_session_db_backend( - client, admin_user, session_changelist_url, db_session_store + client, admin_user, session_changelist_url ): client.force_login(admin_user) sessions = SessionProfileFactory.create_batch(5, user=admin_user) @@ -114,7 +148,7 @@ def test_delete_action_with_session_db_backend( session_keys = [session.session_key for session in sessions] for session_key in session_keys: - assert db_session_store().exists(session_key) + assert DBSessionStore().exists(session_key) response = client.post( session_changelist_url, @@ -127,11 +161,12 @@ def test_delete_action_with_session_db_backend( assert Session.objects.count() == 1 for session_key in session_keys: - assert not db_session_store().exists(session_key) + assert not DBSessionStore().exists(session_key) +@override_settings(SESSION_ENGINE="django.contrib.sessions.backends.cache") def test_delete_action_with_session_cache_backend( - client, admin_user, session_changelist_url, cache_session_store + client, admin_user, session_changelist_url ): client.force_login(admin_user) @@ -145,7 +180,7 @@ def test_delete_action_with_session_cache_backend( # sessions are created for session_key in session_keys: - assert cache_session_store().exists(session_key) + assert CachedSessionStore().exists(session_key) response = client.post( session_changelist_url, @@ -159,4 +194,4 @@ def test_delete_action_with_session_cache_backend( # sessions should be deleted for session_key in session_keys: - assert not cache_session_store().exists(session_key) + assert not CachedSessionStore().exists(session_key)