diff --git a/breccia_mapper/forms.py b/breccia_mapper/forms.py new file mode 100644 index 0000000..a307c7d --- /dev/null +++ b/breccia_mapper/forms.py @@ -0,0 +1,15 @@ +from django import forms +from django.contrib.auth import get_user_model + +User = get_user_model() # pylint: disable=invalid-name + + +class ConsentForm(forms.ModelForm): + """Form used to collect user consent for data collection / processing.""" + class Meta: + model = User + fields = ['consent_given'] + labels = { + 'consent_given': + 'I have read and understood this information and consent to my data being used in this way', + } diff --git a/breccia_mapper/settings.py b/breccia_mapper/settings.py index 395c659..91b5966 100644 --- a/breccia_mapper/settings.py +++ b/breccia_mapper/settings.py @@ -327,7 +327,7 @@ LOGGING = { LOGGING_CONFIG = None logging.config.dictConfig(LOGGING) -logger = logging.getLogger(__name__) +logger = logging.getLogger(__name__) # pylint: disable=invalid-name # Admin panel variables @@ -337,10 +337,17 @@ CONSTANCE_CONFIG = collections.OrderedDict([ 'Text to be displayed in a notice banner at the top of every page.')), ('NOTICE_CLASS', ('alert-warning', 'CSS class to use for background of notice banner.')), + ('CONSENT_TEXT', + ('This is template consent text and should have been replaced. Please contact an admin.', + 'Text to be displayed to ask for consent for data collection.')) ]) CONSTANCE_CONFIG_FIELDSETS = { - 'Notice Banner': ('NOTICE_TEXT', 'NOTICE_CLASS'), + 'Notice Banner': ( + 'NOTICE_TEXT', + 'NOTICE_CLASS', + ), + 'Data Collection': ('CONSENT_TEXT', ), } CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend' @@ -379,12 +386,10 @@ else: default=(EMAIL_PORT == 465), cast=bool) - # Upstream API keys GOOGLE_MAPS_API_KEY = config('GOOGLE_MAPS_API_KEY', default=None) - # Import customisation app settings if present try: diff --git a/breccia_mapper/templates/base.html b/breccia_mapper/templates/base.html index faf19a4..ed255c7 100644 --- a/breccia_mapper/templates/base.html +++ b/breccia_mapper/templates/base.html @@ -156,6 +156,15 @@ {% endif %} + {% if request.user.is_authenticated and not request.user.consent_given %} + + {% endif %} + {% block before_content %}{% endblock %}
diff --git a/breccia_mapper/templates/consent.html b/breccia_mapper/templates/consent.html new file mode 100644 index 0000000..6506f2a --- /dev/null +++ b/breccia_mapper/templates/consent.html @@ -0,0 +1,21 @@ +{% extends 'base.html' %} + +{% block content %} +

Consent

+ +

+ {{ config.CONSENT_TEXT|linebreaks }} +

+ +
+ {% csrf_token %} + + {% load bootstrap4 %} + {% bootstrap_form form %} + + {% buttons %} + + {% endbuttons %} +
+{% endblock %} diff --git a/breccia_mapper/urls.py b/breccia_mapper/urls.py index 0aade11..4db8da3 100644 --- a/breccia_mapper/urls.py +++ b/breccia_mapper/urls.py @@ -32,6 +32,10 @@ urlpatterns = [ views.IndexView.as_view(), name='index'), + path('consent', + views.ConsentTextView.as_view(), + name='consent'), + path('', include('export.urls')), diff --git a/breccia_mapper/views.py b/breccia_mapper/views.py index ff539f6..44c23f2 100644 --- a/breccia_mapper/views.py +++ b/breccia_mapper/views.py @@ -1,13 +1,31 @@ -""" -Views belonging to the core of the project. +"""Views belonging to the core of the project. These views don't represent any of the models in the apps. """ from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.mixins import LoginRequiredMixin +from django.urls import reverse_lazy from django.views.generic import TemplateView +from django.views.generic.edit import UpdateView + +from . import forms + +User = get_user_model() # pylint: disable=invalid-name class IndexView(TemplateView): # Template set in Django settings file - may be customised by a customisation app template_name = settings.TEMPLATE_NAME_INDEX + + +class ConsentTextView(LoginRequiredMixin, UpdateView): + """View with consent text and form for users to indicate consent.""" + model = User + form_class = forms.ConsentForm + template_name = 'consent.html' + success_url = reverse_lazy('index') + + def get_object(self, *args, **kwargs) -> User: + return self.request.user diff --git a/people/migrations/0030_user_consent_given.py b/people/migrations/0030_user_consent_given.py new file mode 100644 index 0000000..e51adfa --- /dev/null +++ b/people/migrations/0030_user_consent_given.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2021-01-20 11:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('people', '0029_organisation_location_fields'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='consent_given', + field=models.BooleanField(default=False), + ), + ] diff --git a/people/models/person.py b/people/models/person.py index 670f0db..914c53d 100644 --- a/people/models/person.py +++ b/people/models/person.py @@ -32,6 +32,9 @@ class User(AbstractUser): """ email = models.EmailField(_('email address'), blank=False, null=False) + #: Have they given consent to collect and store their data? + consent_given = models.BooleanField(default=False) + def has_person(self) -> bool: """ Does this user have a linked :class:`Person` record?