diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index fb81d9624b40750c5f24315112d873516b2ff3ab..c31d13903ab43b26fa7db0fd1f9c570d28e5cb5e 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -70,6 +70,10 @@ def get_subject_columns(request, subject_list_type):
     add_column(result, "Resigned", "resigned", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Endpoint Reached", "endpoint_reached", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Postponed", "postponed", study_subject_columns, "yes_no_filter", study.columns)
+    add_column(result, "Next of keen", "next_of_keen_name", subject_columns, "string_filter")
+    add_column(result, "Next of keen phone", "next_of_keen_phone", subject_columns, "string_filter")
+    add_column(result, "Next of keen address", "next_of_keen_address", subject_columns, "string_filter")
+    add_column(result, "Brain donation agreement", "brain_donation_agreement", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Excluded", "excluded", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Info sent", "information_sent", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Type", "type", study_subject_columns, "type_filter", study.columns)
@@ -113,6 +117,12 @@ def get_subjects_order(subjects_to_be_ordered, order_column, order_direction, co
         result = subjects_to_be_ordered.order_by(order_direction + 'subject__last_name')
     elif order_column == "address":
         result = subjects_to_be_ordered.order_by(order_direction + 'subject__address')
+    elif order_column == "next_of_keen_name":
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__next_of_keen_name')
+    elif order_column == "next_of_keen_phone":
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__next_of_keen_phone')
+    elif order_column == "next_of_keen_address":
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__next_of_keen_address')
     elif order_column == "nd_number":
         result = subjects_to_be_ordered.order_by(order_direction + 'nd_number')
     elif order_column == "referral":
@@ -144,6 +154,8 @@ def get_subjects_order(subjects_to_be_ordered, order_column, order_direction, co
         result = subjects_to_be_ordered.order_by(order_direction + 'subject__social_security_number')
     elif order_column == "postponed":
         result = subjects_to_be_ordered.order_by(order_direction + 'postponed')
+    elif order_column == "brain_donation_agreement":
+        result = subjects_to_be_ordered.order_by(order_direction + 'brain_donation_agreement')
     elif order_column == "excluded":
         result = subjects_to_be_ordered.order_by(order_direction + 'excluded')
     elif order_column == "type":
@@ -242,6 +254,12 @@ def get_subjects_filtered(subjects_to_be_filtered, filters):
             result = result.filter(subject__last_name__icontains=value)
         elif column == "address":
             result = result.filter(subject__address__icontains=value)
+        elif column == "next_of_keen_name":
+            result = result.filter(subject__next_of_keen_name__icontains=value)
+        elif column == "next_of_keen_phone":
+            result = result.filter(subject__next_of_keen_phone__icontains=value)
+        elif column == "next_of_keen_address":
+            result = result.filter(subject__next_of_keen_address__icontains=value)
         elif column == "nd_number":
             result = result.filter(nd_number__icontains=value)
         elif column == "referral":
@@ -254,6 +272,8 @@ def get_subjects_filtered(subjects_to_be_filtered, filters):
             result = result.filter(resigned=(value == "true"))
         elif column == "endpoint_reached":
             result = result.filter(endpoint_reached=(value == "true"))
+        elif column == "brain_donation_agreement":
+            result = result.filter(brain_donation_agreement=(value == "true"))
         elif column == "postponed":
             result = result.filter(postponed=(value == "true"))
         elif column == "excluded":
@@ -402,6 +422,9 @@ def serialize_subject(study_subject):
         "first_name": study_subject.subject.first_name,
         "last_name": study_subject.subject.last_name,
         "address": study_subject.subject.pretty_address(),
+        "next_of_keen_name": study_subject.subject.next_of_keen_name,
+        "next_of_keen_phone": study_subject.subject.next_of_keen_phone,
+        "next_of_keen_address": study_subject.subject.next_of_keen_address,
         "date_born": study_subject.subject.date_born,
         "datetime_contact_reminder": contact_reminder,
         "last_contact_attempt": last_contact_attempt_string,
@@ -414,6 +437,7 @@ def serialize_subject(study_subject):
         "resigned": bool_to_yes_no(study_subject.resigned),
         "endpoint_reached": bool_to_yes_no(study_subject.endpoint_reached),
         "postponed": bool_to_yes_no(study_subject.postponed),
+        "brain_donation_agreement": bool_to_yes_no(study_subject.brain_donation_agreement),
         "excluded": bool_to_yes_no(study_subject.excluded),
         "information_sent": bool_to_yes_no(study_subject.information_sent),
         "health_partner_first_name": health_partner_first_name,
diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py
index ea2849fc6ae8ddce7b8f5ddc62d1bb7467908b8a..2bc880780226734cfa1653501960eb47bc8138b0 100644
--- a/smash/web/forms/study_subject_forms.py
+++ b/smash/web/forms/study_subject_forms.py
@@ -161,6 +161,7 @@ def prepare_study_subject_fields(fields, study):
     prepare_field(fields, study.columns, 'nd_number')
     prepare_field(fields, study.columns, 'datetime_contact_reminder')
     prepare_field(fields, study.columns, 'postponed')
+    prepare_field(fields, study.columns, 'brain_donation_agreement')
     prepare_field(fields, study.columns, 'flying_team')
     prepare_field(fields, study.columns, 'mpower_id')
     prepare_field(fields, study.columns, 'comments')
diff --git a/smash/web/migrations/0148_auto_20200319_1301.py b/smash/web/migrations/0148_auto_20200319_1301.py
new file mode 100644
index 0000000000000000000000000000000000000000..1b2abecbe955819c77d988944336b22ad28bd016
--- /dev/null
+++ b/smash/web/migrations/0148_auto_20200319_1301.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-19 13:01
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('web', '0147_auto_20200320_0931'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='appointmenttypelink',
+            options={'permissions': [('view_daily_planning', 'Can see daily planning')]},
+        ),
+        migrations.AlterField(
+            model_name='appointmenttype',
+            name='calendar_font_color',
+            field=models.CharField(default=b'#00000', max_length=2000, verbose_name=b'Calendar font color'),
+        ),
+    ]
diff --git a/smash/web/migrations/0149_auto_20200319_1415.py b/smash/web/migrations/0149_auto_20200319_1415.py
new file mode 100644
index 0000000000000000000000000000000000000000..c948e9780d3d5da309c62035ff5afb27f0d835fc
--- /dev/null
+++ b/smash/web/migrations/0149_auto_20200319_1415.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-19 14:15
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0148_auto_20200319_1301'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='appointment',
+            options={'permissions': [('send_sample_mail_for_appointments', 'Can send sample collection list')]},
+        ),
+    ]
diff --git a/smash/web/migrations/0150_auto_20200319_1446.py b/smash/web/migrations/0150_auto_20200319_1446.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fcdea7e40cf414c94558b82d7befe42e7dbc275
--- /dev/null
+++ b/smash/web/migrations/0150_auto_20200319_1446.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-19 14:46
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0149_auto_20200319_1415'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='appointment',
+            options={'permissions': [('send_sample_mail_for_appointments', 'Can send sample collection list'), ('view_statistics', 'Can see statistics')]},
+        ),
+    ]
diff --git a/smash/web/migrations/0151_auto_20200319_1518.py b/smash/web/migrations/0151_auto_20200319_1518.py
new file mode 100644
index 0000000000000000000000000000000000000000..a034d7b50283e5a6011cbcf3e9bf24a465c0cfcb
--- /dev/null
+++ b/smash/web/migrations/0151_auto_20200319_1518.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-19 15:18
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0150_auto_20200319_1446'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='subject',
+            options={'permissions': [('send_sample_mail_for_appointments', 'Can send sample collection list'), ('export_subjects', 'Can export subject data to excel/csv')]},
+        ),
+    ]
diff --git a/smash/web/migrations/0152_add_permissions_to_existing_workers.py b/smash/web/migrations/0152_add_permissions_to_existing_workers.py
new file mode 100644
index 0000000000000000000000000000000000000000..67752e4690b59643da8f7ae2fe375db39a43f2a2
--- /dev/null
+++ b/smash/web/migrations/0152_add_permissions_to_existing_workers.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-19 13:01
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('web', '0151_auto_20200319_1518'),
+    ]
+
+    operations = [
+        migrations.RunSQL("insert into web_workerstudyrole_permissions(workerstudyrole_id, permission_id) "
+                          "select web_workerstudyrole.id, auth_permission.id from web_workerstudyrole,auth_permission "
+                          "where codename='view_daily_planning';"),
+        migrations.RunSQL("insert into web_workerstudyrole_permissions(workerstudyrole_id, permission_id) "
+                          "select web_workerstudyrole.id, auth_permission.id from web_workerstudyrole,auth_permission "
+                          "where codename='change_flyingteam';"),
+        migrations.RunSQL("insert into web_workerstudyrole_permissions(workerstudyrole_id, permission_id) "
+                          "select web_workerstudyrole.id, auth_permission.id from web_workerstudyrole,auth_permission "
+                          "where codename='export_subjects';"),
+
+    ]
diff --git a/smash/web/migrations/0153_auto_20200320_0932.py b/smash/web/migrations/0153_auto_20200320_0932.py
new file mode 100644
index 0000000000000000000000000000000000000000..06a7de106240cf856fceb9720477be0b9aa87526
--- /dev/null
+++ b/smash/web/migrations/0153_auto_20200320_0932.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2020-03-20 09:32
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0152_add_permissions_to_existing_workers'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='studycolumns',
+            name='brain_donation_agreement',
+            field=models.BooleanField(default=False, verbose_name=b'Brain donation agreement'),
+        ),
+        migrations.AddField(
+            model_name='studysubject',
+            name='brain_donation_agreement',
+            field=models.BooleanField(default=False, verbose_name=b'Brain donation agreement'),
+        ),
+        migrations.AddField(
+            model_name='subject',
+            name='next_of_keen_address',
+            field=models.TextField(blank=True, max_length=2000, verbose_name=b'Next of keen address'),
+        ),
+        migrations.AddField(
+            model_name='subject',
+            name='next_of_keen_name',
+            field=models.CharField(blank=True, max_length=50, verbose_name=b'Next of keen'),
+        ),
+        migrations.AddField(
+            model_name='subject',
+            name='next_of_keen_phone',
+            field=models.CharField(blank=True, max_length=50, verbose_name=b'Next of keen phone'),
+        ),
+        migrations.AddField(
+            model_name='subjectcolumns',
+            name='next_of_keen_address',
+            field=models.BooleanField(default=False, max_length=1, verbose_name=b'Next of keen address'),
+        ),
+        migrations.AddField(
+            model_name='subjectcolumns',
+            name='next_of_keen_name',
+            field=models.BooleanField(default=False, max_length=1, verbose_name=b'Next of keen'),
+        ),
+        migrations.AddField(
+            model_name='subjectcolumns',
+            name='next_of_keen_phone',
+            field=models.BooleanField(default=False, max_length=1, verbose_name=b'Next of keen phone'),
+        ),
+    ]
diff --git a/smash/web/models/appointment.py b/smash/web/models/appointment.py
index 9b5b3944c623d47a8e090bccab83fbfed6eb245b..c7a52d416f21c313e7930088f85944c91f35cd50 100644
--- a/smash/web/models/appointment.py
+++ b/smash/web/models/appointment.py
@@ -11,6 +11,10 @@ from . import ConfigurationItem
 class Appointment(models.Model):
     class Meta:
         app_label = 'web'
+        permissions = [
+            ("send_sample_mail_for_appointments", "Can send sample collection list"),
+            ("view_statistics", "Can see statistics"),
+        ]
 
     APPOINTMENT_STATUS_SCHEDULED = 'SCHEDULED'
     APPOINTMENT_STATUS_FINISHED = 'FINISHED'
diff --git a/smash/web/models/appointment_type_link.py b/smash/web/models/appointment_type_link.py
index a48a55026880f9437ee66c390a19645dfe3a5671..c2de6050854dc57820b72b3d53b3f945f3d08aaf 100644
--- a/smash/web/models/appointment_type_link.py
+++ b/smash/web/models/appointment_type_link.py
@@ -2,6 +2,10 @@ from django.db import models
 
 
 class AppointmentTypeLink(models.Model):
+    class Meta:
+        permissions = [
+            ("view_daily_planning", "Can see daily planning"),
+        ]
     appointment = models.ForeignKey("web.Appointment", on_delete=models.CASCADE)
     appointment_type = models.ForeignKey("web.AppointmentType", on_delete=models.CASCADE)
     date_when = models.DateTimeField(null=True, default=None)
diff --git a/smash/web/models/study_columns.py b/smash/web/models/study_columns.py
index a1b345700db1db01741b050496d1e609524c30da..7d20b3913d40a71f72fc0b70327a20084e83a158 100644
--- a/smash/web/models/study_columns.py
+++ b/smash/web/models/study_columns.py
@@ -1,8 +1,6 @@
 # coding=utf-8
 from django.db import models
 
-from web.models.constants import BOOL_CHOICES
-
 
 class StudyColumns(models.Model):
     class Meta:
@@ -81,7 +79,7 @@ class StudyColumns(models.Model):
     excluded = models.BooleanField(default=False, verbose_name='Excluded')
 
     endpoint_reached = models.BooleanField(default=True, verbose_name='Endpoint reached')
-    
+
     resign_reason = models.BooleanField(default=True, verbose_name='Endpoint reached comments')
 
     referral_letter = models.BooleanField(
@@ -117,4 +115,9 @@ class StudyColumns(models.Model):
     vouchers = models.BooleanField(
                                    default=False,
                                    verbose_name='Vouchers',
-                                   )
\ No newline at end of file
+                                   )
+
+    brain_donation_agreement = models.BooleanField(
+                                                   default=False,
+                                                   verbose_name='Brain donation agreement',
+                                                   )
diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py
index a4d217784f01a67e34d2698777f743f5a2e06548..f08d450d3b0b516c9de4c943b3347eddc610aad5 100644
--- a/smash/web/models/study_subject.py
+++ b/smash/web/models/study_subject.py
@@ -164,6 +164,11 @@ class StudySubject(models.Model):
         verbose_name='PD in family',
         default=None,
     )
+    brain_donation_agreement = models.BooleanField(
+                                                   default=False,
+                                                   verbose_name='Brain donation agreement',
+                                                   )
+
     resigned = models.BooleanField(
         verbose_name='Resigned',
         default=False,
diff --git a/smash/web/models/subject.py b/smash/web/models/subject.py
index 40c390932411e2f7a4c5bcf622927e5a5935631c..bc70691410f4d7459a0ea7b08336abd8a506d7a0 100644
--- a/smash/web/models/subject.py
+++ b/smash/web/models/subject.py
@@ -1,19 +1,24 @@
 # coding=utf-8
 import logging
+
 from django.db import models
+from django.db.models.signals import post_save
+from django.dispatch import receiver
 
 from constants import SEX_CHOICES, COUNTRY_OTHER_ID
 from web.models import Country, Visit, Appointment, Provenance
 from . import Language
-from django.db.models.signals import post_save
-from django.dispatch import receiver
 
 logger = logging.getLogger(__name__)
 
-class Subject(models.Model):
 
+class Subject(models.Model):
     class Meta:
         app_label = 'web'
+        permissions = [
+            ("send_sample_mail_for_appointments", "Can send sample collection list"),
+            ("export_subjects", "Can export subject data to excel/csv"),
+        ]
 
     sex = models.CharField(max_length=1,
                            choices=SEX_CHOICES,
@@ -96,6 +101,21 @@ class Subject(models.Model):
                                 verbose_name='Country'
                                 )
 
+    next_of_keen_name = models.CharField(max_length=50,
+                                         blank=True,
+                                         verbose_name='Next of keen'
+                                         )
+
+    next_of_keen_phone = models.CharField(max_length=50,
+                                          blank=True,
+                                          verbose_name='Next of keen phone'
+                                          )
+
+    next_of_keen_address = models.TextField(max_length=2000,
+                                            blank=True,
+                                            verbose_name='Next of keen address'
+                                            )
+
     dead = models.BooleanField(
         verbose_name='Deceased',
         default=False,
@@ -103,7 +123,7 @@ class Subject(models.Model):
     )
 
     def pretty_address(self):
-      return u'{} ({}), {}. {}'.format(self.address, self.postal_code, self.city, self.country)
+        return u'{} ({}), {}. {}'.format(self.address, self.postal_code, self.city, self.country)
 
     def mark_as_dead(self):
         self.dead = True
@@ -130,7 +150,7 @@ class Subject(models.Model):
         return "%s %s" % (self.first_name, self.last_name)
 
 
-#SIGNALS
+# SIGNALS
 @receiver(post_save, sender=Subject)
 def set_as_deceased(sender, instance, **kwargs):
     if instance.dead:
diff --git a/smash/web/models/subject_columns.py b/smash/web/models/subject_columns.py
index d83847c7d6589aa98adbcd1740137fcb1a80526b..04a1869b0787f66eb61e8c76bd858419db16798f 100644
--- a/smash/web/models/subject_columns.py
+++ b/smash/web/models/subject_columns.py
@@ -83,3 +83,18 @@ class SubjectColumns(models.Model):
                                default=True,
                                verbose_name='Deceased',
                                )
+
+    next_of_keen_name = models.BooleanField(max_length=1,
+                                            default=False,
+                                            verbose_name='Next of keen',
+                                            )
+
+    next_of_keen_phone = models.BooleanField(max_length=1,
+                                             default=False,
+                                             verbose_name='Next of keen phone',
+                                             )
+
+    next_of_keen_address = models.BooleanField(max_length=1,
+                                               default=False,
+                                               verbose_name='Next of keen address',
+                                               )
diff --git a/smash/web/templates/sidebar.html b/smash/web/templates/sidebar.html
index a91be3d75937d828cecab8216c779c3b557271a7..a575319957dc7bab0a8d2cf03b4204c9796d53b3 100644
--- a/smash/web/templates/sidebar.html
+++ b/smash/web/templates/sidebar.html
@@ -16,12 +16,14 @@
         </a>
     </li>
 
-    <li data-desc="daily_planning">
-        <a href="{% url 'web.views.daily_planning' %}">
-            <i class="fa fa-clock-o"></i>
-            <span>Daily Planning</span>
-        </a>
-    </li>
+    {% if "view_daily_planning" in permissions %}
+        <li data-desc="daily_planning">
+            <a href="{% url 'web.views.daily_planning' %}">
+                <i class="fa fa-clock-o"></i>
+                <span>Daily Planning</span>
+            </a>
+        </li>
+    {% endif %}
 
     {% if "change_worker" in permissions %}
     <li data-desc="workers">
@@ -32,44 +34,63 @@
     </li>
     {% endif %}
 
-    <li data-desc="equipment_and_rooms" class="treeview">
-        <a href="{% url 'web.views.equipment_and_rooms' %}">
-            <i class="fa fa-building-o"></i> <span>Equipment &amp; Rooms</span>
-            <span class="pull-right-container">
+    {% if equipment_perms %}
+        <li data-desc="equipment_and_rooms" class="treeview">
+            <a href="{% url 'web.views.equipment_and_rooms' %}">
+                <i class="fa fa-building-o"></i> <span>Equipment &amp; Rooms</span>
+                <span class="pull-right-container">
               <i class="fa fa-angle-left pull-right"></i>
             </span>
-        </a>
-        <ul class="treeview-menu">
-                <li data-desc="equipment_items"><a href="{% url 'web.views.equipment' %}">Equipment items</a></li>
-            {% if "change_appointmenttype" in permissions %}
-                <li data-desc="appointment_types"><a href="{% url 'web.views.appointment_types' %}">Appointment Types</a></li>
-            {% endif %}
-                <li data-desc="flying_teams"><a href="{% url 'web.views.equipment_and_rooms.flying_teams' %}">Flying teams</a></li>
-                <li data-desc="kit_requests"><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li>
-                <li data-desc="rooms"><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li>
-        </ul>
-    </li>
+            </a>
+            <ul class="treeview-menu">
+                {% if "change_item" in permissions %}
+                    <li data-desc="equipment_items"><a href="{% url 'web.views.equipment' %}">Equipment items</a></li>
+                {% endif %}
+                {% if "change_appointmenttype" in permissions %}
+                    <li data-desc="appointment_types"><a href="{% url 'web.views.appointment_types' %}">Appointment
+                        Types</a></li>
+                {% endif %}
+                {% if "change_flyingteam" in permissions %}
+                    <li data-desc="flying_teams"><a href="{% url 'web.views.equipment_and_rooms.flying_teams' %}">Flying
+                        teams</a></li>
+                {% endif %}
+                {% if "send_sample_mail_for_appointments" in permissions %}
+                    <li data-desc="kit_requests"><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li>
+                {% endif %}
+                {% if "change_room" in permissions %}
+                    <li data-desc="rooms"><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li>
+                {% endif %}
+            </ul>
+        </li>
+    {% endif %}
 
-    <li data-desc="statistics">
-        <a href="{% url 'web.views.statistics' %}">
-            <i class="fa fa-bar-chart" aria-hidden="true"></i>
-            <span>Statistics</span>
-        </a>
-    </li>
+    {% if  "view_statistics" in permissions %}
+        <li data-desc="statistics">
+            <a href="{% url 'web.views.statistics' %}">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Statistics</span>
+            </a>
+        </li>
+    {% endif %}
 
-    <li data-desc="mail_templates">
-        <a href="{% url 'web.views.mail_templates' %}">
-            <i class="fa fa-envelope-o"></i>
-            <span>Mail templates</span>
-        </a>
-    </li>
 
-    <li data-desc="export">
-        <a href="{% url 'web.views.export' %}">
-            <i class="fa fa-file-excel-o"></i>
-            <span>Export</span>
-        </a>
-    </li>
+    {% if  "change_mailtemplate" in permissions %}
+        <li data-desc="mail_templates">
+            <a href="{% url 'web.views.mail_templates' %}">
+                <i class="fa fa-envelope-o"></i>
+                <span>Mail templates</span>
+            </a>
+        </li>
+    {% endif %}
+
+    {% if  "export_subjects" in permissions %}
+        <li data-desc="export">
+            <a href="{% url 'web.views.export' %}">
+                <i class="fa fa-file-excel-o"></i>
+                <span>Export</span>
+            </a>
+        </li>
+    {% endif %}
 
     {% if study.has_vouchers and "change_voucher" in permissions%}
     <li data-desc="vouchers">
diff --git a/smash/web/templates/subjects/edit.html b/smash/web/templates/subjects/edit.html
index a8fe444044085df8d4bb26c9c8203b8e2bc848c1..4fbc1ca90b4063e780d625b930c047c6f4792aef 100644
--- a/smash/web/templates/subjects/edit.html
+++ b/smash/web/templates/subjects/edit.html
@@ -204,6 +204,11 @@
                     $("#confirm-dead-resigned-mark-dialog").modal("show");
                     return false;
                 }
+                var brainDonation = $("#id_study_subject-brain_donation_agreement").is(":checked");
+                if (brainDonation && ($("#id_subject-next_of_keen_phone").val() === '' || $("#id_subject-next_of_keen_address").val() === '' || $("#id_subject-next_of_keen_name").val() === '')) {
+                    alert("Next of keen data must be entered when brain donation agreement is in place");
+                    return false;
+                }
             });
             $("#confirm-save").click(function () {
                 confirmed = true;
diff --git a/smash/web/tests/view/test_daily_planning.py b/smash/web/tests/view/test_daily_planning.py
new file mode 100644
index 0000000000000000000000000000000000000000..096cc9200a770d92d5665aa33ff5cb94ac08635e
--- /dev/null
+++ b/smash/web/tests/view/test_daily_planning.py
@@ -0,0 +1,20 @@
+import logging
+
+from django.urls import reverse
+
+from web.tests import LoggedInTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class DailyPlanningViewTests(LoggedInTestCase):
+    def test_visit_details_request(self):
+        self.login_as_admin()
+        response = self.client.get(reverse('web.views.daily_planning'))
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_visit_details_request_without_permissions(self):
+        self.login_as_staff()
+        response = self.client.get(reverse('web.views.daily_planning'))
+        self.assertEqual(response.status_code, 302)
diff --git a/smash/web/tests/view/test_equipments.py b/smash/web/tests/view/test_equipments.py
index 99e312a8c85d747a66ca3a90396f1c9ece48b9f5..34cba24a89c5595b000dbec28d2f36e967c8f223 100644
--- a/smash/web/tests/view/test_equipments.py
+++ b/smash/web/tests/view/test_equipments.py
@@ -10,7 +10,14 @@ logger = logging.getLogger(__name__)
 
 
 class EquipmentTests(LoggedInTestCase):
+
+    def test_list_without_permissions(self):
+        self.login_as_staff()
+        response = self.client.get(reverse('web.views.equipment'))
+        self.assertEqual(response.status_code, 302)
+
     def test_equipment_requests(self):
+        self.login_as_admin()
         pages = [
             'web.views.equipment',
             'web.views.equipment_add',
@@ -21,6 +28,7 @@ class EquipmentTests(LoggedInTestCase):
             self.assertEqual(response.status_code, 200)
 
     def test_equipment_edit_request(self):
+        self.login_as_admin()
         item = create_item()
         page = reverse('web.views.equipment_edit',
                        kwargs={'equipment_id': str(item.id)})
@@ -28,6 +36,7 @@ class EquipmentTests(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_equipment_delete_request(self):
+        self.login_as_admin()
         item = create_item()
         page = reverse('web.views.equipment_delete',
                        kwargs={'equipment_id': str(item.id)})
@@ -35,6 +44,7 @@ class EquipmentTests(LoggedInTestCase):
         self.assertEqual(response.status_code, 302)
 
     def test_equipment_add(self):
+        self.login_as_admin()
         page = reverse('web.views.equipment_add')
         data = {
             'name': 'The mysterious potion',
@@ -48,6 +58,7 @@ class EquipmentTests(LoggedInTestCase):
         self.assertEqual(len(freshly_created), 1)
 
     def test_equipment_edit(self):
+        self.login_as_admin()
         item = create_item()
         page = reverse('web.views.equipment_edit',
                        kwargs={'equipment_id': str(item.id)})
@@ -64,6 +75,7 @@ class EquipmentTests(LoggedInTestCase):
             self.assertEqual(getattr(freshly_edited, key, ''), data[key])
 
     def test_equipment_delete(self):
+        self.login_as_admin()
         item = create_item()
         page = reverse('web.views.equipment_delete',
                        kwargs={'equipment_id': str(item.id)})
diff --git a/smash/web/tests/view/test_export.py b/smash/web/tests/view/test_export.py
index d6938476f7fd4ea6e3d3b36f2441e448fb02bfad..3f6a5c99b7fc12060eb0aad8ca95a92460d424de 100644
--- a/smash/web/tests/view/test_export.py
+++ b/smash/web/tests/view/test_export.py
@@ -9,26 +9,47 @@ from web.views.export import subject_to_row_for_fields, DROP_OUT_FIELD
 
 class TestExportView(LoggedInTestCase):
     def test_export_subjects_to_csv(self):
+        self.login_as_admin()
         create_study_subject()
         response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"}))
         self.assertEqual(response.status_code, 200)
 
+    def test_export_subjects_to_csv_without_permission(self):
+        response = self.client.get(reverse("web.views.mail_templates"))
+        create_study_subject()
+        response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"}))
+        self.assertEqual(response.status_code, 302)
+
     def test_render_export(self):
+        self.login_as_admin()
         create_study_subject()
         response = self.client.get(reverse('web.views.export'))
         self.assertEqual(response.status_code, 200)
 
+    def test_render_export_without_permission(self):
+        create_study_subject()
+        response = self.client.get(reverse('web.views.export'))
+        self.assertEqual(response.status_code, 302)
+
     def test_export_appointments_to_csv(self):
+        self.login_as_admin()
         create_appointment()
         response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "appointments"}))
         self.assertEqual(response.status_code, 200)
 
     def test_export_subjects_to_excel(self):
+        self.login_as_admin()
         create_study_subject()
         response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"}))
         self.assertEqual(response.status_code, 200)
 
+    def test_export_subjects_to_excel_without_permission(self):
+        create_study_subject()
+        response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"}))
+        self.assertEqual(response.status_code, 302)
+
     def test_export_appointments_to_excel(self):
+        self.login_as_admin()
         appointment = create_appointment()
         appointment.visit = None
         appointment.save()
diff --git a/smash/web/tests/view/test_flying_teams.py b/smash/web/tests/view/test_flying_teams.py
index 32cfe22ff9d0ac7cbd073f66dd3691ff051a06b9..e282c3e9cc14987d9c4a4a7ca5b90ca26af1c907 100644
--- a/smash/web/tests/view/test_flying_teams.py
+++ b/smash/web/tests/view/test_flying_teams.py
@@ -17,6 +17,7 @@ class FlyingTeamTests(LoggedInTestCase):
         return 'Random' + ''.join(random.choice(letters) for x in range(15))
 
     def test_flying_team_requests(self):
+        self.login_as_admin()
         pages = [
             'web.views.equipment_and_rooms.flying_teams',
             'web.views.equipment_and_rooms.flying_teams_add',
@@ -26,7 +27,18 @@ class FlyingTeamTests(LoggedInTestCase):
             response = self.client.get(reverse(page))
             self.assertEqual(response.status_code, 200)
 
+    def test_flying_team_requests_without_permission(self):
+        pages = [
+            'web.views.equipment_and_rooms.flying_teams',
+            'web.views.equipment_and_rooms.flying_teams_add',
+        ]
+
+        for page in pages:
+            response = self.client.get(reverse(page))
+            self.assertEqual(response.status_code, 302)
+
     def test_flying_team_add(self):
+        self.login_as_admin()
         page = reverse('web.views.equipment_and_rooms.flying_teams_add')
         data = {
             'place': self.generate_more_or_less_random_name()
@@ -38,6 +50,7 @@ class FlyingTeamTests(LoggedInTestCase):
         self.assertEqual(len(freshly_created), 1)
 
     def test_flying_team_edit(self):
+        self.login_as_admin()
         flying_team = create_flying_team()
         page = reverse('web.views.equipment_and_rooms.flying_teams_edit',
                        kwargs={'flying_team_id': str(flying_team.id)})
@@ -51,6 +64,7 @@ class FlyingTeamTests(LoggedInTestCase):
         self.assertEqual(freshly_edited.place, data["place"])
 
     def test_flying_team_edit_request(self):
+        self.login_as_admin()
         flying_team = create_flying_team()
         page = reverse('web.views.equipment_and_rooms.flying_teams_edit',
                        kwargs={'flying_team_id': str(flying_team.id)})
diff --git a/smash/web/tests/view/test_kit_request.py b/smash/web/tests/view/test_kit_request.py
index 387001f3bd804c87fef7db3dccac4de4897dd97f..72222f5df0f4de62743ed4d3edbf388f8232b008 100644
--- a/smash/web/tests/view/test_kit_request.py
+++ b/smash/web/tests/view/test_kit_request.py
@@ -5,7 +5,8 @@ from django.urls import reverse
 
 from web.models import Item, Appointment, AppointmentTypeLink
 from web.tests import LoggedInTestCase
-from web.tests.functions import create_appointment_type, create_appointment, create_visit, create_appointment_without_visit
+from web.tests.functions import create_appointment_type, create_appointment, create_visit, \
+    create_appointment_without_visit
 from web.views.kit import get_kit_requests
 from web.views.notifications import get_today_midnight_date
 
@@ -13,10 +14,16 @@ from web.views.notifications import get_today_midnight_date
 class ViewFunctionsTests(LoggedInTestCase):
 
     def test_kit_requests(self):
+        self.login_as_admin()
         response = self.client.get(reverse('web.views.kit_requests'))
         self.assertEqual(response.status_code, 200)
 
+    def test_kit_requests_without_permission(self):
+        response = self.client.get(reverse('web.views.kit_requests'))
+        self.assertEqual(response.status_code, 302)
+
     def test_kit_requests_2(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
@@ -35,6 +42,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertTrue(item_name in response.content)
 
     def test_kit_requests_4(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
@@ -54,6 +62,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertFalse(item_name in response.content)
 
     def test_kit_requests_3(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
@@ -72,6 +81,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertTrue(item_name in response.content)
 
     def test_kit_requests_order(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
@@ -104,6 +114,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertEqual(appointment2, result['appointments'][2])
 
     def test_kit_requests_for_appointment_with_two_types(self):
+        self.login_as_admin()
         item = Item.objects.create(disposable=True, name="item 1")
         appointment_type = create_appointment_type()
         appointment_type.required_equipment.add(item)
@@ -129,6 +140,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertEqual(1, len(result["appointments"]))
 
     def test_kit_requests_send_email(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
@@ -150,6 +162,7 @@ class ViewFunctionsTests(LoggedInTestCase):
         self.assertEqual(1, len(mail.outbox))
 
     def test_kit_request_send_mail_with_general_appointment(self):
+        self.login_as_admin()
         item_name = "Test item to be ordered"
         item = Item.objects.create(disposable=True, name=item_name)
         appointment_type = create_appointment_type()
diff --git a/smash/web/tests/view/test_mail.py b/smash/web/tests/view/test_mail.py
index 900c84a7bcadf38a37c420308d638eb4f2c74d14..1f11340a796aedc4e9c0eebf7662ddd50d3cce33 100644
--- a/smash/web/tests/view/test_mail.py
+++ b/smash/web/tests/view/test_mail.py
@@ -4,8 +4,8 @@ from django.urls import reverse
 
 from web.models import MailTemplate
 from web.models.constants import MAIL_TEMPLATE_CONTEXT_VOUCHER
-from web.tests.functions import create_voucher, get_resource_path
 from web.tests import LoggedInTestCase
+from web.tests.functions import create_voucher, get_resource_path
 
 logger = logging.getLogger(__name__)
 
@@ -20,3 +20,12 @@ class MailTests(LoggedInTestCase):
         page = reverse('web.views.mail_template_generate_for_vouchers') + "?voucher_id=" + str(voucher.id)
         response = self.client.get(page)
         self.assertEqual(response.status_code, 200)
+
+    def test_list_mail_templates(self):
+        self.login_as_admin()
+        response = self.client.get(reverse("web.views.mail_templates"))
+        self.assertEqual(response.status_code, 200)
+
+    def test_list_mail_templates_without_permission(self):
+        response = self.client.get(reverse("web.views.mail_templates"))
+        self.assertEqual(response.status_code, 302)
diff --git a/smash/web/tests/view/test_rooms.py b/smash/web/tests/view/test_rooms.py
index ecf1161677c0a104d9861bd356c2c96416b81bf0..b607e8105b025ac6e5492ff5b53f6ec0e9aba7ea 100644
--- a/smash/web/tests/view/test_rooms.py
+++ b/smash/web/tests/view/test_rooms.py
@@ -2,15 +2,16 @@ import logging
 
 from django.urls import reverse
 
-from web.tests.functions import create_room, create_item
-from web.models import Item, Room
+from web.models import Room
 from web.tests import LoggedInTestCase
+from web.tests.functions import create_room, create_item
 
 logger = logging.getLogger(__name__)
 
 
 class RoomsTests(LoggedInTestCase):
     def test_rooms_requests(self):
+        self.login_as_admin()
         pages = [
             'web.views.equipment_and_rooms.rooms',
             'web.views.equipment_and_rooms.rooms_add',
@@ -20,7 +21,18 @@ class RoomsTests(LoggedInTestCase):
             response = self.client.get(reverse(page))
             self.assertEqual(response.status_code, 200)
 
+    def test_rooms_requests_without_permission(self):
+        pages = [
+            'web.views.equipment_and_rooms.rooms',
+            'web.views.equipment_and_rooms.rooms_add',
+        ]
+
+        for page in pages:
+            response = self.client.get(reverse(page))
+            self.assertEqual(response.status_code, 302)
+
     def test_rooms_edit_request(self):
+        self.login_as_admin()
         room = create_room()
         page = reverse('web.views.equipment_and_rooms.rooms_edit',
                        kwargs={'room_id': str(room.id)})
@@ -28,6 +40,7 @@ class RoomsTests(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_rooms_delete_request(self):
+        self.login_as_admin()
         room = create_room()
         page = reverse('web.views.equipment_and_rooms.rooms_delete',
                        kwargs={'room_id': str(room.id)})
@@ -35,6 +48,7 @@ class RoomsTests(LoggedInTestCase):
         self.assertEqual(response.status_code, 302)
 
     def test_rooms_add(self):
+        self.login_as_admin()
         page = reverse('web.views.equipment_and_rooms.rooms_add')
         item = create_item()
         data = {
@@ -53,6 +67,7 @@ class RoomsTests(LoggedInTestCase):
         self.assertEqual(len(freshly_created), 1)
 
     def test_rooms_edit(self):
+        self.login_as_admin()
         room = create_room()
         page = reverse('web.views.equipment_and_rooms.rooms_edit',
                        kwargs={'room_id': str(room.id)})
@@ -72,6 +87,7 @@ class RoomsTests(LoggedInTestCase):
             self.assertEqual(getattr(freshly_edited, key, ''), data[key])
 
     def test_rooms_delete(self):
+        self.login_as_admin()
         room = create_room()
         page = reverse('web.views.equipment_and_rooms.rooms_delete',
                        kwargs={'room_id': str(room.id)})
diff --git a/smash/web/tests/view/test_statistics.py b/smash/web/tests/view/test_statistics.py
index 737371076825bc63c5cbbe510da8a156ae5d17a5..aa7fee20b0dcffbe402185e823e885a598ec0850 100644
--- a/smash/web/tests/view/test_statistics.py
+++ b/smash/web/tests/view/test_statistics.py
@@ -10,6 +10,7 @@ __author__ = 'Valentin Grouès'
 
 class TestStatisticsView(LoggedInTestCase):
     def test_statistics_request(self):
+        self.login_as_admin()
         url = reverse('web.views.statistics')
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
@@ -19,3 +20,8 @@ class TestStatisticsView(LoggedInTestCase):
         response = self.client.get(url, {"month": 10, "year": 2017, "subject_type": -1, "visit": -1})
         content = response.content
         self.assertIn('<option value="10" selected>October', content)
+
+    def test_statistics_request_without_permission(self):
+        url = reverse('web.views.statistics')
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 302)
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index 04dd18e6f48f979fb473a0626544776129c86777..66c3b6339e4afecdf3332e273a6f03d4e1c43705 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -52,7 +52,7 @@ def extend_context(params, request):
     else:
         #use full name if available, username otherwise
         if len(request.user.get_full_name()) > 1:
-            person = request.user.get_full_name()  
+            person = request.user.get_full_name()
         else:
             person = request.user.get_username()
         role   = '<No worker information>'
@@ -61,6 +61,7 @@ def extend_context(params, request):
     final_params.update({
         'permissions' : permissions,
         'conf_perms'  : permissions & PermissionDecorator.codename_groups['configuration'],
+        'equipment_perms'  : permissions & PermissionDecorator.codename_groups['equipment'],
         'person': person,
         'role': role,
         'notifications': notifications,
diff --git a/smash/web/views/appointment_type.py b/smash/web/views/appointment_type.py
index 9aa924d1af11b85b9aa54d6a0594866325898277..2637c26ade7f9f8809b8a7ca031368f29142b579 100644
--- a/smash/web/views/appointment_type.py
+++ b/smash/web/views/appointment_type.py
@@ -11,7 +11,7 @@ class AppointmentTypeListView(ListView, WrappedView):
     template_name = 'appointment_types/index.html'
     context_object_name = "appointment_types"
 
-    @PermissionDecorator('change_appointmenttype', 'configuration')
+    @PermissionDecorator('change_appointmenttype', 'equipment')
     def dispatch(self, *args, **kwargs):
         return super(AppointmentTypeListView, self).dispatch(*args, **kwargs)
 
@@ -22,7 +22,7 @@ class AppointmentTypeCreateView(CreateView, WrappedView):
     success_url = reverse_lazy('web.views.appointment_types')
     success_message = "Appointment type created"
 
-    @PermissionDecorator('change_appointmenttype', 'configuration')
+    @PermissionDecorator('change_appointmenttype', 'equipment')
     def dispatch(self, *args, **kwargs):
         return super(AppointmentTypeCreateView, self).dispatch(*args, **kwargs)
 
@@ -34,7 +34,7 @@ class AppointmentTypeEditView(UpdateView, WrappedView):
     template_name = "appointment_types/edit.html"
     context_object_name = "appointment_types"
 
-    @PermissionDecorator('change_appointmenttype', 'configuration')
+    @PermissionDecorator('change_appointmenttype', 'equipment')
     def dispatch(self, *args, **kwargs):
         return super(AppointmentTypeEditView, self).dispatch(*args, **kwargs)
 
@@ -47,6 +47,6 @@ class AppointmentTypeDeleteView(DeleteView, WrappedView):
         messages.success(request, "Appointment Type deleted")
         return super(AppointmentTypeDeleteView, self).delete(request, *args, **kwargs)
 
-    @PermissionDecorator('change_appointmenttype', 'configuration')
+    @PermissionDecorator('change_appointmenttype', 'equipment')
     def dispatch(self, *args, **kwargs):
         return super(AppointmentTypeDeleteView, self).dispatch(*args, **kwargs)
\ No newline at end of file
diff --git a/smash/web/views/daily_planning.py b/smash/web/views/daily_planning.py
index 40ab776c754d5bc3c8b89e8d9e1ec70701669f53..d720816f0672bb455260b5fc3f4a9caa9fc4c2db 100644
--- a/smash/web/views/daily_planning.py
+++ b/smash/web/views/daily_planning.py
@@ -1,12 +1,15 @@
 # coding=utf-8
-import logging
 
 from django.views.generic import TemplateView
-from . import wrap_response
+
+from web.decorators import PermissionDecorator
 from web.models.worker_study_role import STUDY_ROLE_CHOICES
+from . import wrap_response
+
 
 class TemplateDailyPlannerView(TemplateView):
+    @PermissionDecorator('view_daily_planning', 'daily_planning')
     def get(self, request, *args, **kwargs):
         context = self.get_context_data(**kwargs)
         context['worker_study_roles'] = STUDY_ROLE_CHOICES
-        return wrap_response(request, 'daily_planning.html', context)
\ No newline at end of file
+        return wrap_response(request, 'daily_planning.html', context)
diff --git a/smash/web/views/equipment.py b/smash/web/views/equipment.py
index ff498134cab372d0f026c0316f89295d60b83191..4d006e41d3db59e1d8785f6e0d35ddab089cf3d1 100644
--- a/smash/web/views/equipment.py
+++ b/smash/web/views/equipment.py
@@ -1,11 +1,13 @@
 # coding=utf-8
 from django.shortcuts import redirect, get_object_or_404
 
+from web.decorators import PermissionDecorator
 from . import wrap_response
-from ..models import Item
 from ..forms.forms import ItemForm
+from ..models import Item
 
 
+@PermissionDecorator('change_item', 'equipment')
 def equipment(request):
     equipment_list = Item.objects.order_by('-name')
     context = {
@@ -15,6 +17,7 @@ def equipment(request):
     return wrap_response(request, "equipment_and_rooms/equipment/index.html", context)
 
 
+@PermissionDecorator('change_item', 'equipment')
 def equipment_add(request):
     if request.method == 'POST':
         form = ItemForm(request.POST)
@@ -27,6 +30,7 @@ def equipment_add(request):
     return wrap_response(request, 'equipment_and_rooms/equipment/add.html', {'form': form})
 
 
+@PermissionDecorator('change_item', 'equipment')
 def equipment_edit(request, equipment_id):
     the_item = get_object_or_404(Item, id=equipment_id)
     if request.method == 'POST':
@@ -40,6 +44,7 @@ def equipment_edit(request, equipment_id):
     return wrap_response(request, 'equipment_and_rooms/equipment/edit.html', {'form': form})
 
 
+@PermissionDecorator('change_item', 'equipment')
 def equipment_delete(request, equipment_id):
     the_item = get_object_or_404(Item, id=equipment_id)
     the_item.delete()
diff --git a/smash/web/views/export.py b/smash/web/views/export.py
index 02fc1a82c1cb8a61341f3f1c0af9469209da0a0c..1cb6271207a31855a0199c62945cd654e336849a 100644
--- a/smash/web/views/export.py
+++ b/smash/web/views/export.py
@@ -5,10 +5,12 @@ import django_excel as excel
 from django.http import HttpResponse
 
 from notifications import get_today_midnight_date
+from web.decorators import PermissionDecorator
 from . import e500_error, wrap_response
 from ..models import Subject, StudySubject, Appointment
 
 
+@PermissionDecorator('export_subjects', 'subject')
 def export_to_csv(request, data_type="subjects"):
     # Create the HttpResponse object with the appropriate CSV header.
     selected_fields = request.GET.get('fields', None)
@@ -29,6 +31,7 @@ def export_to_csv(request, data_type="subjects"):
     return response
 
 
+@PermissionDecorator('export_subjects', 'subject')
 def export_to_excel(request, data_type="subjects"):
     selected_fields = request.GET.get('fields', None)
     filename = data_type + '-' + get_today_midnight_date().strftime("%Y-%m-%d") + ".xls"
@@ -53,26 +56,27 @@ class CustomField:
 
 DROP_OUT_FIELD = CustomField({'verbose_name': "DROP OUT", 'name': "custom-drop-out"})
 APPOINTMENT_TYPE_FIELD = CustomField({
-        'name': 'appointment_types',
-        'verbose_name': 'Appointment Types'
-    })
+    'name': 'appointment_types',
+    'verbose_name': 'Appointment Types'
+})
 STUDY_SUBJECT_FIELDS = [CustomField({
-        'name': 'nd_number',
-        'verbose_name' : 'ND number'
-    })]
+    'name': 'nd_number',
+    'verbose_name': 'ND number'
+})]
 
 SUBJECT_FIELDS = [CustomField({
-        'name': 'last_name',
-        'verbose_name': 'Family name'
-    }),
+    'name': 'last_name',
+    'verbose_name': 'Family name'
+}),
     CustomField({
         'name': 'first_name',
         'verbose_name': 'Name'
     })]
 VISIT_FIELDS = [CustomField({
-        'name': 'visit_number',
-        'verbose_name': 'Visit'
-    })]
+    'name': 'visit_number',
+    'verbose_name': 'Visit'
+})]
+
 
 def filter_fields_from_selected_fields(fields, selected_fields):
     if selected_fields is None:
@@ -80,6 +84,7 @@ def filter_fields_from_selected_fields(fields, selected_fields):
     selected_fields = set(selected_fields.split(','))
     return [field for field in fields if field.name in selected_fields]
 
+
 def get_default_subject_fields():
     subject_fields = []
     for field in Subject._meta.fields:
@@ -91,12 +96,13 @@ def get_default_subject_fields():
     subject_fields.append(DROP_OUT_FIELD)
     return subject_fields
 
+
 def get_subjects_as_array(selected_fields=None):
     result = []
-    subject_fields = get_default_subject_fields() 
+    subject_fields = get_default_subject_fields()
     subject_fields = filter_fields_from_selected_fields(subject_fields, selected_fields)
 
-    field_names = [field.verbose_name for field in subject_fields] #faster than loop
+    field_names = [field.verbose_name for field in subject_fields]  # faster than loop
     result.append(field_names)
 
     subjects = StudySubject.objects.order_by('-subject__last_name')
@@ -105,6 +111,7 @@ def get_subjects_as_array(selected_fields=None):
         result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row])
     return result
 
+
 def subject_to_row_for_fields(study_subject, subject_fields):
     row = []
     for field in subject_fields:
@@ -128,31 +135,33 @@ def subject_to_row_for_fields(study_subject, subject_fields):
         row.append(cell)
     return row
 
+
 def get_appointment_fields():
     appointments_fields = []
     for field in Appointment._meta.fields:
         if field.name.upper() != "VISIT" and field.name.upper() != "ID" and \
-                        field.name.upper() != "WORKER_ASSIGNED" and field.name.upper() != "APPOINTMENT_TYPES" and \
-                        field.name.upper() != "ROOM" and field.name.upper() != "FLYING_TEAM":
+                field.name.upper() != "WORKER_ASSIGNED" and field.name.upper() != "APPOINTMENT_TYPES" and \
+                field.name.upper() != "ROOM" and field.name.upper() != "FLYING_TEAM":
             appointments_fields.append(field)
 
     all_fields = STUDY_SUBJECT_FIELDS + SUBJECT_FIELDS + VISIT_FIELDS + appointments_fields + [APPOINTMENT_TYPE_FIELD]
 
     return all_fields, appointments_fields
 
+
 def get_appointments_as_array(selected_fields=None):
     result = []
     all_fields, appointments_fields = get_appointment_fields()
     all_fields = filter_fields_from_selected_fields(all_fields, selected_fields)
     appointments_fields = filter_fields_from_selected_fields(appointments_fields, selected_fields)
 
-    field_names = [field.verbose_name for field in all_fields] #faster than loop
+    field_names = [field.verbose_name for field in all_fields]  # faster than loop
     result.append(field_names)
 
     appointments = Appointment.objects.order_by('-datetime_when')
 
     for appointment in appointments:
-        #add field_names ['ND number', 'Family name', 'Name', 'Visit'] first
+        # add field_names ['ND number', 'Family name', 'Name', 'Visit'] first
         row = []
         for field in STUDY_SUBJECT_FIELDS:
             if field.verbose_name in field_names:
@@ -175,15 +184,16 @@ def get_appointments_as_array(selected_fields=None):
         for field in appointments_fields:
             row.append(getattr(appointment, field.name))
         if APPOINTMENT_TYPE_FIELD.verbose_name in field_names:
-            #avoid last comma in the list of appointment types
+            # avoid last comma in the list of appointment types
             type_string = ','.join([appointment_type.code for appointment_type in appointment.appointment_types.all()])
             row.append(type_string)
             result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row])
     return result
 
 
+@PermissionDecorator('export_subjects', 'subject')
 def export(request):
     return wrap_response(request, 'export/index.html', {
         'subject_fields': get_default_subject_fields(),
         'appointment_fields': get_appointment_fields()[0]
-    })
\ No newline at end of file
+    })
diff --git a/smash/web/views/flying_teams.py b/smash/web/views/flying_teams.py
index dc6c4752045cef881778084f6ece845aa259ef2f..b0f5c7b01f0403daf1bea1a4f5c9f69c52b4f03e 100644
--- a/smash/web/views/flying_teams.py
+++ b/smash/web/views/flying_teams.py
@@ -1,11 +1,13 @@
 # coding=utf-8
 from django.shortcuts import redirect, get_object_or_404
 
+from web.decorators import PermissionDecorator
 from . import wrap_response
-from ..models import FlyingTeam
 from ..forms.forms import FlyingTeamAddForm, FlyingTeamEditForm
+from ..models import FlyingTeam
 
 
+@PermissionDecorator('change_flyingteam', 'equipment')
 def flying_teams(request):
     flying_team_list = FlyingTeam.objects.order_by('-place')
     context = {
@@ -16,6 +18,8 @@ def flying_teams(request):
                          "equipment_and_rooms/flying_teams/index.html",
                          context)
 
+
+@PermissionDecorator('change_flyingteam', 'equipment')
 def flying_teams_add(request):
     if request.method == 'POST':
         form = FlyingTeamAddForm(request.POST)
@@ -28,6 +32,7 @@ def flying_teams_add(request):
     return wrap_response(request, 'equipment_and_rooms/flying_teams/add.html', {'form': form})
 
 
+@PermissionDecorator('change_flyingteam', 'equipment')
 def flying_teams_edit(request, flying_team_id):
     the_flying_team = get_object_or_404(FlyingTeam, id=flying_team_id)
     if request.method == 'POST':
diff --git a/smash/web/views/kit.py b/smash/web/views/kit.py
index 79c42ef5fb89430026ceaa05c20e766f7175e7ca..c099d903f2716b474cadbcc60be70ce2f1d376db 100644
--- a/smash/web/views/kit.py
+++ b/smash/web/views/kit.py
@@ -13,6 +13,7 @@ from django_cron import CronJobBase, Schedule
 from django_cron.models import CronJobLog
 
 from notifications import get_filter_locations, get_today_midnight_date
+from web.decorators import PermissionDecorator
 from web.models import ConfigurationItem, Language, Worker
 from web.models.constants import KIT_EMAIL_HOUR_CONFIGURATION_TYPE, \
     KIT_EMAIL_DAY_OF_WEEK_CONFIGURATION_TYPE, CRON_JOB_TIMEOUT
@@ -60,6 +61,7 @@ def get_kit_requests(user, start_date=None, end_date=None):
     return result
 
 
+@PermissionDecorator('send_sample_mail_for_appointments', 'equipment')
 def get_kit_requests_data(request, start_date=None, end_date=None):
     form = KitRequestForm()
     if request.method == 'POST':
@@ -76,6 +78,7 @@ def get_kit_requests_data(request, start_date=None, end_date=None):
     return params
 
 
+@PermissionDecorator('send_sample_mail_for_appointments', 'equipment')
 def kit_requests(request):
     return wrap_response(request, 'equipment_and_rooms/kit_requests/kit_requests.html', get_kit_requests_data(request))
 
@@ -85,7 +88,7 @@ def send_mail(data):
     if data["end_date"] is not None:
         end_date_str = data["end_date"].strftime('%Y-%m-%d')
     title = "Samples between " + \
-        data["start_date"].strftime('%Y-%m-%d') + " and " + end_date_str
+            data["start_date"].strftime('%Y-%m-%d') + " and " + end_date_str
 
     cell_style = "padding: 8px; line-height: 1.42857143; vertical-align: top; " \
                  "font-size: 14px; font-family: 'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif;"
@@ -109,10 +112,10 @@ def send_mail(data):
             row_style = ' background-color: #f9f9f9;'
         email_body += "<tr style='" + row_style + "'>"
         email_body += "<td style='" + cell_style + "'>" + \
-            appointment.datetime_when.strftime('%Y-%m-%d %H:%M') + "</td>"
+                      appointment.datetime_when.strftime('%Y-%m-%d %H:%M') + "</td>"
         if appointment.visit is not None and appointment.visit.subject is not None:
             email_body += "<td style='" + cell_style + "'>" + \
-                appointment.visit.subject.nd_number + "</td>"
+                          appointment.visit.subject.nd_number + "</td>"
         else:
             email_body += "<td style='" + cell_style + "'>" + '-' + "</td>"
         email_body += "<td style='" + cell_style + "'>"
@@ -126,7 +129,7 @@ def send_mail(data):
             location += " (" + unicode(appointment.flying_team) + ")"
         email_body += "<td style='" + cell_style + "'>" + location + "</td>"
         email_body += "<td style='" + cell_style + "'>" + \
-            unicode(appointment.worker_assigned) + "</td>"
+                      unicode(appointment.worker_assigned) + "</td>"
         email_body += "</tr>"
     email_body += "</tbody></table>"
     recipients = ConfigurationItem.objects.get(
@@ -136,6 +139,7 @@ def send_mail(data):
     EmailSender().send_email(title, email_body, recipients, cc_recipients)
 
 
+@PermissionDecorator('send_sample_mail_for_appointments', 'equipment')
 def kit_requests_send_mail(request, start_date, end_date=None):
     data = get_kit_requests_data(request, start_date, end_date)
     try:
diff --git a/smash/web/views/mails.py b/smash/web/views/mails.py
index ef4cf0b3bb6ce05c8ff4f35b0246c0f830ea5171..7b49409c99a1f1fafb6c4600bf16fbd9af6897d2 100644
--- a/smash/web/views/mails.py
+++ b/smash/web/views/mails.py
@@ -9,6 +9,7 @@ from django.urls import reverse_lazy
 from django.views.generic import DeleteView
 from django.views.generic import ListView
 
+from web.decorators import PermissionDecorator
 from web.docx_helper import merge_files
 from . import WrappedView
 from . import wrap_response
@@ -32,7 +33,11 @@ class MailTemplatesListView(ListView, WrappedView):
     context_object_name = "mail_templates"
     template_name = 'mail_templates/list.html'
 
-    def get_context_data(self, **kwargs):
+    @PermissionDecorator('change_mailtemplate', 'mailtemplate')
+    def dispatch(self, *args, **kwargs):
+        return super(MailTemplatesListView, self).dispatch(*args, **kwargs)
+
+    def get_context_data(self, *args, **kwargs):
         context = super(MailTemplatesListView, self).get_context_data()
         context['explanations'] = {"generic": MailTemplate.MAILS_TEMPLATE_GENERIC_TAGS,
                                    "subject": MailTemplate.MAILS_TEMPLATE_SUBJECT_TAGS,
@@ -43,6 +48,7 @@ class MailTemplatesListView(ListView, WrappedView):
         return context
 
 
+@PermissionDecorator('change_mailtemplate', 'mailtemplate')
 def mail_template_add(request):
     if request.method == 'POST':
         form = MailTemplateForm(request.POST, request.FILES)
@@ -59,6 +65,7 @@ def mail_template_add(request):
     return wrap_response(request, 'mail_templates/add.html', {'form': form})
 
 
+@PermissionDecorator('change_mailtemplate', 'mailtemplate')
 def mail_template_edit(request, pk):
     template = get_object_or_404(MailTemplate, pk=pk)
     if request.method == 'POST':
@@ -82,6 +89,7 @@ class MailTemplatesDeleteView(DeleteView, WrappedView):
     success_url = reverse_lazy('web.views.mail_templates')
     template_name = 'mail_templates/confirm_delete.html'
 
+    @PermissionDecorator('change_mailtemplate', 'mailtemplate')
     def delete(self, request, *args, **kwargs):
         messages.success(request, "Template deleted")
         try:
diff --git a/smash/web/views/rooms.py b/smash/web/views/rooms.py
index 2ff626e95a9259a0769bcb7b8e840a40908952bc..a5ca91933a09431edc200fb0febb51cd43fe3134 100644
--- a/smash/web/views/rooms.py
+++ b/smash/web/views/rooms.py
@@ -1,11 +1,13 @@
 # coding=utf-8
 from django.shortcuts import redirect, get_object_or_404
 
+from web.decorators import PermissionDecorator
 from . import wrap_response
 from ..forms.forms import RoomForm
 from ..models import Room
 
 
+@PermissionDecorator('change_room', 'equipment')
 def rooms(request):
     rooms_list = Room.objects.order_by('-city')
     context = {
@@ -17,6 +19,7 @@ def rooms(request):
                          context)
 
 
+@PermissionDecorator('change_room', 'equipment')
 def rooms_add(request):
     if request.method == 'POST':
         form = RoomForm(request.POST)
@@ -29,6 +32,7 @@ def rooms_add(request):
     return wrap_response(request, 'equipment_and_rooms/rooms/add.html', {'form': form})
 
 
+@PermissionDecorator('change_room', 'equipment')
 def rooms_edit(request, room_id):
     the_room = get_object_or_404(Room, id=room_id)
     if request.method == 'POST':
@@ -42,6 +46,7 @@ def rooms_edit(request, room_id):
     return wrap_response(request, 'equipment_and_rooms/rooms/edit.html', {'form': form})
 
 
+@PermissionDecorator('change_room', 'equipment')
 def rooms_delete(request, room_id):
     the_room = get_object_or_404(Room, id=room_id)
     the_room.delete()
diff --git a/smash/web/views/statistics.py b/smash/web/views/statistics.py
index 67bdb79c8784b427bba9526b546661f266eaf10f..b8cd84cc9cb8316a434b6c8dfe438a038a00f126 100644
--- a/smash/web/views/statistics.py
+++ b/smash/web/views/statistics.py
@@ -1,9 +1,11 @@
 # coding=utf-8
+from web.decorators import PermissionDecorator
 from . import wrap_response
 from ..forms import StatisticsForm
 from ..statistics import StatisticsManager, get_previous_year_and_month
 
 
+@PermissionDecorator('view_statistics', 'appointment')
 def statistics(request):
     statistics_manager = StatisticsManager()
     visit_choices = [("-1", "all")]