mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-26 19:07:40 +00:00 
			
		
		
		
	Adds custom DRF metadata handler
- Limit available "actions" data to only what the user is allowed to do
This commit is contained in:
		
							
								
								
									
										67
									
								
								InvenTree/InvenTree/metadata.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								InvenTree/InvenTree/metadata.py
									
									
									
									
									
										Normal 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 | ||||||
| @@ -341,6 +341,7 @@ REST_FRAMEWORK = { | |||||||
|         'InvenTree.permissions.RolePermission', |         'InvenTree.permissions.RolePermission', | ||||||
|     ), |     ), | ||||||
|     'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', |     'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', | ||||||
|  |     'DEFAULT_METADATA_CLASS': 'InvenTree.metadata.InvenTreeMetadata' | ||||||
| } | } | ||||||
|  |  | ||||||
| WSGI_APPLICATION = 'InvenTree.wsgi.application' | WSGI_APPLICATION = 'InvenTree.wsgi.application' | ||||||
|   | |||||||
| @@ -23,7 +23,8 @@ | |||||||
|  */ |  */ | ||||||
| function getApiEndpointOptions(url, options={}) { | function getApiEndpointOptions(url, options={}) { | ||||||
|  |  | ||||||
|     $.ajax({ |     // Return the ajax request object | ||||||
|  |     return $.ajax({ | ||||||
|         url: url, |         url: url, | ||||||
|         type: 'OPTIONS', |         type: 'OPTIONS', | ||||||
|         contentType: 'application/json', |         contentType: 'application/json', | ||||||
| @@ -31,8 +32,7 @@ function getApiEndpointOptions(url, options={}) { | |||||||
|         accepts: { |         accepts: { | ||||||
|             json: 'application/json', |             json: 'application/json', | ||||||
|         }, |         }, | ||||||
|         success: function(response) { |  | ||||||
|             console.log(response); |  | ||||||
|         } |  | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user