mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 03:56:43 +00:00
Fix API endpoint permission for the "AttachmentMixin" class (#3218)
* Fix API endpoint permission for the "AttachmentMixin" class - Any authenticated user could perform CREATE and UPDATE operations on attachments - Could be performed via the browsable DRF API - Could also be performed via the front-end (with some advaned jiggering of OPTIONS code) * Show or hide buttons depending on the permissions of the user * Add shortcut for table permission check
This commit is contained in:
parent
18cf92ec8b
commit
12fcccb5a6
@ -11,6 +11,7 @@ from rest_framework.response import Response
|
|||||||
from rest_framework.serializers import ValidationError
|
from rest_framework.serializers import ValidationError
|
||||||
|
|
||||||
from InvenTree.mixins import ListCreateAPI
|
from InvenTree.mixins import ListCreateAPI
|
||||||
|
from InvenTree.permissions import RolePermission
|
||||||
|
|
||||||
from .status import is_worker_running
|
from .status import is_worker_running
|
||||||
from .version import (inventreeApiVersion, inventreeInstanceName,
|
from .version import (inventreeApiVersion, inventreeInstanceName,
|
||||||
@ -182,7 +183,10 @@ class APIDownloadMixin:
|
|||||||
class AttachmentMixin:
|
class AttachmentMixin:
|
||||||
"""Mixin for creating attachment objects, and ensuring the user information is saved correctly."""
|
"""Mixin for creating attachment objects, and ensuring the user information is saved correctly."""
|
||||||
|
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
permission_classes = [
|
||||||
|
permissions.IsAuthenticated,
|
||||||
|
RolePermission,
|
||||||
|
]
|
||||||
|
|
||||||
filter_backends = [
|
filter_backends = [
|
||||||
DjangoFilterBackend,
|
DjangoFilterBackend,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div id='attachment-buttons'>
|
<div id='attachment-buttons'>
|
||||||
<div class='btn-group' role='group'>
|
<div class='btn-group' role='group'>
|
||||||
<div class='btn-group'>
|
<div class='btn-group' id='multi-attachment-actions'>
|
||||||
<button class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Actions" %}'>
|
<button class='btn btn-primary dropdown-toggle' type='button' data-bs-toggle='dropdown' title='{% trans "Actions" %}'>
|
||||||
<span class='fas fa-tools'></span> <span class='caret'></span>
|
<span class='fas fa-tools'></span> <span class='caret'></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -136,10 +136,44 @@ function loadAttachmentTable(url, options) {
|
|||||||
|
|
||||||
var table = options.table || '#attachment-table';
|
var table = options.table || '#attachment-table';
|
||||||
|
|
||||||
|
var permissions = {};
|
||||||
|
|
||||||
|
// 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 (response.actions.POST) {
|
||||||
|
permissions.change = true;
|
||||||
|
permissions.add = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
showApiError(xhr, url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setupFilterList('attachments', $(table), '#filter-list-attachments');
|
setupFilterList('attachments', $(table), '#filter-list-attachments');
|
||||||
|
|
||||||
|
if (permissions.add) {
|
||||||
addAttachmentButtonCallbacks(url, options.fields || {});
|
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
|
// Add callback for the 'multi delete' button
|
||||||
$('#multi-attachment-delete').click(function() {
|
$('#multi-attachment-delete').click(function() {
|
||||||
var attachments = getTableData(table);
|
var attachments = getTableData(table);
|
||||||
@ -148,6 +182,9 @@ function loadAttachmentTable(url, options) {
|
|||||||
deleteAttachments(attachments, url, options);
|
deleteAttachments(attachments, url, options);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
$('#multi-attachment-actions').hide();
|
||||||
|
}
|
||||||
|
|
||||||
$(table).inventreeTable({
|
$(table).inventreeTable({
|
||||||
url: url,
|
url: url,
|
||||||
@ -162,6 +199,7 @@ function loadAttachmentTable(url, options) {
|
|||||||
onPostBody: function() {
|
onPostBody: function() {
|
||||||
|
|
||||||
// Add callback for 'edit' button
|
// Add callback for 'edit' button
|
||||||
|
if (permissions.change) {
|
||||||
$(table).find('.button-attachment-edit').click(function() {
|
$(table).find('.button-attachment-edit').click(function() {
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
@ -180,7 +218,9 @@ function loadAttachmentTable(url, options) {
|
|||||||
title: '{% trans "Edit Attachment" %}',
|
title: '{% trans "Edit Attachment" %}',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissions.delete) {
|
||||||
// Add callback for 'delete' button
|
// Add callback for 'delete' button
|
||||||
$(table).find('.button-attachment-delete').click(function() {
|
$(table).find('.button-attachment-delete').click(function() {
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
@ -188,6 +228,7 @@ function loadAttachmentTable(url, options) {
|
|||||||
var attachment = $(table).bootstrapTable('getRowByUniqueId', pk);
|
var attachment = $(table).bootstrapTable('getRowByUniqueId', pk);
|
||||||
deleteAttachments([attachment], url, options);
|
deleteAttachments([attachment], url, options);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
@ -261,19 +302,23 @@ function loadAttachmentTable(url, options) {
|
|||||||
|
|
||||||
html = `<div class='btn-group float-right' role='group'>`;
|
html = `<div class='btn-group float-right' role='group'>`;
|
||||||
|
|
||||||
|
if (permissions.change) {
|
||||||
html += makeIconButton(
|
html += makeIconButton(
|
||||||
'fa-edit icon-blue',
|
'fa-edit icon-blue',
|
||||||
'button-attachment-edit',
|
'button-attachment-edit',
|
||||||
row.pk,
|
row.pk,
|
||||||
'{% trans "Edit attachment" %}',
|
'{% trans "Edit attachment" %}',
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissions.delete) {
|
||||||
html += makeIconButton(
|
html += makeIconButton(
|
||||||
'fa-trash-alt icon-red',
|
'fa-trash-alt icon-red',
|
||||||
'button-attachment-delete',
|
'button-attachment-delete',
|
||||||
row.pk,
|
row.pk,
|
||||||
'{% trans "Delete attachment" %}',
|
'{% trans "Delete attachment" %}',
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
html += `</div>`;
|
html += `</div>`;
|
||||||
|
|
||||||
|
@ -222,6 +222,11 @@ class RuleSet(models.Model):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def check_table_permission(cls, user, table, permission):
|
def check_table_permission(cls, user, table, permission):
|
||||||
"""Check if the provided user has the specified permission against the table."""
|
"""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 the table does *not* require permissions
|
||||||
if table in cls.RULESET_IGNORE:
|
if table in cls.RULESET_IGNORE:
|
||||||
return True
|
return True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user