diff --git a/InvenTree/InvenTree/api.py b/InvenTree/InvenTree/api.py index 38a3d559a05..ff2a489c5f4 100644 --- a/InvenTree/InvenTree/api.py +++ b/InvenTree/InvenTree/api.py @@ -11,6 +11,7 @@ from rest_framework.serializers import ValidationError from InvenTree.mixins import ListCreateAPI +from InvenTree.permissions import RolePermission from .status import is_worker_running from .version import (inventreeApiVersion, inventreeInstanceName, @@ -182,7 +183,10 @@ def download_queryset(self, queryset, export_format): class AttachmentMixin: """Mixin for creating attachment objects, and ensuring the user information is saved correctly.""" - permission_classes = [permissions.IsAuthenticated] + permission_classes = [ + permissions.IsAuthenticated, + RolePermission, + ] filter_backends = [ DjangoFilterBackend, diff --git a/InvenTree/templates/attachment_table.html b/InvenTree/templates/attachment_table.html index f47e1f5173e..fbabb7e5104 100644 --- a/InvenTree/templates/attachment_table.html +++ b/InvenTree/templates/attachment_table.html @@ -2,7 +2,7 @@
-
+
diff --git a/InvenTree/templates/js/translated/attachment.js b/InvenTree/templates/js/translated/attachment.js index 991d3efeba7..e070cc65b1e 100644 --- a/InvenTree/templates/js/translated/attachment.js +++ b/InvenTree/templates/js/translated/attachment.js @@ -136,19 +136,56 @@ function loadAttachmentTable(url, options) { var table = options.table || '#attachment-table'; - setupFilterList('attachments', $(table), '#filter-list-attachments'); - - addAttachmentButtonCallbacks(url, options.fields || {}); + var permissions = {}; - // Add callback for the 'multi delete' button - $('#multi-attachment-delete').click(function() { - var attachments = getTableData(table); + // First we determine which permissions the user has for this attachment table + $.ajax({ + url: url, + async: false, + type: 'OPTIONS', + contentType: 'application/json', + dataType: 'json', + accepts: { + json: 'application/json', + }, + success: function(response) { + if (response.actions.DELETE) { + permissions.delete = true; + } - if (attachments.length > 0) { - deleteAttachments(attachments, url, options); + if (response.actions.POST) { + permissions.change = true; + permissions.add = true; + } + }, + error: function(xhr) { + showApiError(xhr, url); } }); + setupFilterList('attachments', $(table), '#filter-list-attachments'); + + if (permissions.add) { + addAttachmentButtonCallbacks(url, options.fields || {}); + } else { + // Hide the buttons + $('#new-attachment').hide(); + $('#new-attachment-link').hide(); + } + + if (permissions.delete) { + // Add callback for the 'multi delete' button + $('#multi-attachment-delete').click(function() { + var attachments = getTableData(table); + + if (attachments.length > 0) { + deleteAttachments(attachments, url, options); + } + }); + } else { + $('#multi-attachment-actions').hide(); + } + $(table).inventreeTable({ url: url, name: options.name || 'attachments', @@ -162,32 +199,36 @@ function loadAttachmentTable(url, options) { onPostBody: function() { // Add callback for 'edit' button - $(table).find('.button-attachment-edit').click(function() { - var pk = $(this).attr('pk'); - - constructForm(`${url}${pk}/`, { - fields: { - link: {}, - comment: {}, - }, - processResults: function(data, fields, opts) { - // Remove the "link" field if the attachment is a file! - if (data.attachment) { - delete opts.fields.link; - } - }, - onSuccess: reloadAttachmentTable, - title: '{% trans "Edit Attachment" %}', + if (permissions.change) { + $(table).find('.button-attachment-edit').click(function() { + var pk = $(this).attr('pk'); + + constructForm(`${url}${pk}/`, { + fields: { + link: {}, + comment: {}, + }, + processResults: function(data, fields, opts) { + // Remove the "link" field if the attachment is a file! + if (data.attachment) { + delete opts.fields.link; + } + }, + onSuccess: reloadAttachmentTable, + title: '{% trans "Edit Attachment" %}', + }); }); - }); + } - // Add callback for 'delete' button - $(table).find('.button-attachment-delete').click(function() { - var pk = $(this).attr('pk'); + if (permissions.delete) { + // Add callback for 'delete' button + $(table).find('.button-attachment-delete').click(function() { + var pk = $(this).attr('pk'); - var attachment = $(table).bootstrapTable('getRowByUniqueId', pk); - deleteAttachments([attachment], url, options); - }); + var attachment = $(table).bootstrapTable('getRowByUniqueId', pk); + deleteAttachments([attachment], url, options); + }); + } }, columns: [ { @@ -261,19 +302,23 @@ function loadAttachmentTable(url, options) { html = `
`; - html += makeIconButton( - 'fa-edit icon-blue', - 'button-attachment-edit', - row.pk, - '{% trans "Edit attachment" %}', - ); - - html += makeIconButton( - 'fa-trash-alt icon-red', - 'button-attachment-delete', - row.pk, - '{% trans "Delete attachment" %}', - ); + if (permissions.change) { + html += makeIconButton( + 'fa-edit icon-blue', + 'button-attachment-edit', + row.pk, + '{% trans "Edit attachment" %}', + ); + } + + if (permissions.delete) { + html += makeIconButton( + 'fa-trash-alt icon-red', + 'button-attachment-delete', + row.pk, + '{% trans "Delete attachment" %}', + ); + } html += `
`; diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py index ca9ee7c240a..b3bafb2657d 100644 --- a/InvenTree/users/models.py +++ b/InvenTree/users/models.py @@ -222,6 +222,11 @@ class Meta: @classmethod def check_table_permission(cls, user, table, permission): """Check if the provided user has the specified permission against the table.""" + + # Superuser knows no bounds + if user.is_superuser: + return True + # If the table does *not* require permissions if table in cls.RULESET_IGNORE: return True