From 103cf8ee557e2b66aa3bd544f7290b1d384edc8b Mon Sep 17 00:00:00 2001 From: aschumann-virtualcable Date: Fri, 13 Mar 2026 12:36:40 +0100 Subject: [PATCH] Switches server import to parse CSV string input Updates the import logic to accept a CSV-formatted string instead of a JSON array, improving compatibility and aligning with common data exchange formats. Enhances input handling by leveraging the CSV parser for more robust processing and easier integration. --- .../src/uds/REST/methods/servers_management.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/server/src/uds/REST/methods/servers_management.py b/server/src/uds/REST/methods/servers_management.py index 3cdfe5bcc..066b9d930 100644 --- a/server/src/uds/REST/methods/servers_management.py +++ b/server/src/uds/REST/methods/servers_management.py @@ -31,6 +31,8 @@ """ import logging import typing +import io +import csv from django.utils.translation import gettext from django.utils.translation import gettext_lazy as _ @@ -345,11 +347,11 @@ def maintenance(self, parent: 'Model', id: str) -> typing.Any: def importcsv(self, parent: 'Model') -> typing.Any: """ - We receive a json with string[][] format with the data. + We receive a csv string with the data. Has no header, only the data. """ parent = ensure.is_instance(parent, models.ServerGroup) - data: list[list[str]] = self._params.get('data', []) + data: typing.Any = self._params.get('data', '') logger.debug('Data received: %s', data) # String lines can have 1, 2 or 3 fields. # if 1, it's a IP @@ -358,16 +360,20 @@ def importcsv(self, parent: 'Model') -> typing.Any: # if ip is empty and has a hostname, it will be kept, but if it has no hostname, it will be skipped # If the IP is invalid and has no hostname, it will be skipped import_errors: list[str] = [] - for line_number, row in enumerate(data, 1): + + f = io.StringIO('\n'.join(','.join(row) for row in data)) + reader: typing.Iterable[list[str]] = csv.reader(f) + + for line_number, row in enumerate(reader, 1): if len(row) == 0: continue - hostname = row[0].strip() + hostname = row[0] ip = '' mac = consts.MAC_UNKNOWN if len(row) > 1: - ip = row[1].strip() + ip = row[1] if len(row) > 2: - mac = row[2].strip().upper().strip() or consts.MAC_UNKNOWN + mac = row[2].upper() or consts.MAC_UNKNOWN if mac and not net.is_valid_mac(mac): import_errors.append(f'Line {line_number}: MAC {mac} is invalid, skipping') continue # skip invalid macs