From a86b26744db9c932e4c7ea787d956e8efc9235e3 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Thu, 26 Nov 2020 11:56:59 +0100 Subject: [PATCH] passwords are hidden in configuration and API --- CHANGELOG | 2 + smash/web/api_views/configuration.py | 7 +++- .../web/migrations/0182_auto_20201126_1042.py | 42 +++++++++++++++++++ smash/web/models/configuration_item.py | 8 +++- smash/web/models/constants.py | 9 ++++ .../api_views/test_configuration_item.py | 14 ++++++- 6 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 smash/web/migrations/0182_auto_20201126_1042.py diff --git a/CHANGELOG b/CHANGELOG index 69dc0ae8..542e4dc8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,8 @@ smasch (1.0.0~alpha.1-0) unstable; urgency=low * small improvement: all configuration options that are not obligatory are moved to configuration panel (#343) * small improvement: 2FA can be configured to be required option (#358) + * small improvement: redcap API token is not visible in configuration panel + (#359) -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 10 Nov 2020 14:00:00 +0200 diff --git a/smash/web/api_views/configuration.py b/smash/web/api_views/configuration.py index 12c420dc..d351af34 100644 --- a/smash/web/api_views/configuration.py +++ b/smash/web/api_views/configuration.py @@ -1,6 +1,7 @@ from django.http import JsonResponse from web.models import ConfigurationItem +from web.models.constants import VALUE_TYPE_PASSWORD def configuration_items(request): @@ -18,10 +19,14 @@ def configuration_items(request): data = [] for configuration_item in sliced_items: + value = configuration_item.value + if configuration_item.value_type == VALUE_TYPE_PASSWORD: + value = '' data.append({ "id": configuration_item.id, "name": configuration_item.name, - "value": configuration_item.value + "value": value, + "value_type": configuration_item.value_type, }) return JsonResponse({ "draw": draw, diff --git a/smash/web/migrations/0182_auto_20201126_1042.py b/smash/web/migrations/0182_auto_20201126_1042.py new file mode 100644 index 00000000..6260bec1 --- /dev/null +++ b/smash/web/migrations/0182_auto_20201126_1042.py @@ -0,0 +1,42 @@ +# Generated by Django 2.0.13 on 2020-11-26 10:42 + +import django.core.files.storage +from django.db import migrations, models + +from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, VALUE_TYPE_PASSWORD, NEXMO_API_KEY, NEXMO_API_SECRET + + +def configuration_items(apps, item_type): + # We can't import the ConfigurationItem model directly as it may be a newer + # version than this migration expects. We use the historical version. + + # noinspection PyPep8Naming + ConfigurationItem = apps.get_model("web", "ConfigurationItem") + items = ConfigurationItem.objects.filter( + type__in=[REDCAP_TOKEN_CONFIGURATION_TYPE, NEXMO_API_KEY, NEXMO_API_SECRET]).all() + for item in items: + item.value_type = VALUE_TYPE_PASSWORD + item.save() + + +class Migration(migrations.Migration): + dependencies = [ + ('web', '0181_worker_privacy_notice_accepted'), + ] + + operations = [ + migrations.AddField( + model_name='configurationitem', + name='value_type', + field=models.CharField(choices=[('PASSWORD', 'Password'), ('TEXT', 'Text')], default='TEXT', max_length=32, + verbose_name='Value type'), + ), + migrations.AlterField( + model_name='studysubject', + name='referral_letter', + field=models.FileField(blank=True, null=True, + storage=django.core.files.storage.FileSystemStorage(location='~/tmp/upload'), + upload_to='referral_letters', verbose_name='Referral letter'), + ), + migrations.RunPython(configuration_items), + ] diff --git a/smash/web/models/configuration_item.py b/smash/web/models/configuration_item.py index 9879847c..f873981e 100644 --- a/smash/web/models/configuration_item.py +++ b/smash/web/models/configuration_item.py @@ -5,7 +5,8 @@ from django.db import models from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE, \ NO_SHOW_APPOINTMENT_COLOR_CONFIGURATION_TYPE, KIT_EMAIL_HOUR_CONFIGURATION_TYPE, \ - KIT_EMAIL_DAY_OF_WEEK_CONFIGURATION_TYPE, KIT_DAILY_EMAIL_TIME_FORMAT_TYPE, KIT_DAILY_EMAIL_DAYS_PERIOD_TYPE + KIT_EMAIL_DAY_OF_WEEK_CONFIGURATION_TYPE, KIT_DAILY_EMAIL_TIME_FORMAT_TYPE, KIT_DAILY_EMAIL_DAYS_PERIOD_TYPE, \ + VALUE_TYPE_CHOICES, VALUE_TYPE_TEXT class ConfigurationItem(models.Model): @@ -24,6 +25,11 @@ class ConfigurationItem(models.Model): value = models.CharField(max_length=1024, verbose_name='Value', ) + value_type = models.CharField(max_length=32, + choices=VALUE_TYPE_CHOICES, + verbose_name='Value type', + default=VALUE_TYPE_TEXT + ) def __str__(self): return "%s %s" % (self.name, self.value) diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py index 34f44a48..664604bb 100644 --- a/smash/web/models/constants.py +++ b/smash/web/models/constants.py @@ -16,6 +16,15 @@ BOOL_CHOICES_WITH_NONE = ( (False, 'No'), (None, 'N/A'), ) + +VALUE_TYPE_PASSWORD = 'PASSWORD' +VALUE_TYPE_TEXT = 'TEXT' +VALUE_TYPE_CHOICES = ( + (VALUE_TYPE_PASSWORD, 'Password'), + (VALUE_TYPE_TEXT, 'Text'), +) + + SUBJECT_TYPE_CHOICES_CONTROL = 'C' SUBJECT_TYPE_CHOICES_PATIENT = 'P' SUBJECT_TYPE_CHOICES = { diff --git a/smash/web/tests/api_views/test_configuration_item.py b/smash/web/tests/api_views/test_configuration_item.py index 0628c171..a928dd01 100644 --- a/smash/web/tests/api_views/test_configuration_item.py +++ b/smash/web/tests/api_views/test_configuration_item.py @@ -4,7 +4,7 @@ from django.urls import reverse from web.models import ConfigurationItem -from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE +from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE, VALUE_TYPE_PASSWORD from web.tests import LoggedInTestCase from web.tests.functions import create_configuration_item @@ -15,6 +15,18 @@ class TestConfigurationItemApi(LoggedInTestCase): response = self.client.get(reverse('web.api.configuration_items')) self.assertEqual(response.status_code, 200) + def test_password_item(self): + item = ConfigurationItem.objects.create() + item.type = "TEST" + item.value = "secret_password" + item.name = "yyy" + item.value_type = VALUE_TYPE_PASSWORD + item.save() + response = self.client.get(reverse('web.api.configuration_items')) + self.assertFalse(item.value in response.content.decode("utf-8")) + self.assertTrue(item.value_type in response.content.decode("utf-8")) + self.assertEqual(response.status_code, 200) + def test_configuration_modify_invalid(self): response = self.client.get(reverse('web.api.update_configuration_item')) self.assertEqual(response.status_code, 200) -- GitLab