Adds custom DRF metadata handler

- Limit available "actions" data to only what the user is allowed to do
This commit is contained in:
Oliver 2021-06-23 20:30:26 +10:00
parent 058e53459b
commit eaa5913c8c
3 changed files with 72 additions and 4 deletions

View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from rest_framework.metadata import SimpleMetadata
import users.models
class InvenTreeMetadata(SimpleMetadata):
"""
Custom metadata class for the DRF API.
This custom metadata class imits the available "actions",
based on the user's role permissions.
Thus when a client send an OPTIONS request to an API endpoint,
it will only receive a list of actions which it is allowed to perform!
"""
def determine_metadata(self, request, view):
metadata = super().determine_metadata(request, view)
user = request.user
if user is None:
# No actions for you!
metadata['actions'] = {}
return metadata
try:
# Extract the model name associated with the view
model = view.serializer_class.Meta.model
# Construct the 'table name' from the model
app_label = model._meta.app_label
tbl_label = model._meta.model_name
table = f"{app_label}_{tbl_label}"
actions = metadata['actions']
check = users.models.RuleSet.check_table_permission
# Map the request method to a permission type
rolemap = {
'GET': 'view',
'OPTIONS': 'view',
'POST': 'add',
'PUT': 'change',
'PATCH': 'change',
'DELETE': 'delete',
}
# Remove any HTTP methods that the user does not have permission for
for method, permission in rolemap.items():
if method in actions and not check(user, table, permission):
del actions[method]
except AttributeError:
# We will assume that if the serializer class does *not* have a Meta
# then we don't need a permission
pass
return metadata

View File

@ -341,6 +341,7 @@ REST_FRAMEWORK = {
'InvenTree.permissions.RolePermission',
),
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'DEFAULT_METADATA_CLASS': 'InvenTree.metadata.InvenTreeMetadata'
}
WSGI_APPLICATION = 'InvenTree.wsgi.application'

View File

@ -23,7 +23,8 @@
*/
function getApiEndpointOptions(url, options={}) {
$.ajax({
// Return the ajax request object
return $.ajax({
url: url,
type: 'OPTIONS',
contentType: 'application/json',
@ -31,8 +32,7 @@ function getApiEndpointOptions(url, options={}) {
accepts: {
json: 'application/json',
},
success: function(response) {
console.log(response);
}
});
}