diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py
index cd8575177a..3cc50bc889 100644
--- a/InvenTree/InvenTree/urls.py
+++ b/InvenTree/InvenTree/urls.py
@@ -43,7 +43,7 @@ from .views import CurrencySettingsView, CurrencyRefreshView
 from .views import AppearanceSelectView, SettingCategorySelectView
 from .views import DynamicJsView
 
-from common.views import SettingEdit
+from common.views import SettingEdit, UserSettingEdit
 
 from .api import InfoView, NotFoundView
 from .api import ActionPluginView
@@ -79,6 +79,7 @@ apipatterns = [
 
 settings_urls = [
 
+    url(r'^usersettings/', SettingsView.as_view(template_name='InvenTree/settings/user_settings.html'), name='settings-user-settings'),
     url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
     url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
     url(r'^i18n/?', include('django.conf.urls.i18n')),
@@ -94,6 +95,7 @@ settings_urls = [
     url(r'^currencies/', CurrencySettingsView.as_view(), name='settings-currencies'),
     url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
 
+    url(r'^(?P<pk>\d+)/edit/user', UserSettingEdit.as_view(), name='user-setting-edit'),
     url(r'^(?P<pk>\d+)/edit/', SettingEdit.as_view(), name='setting-edit'),
 
     # Catch any other urls
diff --git a/InvenTree/common/admin.py b/InvenTree/common/admin.py
index c2da1ddd63..1eda18e869 100644
--- a/InvenTree/common/admin.py
+++ b/InvenTree/common/admin.py
@@ -5,7 +5,7 @@ from django.contrib import admin
 
 from import_export.admin import ImportExportModelAdmin
 
-from .models import InvenTreeSetting
+from .models import InvenTreeSetting, InvenTreeUserSetting
 
 
 class SettingsAdmin(ImportExportModelAdmin):
@@ -13,4 +13,10 @@ class SettingsAdmin(ImportExportModelAdmin):
     list_display = ('key', 'value')
 
 
+class UserSettingsAdmin(ImportExportModelAdmin):
+
+    list_display = ('key', 'value', 'user', )
+
+
 admin.site.register(InvenTreeSetting, SettingsAdmin)
+admin.site.register(InvenTreeUserSetting, UserSettingsAdmin)
diff --git a/InvenTree/common/migrations/0011_auto_20210722_2114.py b/InvenTree/common/migrations/0011_auto_20210722_2114.py
new file mode 100644
index 0000000000..388117f261
--- /dev/null
+++ b/InvenTree/common/migrations/0011_auto_20210722_2114.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.2.4 on 2021-07-22 21:14
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('common', '0010_migrate_currency_setting'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='InvenTreeUserSetting',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('value', models.CharField(blank=True, help_text='Settings value', max_length=200)),
+                ('key', models.CharField(help_text='Settings key (must be unique - case insensitive', max_length=50)),
+                ('user', models.ForeignKey(blank=True, help_text='User', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
+            ],
+            options={
+                'verbose_name': 'InvenTree User Setting',
+                'verbose_name_plural': 'InvenTree User Settings',
+            },
+        ),
+        migrations.AddConstraint(
+            model_name='inventreeusersetting',
+            constraint=models.UniqueConstraint(fields=('key', 'user'), name='unique key and user'),
+        ),
+    ]
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
index a1738bcea9..b97bb539e3 100644
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -11,6 +11,7 @@ import decimal
 import math
 
 from django.db import models, transaction
+from django.contrib.auth.models import User
 from django.db.utils import IntegrityError, OperationalError
 from django.conf import settings
 
@@ -26,7 +27,397 @@ import InvenTree.helpers
 import InvenTree.fields
 
 
-class InvenTreeSetting(models.Model):
+class BaseInvenTreeSetting(models.Model):
+    """
+    An base InvenTreeSetting object is a key:value pair used for storing
+    single values (e.g. one-off settings values).
+    """
+
+    GLOBAL_SETTINGS = {}
+
+    class Meta:
+        abstract = True
+
+    @classmethod
+    def get_setting_name(cls, key):
+        """
+        Return the name of a particular setting.
+
+        If it does not exist, return an empty string.
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            return setting.get('name', '')
+        else:
+            return ''
+
+    @classmethod
+    def get_setting_description(cls, key):
+        """
+        Return the description for a particular setting.
+
+        If it does not exist, return an empty string.
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            return setting.get('description', '')
+        else:
+            return ''
+
+    @classmethod
+    def get_setting_units(cls, key):
+        """
+        Return the units for a particular setting.
+
+        If it does not exist, return an empty string.
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            return setting.get('units', '')
+        else:
+            return ''
+
+    @classmethod
+    def get_setting_validator(cls, key):
+        """
+        Return the validator for a particular setting.
+
+        If it does not exist, return None
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            return setting.get('validator', None)
+        else:
+            return None
+
+    @classmethod
+    def get_setting_default(cls, key):
+        """
+        Return the default value for a particular setting.
+
+        If it does not exist, return an empty string
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            return setting.get('default', '')
+        else:
+            return ''
+
+    @classmethod
+    def get_setting_choices(cls, key):
+        """
+        Return the validator choices available for a particular setting.
+        """
+
+        key = str(key).strip().upper()
+
+        if key in cls.GLOBAL_SETTINGS:
+            setting = cls.GLOBAL_SETTINGS[key]
+            choices = setting.get('choices', None)
+        else:
+            choices = None
+
+        """
+        TODO:
+        if type(choices) is function:
+            # Evaluate the function (we expect it will return a list of tuples...)
+            return choices()
+        """
+
+        return choices
+
+    @classmethod
+    def get_filters(cls, key, **kwargs):
+        return {'key__iexact': key}
+
+    @classmethod
+    def get_setting_object(cls, key, **kwargs):
+        """
+        Return an InvenTreeSetting object matching the given key.
+
+        - Key is case-insensitive
+        - Returns None if no match is made
+        """
+
+        key = str(key).strip().upper()
+
+        try:
+            setting = cls.objects.filter(**cls.get_filters(key, **kwargs)).first()
+        except (ValueError, cls.DoesNotExist):
+            setting = None
+        except (IntegrityError, OperationalError):
+            setting = None
+
+        # Setting does not exist! (Try to create it)
+        if not setting:
+
+            setting = cls(key=key, value=cls.get_setting_default(key), **kwargs)
+
+            try:
+                # Wrap this statement in "atomic", so it can be rolled back if it fails
+                with transaction.atomic():
+                    setting.save()
+            except (IntegrityError, OperationalError):
+                # It might be the case that the database isn't created yet
+                pass
+
+        return setting
+
+    @classmethod
+    def get_setting_pk(cls, key):
+        """
+        Return the primary-key value for a given setting.
+
+        If the setting does not exist, return None
+        """
+
+        setting = cls.get_setting_object(cls)
+
+        if setting:
+            return setting.pk
+        else:
+            return None
+
+    @classmethod
+    def get_setting(cls, key, backup_value=None, **kwargs):
+        """
+        Get the value of a particular setting.
+        If it does not exist, return the backup value (default = None)
+        """
+
+        # If no backup value is specified, atttempt to retrieve a "default" value
+        if backup_value is None:
+            backup_value = cls.get_setting_default(key)
+
+        setting = cls.get_setting_object(key, **kwargs)
+
+        if setting:
+            value = setting.value
+
+            # If the particular setting is defined as a boolean, cast the value to a boolean
+            if setting.is_bool():
+                value = InvenTree.helpers.str2bool(value)
+
+            if setting.is_int():
+                try:
+                    value = int(value)
+                except (ValueError, TypeError):
+                    value = backup_value
+
+        else:
+            value = backup_value
+
+        return value
+
+    @classmethod
+    def set_setting(cls, key, value, change_user, create=True, **kwargs):
+        """
+        Set the value of a particular setting.
+        If it does not exist, option to create it.
+
+        Args:
+            key: settings key
+            value: New value
+            change_user: User object (must be staff member to update a core setting)
+            create: If True, create a new setting if the specified key does not exist.
+        """
+
+        if change_user is not None and not change_user.is_staff:
+            return
+
+        try:
+            setting = cls.objects.get(**cls.get_filters(key, **kwargs))
+        except cls.DoesNotExist:
+
+            if create:
+                setting = cls(key=key, **kwargs)
+            else:
+                return
+
+        # Enforce standard boolean representation
+        if setting.is_bool():
+            value = InvenTree.helpers.str2bool(value)
+
+        setting.value = str(value)
+        setting.save()
+
+    key = models.CharField(max_length=50, blank=False, unique=False, help_text=_('Settings key (must be unique - case insensitive'))
+
+    value = models.CharField(max_length=200, blank=True, unique=False, help_text=_('Settings value'))
+
+    @property
+    def name(self):
+        return self.__class__.get_setting_name(self.key)
+
+    @property
+    def default_value(self):
+        return self.__class__.get_setting_default(self.key)
+
+    @property
+    def description(self):
+        return self.__class__.get_setting_description(self.key)
+
+    @property
+    def units(self):
+        return self.__class__.get_setting_units(self.key)
+
+    def clean(self):
+        """
+        If a validator (or multiple validators) are defined for a particular setting key,
+        run them against the 'value' field.
+        """
+
+        super().clean()
+
+        validator = self.__class__.get_setting_validator(self.key)
+
+        if self.is_bool():
+            self.value = InvenTree.helpers.str2bool(self.value)
+
+        if self.is_int():
+            try:
+                self.value = int(self.value)
+            except (ValueError):
+                raise ValidationError(_('Must be an integer value'))
+
+        if validator is not None:
+            self.run_validator(validator)
+
+    def run_validator(self, validator):
+        """
+        Run a validator against the 'value' field for this InvenTreeSetting object.
+        """
+
+        if validator is None:
+            return
+
+        value = self.value
+
+        # Boolean validator
+        if self.is_bool():
+            # Value must "look like" a boolean value
+            if InvenTree.helpers.is_bool(value):
+                # Coerce into either "True" or "False"
+                value = InvenTree.helpers.str2bool(value)
+            else:
+                raise ValidationError({
+                    'value': _('Value must be a boolean value')
+                })
+
+        # Integer validator
+        if self.is_int():
+
+            try:
+                # Coerce into an integer value
+                value = int(value)
+            except (ValueError, TypeError):
+                raise ValidationError({
+                    'value': _('Value must be an integer value'),
+                })
+
+        # If a list of validators is supplied, iterate through each one
+        if type(validator) in [list, tuple]:
+            for v in validator:
+                self.run_validator(v)
+
+        if callable(validator):
+            # We can accept function validators with a single argument
+            validator(self.value)
+
+    def validate_unique(self, exclude=None, **kwargs):
+        """ Ensure that the key:value pair is unique.
+        In addition to the base validators, this ensures that the 'key'
+        is unique, using a case-insensitive comparison.
+        """
+
+        super().validate_unique(exclude)
+
+        try:
+            setting = self.__class__.objects.exclude(id=self.id).filter(**self.get_filters(self.key, **kwargs))
+            if setting.exists():
+                raise ValidationError({'key': _('Key string must be unique')})
+        except self.DoesNotExist:
+            pass
+
+    def choices(self):
+        """
+        Return the available choices for this setting (or None if no choices are defined)
+        """
+
+        return self.__class__.get_setting_choices(self.key)
+
+    def is_bool(self):
+        """
+        Check if this setting is required to be a boolean value
+        """
+
+        validator = self.__class__.get_setting_validator(self.key)
+
+        if validator == bool:
+            return True
+
+        if type(validator) in [list, tuple]:
+            for v in validator:
+                if v == bool:
+                    return True
+
+    def as_bool(self):
+        """
+        Return the value of this setting converted to a boolean value.
+
+        Warning: Only use on values where is_bool evaluates to true!
+        """
+
+        return InvenTree.helpers.str2bool(self.value)
+
+    def is_int(self):
+        """
+        Check if the setting is required to be an integer value:
+        """
+
+        validator = self.__class__.get_setting_validator(self.key)
+
+        if validator == int:
+            return True
+
+        if type(validator) in [list, tuple]:
+            for v in validator:
+                if v == int:
+                    return True
+
+        return False
+
+    def as_int(self):
+        """
+        Return the value of this setting converted to a boolean value.
+
+        If an error occurs, return the default value
+        """
+
+        try:
+            value = int(self.value)
+        except (ValueError, TypeError):
+            value = self.default_value()
+
+        return value
+
+
+class InvenTreeSetting(BaseInvenTreeSetting):
     """
     An InvenTreeSetting object is a key:value pair used for storing
     single values (e.g. one-off settings values).
@@ -362,379 +753,144 @@ class InvenTreeSetting(models.Model):
         verbose_name = "InvenTree Setting"
         verbose_name_plural = "InvenTree Settings"
 
-    @classmethod
-    def get_setting_name(cls, key):
-        """
-        Return the name of a particular setting.
+    key = models.CharField(
+        max_length=50,
+        blank=False,
+        unique=True,
+        help_text=_('Settings key (must be unique - case insensitive'),
+    )
 
-        If it does not exist, return an empty string.
-        """
 
-        key = str(key).strip().upper()
+class InvenTreeUserSetting(BaseInvenTreeSetting):
+    """
+    An InvenTreeSetting object with a usercontext
+    """
 
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            return setting.get('name', '')
-        else:
-            return ''
+    GLOBAL_SETTINGS = {
+        'HOMEPAGE_PART_STARRED': {
+            'name': _('Show starred parts'),
+            'description': _('Show starred parts on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_PART_LATEST': {
+            'name': _('Show latest parts'),
+            'description': _('Show latest parts on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_BOM_VALIDATION': {
+            'name': _('Show unvalidated BOMs'),
+            'description': _('Show BOMs that await validation on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_RECENT': {
+            'name': _('Show recent stock changes'),
+            'description': _('Show recently changed stock items on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_LOW': {
+            'name': _('Show low stock'),
+            'description': _('Show low stock items on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_DEPLETED': {
+            'name': _('Show depleted stock'),
+            'description': _('Show depleted stock items on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_NEEDED': {
+            'name': _('Show needed stock'),
+            'description': _('Show stock items needed for builds on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_EXPIRED': {
+            'name': _('Show expired stock'),
+            'description': _('Show expired stock items on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_STOCK_STALE': {
+            'name': _('Show stale stock'),
+            'description': _('Show stale stock items on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_BUILD_PENDING': {
+            'name': _('Show pending builds'),
+            'description': _('Show pending builds on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_BUILD_OVERDUE': {
+            'name': _('Show overdue builds'),
+            'description': _('Show overdue builds on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_PO_OUTSTANDING': {
+            'name': _('Show outstanding POs'),
+            'description': _('Show outstanding POs on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_PO_OVERDUE': {
+            'name': _('Show overdue POs'),
+            'description': _('Show overdue POs on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_SO_OUTSTANDING': {
+            'name': _('Show outstanding SOs'),
+            'description': _('Show outstanding SOs on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+        'HOMEPAGE_SO_OVERDUE': {
+            'name': _('Show overdue SOs'),
+            'description': _('Show overdue SOs on the homepage'),
+            'default': True,
+            'validator': bool,
+        },
+    }
+
+    class Meta:
+        verbose_name = "InvenTree User Setting"
+        verbose_name_plural = "InvenTree User Settings"
+        constraints = [
+            models.UniqueConstraint(fields=['key', 'user'], name='unique key and user')
+        ]
+
+    key = models.CharField(
+        max_length=50,
+        blank=False,
+        unique=False,
+        help_text=_('Settings key (must be unique - case insensitive'),
+    )
+
+    user = models.ForeignKey(
+        User,
+        on_delete=models.CASCADE,
+        blank=True, null=True,
+        verbose_name=_('User'),
+        help_text=_('User'),
+    )
 
     @classmethod
-    def get_setting_description(cls, key):
-        """
-        Return the description for a particular setting.
-
-        If it does not exist, return an empty string.
-        """
-
-        key = str(key).strip().upper()
-
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            return setting.get('description', '')
-        else:
-            return ''
-
-    @classmethod
-    def get_setting_units(cls, key):
-        """
-        Return the units for a particular setting.
-
-        If it does not exist, return an empty string.
-        """
-
-        key = str(key).strip().upper()
-
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            return setting.get('units', '')
-        else:
-            return ''
-
-    @classmethod
-    def get_setting_validator(cls, key):
-        """
-        Return the validator for a particular setting.
-
-        If it does not exist, return None
-        """
-
-        key = str(key).strip().upper()
-
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            return setting.get('validator', None)
-        else:
-            return None
-
-    @classmethod
-    def get_setting_default(cls, key):
-        """
-        Return the default value for a particular setting.
-
-        If it does not exist, return an empty string
-        """
-
-        key = str(key).strip().upper()
-
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            return setting.get('default', '')
-        else:
-            return ''
-
-    @classmethod
-    def get_setting_choices(cls, key):
-        """
-        Return the validator choices available for a particular setting.
-        """
-
-        key = str(key).strip().upper()
-
-        if key in cls.GLOBAL_SETTINGS:
-            setting = cls.GLOBAL_SETTINGS[key]
-            choices = setting.get('choices', None)
-        else:
-            choices = None
-
-        """
-        TODO:
-        if type(choices) is function:
-            # Evaluate the function (we expect it will return a list of tuples...)
-            return choices()
-        """
-
-        return choices
-
-    @classmethod
-    def get_setting_object(cls, key):
-        """
-        Return an InvenTreeSetting object matching the given key.
-
-        - Key is case-insensitive
-        - Returns None if no match is made
-        """
-
-        key = str(key).strip().upper()
-
-        try:
-            setting = InvenTreeSetting.objects.filter(key__iexact=key).first()
-        except (ValueError, InvenTreeSetting.DoesNotExist):
-            setting = None
-        except (IntegrityError, OperationalError):
-            setting = None
-
-        # Setting does not exist! (Try to create it)
-        if not setting:
-
-            setting = InvenTreeSetting(key=key, value=InvenTreeSetting.get_setting_default(key))
-
-            try:
-                # Wrap this statement in "atomic", so it can be rolled back if it fails
-                with transaction.atomic():
-                    setting.save()
-            except (IntegrityError, OperationalError):
-                # It might be the case that the database isn't created yet
-                pass
-
-        return setting
-
-    @classmethod
-    def get_setting_pk(cls, key):
-        """
-        Return the primary-key value for a given setting.
-
-        If the setting does not exist, return None
-        """
-
-        setting = InvenTreeSetting.get_setting_object(cls)
-
-        if setting:
-            return setting.pk
-        else:
-            return None
-
-    @classmethod
-    def get_setting(cls, key, backup_value=None):
-        """
-        Get the value of a particular setting.
-        If it does not exist, return the backup value (default = None)
-        """
-
-        # If no backup value is specified, atttempt to retrieve a "default" value
-        if backup_value is None:
-            backup_value = cls.get_setting_default(key)
-
-        setting = InvenTreeSetting.get_setting_object(key)
-
-        if setting:
-            value = setting.value
-
-            # If the particular setting is defined as a boolean, cast the value to a boolean
-            if setting.is_bool():
-                value = InvenTree.helpers.str2bool(value)
-
-            if setting.is_int():
-                try:
-                    value = int(value)
-                except (ValueError, TypeError):
-                    value = backup_value
-
-        else:
-            value = backup_value
-
-        return value
-
-    @classmethod
-    def set_setting(cls, key, value, user, create=True):
-        """
-        Set the value of a particular setting.
-        If it does not exist, option to create it.
-
-        Args:
-            key: settings key
-            value: New value
-            user: User object (must be staff member to update a core setting)
-            create: If True, create a new setting if the specified key does not exist.
-        """
-
-        if user is not None and not user.is_staff:
-            return
-
-        try:
-            setting = InvenTreeSetting.objects.get(key__iexact=key)
-        except InvenTreeSetting.DoesNotExist:
-
-            if create:
-                setting = InvenTreeSetting(key=key)
-            else:
-                return
-
-        # Enforce standard boolean representation
-        if setting.is_bool():
-            value = InvenTree.helpers.str2bool(value)
-
-        setting.value = str(value)
-        setting.save()
-
-    key = models.CharField(max_length=50, blank=False, unique=True, help_text=_('Settings key (must be unique - case insensitive'))
-
-    value = models.CharField(max_length=200, blank=True, unique=False, help_text=_('Settings value'))
-
-    @property
-    def name(self):
-        return InvenTreeSetting.get_setting_name(self.key)
-
-    @property
-    def default_value(self):
-        return InvenTreeSetting.get_setting_default(self.key)
-
-    @property
-    def description(self):
-        return InvenTreeSetting.get_setting_description(self.key)
-
-    @property
-    def units(self):
-        return InvenTreeSetting.get_setting_units(self.key)
-
-    def clean(self):
-        """
-        If a validator (or multiple validators) are defined for a particular setting key,
-        run them against the 'value' field.
-        """
-
-        super().clean()
-
-        validator = InvenTreeSetting.get_setting_validator(self.key)
-
-        if self.is_bool():
-            self.value = InvenTree.helpers.str2bool(self.value)
-
-        if self.is_int():
-            try:
-                self.value = int(self.value)
-            except (ValueError):
-                raise ValidationError(_('Must be an integer value'))
-
-        if validator is not None:
-            self.run_validator(validator)
-
-    def run_validator(self, validator):
-        """
-        Run a validator against the 'value' field for this InvenTreeSetting object.
-        """
-
-        if validator is None:
-            return
-
-        value = self.value
-
-        # Boolean validator
-        if self.is_bool():
-            # Value must "look like" a boolean value
-            if InvenTree.helpers.is_bool(value):
-                # Coerce into either "True" or "False"
-                value = InvenTree.helpers.str2bool(value)
-            else:
-                raise ValidationError({
-                    'value': _('Value must be a boolean value')
-                })
-
-        # Integer validator
-        if self.is_int():
-
-            try:
-                # Coerce into an integer value
-                value = int(value)
-            except (ValueError, TypeError):
-                raise ValidationError({
-                    'value': _('Value must be an integer value'),
-                })
-
-        # If a list of validators is supplied, iterate through each one
-        if type(validator) in [list, tuple]:
-            for v in validator:
-                self.run_validator(v)
-
-        if callable(validator):
-            # We can accept function validators with a single argument
-            validator(self.value)
+    def get_setting_object(cls, key, user):
+        return super().get_setting_object(key, user=user)
 
     def validate_unique(self, exclude=None):
-        """ Ensure that the key:value pair is unique.
-        In addition to the base validators, this ensures that the 'key'
-        is unique, using a case-insensitive comparison.
-        """
+        return super().validate_unique(exclude=exclude, user=self.user)
 
-        super().validate_unique(exclude)
-
-        try:
-            setting = InvenTreeSetting.objects.exclude(id=self.id).filter(key__iexact=self.key)
-            if setting.exists():
-                raise ValidationError({'key': _('Key string must be unique')})
-        except InvenTreeSetting.DoesNotExist:
-            pass
-
-    def choices(self):
-        """
-        Return the available choices for this setting (or None if no choices are defined)
-        """
-
-        return InvenTreeSetting.get_setting_choices(self.key)
-
-    def is_bool(self):
-        """
-        Check if this setting is required to be a boolean value
-        """
-
-        validator = InvenTreeSetting.get_setting_validator(self.key)
-
-        if validator == bool:
-            return True
-
-        if type(validator) in [list, tuple]:
-            for v in validator:
-                if v == bool:
-                    return True
-
-    def as_bool(self):
-        """
-        Return the value of this setting converted to a boolean value.
-
-        Warning: Only use on values where is_bool evaluates to true!
-        """
-
-        return InvenTree.helpers.str2bool(self.value)
-
-    def is_int(self):
-        """
-        Check if the setting is required to be an integer value:
-        """
-
-        validator = InvenTreeSetting.get_setting_validator(self.key)
-
-        if validator == int:
-            return True
-
-        if type(validator) in [list, tuple]:
-            for v in validator:
-                if v == int:
-                    return True
-
-        return False
-
-    def as_int(self):
-        """
-        Return the value of this setting converted to a boolean value.
-
-        If an error occurs, return the default value
-        """
-
-        try:
-            value = int(self.value)
-        except (ValueError, TypeError):
-            value = self.default_value()
-
-        return value
+    @classmethod
+    def get_filters(cls, key, **kwargs):
+        return {'key__iexact': key, 'user__id__iexact': kwargs['user'].id}
 
 
 class PriceBreak(models.Model):
diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py
index f953dffa81..75fc78b4e3 100644
--- a/InvenTree/common/views.py
+++ b/InvenTree/common/views.py
@@ -45,8 +45,8 @@ class SettingEdit(AjaxUpdateView):
 
         ctx['key'] = setting.key
         ctx['value'] = setting.value
-        ctx['name'] = models.InvenTreeSetting.get_setting_name(setting.key)
-        ctx['description'] = models.InvenTreeSetting.get_setting_description(setting.key)
+        ctx['name'] = self.model.get_setting_name(setting.key)
+        ctx['description'] = self.model.get_setting_description(setting.key)
 
         return ctx
 
@@ -69,12 +69,12 @@ class SettingEdit(AjaxUpdateView):
             self.object.value = str2bool(setting.value)
             form.fields['value'].value = str2bool(setting.value)
 
-        name = models.InvenTreeSetting.get_setting_name(setting.key)
+        name = self.model.get_setting_name(setting.key)
 
         if name:
             form.fields['value'].label = name
 
-        description = models.InvenTreeSetting.get_setting_description(setting.key)
+        description = self.model.get_setting_description(setting.key)
 
         if description:
             form.fields['value'].help_text = description
@@ -111,6 +111,18 @@ class SettingEdit(AjaxUpdateView):
                 form.add_error('value', _('Supplied value must be a boolean'))
 
 
+class UserSettingEdit(SettingEdit):
+    """
+    View for editing an InvenTree key:value user  settings object,
+    (or creating it if the key does not already exist)
+    """
+
+    model = models.InvenTreeUserSetting
+    ajax_form_title = _('Change User Setting')
+    form_class = forms.SettingEditForm
+    ajax_template_name = "common/edit_setting.html"
+
+
 class MultiStepFormView(SessionWizardView):
     """ Setup basic methods of multi-step form
 
diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py
index 38689df26b..a7887ec250 100644
--- a/InvenTree/part/templatetags/inventree_extras.py
+++ b/InvenTree/part/templatetags/inventree_extras.py
@@ -18,7 +18,7 @@ from InvenTree import version, settings
 
 import InvenTree.helpers
 
-from common.models import InvenTreeSetting, ColorTheme
+from common.models import InvenTreeSetting, ColorTheme, InvenTreeUserSetting
 from common.settings import currency_code_default
 
 register = template.Library()
@@ -69,6 +69,12 @@ def add(x, y, *args, **kwargs):
     return x + y
 
 
+@register.simple_tag()
+def to_list(*args):
+    """ Return the input arguments as list """
+    return args
+
+
 @register.simple_tag()
 def part_allocation_count(build, part, *args, **kwargs):
     """ Return the total number of <part> allocated to <build> """
@@ -182,11 +188,12 @@ def setting_object(key, *args, **kwargs):
     """
     Return a setting object speciifed by the given key
     (Or return None if the setting does not exist)
+    if a user-setting was requested return that
     """
 
-    setting = InvenTreeSetting.get_setting_object(key)
-
-    return setting
+    if 'user' in kwargs:
+        return InvenTreeUserSetting.get_setting_object(key, user=kwargs['user'])
+    return InvenTreeSetting.get_setting_object(key)
 
 
 @register.simple_tag()
@@ -195,6 +202,8 @@ def settings_value(key, *args, **kwargs):
     Return a settings value specified by the given key
     """
 
+    if 'user' in kwargs:
+        return InvenTreeUserSetting.get_setting(key, user=kwargs['user'])
     return InvenTreeSetting.get_setting(key)
 
 
diff --git a/InvenTree/templates/InvenTree/index.html b/InvenTree/templates/InvenTree/index.html
index a3d793dd26..ee08777502 100644
--- a/InvenTree/templates/InvenTree/index.html
+++ b/InvenTree/templates/InvenTree/index.html
@@ -93,13 +93,26 @@ function addHeaderAction(label, title, icon, options) {
     });
 }
 
-{% if roles.part.view %}
+{% settings_value 'HOMEPAGE_PART_STARRED' user=request.user as setting_part_starred %}
+{% settings_value 'HOMEPAGE_PART_LATEST' user=request.user as setting_part_latest %}
+{% settings_value 'HOMEPAGE_BOM_VALIDATION' user=request.user as setting_bom_validation %}
+{% to_list setting_part_starred setting_part_latest setting_bom_validation as settings_list_part %}
+
+{% if roles.part.view and True in settings_list_part %}
 addHeaderTitle('{% trans "Parts" %}');
+
+{% if setting_part_starred %}
 addHeaderAction('starred-parts', '{% trans "Starred Parts" %}', 'fa-star');
+loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", {
+    params: {
+        "starred": true,
+    },
+    name: 'starred_parts',
+});
+{% endif %}
+
+{% if setting_part_latest %}
 addHeaderAction('latest-parts', '{% trans "Latest Parts" %}', 'fa-newspaper');
-addHeaderAction('bom-validation', '{% trans "BOM Waiting Validation" %}', 'fa-times-circle');
-
-
 loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
     params: {
         ordering: "-creation_date",
@@ -107,30 +120,37 @@ loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", {
     },
     name: 'latest_parts',
 });
+{% endif %}
 
-loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", {
-    params: {
-        "starred": true,
-    },
-    name: 'starred_parts',
-});
-
+{% if setting_bom_validation %}
+addHeaderAction('bom-validation', '{% trans "BOM Waiting Validation" %}', 'fa-times-circle');
 loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", {
     params: {
         "bom_valid": false,
     },
     name: 'bom_invalid_parts',
 });
-
+{% endif %}
 {% endif %}
 
-{% if roles.stock.view %}
-addHeaderTitle('{% trans "Stock" %}');
-addHeaderAction('recently-updated-stock', '{% trans "Recently Updated" %}', 'fa-clock');
-addHeaderAction('low-stock', '{% trans "Low Stock" %}', 'fa-shopping-cart');
-addHeaderAction('depleted-stock', '{% trans "Depleted Stock" %}', 'fa-times');
-addHeaderAction('stock-to-build', '{% trans "Required for Build Orders" %}', 'fa-bullhorn');
+{% settings_value 'HOMEPAGE_STOCK_RECENT' user=request.user as setting_stock_recent %}
+{% settings_value 'HOMEPAGE_STOCK_LOW' user=request.user as setting_stock_low %}
+{% settings_value 'HOMEPAGE_STOCK_DEPLETED' user=request.user as setting_stock_depleted %}
+{% settings_value 'HOMEPAGE_STOCK_NEEDED' user=request.user as setting_stock_needed %}
+{% settings_value "STOCK_ENABLE_EXPIRY" as expiry %}
+{% if expiry %}
+{% settings_value 'HOMEPAGE_STOCK_EXPIRED' user=request.user as setting_stock_expired %}
+{% settings_value 'HOMEPAGE_STOCK_STALE' user=request.user as setting_stock_stale %}
+{% to_list setting_stock_recent setting_stock_low setting_stock_depleted setting_stock_needed setting_stock_expired setting_stock_stale as settings_list_stock %}
+{% else %}
+{% to_list setting_stock_recent setting_stock_low setting_stock_depleted setting_stock_needed as settings_list_stock %}
+{% endif %}
 
+{% if roles.stock.view and True in settings_list_stock %}
+addHeaderTitle('{% trans "Stock" %}');
+
+{% if setting_stock_recent %}
+addHeaderAction('recently-updated-stock', '{% trans "Recently Updated" %}', 'fa-clock');
 loadStockTable($('#table-recently-updated-stock'), {
     params: {
         part_detail: true,
@@ -140,12 +160,43 @@ loadStockTable($('#table-recently-updated-stock'), {
     name: 'recently-updated-stock',
     grouping: false,
 });
+{% endif %}
+
+{% if setting_stock_low %}
+addHeaderAction('low-stock', '{% trans "Low Stock" %}', 'fa-shopping-cart');
+loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", {
+    params: {
+        low_stock: true,
+    },
+    name: "low_stock_parts",
+});
+{% endif %}
+
+{% if setting_stock_depleted %}
+addHeaderAction('depleted-stock', '{% trans "Depleted Stock" %}', 'fa-times');
+loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", {
+    params: {
+        depleted_stock: true,
+    },
+    name: "depleted_stock_parts",
+});
+{% endif %}
+
+{% if setting_stock_needed %}
+addHeaderAction('stock-to-build', '{% trans "Required for Build Orders" %}', 'fa-bullhorn');
+loadSimplePartTable("#table-stock-to-build", "{% url 'api-part-list' %}", {
+    params: {
+        stock_to_build: true,
+    },
+    name: "to_build_parts",
+});
+{% endif %}
+
 
-{% settings_value "STOCK_ENABLE_EXPIRY" as expiry %}
 {% if expiry %}
-addHeaderAction('expired-stock', '{% trans "Expired Stock" %}', 'fa-calendar-times');
-addHeaderAction('stale-stock', '{% trans "Stale Stock" %}', 'fa-stopwatch');
 
+{% if setting_stock_expired %}
+addHeaderAction('expired-stock', '{% trans "Expired Stock" %}', 'fa-calendar-times');
 loadStockTable($("#table-expired-stock"), {
     params: {
         expired: true,
@@ -153,7 +204,10 @@ loadStockTable($("#table-expired-stock"), {
         part_detail: true,
     },
 });
+{% endif %}
 
+{% if setting_stock_stale %}
+addHeaderAction('stale-stock', '{% trans "Stale Stock" %}', 'fa-stopwatch');
 loadStockTable($("#table-stale-stock"), {
     params: {
         stale: true,
@@ -164,34 +218,18 @@ loadStockTable($("#table-stale-stock"), {
 });
 {% endif %}
 
-loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", {
-    params: {
-        low_stock: true,
-    },
-    name: "low_stock_parts",
-});
-
-loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", {
-    params: {
-        depleted_stock: true,
-    },
-    name: "depleted_stock_parts",
-});
-
-loadSimplePartTable("#table-stock-to-build", "{% url 'api-part-list' %}", {
-    params: {
-        stock_to_build: true,
-    },
-    name: "to_build_parts",
-});
-
+{% endif %}
 {% endif %}
 
-{% if roles.build.view %}
-addHeaderTitle('{% trans "Build Orders" %}');
-addHeaderAction('build-pending', '{% trans "Build Orders In Progress" %}', 'fa-cogs');
-addHeaderAction('build-overdue', '{% trans "Overdue Build Orders" %}', 'fa-calendar-times');
+{% settings_value 'HOMEPAGE_BUILD_PENDING' user=request.user as setting_build_pending %}
+{% settings_value 'HOMEPAGE_BUILD_OVERDUE' user=request.user as setting_build_overdue %}
+{% to_list setting_build_pending setting_build_overdue as settings_list_build %}
 
+{% if roles.build.view and True in settings_list_build %}
+addHeaderTitle('{% trans "Build Orders" %}');
+
+{% if setting_build_pending %}
+addHeaderAction('build-pending', '{% trans "Build Orders In Progress" %}', 'fa-cogs');
 loadBuildTable("#table-build-pending", {
     url: "{% url 'api-build-list' %}",
     params: {
@@ -199,7 +237,10 @@ loadBuildTable("#table-build-pending", {
     },
     disableFilters: true,
 });
+{% endif %}
 
+{% if setting_build_overdue %}
+addHeaderAction('build-overdue', '{% trans "Overdue Build Orders" %}', 'fa-calendar-times');
 loadBuildTable("#table-build-overdue", {
     url: "{% url 'api-build-list' %}",
     params: {
@@ -209,11 +250,17 @@ loadBuildTable("#table-build-overdue", {
 });
 {% endif %}
 
-{% if roles.purchase_order.view %}
-addHeaderTitle('{% trans "Purchase Orders" %}');
-addHeaderAction('po-outstanding', '{% trans "Outstanding Purchase Orders" %}', 'fa-sign-in-alt');
-addHeaderAction('po-overdue', '{% trans "Overdue Purchase Orders" %}', 'fa-calendar-times');
+{% endif %}
 
+{% settings_value 'HOMEPAGE_PO_OUTSTANDING' user=request.user as setting_po_outstanding %}
+{% settings_value 'HOMEPAGE_PO_OVERDUE' user=request.user as setting_po_overdue %}
+{% to_list setting_po_outstanding setting_po_overdue as settings_list_po %}
+
+{% if roles.purchase_order.view and True in settings_list_po %}
+addHeaderTitle('{% trans "Purchase Orders" %}');
+
+{% if setting_po_outstanding %}
+addHeaderAction('po-outstanding', '{% trans "Outstanding Purchase Orders" %}', 'fa-sign-in-alt');
 loadPurchaseOrderTable("#table-po-outstanding", {
     url: "{% url 'api-po-list' %}",
     params: {
@@ -221,7 +268,10 @@ loadPurchaseOrderTable("#table-po-outstanding", {
         outstanding: true,
     }
 });
+{% endif %}
 
+{% if setting_po_overdue %}
+addHeaderAction('po-overdue', '{% trans "Overdue Purchase Orders" %}', 'fa-calendar-times');
 loadPurchaseOrderTable("#table-po-overdue", {
     url: "{% url 'api-po-list' %}",
     params: {
@@ -229,14 +279,19 @@ loadPurchaseOrderTable("#table-po-overdue", {
         overdue: true,
     }
 });
+{% endif %}
 
 {% endif %}
 
-{% if roles.sales_order.view %}
-addHeaderTitle('{% trans "Sales Orders" %}');
-addHeaderAction('so-outstanding', '{% trans "Outstanding Sales Orders" %}', 'fa-sign-out-alt');
-addHeaderAction('so-overdue', '{% trans "Overdue Sales Orders" %}', 'fa-calendar-times');
+{% settings_value 'HOMEPAGE_SO_OUTSTANDING' user=request.user as setting_so_outstanding %}
+{% settings_value 'HOMEPAGE_SO_OVERDUE' user=request.user as setting_so_overdue %}
+{% to_list setting_so_outstanding setting_so_overdue as settings_list_so %}
 
+{% if roles.sales_order.view and True in settings_list_so %}
+addHeaderTitle('{% trans "Sales Orders" %}');
+
+{% if setting_so_outstanding %}
+addHeaderAction('so-outstanding', '{% trans "Outstanding Sales Orders" %}', 'fa-sign-out-alt');
 loadSalesOrderTable("#table-so-outstanding", {
     url: "{% url 'api-so-list' %}",
     params: {
@@ -244,7 +299,10 @@ loadSalesOrderTable("#table-so-outstanding", {
         outstanding: true,
     },
 });
+{% endif %}
 
+{% if setting_so_overdue %}
+addHeaderAction('so-overdue', '{% trans "Overdue Sales Orders" %}', 'fa-calendar-times');
 loadSalesOrderTable("#table-so-overdue", {
     url: "{% url 'api-so-list' %}",
     params: {
@@ -252,6 +310,7 @@ loadSalesOrderTable("#table-so-overdue", {
         customer_detail: true,
     }
 });
+{% endif %}
 
 {% endif %}
 
diff --git a/InvenTree/templates/InvenTree/settings/appearance.html b/InvenTree/templates/InvenTree/settings/appearance.html
index 8cd7a8d2db..d0b414e423 100644
--- a/InvenTree/templates/InvenTree/settings/appearance.html
+++ b/InvenTree/templates/InvenTree/settings/appearance.html
@@ -62,6 +62,4 @@
         </div>
     </form>
 </div>
-
-
 {% endblock %}
diff --git a/InvenTree/templates/InvenTree/settings/setting.html b/InvenTree/templates/InvenTree/settings/setting.html
index 7376adf8d9..66f3f9f3b0 100644
--- a/InvenTree/templates/InvenTree/settings/setting.html
+++ b/InvenTree/templates/InvenTree/settings/setting.html
@@ -1,7 +1,12 @@
 {% load inventree_extras %}
 {% load i18n %}
 
-{% setting_object key as setting %}
+{% if user_setting %}
+    {% setting_object key user=request.user as setting %}
+{% else %}
+    {% setting_object key as setting %}
+{% endif %}
+
 <tr>
     <td>
         {% if icon %}
@@ -28,7 +33,7 @@
     </td>
     <td>
         <div class='btn-group float-right'>
-            <button class='btn btn-default btn-glyph btn-edit-setting' pk='{{ setting.pk }}' setting='{{ key }}' title='{% trans "Edit setting" %}'>
+            <button class='btn btn-default btn-glyph btn-edit-setting' pk='{{ setting.pk }}' setting='{{ key }}' title='{% trans "Edit setting" %}' {% if user_setting %}user='{{request.user.id}}'{% endif %}>
                 <span class='fas fa-edit icon-green'></span>
             </button>
         </div>
diff --git a/InvenTree/templates/InvenTree/settings/settings.html b/InvenTree/templates/InvenTree/settings/settings.html
index 25ae5d24b2..03cf276594 100644
--- a/InvenTree/templates/InvenTree/settings/settings.html
+++ b/InvenTree/templates/InvenTree/settings/settings.html
@@ -45,9 +45,14 @@
 $('table').find('.btn-edit-setting').click(function() {
     var setting = $(this).attr('setting');
     var pk = $(this).attr('pk');
+    var url = `/settings/${pk}/edit/`;
+
+    if ($(this).attr('user')){
+        url += `user/`;
+    }
 
     launchModalForm(
-        `/settings/${pk}/edit/`,
+        url,
         {
             reload: true,
         }
diff --git a/InvenTree/templates/InvenTree/settings/tabs.html b/InvenTree/templates/InvenTree/settings/tabs.html
index 86a88b68f0..846dfccd23 100644
--- a/InvenTree/templates/InvenTree/settings/tabs.html
+++ b/InvenTree/templates/InvenTree/settings/tabs.html
@@ -8,6 +8,9 @@
     <li{% ifequal tab 'theme' %} class='active'{% endifequal %}>
         <a href="{% url 'settings-appearance' %}"><span class='fas fa-fill'></span> {% trans "Appearance" %}</a>
     </li>
+    <li{% ifequal tab 'user_settings' %} class='active'{% endifequal %}>
+        <a href="{% url 'settings-user-settings' %}"><span class='fas fa-cog'></span> {% trans "User Settings" %}</a>
+    </li>
 </ul>
 {% if user.is_staff %}
 <h4><span class='fas fa-cogs'></span> {% trans "InvenTree Settings" %}</h4>
diff --git a/InvenTree/templates/InvenTree/settings/user_settings.html b/InvenTree/templates/InvenTree/settings/user_settings.html
new file mode 100644
index 0000000000..0b76b930c5
--- /dev/null
+++ b/InvenTree/templates/InvenTree/settings/user_settings.html
@@ -0,0 +1,41 @@
+{% extends "InvenTree/settings/settings.html" %}
+{% load i18n %}
+{% load inventree_extras %}
+
+{% block tabs %}
+{% include "InvenTree/settings/tabs.html" with tab='user_settings' %}
+{% endblock %}
+
+{% block subtitle %}
+{% trans "User Settings" %}
+{% endblock %}
+
+{% block settings %}
+
+<div class='row'>
+    <table class='table table-striped table-condensed'>
+        {% include "InvenTree/settings/header.html" %}
+        <tbody>
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PART_STARRED" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PART_LATEST" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BOM_VALIDATION" user_setting=True %}
+            <tr><td colspan='5'></td></tr>
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_RECENT" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_LOW" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_DEPLETED" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_NEEDED" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_EXPIRED" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_STOCK_STALE" user_setting=True %}
+            <tr><td colspan='5'></td></tr>
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_PENDING" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_BUILD_OVERDUE" user_setting=True %}
+            <tr><td colspan='5'></td></tr>
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OUTSTANDING" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_PO_OVERDUE" user_setting=True %}
+            <tr><td colspan='5'></td></tr>
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OUTSTANDING" user_setting=True %}
+            {% include "InvenTree/settings/setting.html" with key="HOMEPAGE_SO_OVERDUE" user_setting=True %}
+        </tbody>
+    </table>
+</div>
+{% endblock %}
diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py
index 73bc5b6695..179a70ed74 100644
--- a/InvenTree/users/models.py
+++ b/InvenTree/users/models.py
@@ -141,6 +141,7 @@ class RuleSet(models.Model):
         # Models which currently do not require permissions
         'common_colortheme',
         'common_inventreesetting',
+        'common_inventreeusersetting',
         'company_contact',
         'users_owner',