From 0257da33610b4b35c342bcac89a762cb6abebe14 Mon Sep 17 00:00:00 2001 From: Anna Shamray Date: Tue, 12 Mar 2024 15:30:38 +0100 Subject: [PATCH] :sparkles: [https://github.com/maykinmedia/django-setup-configuration/issues/1] add demo user configuration step --- src/objecttypes/conf/base.py | 6 ++ src/objecttypes/config/demo.py | 60 ++++++++++++++++ .../commands/test_setup_configuration.py | 18 ++++- .../tests/config/test_demo_configuration.py | 72 +++++++++++++++++++ 4 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/objecttypes/config/demo.py create mode 100644 src/objecttypes/tests/config/test_demo_configuration.py diff --git a/src/objecttypes/conf/base.py b/src/objecttypes/conf/base.py index 28598932..2192d521 100644 --- a/src/objecttypes/conf/base.py +++ b/src/objecttypes/conf/base.py @@ -433,6 +433,7 @@ SETUP_CONFIGURATION_STEPS = [ "objecttypes.config.site.SiteConfigurationStep", "objecttypes.config.objects.ObjectsAuthStep", + "objecttypes.config.demo.DemoUserStep", ] @@ -452,3 +453,8 @@ OBJECTS_OBJECTTYPES_TOKEN = config("OBJECTS_OBJECTTYPES_TOKEN", "") OBJECTS_OBJECTTYPES_PERSON = config("OBJECTS_OBJECTTYPES_PERSON", "") OBJECTS_OBJECTTYPES_EMAIL = config("OBJECTS_OBJECTTYPES_EMAIL", "") +# Demo User Configuration +DEMO_CONFIG_ENABLE = config("DEMO_CONFIG_ENABLE", default=DEBUG) +DEMO_TOKEN = config("DEMO_TOKEN", "") +DEMO_PERSON = config("DEMO_PERSON", "") +DEMO_EMAIL = config("DEMO_EMAIL", "") diff --git a/src/objecttypes/config/demo.py b/src/objecttypes/config/demo.py new file mode 100644 index 00000000..18e3797d --- /dev/null +++ b/src/objecttypes/config/demo.py @@ -0,0 +1,60 @@ +from django.conf import settings +from django.urls import reverse + +import requests +from django_setup_configuration.configuration import BaseConfigurationStep +from django_setup_configuration.exceptions import SelfTestFailed + +from objecttypes.token.models import TokenAuth +from objecttypes.utils import build_absolute_url + + +class DemoUserStep(BaseConfigurationStep): + """ + Create demo user to request Objectypes API + """ + + verbose_name = "Demo User Configuration" + required_settings = [ + "DEMO_TOKEN", + "DEMO_PERSON", + "DEMO_EMAIL", + ] + enable_setting = "DEMO_CONFIG_ENABLE" + + def is_configured(self) -> bool: + return TokenAuth.objects.filter(token=settings.DEMO_TOKEN).exists() + + def configure(self): + token_auth, created = TokenAuth.objects.get_or_create( + token=settings.DEMO_TOKEN, + defaults={ + "contact_person": settings.DEMO_PERSON, + "email": settings.DEMO_EMAIL, + }, + ) + if ( + token_auth.contact_person != settings.DEMO_PERSON + or token_auth.email != settings.DEMO_EMAIL + ): + token_auth.contact_person = settings.DEMO_PERSON + token_auth.email = settings.DEMO_EMAIL + token_auth.save(update_fields=["contact_person", "email"]) + + def test_configuration(self): + endpoint = reverse("v2:objecttype-list") + full_url = build_absolute_url(endpoint, request=None) + + try: + response = requests.get( + full_url, + headers={ + "Authorization": f"Token {settings.DEMO_TOKEN}", + "Accept": "application/json", + }, + ) + response.raise_for_status() + except requests.RequestException as exc: + raise SelfTestFailed( + "Could not list objecttypes for the configured token" + ) from exc diff --git a/src/objecttypes/tests/commands/test_setup_configuration.py b/src/objecttypes/tests/commands/test_setup_configuration.py index 40304559..3e65d74d 100644 --- a/src/objecttypes/tests/commands/test_setup_configuration.py +++ b/src/objecttypes/tests/commands/test_setup_configuration.py @@ -1,4 +1,3 @@ -import uuid from io import StringIO from django.contrib.sites.models import Site @@ -9,6 +8,7 @@ import requests_mock from rest_framework import status +from objecttypes.config.demo import DemoUserStep from objecttypes.config.objects import ObjectsAuthStep from objecttypes.config.site import SiteConfigurationStep @@ -19,6 +19,10 @@ OBJECTS_OBJECTTYPES_TOKEN="some-random-string", OBJECTS_OBJECTTYPES_PERSON="Some Person", OBJECTS_OBJECTTYPES_EMAIL="objects@objects.local", + DEMO_CONFIG_ENABLE=True, + DEMO_TOKEN="demo-random-string", + DEMO_PERSON="Demo", + DEMO_EMAIL="demo@demo.local", ) class SetupConfigurationTests(TestCase): def setUp(self): @@ -39,11 +43,13 @@ def test_setup_configuration(self, m): command_output = stdout.getvalue().splitlines() expected_output = [ f"Configuration will be set up with following steps: [{SiteConfigurationStep()}, " - f"{ObjectsAuthStep()}]", + f"{ObjectsAuthStep()}, {DemoUserStep()}]", f"Configuring {SiteConfigurationStep()}...", f"{SiteConfigurationStep()} is successfully configured", f"Configuring {ObjectsAuthStep()}...", f"{ObjectsAuthStep()} is successfully configured", + f"Configuring {DemoUserStep()}...", + f"{DemoUserStep()} is successfully configured", "Instance configuration completed.", ] @@ -62,6 +68,14 @@ def test_setup_configuration(self, m): self.assertEqual(response.status_code, status.HTTP_200_OK) + with self.subTest("Demo user configured correctly"): + response = self.client.get( + reverse("v2:objecttype-list"), + HTTP_AUTHORIZATION="Token demo-random-string", + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + @requests_mock.Mocker() def test_setup_configuration_selftest_fails(self, m): m.get("http://objecttypes.example.com/", status_code=200) diff --git a/src/objecttypes/tests/config/test_demo_configuration.py b/src/objecttypes/tests/config/test_demo_configuration.py new file mode 100644 index 00000000..952cfdb5 --- /dev/null +++ b/src/objecttypes/tests/config/test_demo_configuration.py @@ -0,0 +1,72 @@ +from unittest.mock import patch + +from django.test import TestCase, override_settings + +import requests +import requests_mock +from django_setup_configuration.exceptions import SelfTestFailed + +from objecttypes.config.demo import DemoUserStep +from objecttypes.token.models import TokenAuth + + +@override_settings( + DEMO_TOKEN="demo-random-string", DEMO_PERSON="Demo", DEMO_EMAIL="demo@demo.local" +) +class DemoConfigurationTests(TestCase): + def test_configure(self): + configuration = DemoUserStep() + + configuration.configure() + + token_auth = TokenAuth.objects.get() + self.assertEqual(token_auth.token, "demo-random-string") + self.assertEqual(token_auth.contact_person, "Demo") + self.assertEqual(token_auth.email, "demo@demo.local") + + @requests_mock.Mocker() + @patch( + "objecttypes.config.demo.build_absolute_url", + return_value="http://testserver/objecttypes", + ) + def test_configuration_check_ok(self, m, *mocks): + configuration = DemoUserStep() + configuration.configure() + m.get("http://testserver/objecttypes", json=[]) + + configuration.test_configuration() + + self.assertEqual(m.last_request.url, "http://testserver/objecttypes") + self.assertEqual(m.last_request.method, "GET") + + @requests_mock.Mocker() + @patch( + "objecttypes.config.demo.build_absolute_url", + return_value="http://testserver/objecttypes", + ) + def test_configuration_check_failures(self, m, *mocks): + configuration = DemoUserStep() + configuration.configure() + + mock_kwargs = ( + {"exc": requests.ConnectTimeout}, + {"exc": requests.ConnectionError}, + {"status_code": 404}, + {"status_code": 403}, + {"status_code": 500}, + ) + for mock_config in mock_kwargs: + with self.subTest(mock=mock_config): + m.get("http://testserver/objecttypes", **mock_config) + + with self.assertRaises(SelfTestFailed): + configuration.test_configuration() + + def test_is_configured(self): + configuration = DemoUserStep() + + self.assertFalse(configuration.is_configured()) + + configuration.configure() + + self.assertTrue(configuration.is_configured())