mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 20:16:44 +00:00
Merge pull request from GHSA-7rq4-qcpw-74gq
* Create custom ModelResource subclass - Strips illegal starting characters from string cells - Prevents formula injection * Update all existing ModelResource classes to base off InvenTreeResource * Handle more complex case where an illegal char is hidden behind another one
This commit is contained in:
parent
76aa3a75f2
commit
57563f6b7a
33
InvenTree/InvenTree/admin.py
Normal file
33
InvenTree/InvenTree/admin.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""Admin classes"""
|
||||||
|
|
||||||
|
from import_export.resources import ModelResource
|
||||||
|
|
||||||
|
|
||||||
|
class InvenTreeResource(ModelResource):
|
||||||
|
"""Custom subclass of the ModelResource class provided by django-import-export"
|
||||||
|
|
||||||
|
Ensures that exported data are escaped to prevent malicious formula injection.
|
||||||
|
Ref: https://owasp.org/www-community/attacks/CSV_Injection
|
||||||
|
"""
|
||||||
|
|
||||||
|
def export_resource(self, obj):
|
||||||
|
"""Custom function to override default row export behaviour.
|
||||||
|
|
||||||
|
Specifically, strip illegal leading characters to prevent formula injection
|
||||||
|
"""
|
||||||
|
row = super().export_resource(obj)
|
||||||
|
|
||||||
|
illegal_start_vals = ['@', '=', '+', '-', '@', '\t', '\r', '\n']
|
||||||
|
|
||||||
|
for idx, val in enumerate(row):
|
||||||
|
if type(val) is str:
|
||||||
|
val = val.strip()
|
||||||
|
|
||||||
|
# If the value starts with certain 'suspicious' values, remove it!
|
||||||
|
while len(val) > 0 and val[0] in illegal_start_vals:
|
||||||
|
# Remove the first character
|
||||||
|
val = val[1:]
|
||||||
|
|
||||||
|
row[idx] = val
|
||||||
|
|
||||||
|
return row
|
@ -4,15 +4,14 @@ from django.contrib import admin
|
|||||||
|
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
|
||||||
import import_export.widgets as widgets
|
import import_export.widgets as widgets
|
||||||
|
|
||||||
from build.models import Build, BuildItem
|
from build.models import Build, BuildItem
|
||||||
|
from InvenTree.admin import InvenTreeResource
|
||||||
import part.models
|
import part.models
|
||||||
|
|
||||||
|
|
||||||
class BuildResource(ModelResource):
|
class BuildResource(InvenTreeResource):
|
||||||
"""Class for managing import/export of Build data."""
|
"""Class for managing import/export of Build data."""
|
||||||
# For some reason, we need to specify the fields individually for this ModelResource,
|
# For some reason, we need to specify the fields individually for this ModelResource,
|
||||||
# but we don't for other ones.
|
# but we don't for other ones.
|
||||||
|
@ -5,8 +5,8 @@ from django.contrib import admin
|
|||||||
import import_export.widgets as widgets
|
import import_export.widgets as widgets
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
|
||||||
|
|
||||||
|
from InvenTree.admin import InvenTreeResource
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
|
|
||||||
from .models import (Company, ManufacturerPart, ManufacturerPartAttachment,
|
from .models import (Company, ManufacturerPart, ManufacturerPartAttachment,
|
||||||
@ -14,7 +14,7 @@ from .models import (Company, ManufacturerPart, ManufacturerPartAttachment,
|
|||||||
SupplierPriceBreak)
|
SupplierPriceBreak)
|
||||||
|
|
||||||
|
|
||||||
class CompanyResource(ModelResource):
|
class CompanyResource(InvenTreeResource):
|
||||||
"""Class for managing Company data import/export."""
|
"""Class for managing Company data import/export."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -38,7 +38,7 @@ class CompanyAdmin(ImportExportModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SupplierPartResource(ModelResource):
|
class SupplierPartResource(InvenTreeResource):
|
||||||
"""Class for managing SupplierPart data import/export."""
|
"""Class for managing SupplierPart data import/export."""
|
||||||
|
|
||||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||||
@ -74,7 +74,7 @@ class SupplierPartAdmin(ImportExportModelAdmin):
|
|||||||
autocomplete_fields = ('part', 'supplier', 'manufacturer_part',)
|
autocomplete_fields = ('part', 'supplier', 'manufacturer_part',)
|
||||||
|
|
||||||
|
|
||||||
class ManufacturerPartResource(ModelResource):
|
class ManufacturerPartResource(InvenTreeResource):
|
||||||
"""Class for managing ManufacturerPart data import/export."""
|
"""Class for managing ManufacturerPart data import/export."""
|
||||||
|
|
||||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||||
@ -117,7 +117,7 @@ class ManufacturerPartAttachmentAdmin(ImportExportModelAdmin):
|
|||||||
autocomplete_fields = ('manufacturer_part',)
|
autocomplete_fields = ('manufacturer_part',)
|
||||||
|
|
||||||
|
|
||||||
class ManufacturerPartParameterResource(ModelResource):
|
class ManufacturerPartParameterResource(InvenTreeResource):
|
||||||
"""Class for managing ManufacturerPartParameter data import/export."""
|
"""Class for managing ManufacturerPartParameter data import/export."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -144,7 +144,7 @@ class ManufacturerPartParameterAdmin(ImportExportModelAdmin):
|
|||||||
autocomplete_fields = ('manufacturer_part',)
|
autocomplete_fields = ('manufacturer_part',)
|
||||||
|
|
||||||
|
|
||||||
class SupplierPriceBreakResource(ModelResource):
|
class SupplierPriceBreakResource(InvenTreeResource):
|
||||||
"""Class for managing SupplierPriceBreak data import/export."""
|
"""Class for managing SupplierPriceBreak data import/export."""
|
||||||
|
|
||||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(SupplierPart))
|
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(SupplierPart))
|
||||||
|
@ -5,7 +5,8 @@ from django.contrib import admin
|
|||||||
import import_export.widgets as widgets
|
import import_export.widgets as widgets
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
|
||||||
|
from InvenTree.admin import InvenTreeResource
|
||||||
|
|
||||||
from .models import (PurchaseOrder, PurchaseOrderExtraLine,
|
from .models import (PurchaseOrder, PurchaseOrderExtraLine,
|
||||||
PurchaseOrderLineItem, SalesOrder, SalesOrderAllocation,
|
PurchaseOrderLineItem, SalesOrder, SalesOrderAllocation,
|
||||||
@ -97,7 +98,7 @@ class SalesOrderAdmin(ImportExportModelAdmin):
|
|||||||
autocomplete_fields = ('customer',)
|
autocomplete_fields = ('customer',)
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderResource(ModelResource):
|
class PurchaseOrderResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of PurchaseOrder data."""
|
"""Class for managing import / export of PurchaseOrder data."""
|
||||||
|
|
||||||
# Add number of line items
|
# Add number of line items
|
||||||
@ -116,7 +117,7 @@ class PurchaseOrderResource(ModelResource):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderLineItemResource(ModelResource):
|
class PurchaseOrderLineItemResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of PurchaseOrderLineItem data."""
|
"""Class for managing import / export of PurchaseOrderLineItem data."""
|
||||||
|
|
||||||
part_name = Field(attribute='part__part__name', readonly=True)
|
part_name = Field(attribute='part__part__name', readonly=True)
|
||||||
@ -135,7 +136,7 @@ class PurchaseOrderLineItemResource(ModelResource):
|
|||||||
clean_model_instances = True
|
clean_model_instances = True
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderExtraLineResource(ModelResource):
|
class PurchaseOrderExtraLineResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of PurchaseOrderExtraLine data."""
|
"""Class for managing import / export of PurchaseOrderExtraLine data."""
|
||||||
|
|
||||||
class Meta(GeneralExtraLineMeta):
|
class Meta(GeneralExtraLineMeta):
|
||||||
@ -144,7 +145,7 @@ class PurchaseOrderExtraLineResource(ModelResource):
|
|||||||
model = PurchaseOrderExtraLine
|
model = PurchaseOrderExtraLine
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderResource(ModelResource):
|
class SalesOrderResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of SalesOrder data."""
|
"""Class for managing import / export of SalesOrder data."""
|
||||||
|
|
||||||
# Add number of line items
|
# Add number of line items
|
||||||
@ -163,7 +164,7 @@ class SalesOrderResource(ModelResource):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderLineItemResource(ModelResource):
|
class SalesOrderLineItemResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of SalesOrderLineItem data."""
|
"""Class for managing import / export of SalesOrderLineItem data."""
|
||||||
|
|
||||||
part_name = Field(attribute='part__name', readonly=True)
|
part_name = Field(attribute='part__name', readonly=True)
|
||||||
@ -192,7 +193,7 @@ class SalesOrderLineItemResource(ModelResource):
|
|||||||
clean_model_instances = True
|
clean_model_instances = True
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderExtraLineResource(ModelResource):
|
class SalesOrderExtraLineResource(InvenTreeResource):
|
||||||
"""Class for managing import / export of SalesOrderExtraLine data."""
|
"""Class for managing import / export of SalesOrderExtraLine data."""
|
||||||
|
|
||||||
class Meta(GeneralExtraLineMeta):
|
class Meta(GeneralExtraLineMeta):
|
||||||
|
@ -5,14 +5,14 @@ from django.contrib import admin
|
|||||||
import import_export.widgets as widgets
|
import import_export.widgets as widgets
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
|
||||||
|
|
||||||
import part.models as models
|
import part.models as models
|
||||||
from company.models import SupplierPart
|
from company.models import SupplierPart
|
||||||
|
from InvenTree.admin import InvenTreeResource
|
||||||
from stock.models import StockLocation
|
from stock.models import StockLocation
|
||||||
|
|
||||||
|
|
||||||
class PartResource(ModelResource):
|
class PartResource(InvenTreeResource):
|
||||||
"""Class for managing Part data import/export."""
|
"""Class for managing Part data import/export."""
|
||||||
|
|
||||||
# ForeignKey fields
|
# ForeignKey fields
|
||||||
@ -92,7 +92,7 @@ class PartAdmin(ImportExportModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class PartCategoryResource(ModelResource):
|
class PartCategoryResource(InvenTreeResource):
|
||||||
"""Class for managing PartCategory data import/export."""
|
"""Class for managing PartCategory data import/export."""
|
||||||
|
|
||||||
parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(models.PartCategory))
|
parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(models.PartCategory))
|
||||||
@ -157,7 +157,7 @@ class PartTestTemplateAdmin(admin.ModelAdmin):
|
|||||||
autocomplete_fields = ('part',)
|
autocomplete_fields = ('part',)
|
||||||
|
|
||||||
|
|
||||||
class BomItemResource(ModelResource):
|
class BomItemResource(InvenTreeResource):
|
||||||
"""Class for managing BomItem data import/export."""
|
"""Class for managing BomItem data import/export."""
|
||||||
|
|
||||||
level = Field(attribute='level', readonly=True)
|
level = Field(attribute='level', readonly=True)
|
||||||
@ -266,7 +266,7 @@ class ParameterTemplateAdmin(ImportExportModelAdmin):
|
|||||||
search_fields = ('name', 'units')
|
search_fields = ('name', 'units')
|
||||||
|
|
||||||
|
|
||||||
class ParameterResource(ModelResource):
|
class ParameterResource(InvenTreeResource):
|
||||||
"""Class for managing PartParameter data import/export."""
|
"""Class for managing PartParameter data import/export."""
|
||||||
|
|
||||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(models.Part))
|
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(models.Part))
|
||||||
|
@ -5,10 +5,10 @@ from django.contrib import admin
|
|||||||
import import_export.widgets as widgets
|
import import_export.widgets as widgets
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from import_export.fields import Field
|
from import_export.fields import Field
|
||||||
from import_export.resources import ModelResource
|
|
||||||
|
|
||||||
from build.models import Build
|
from build.models import Build
|
||||||
from company.models import Company, SupplierPart
|
from company.models import Company, SupplierPart
|
||||||
|
from InvenTree.admin import InvenTreeResource
|
||||||
from order.models import PurchaseOrder, SalesOrder
|
from order.models import PurchaseOrder, SalesOrder
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ from .models import (StockItem, StockItemAttachment, StockItemTestResult,
|
|||||||
StockItemTracking, StockLocation)
|
StockItemTracking, StockLocation)
|
||||||
|
|
||||||
|
|
||||||
class LocationResource(ModelResource):
|
class LocationResource(InvenTreeResource):
|
||||||
"""Class for managing StockLocation data import/export."""
|
"""Class for managing StockLocation data import/export."""
|
||||||
|
|
||||||
parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(StockLocation))
|
parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(StockLocation))
|
||||||
@ -68,7 +68,7 @@ class LocationAdmin(ImportExportModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class StockItemResource(ModelResource):
|
class StockItemResource(InvenTreeResource):
|
||||||
"""Class for managing StockItem data import/export."""
|
"""Class for managing StockItem data import/export."""
|
||||||
|
|
||||||
# Custom managers for ForeignKey fields
|
# Custom managers for ForeignKey fields
|
||||||
|
Loading…
x
Reference in New Issue
Block a user