Skip to content
Snippets Groups Projects
Commit a86b2674 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

passwords are hidden in configuration and API

parent d362aa40
No related branches found
No related tags found
1 merge request!280Resolve "sensitive configuration options should be only write only"
Pipeline #34750 failed
...@@ -11,6 +11,8 @@ smasch (1.0.0~alpha.1-0) unstable; urgency=low ...@@ -11,6 +11,8 @@ smasch (1.0.0~alpha.1-0) unstable; urgency=low
* small improvement: all configuration options that are not obligatory are * small improvement: all configuration options that are not obligatory are
moved to configuration panel (#343) moved to configuration panel (#343)
* small improvement: 2FA can be configured to be required option (#358) * 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 -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 10 Nov 2020 14:00:00 +0200
......
from django.http import JsonResponse from django.http import JsonResponse
from web.models import ConfigurationItem from web.models import ConfigurationItem
from web.models.constants import VALUE_TYPE_PASSWORD
def configuration_items(request): def configuration_items(request):
...@@ -18,10 +19,14 @@ def configuration_items(request): ...@@ -18,10 +19,14 @@ def configuration_items(request):
data = [] data = []
for configuration_item in sliced_items: for configuration_item in sliced_items:
value = configuration_item.value
if configuration_item.value_type == VALUE_TYPE_PASSWORD:
value = ''
data.append({ data.append({
"id": configuration_item.id, "id": configuration_item.id,
"name": configuration_item.name, "name": configuration_item.name,
"value": configuration_item.value "value": value,
"value_type": configuration_item.value_type,
}) })
return JsonResponse({ return JsonResponse({
"draw": draw, "draw": draw,
......
# 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),
]
...@@ -5,7 +5,8 @@ from django.db import models ...@@ -5,7 +5,8 @@ from django.db import models
from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE, \ from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE, \
NO_SHOW_APPOINTMENT_COLOR_CONFIGURATION_TYPE, KIT_EMAIL_HOUR_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): class ConfigurationItem(models.Model):
...@@ -24,6 +25,11 @@ class ConfigurationItem(models.Model): ...@@ -24,6 +25,11 @@ class ConfigurationItem(models.Model):
value = models.CharField(max_length=1024, value = models.CharField(max_length=1024,
verbose_name='Value', 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): def __str__(self):
return "%s %s" % (self.name, self.value) return "%s %s" % (self.name, self.value)
......
...@@ -16,6 +16,15 @@ BOOL_CHOICES_WITH_NONE = ( ...@@ -16,6 +16,15 @@ BOOL_CHOICES_WITH_NONE = (
(False, 'No'), (False, 'No'),
(None, 'N/A'), (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_CONTROL = 'C'
SUBJECT_TYPE_CHOICES_PATIENT = 'P' SUBJECT_TYPE_CHOICES_PATIENT = 'P'
SUBJECT_TYPE_CHOICES = { SUBJECT_TYPE_CHOICES = {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
from django.urls import reverse from django.urls import reverse
from web.models import ConfigurationItem 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 import LoggedInTestCase
from web.tests.functions import create_configuration_item from web.tests.functions import create_configuration_item
...@@ -15,6 +15,18 @@ class TestConfigurationItemApi(LoggedInTestCase): ...@@ -15,6 +15,18 @@ class TestConfigurationItemApi(LoggedInTestCase):
response = self.client.get(reverse('web.api.configuration_items')) response = self.client.get(reverse('web.api.configuration_items'))
self.assertEqual(response.status_code, 200) 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): def test_configuration_modify_invalid(self):
response = self.client.get(reverse('web.api.update_configuration_item')) response = self.client.get(reverse('web.api.update_configuration_item'))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment