diff --git a/InvenTree/InvenTree/static/script/inventree/modals.js b/InvenTree/InvenTree/static/script/inventree/modals.js
index 1cb5346a68..80ada1596f 100644
--- a/InvenTree/InvenTree/static/script/inventree/modals.js
+++ b/InvenTree/InvenTree/static/script/inventree/modals.js
@@ -807,7 +807,19 @@ function launchModalForm(url, options = {}) {
}
},
error: function (xhr, ajaxOptions, thrownError) {
+
$(modal).modal('hide');
+
+ // Permission denied!
+ if (xhr.status == 403) {
+ showAlertDialog(
+ "Permission Denied",
+ "You do not have the required permissions to access this function"
+ );
+
+ return;
+ }
+
showAlertDialog('Error requesting form data', renderErrorMessage(xhr));
}
};
diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py
index 3f9bc5b0a9..d940229ebe 100644
--- a/InvenTree/InvenTree/views.py
+++ b/InvenTree/InvenTree/views.py
@@ -13,6 +13,8 @@ from django.template.loader import render_to_string
from django.http import JsonResponse, HttpResponseRedirect
from django.urls import reverse_lazy
+from django.contrib.auth.mixins import PermissionRequiredMixin
+
from django.views import View
from django.views.generic import UpdateView, CreateView, FormView
from django.views.generic.base import TemplateView
@@ -105,12 +107,32 @@ class TreeSerializer(views.APIView):
return JsonResponse(response, safe=False)
-class AjaxMixin(object):
+class AjaxMixin(PermissionRequiredMixin):
""" AjaxMixin provides basic functionality for rendering a Django form to JSON.
Handles jsonResponse rendering, and adds extra data for the modal forms to process
on the client side.
+
+ Any view which inherits the AjaxMixin will need
+ correct permissions set using the 'permission_required' attribute
+
"""
+ # By default, allow *any* permissions
+ permission_required = '*'
+
+ def has_permission(self):
+ """
+ Override the default behaviour of has_permission from PermissionRequiredMixin.
+
+ Basically, if permission_required attribute = '*',
+ no permissions are actually required!
+ """
+
+ if self.permission_required == '*':
+ return True
+ else:
+ return super().has_permission()
+
# By default, point to the modal_form template
# (this can be overridden by a child class)
ajax_template_name = 'modal_form.html'
diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html
index d9764d6e25..915433b055 100644
--- a/InvenTree/build/templates/build/build_base.html
+++ b/InvenTree/build/templates/build/build_base.html
@@ -35,7 +35,7 @@ src="{% static 'img/blank_image.png' %}"
{{ build.quantity }} x {{ build.part.full_name }}
- {% if user.is_staff %}
+ {% if user.is_staff and perms.build.change_build %}
{% endif %}
diff --git a/InvenTree/company/templates/company/company_base.html b/InvenTree/company/templates/company/company_base.html
index edcc817ab3..73ebecf979 100644
--- a/InvenTree/company/templates/company/company_base.html
+++ b/InvenTree/company/templates/company/company_base.html
@@ -23,7 +23,7 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
{{ company.name }}
- {% if user.is_staff %}
+ {% if user.is_staff and perms.company.change_company %}
{% endif %}
diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html
index e047c5607f..036021b12d 100644
--- a/InvenTree/order/templates/order/order_base.html
+++ b/InvenTree/order/templates/order/order_base.html
@@ -22,7 +22,12 @@ src="{% static 'img/blank_image.png' %}"
{% block page_data %}
{% trans "Purchase Order" %} {% purchase_order_status_label order.status large=True %}
-{{ order }}
+
+ {{ order }}
+ {% if user.is_staff and perms.order.change_purchaseorder %}
+
+ {% endif %}
+
{{ order.description }}
diff --git a/InvenTree/order/templates/order/sales_order_base.html b/InvenTree/order/templates/order/sales_order_base.html
index 6028157a22..70505ddccc 100644
--- a/InvenTree/order/templates/order/sales_order_base.html
+++ b/InvenTree/order/templates/order/sales_order_base.html
@@ -32,7 +32,12 @@ src="{% static 'img/blank_image.png' %}"
{% trans "Sales Order" %} {% sales_order_status_label order.status large=True %}
-
{{ order }}
+
+ {{ order }}
+ {% if user.is_staff and perms.order.change_salesorder %}
+
+ {% endif %}
+
{{ order.description }}
-
-
-
+
+
+
diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html
index e5dcd9e24e..1de4976740 100644
--- a/InvenTree/part/templates/part/part_base.html
+++ b/InvenTree/part/templates/part/part_base.html
@@ -28,7 +28,7 @@
{{ part.full_name }}
- {% if user.is_staff %}
+ {% if user.is_staff and perms.part.change_part %}
{% endif %}
{% if not part.active %}
diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html
index c6de4c058f..b3fb9af743 100644
--- a/InvenTree/stock/templates/stock/item_base.html
+++ b/InvenTree/stock/templates/stock/item_base.html
@@ -65,7 +65,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% else %}
{{ item.part.full_name }} × {% decimal item.quantity %}
{% endif %}
-{% if user.is_staff %}
+{% if user.is_staff and perms.stock.change_stockitem %}
{% endif %}
diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html
index 802175ff53..2f319f4925 100644
--- a/InvenTree/stock/templates/stock/location.html
+++ b/InvenTree/stock/templates/stock/location.html
@@ -8,7 +8,7 @@
{% if location %}
{{ location.name }}
- {% if user.is_staff %}
+ {% if user.is_staff and perms.stock.change_stocklocation %}
{% endif %}
diff --git a/InvenTree/templates/stock_table.html b/InvenTree/templates/stock_table.html
index 50d18c6386..c41d2181c9 100644
--- a/InvenTree/templates/stock_table.html
+++ b/InvenTree/templates/stock_table.html
@@ -2,22 +2,24 @@