Refactor python code to address Sonarcloud issues (#900)

- copy/move/delete file class methods now take Path objects as arguments
- The file download endpoint in the Web UI uses the safer download from dir method
- Simplified logging
- Merged nested if statements
- Removed naked handling of unknown error states
- Added fallback empty list for drive_properties, to avoid errors when json file is missing or broken
- Move drive_properties to env[]
- Constants for common error messages
- Dummy variable for list comprehension
This commit is contained in:
Daniel Markstedt 2022-10-09 13:50:20 -07:00 committed by GitHub
parent ca23d9b7a3
commit 1b10b123d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 105 additions and 154 deletions

View File

@ -23,4 +23,7 @@ ARCHIVE_FILE_SUFFIXES = [
# The RESERVATIONS list is used to keep track of the reserved ID memos. # The RESERVATIONS list is used to keep track of the reserved ID memos.
# Initialize with a list of 8 empty strings. # Initialize with a list of 8 empty strings.
RESERVATIONS = ["" for x in range(0, 8)] RESERVATIONS = ["" for _ in range(0, 8)]
# Standard error message for shell commands
SHELL_ERROR = "Shell command: \"%s\" led to error: %s"

View File

@ -6,7 +6,7 @@ import os
import logging import logging
import asyncio import asyncio
from functools import lru_cache from functools import lru_cache
from pathlib import PurePath from pathlib import PurePath, Path
from zipfile import ZipFile, is_zipfile from zipfile import ZipFile, is_zipfile
from time import time from time import time
from subprocess import run, CalledProcessError from subprocess import run, CalledProcessError
@ -16,12 +16,21 @@ from shutil import copyfile
import requests import requests
import rascsi_interface_pb2 as proto import rascsi_interface_pb2 as proto
from rascsi.common_settings import CFG_DIR, CONFIG_FILE_SUFFIX, PROPERTIES_SUFFIX, ARCHIVE_FILE_SUFFIXES, RESERVATIONS from rascsi.common_settings import (
CFG_DIR,
CONFIG_FILE_SUFFIX,
PROPERTIES_SUFFIX,
ARCHIVE_FILE_SUFFIXES,
RESERVATIONS,
SHELL_ERROR,
)
from rascsi.ractl_cmds import RaCtlCmds from rascsi.ractl_cmds import RaCtlCmds
from rascsi.return_codes import ReturnCodes from rascsi.return_codes import ReturnCodes
from rascsi.socket_cmds import SocketCmds from rascsi.socket_cmds import SocketCmds
from util import unarchiver from util import unarchiver
FILE_READ_ERROR = "Unhandled exception when reading file: %s"
FILE_WRITE_ERROR = "Unhandled exception when writing to file: %s"
class FileCmds: class FileCmds:
""" """
@ -148,7 +157,7 @@ class FileCmds:
command.params["token"] = self.token command.params["token"] = self.token
command.params["locale"] = self.locale command.params["locale"] = self.locale
command.params["file"] = file_name + "." + file_type command.params["file"] = f"{file_name}.{file_type}"
command.params["size"] = str(size) command.params["size"] = str(size)
command.params["read_only"] = "false" command.params["read_only"] = "false"
@ -216,14 +225,15 @@ class FileCmds:
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
def delete_file(self, file_path): def delete_file(self, file_path):
""" """
Takes (str) file_path with the full path to the file to delete Takes (Path) file_path for the file to delete
Returns (dict) with (bool) status and (str) msg Returns (dict) with (bool) status and (str) msg
""" """
parameters = { parameters = {
"file_path": file_path "file_path": file_path
} }
if os.path.exists(file_path):
os.remove(file_path) if file_path.exists():
file_path.unlink()
return { return {
"status": True, "status": True,
"return_code": ReturnCodes.DELETEFILE_SUCCESS, "return_code": ReturnCodes.DELETEFILE_SUCCESS,
@ -238,14 +248,16 @@ class FileCmds:
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
def rename_file(self, file_path, target_path): def rename_file(self, file_path, target_path):
""" """
Takes (str) file_path and (str) target_path Takes:
- (Path) file_path for the file to rename
- (Path) target_path for the name to rename
Returns (dict) with (bool) status and (str) msg Returns (dict) with (bool) status and (str) msg
""" """
parameters = { parameters = {
"target_path": target_path "target_path": target_path
} }
if os.path.exists(PurePath(target_path).parent): if target_path.parent.exists:
os.rename(file_path, target_path) file_path.rename(target_path)
return { return {
"status": True, "status": True,
"return_code": ReturnCodes.RENAMEFILE_SUCCESS, "return_code": ReturnCodes.RENAMEFILE_SUCCESS,
@ -260,14 +272,16 @@ class FileCmds:
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
def copy_file(self, file_path, target_path): def copy_file(self, file_path, target_path):
""" """
Takes (str) file_path and (str) target_path Takes:
- (Path) file_path for the file to copy from
- (Path) target_path for the name to copy to
Returns (dict) with (bool) status and (str) msg Returns (dict) with (bool) status and (str) msg
""" """
parameters = { parameters = {
"target_path": target_path "target_path": target_path
} }
if os.path.exists(PurePath(target_path).parent): if target_path.parent.exists:
copyfile(file_path, target_path) copyfile(str(file_path), str(target_path))
return { return {
"status": True, "status": True,
"return_code": ReturnCodes.WRITEFILE_SUCCESS, "return_code": ReturnCodes.WRITEFILE_SUCCESS,
@ -305,21 +319,22 @@ class FileCmds:
properties_files_moved = [] properties_files_moved = []
if move_properties_files_to_config: if move_properties_files_to_config:
for file in extract_result["extracted"]: for file in extract_result["extracted"]:
if file.get("name").endswith(".properties"): if file.get("name").endswith(f".{PROPERTIES_SUFFIX}"):
prop_path = Path(CFG_DIR) / file["name"]
if (self.rename_file( if (self.rename_file(
file["absolute_path"], Path(file["absolute_path"]),
f"{CFG_DIR}/{file['name']}" prop_path,
)): )):
properties_files_moved.append({ properties_files_moved.append({
"status": True, "status": True,
"name": file["path"], "name": file["path"],
"path": f"{CFG_DIR}/{file['name']}", "path": str(prop_path),
}) })
else: else:
properties_files_moved.append({ properties_files_moved.append({
"status": False, "status": False,
"name": file["path"], "name": file["path"],
"path": f"{CFG_DIR}/{file['name']}", "path": str(prop_path),
}) })
return { return {
@ -386,7 +401,7 @@ class FileCmds:
"%s was successfully unzipped. Deleting the zipfile.", "%s was successfully unzipped. Deleting the zipfile.",
tmp_full_path, tmp_full_path,
) )
self.delete_file(tmp_full_path) self.delete_file(Path(tmp_full_path))
try: try:
run( run(
@ -401,8 +416,7 @@ class FileCmds:
check=True, check=True,
) )
except CalledProcessError as error: except CalledProcessError as error:
logging.warning("Executed shell command: %s", " ".join(error.cmd)) logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
logging.warning("Got error: %s", error.stderr.decode("utf-8"))
return {"status": False, "msg": error.stderr.decode("utf-8")} return {"status": False, "msg": error.stderr.decode("utf-8")}
parameters = { parameters = {
@ -452,9 +466,9 @@ class FileCmds:
Takes (str) file_name Takes (str) file_name
Returns (dict) with (bool) status and (str) msg Returns (dict) with (bool) status and (str) msg
""" """
file_name = f"{CFG_DIR}/{file_name}" file_path = f"{CFG_DIR}/{file_name}"
try: try:
with open(file_name, "w", encoding="ISO-8859-1") as json_file: with open(file_path, "w", encoding="ISO-8859-1") as json_file:
version = self.ractl.get_server_info()["version"] version = self.ractl.get_server_info()["version"]
devices = self.ractl.list_devices()["device_list"] devices = self.ractl.list_devices()["device_list"]
for device in devices: for device in devices:
@ -485,7 +499,7 @@ class FileCmds:
indent=4 indent=4
) )
parameters = { parameters = {
"target_path": file_name "target_path": file_path
} }
return { return {
"status": True, "status": True,
@ -494,19 +508,12 @@ class FileCmds:
} }
except (IOError, ValueError, EOFError, TypeError) as error: except (IOError, ValueError, EOFError, TypeError) as error:
logging.error(str(error)) logging.error(str(error))
self.delete_file(file_name) self.delete_file(Path(file_path))
return {"status": False, "msg": str(error)} return {"status": False, "msg": str(error)}
except: except:
logging.error("Could not write to file: %s", file_name) logging.error(FILE_WRITE_ERROR, file_name)
self.delete_file(file_name) self.delete_file(Path(file_path))
parameters = { raise
"file_name": file_name
}
return {
"status": False,
"return_code": ReturnCodes.WRITEFILE_COULD_NOT_WRITE,
"parameters": parameters,
}
def read_config(self, file_name): def read_config(self, file_name):
""" """
@ -577,15 +584,8 @@ class FileCmds:
logging.error(str(error)) logging.error(str(error))
return {"status": False, "msg": str(error)} return {"status": False, "msg": str(error)}
except: except:
logging.error("Could not read file: %s", file_name) logging.error(FILE_READ_ERROR, file_name)
parameters = { raise
"file_name": file_name
}
return {
"status": False,
"return_code": ReturnCodes.READCONFIG_COULD_NOT_READ,
"parameters": parameters
}
def write_drive_properties(self, file_name, conf): def write_drive_properties(self, file_name, conf):
""" """
@ -607,19 +607,12 @@ class FileCmds:
} }
except (IOError, ValueError, EOFError, TypeError) as error: except (IOError, ValueError, EOFError, TypeError) as error:
logging.error(str(error)) logging.error(str(error))
self.delete_file(file_path) self.delete_file(Path(file_path))
return {"status": False, "msg": str(error)} return {"status": False, "msg": str(error)}
except: except:
logging.error("Could not write to file: %s", file_path) logging.error(FILE_WRITE_ERROR, file_path)
self.delete_file(file_path) self.delete_file(Path(file_path))
parameters = { raise
"target_path": file_path
}
return {
"status": False,
"return_code": ReturnCodes.WRITEFILE_COULD_NOT_WRITE,
"parameters": parameters,
}
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
def read_drive_properties(self, file_path): def read_drive_properties(self, file_path):
@ -644,15 +637,8 @@ class FileCmds:
logging.error(str(error)) logging.error(str(error))
return {"status": False, "msg": str(error)} return {"status": False, "msg": str(error)}
except: except:
logging.error("Could not read file: %s", file_path) logging.error(FILE_READ_ERROR, file_path)
parameters = { raise
"file_path": file_path
}
return {
"status": False,
"return_codes": ReturnCodes.READDRIVEPROPS_COULD_NOT_READ,
"parameters": parameters,
}
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
async def run_async(self, program, args): async def run_async(self, program, args):

View File

@ -224,14 +224,11 @@ class RaCtlCmds:
devices = proto.PbDeviceDefinition() devices = proto.PbDeviceDefinition()
devices.id = int(scsi_id) devices.id = int(scsi_id)
if "device_type" in kwargs.keys(): if kwargs.get("device_type"):
if kwargs["device_type"]:
devices.type = proto.PbDeviceType.Value(str(kwargs["device_type"])) devices.type = proto.PbDeviceType.Value(str(kwargs["device_type"]))
if "unit" in kwargs.keys(): if kwargs.get("unit"):
if kwargs["unit"]:
devices.unit = kwargs["unit"] devices.unit = kwargs["unit"]
if "params" in kwargs.keys(): if kwargs.get("params") and isinstance(kwargs["params"], dict):
if isinstance(kwargs["params"], dict):
for param in kwargs["params"]: for param in kwargs["params"]:
devices.params[param] = kwargs["params"][param] devices.params[param] = kwargs["params"][param]
@ -260,17 +257,13 @@ class RaCtlCmds:
# Handling attaching a new device # Handling attaching a new device
else: else:
command.operation = proto.PbOperation.ATTACH command.operation = proto.PbOperation.ATTACH
if "vendor" in kwargs.keys(): if kwargs.get("vendor"):
if kwargs["vendor"]:
devices.vendor = kwargs["vendor"] devices.vendor = kwargs["vendor"]
if "product" in kwargs.keys(): if kwargs.get("product"):
if kwargs["product"]:
devices.product = kwargs["product"] devices.product = kwargs["product"]
if "revision" in kwargs.keys(): if kwargs.get("revision"):
if kwargs["revision"]:
devices.revision = kwargs["revision"] devices.revision = kwargs["revision"]
if "block_size" in kwargs.keys(): if kwargs.get("block_size"):
if kwargs["block_size"]:
devices.block_size = int(kwargs["block_size"]) devices.block_size = int(kwargs["block_size"])
command.devices.append(devices) command.devices.append(devices)

View File

@ -8,6 +8,7 @@ from shutil import disk_usage
from re import findall, match from re import findall, match
from socket import socket, gethostname, AF_INET, SOCK_DGRAM from socket import socket, gethostname, AF_INET, SOCK_DGRAM
from rascsi.common_settings import SHELL_ERROR
class SysCmds: class SysCmds:
""" """
@ -32,8 +33,7 @@ class SysCmds:
.strip() .strip()
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
logging.warning("Executed shell command: %s", " ".join(error.cmd)) logging.warning(SHELL_ERROR, error.cmd, error.stderr.decode("utf-8"))
logging.warning("Got error: %s", error.stderr.decode("utf-8"))
ra_git_version = "" ra_git_version = ""
try: try:
@ -47,9 +47,8 @@ class SysCmds:
.strip() .strip()
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
logging.warning("Executed shell command: %s", " ".join(error.cmd)) logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
logging.warning("Got error: %s", error.stderr.decode("utf-8")) pi_version = "?"
pi_version = "Unknown"
return {"git": ra_git_version, "env": pi_version} return {"git": ra_git_version, "env": pi_version}
@ -70,8 +69,7 @@ class SysCmds:
.strip() .strip()
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
logging.warning("Executed shell command: %s", " ".join(error.cmd)) logging.warning(SHELL_ERROR, error.cmd, error.stderr.decode("utf-8"))
logging.warning("Got error: %s", error.stderr.decode("utf-8"))
processes = "" processes = ""
matching_processes = findall(daemon, processes) matching_processes = findall(daemon, processes)
@ -93,8 +91,7 @@ class SysCmds:
.strip() .strip()
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
logging.warning("Executed shell command: %s", " ".join(error.cmd)) logging.warning(SHELL_ERROR, error.cmd, error.stderr.decode("utf-8"))
logging.warning("Got error: %s", error.stderr.decode("utf-8"))
bridges = "" bridges = ""
if "rascsi_bridge" in bridges: if "rascsi_bridge" in bridges:

View File

@ -13,7 +13,7 @@
<th scope="col">{{ _("Description") }}</th> <th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th> <th scope="col">{{ _("Action") }}</th>
</tr> </tr>
{% for hd in drive_properties['hd_conf']|sort(attribute='name') %} {% for hd in env['drive_properties']['hd_conf']|sort(attribute='name') %}
<tr> <tr>
<td align="center"> <td align="center">
{% if hd.url != "" %} {% if hd.url != "" %}
@ -48,7 +48,7 @@
<th scope="col">{{ _("Description") }}</th> <th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th> <th scope="col">{{ _("Action") }}</th>
</tr> </tr>
{% for cd in drive_properties['cd_conf']|sort(attribute='name') %} {% for cd in env['drive_properties']['cd_conf']|sort(attribute='name') %}
<tr> <tr>
<td align="center"> <td align="center">
{% if cd.url != "" %} {% if cd.url != "" %}
@ -88,7 +88,7 @@
<th scope="col">{{ _("Description") }}</th> <th scope="col">{{ _("Description") }}</th>
<th scope="col">{{ _("Action") }}</th> <th scope="col">{{ _("Action") }}</th>
</tr> </tr>
{% for rm in drive_properties['rm_conf']|sort(attribute='name') %} {% for rm in env['drive_properties']['rm_conf']|sort(attribute='name') %}
<tr> <tr>
<td align="center"> <td align="center">
{% if rm.url != "" %} {% if rm.url != "" %}

View File

@ -256,7 +256,7 @@
{% endif %} {% endif %}
<td align="center"> <td align="center">
<form action="/files/download" method="post"> <form action="/files/download" method="post">
<input name="file" type="hidden" value="{{ env["image_dir"] }}/{{ file['name'] }}"> <input name="file" type="hidden" value="{{ file['name'] }}">
<input type="submit" value="{{ file['size_mb'] }} {{ _("MiB") }} &#8595;"> <input type="submit" value="{{ file['size_mb'] }} {{ _("MiB") }} &#8595;">
</form> </form>
</td> </td>
@ -392,21 +392,21 @@
{{ _("None") }} {{ _("None") }}
</option> </option>
{% if type == "SCCD" %} {% if type == "SCCD" %}
{% for drive in drive_properties["cd_conf"] | sort(attribute='name') %} {% for drive in env["drive_properties"]["cd_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}"> <option value="{{ drive.name }}">
{{ drive.name }} {{ drive.name }}
</option> </option>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if type == "SCRM" %} {% if type == "SCRM" %}
{% for drive in drive_properties["rm_conf"] | sort(attribute='name') %} {% for drive in env["drive_properties"]["rm_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}"> <option value="{{ drive.name }}">
{{ drive.name }} {{ drive.name }}
</option> </option>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if type == "SCMO" %} {% if type == "SCMO" %}
{% for drive in drive_properties["mo_conf"] | sort(attribute='name') %} {% for drive in env["drive_properties"]["mo_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}"> <option value="{{ drive.name }}">
{{ drive.name }} {{ drive.name }}
</option> </option>
@ -581,7 +581,7 @@
<option value=""> <option value="">
{{ _("None") }} {{ _("None") }}
</option> </option>
{% for drive in drive_properties["hd_conf"] | sort(attribute='name') %} {% for drive in env["drive_properties"]["hd_conf"] | sort(attribute='name') %}
<option value="{{ drive.name }}"> <option value="{{ drive.name }}">
{{ drive.name }} {{ drive.name }}
</option> </option>

View File

@ -22,7 +22,6 @@ from flask import (
flash, flash,
url_for, url_for,
redirect, redirect,
send_file,
send_from_directory, send_from_directory,
make_response, make_response,
session, session,
@ -98,6 +97,7 @@ def get_env_info():
"cd_suffixes": tuple(server_info["sccd"]), "cd_suffixes": tuple(server_info["sccd"]),
"rm_suffixes": tuple(server_info["scrm"]), "rm_suffixes": tuple(server_info["scrm"]),
"mo_suffixes": tuple(server_info["scmo"]), "mo_suffixes": tuple(server_info["scmo"]),
"drive_properties": format_drive_properties(APP.config["RASCSI_DRIVE_PROPERTIES"]),
} }
@ -229,16 +229,6 @@ def index():
server_info["sccd"] server_info["sccd"]
) )
try:
drive_properties = format_drive_properties(APP.config["RASCSI_DRIVE_PROPERTIES"])
except:
drive_properties = {
"hd_conf": [],
"cd_conf": [],
"rm_conf": [],
"mo_conf": [],
}
return response( return response(
template="index.html", template="index.html",
locales=get_supported_locales(), locales=get_supported_locales(),
@ -257,7 +247,6 @@ def index():
reserved_scsi_ids=reserved_scsi_ids, reserved_scsi_ids=reserved_scsi_ids,
image_suffixes_to_create=image_suffixes_to_create, image_suffixes_to_create=image_suffixes_to_create,
valid_image_suffixes=valid_image_suffixes, valid_image_suffixes=valid_image_suffixes,
drive_properties=drive_properties,
max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024), max_file_size=int(int(MAX_FILE_SIZE) / 1024 / 1024),
RESERVATIONS=RESERVATIONS, RESERVATIONS=RESERVATIONS,
CFG_DIR=CFG_DIR, CFG_DIR=CFG_DIR,
@ -284,20 +273,10 @@ def drive_list():
""" """
Sets up the data structures and kicks off the rendering of the drive list page Sets up the data structures and kicks off the rendering of the drive list page
""" """
try:
drive_properties = format_drive_properties(APP.config["RASCSI_DRIVE_PROPERTIES"])
except:
drive_properties = {
"hd_conf": [],
"cd_conf": [],
"rm_conf": [],
"mo_conf": [],
}
return response( return response(
template="drives.html", template="drives.html",
files=file_cmd.list_images()["files"], files=file_cmd.list_images()["files"],
drive_properties=drive_properties,
) )
@ -310,8 +289,7 @@ def login():
password = request.form["password"] password = request.form["password"]
groups = [g.gr_name for g in getgrall() if username in g.gr_mem] groups = [g.gr_name for g in getgrall() if username in g.gr_mem]
if AUTH_GROUP in groups: if AUTH_GROUP in groups and authenticate(str(username), str(password)):
if authenticate(str(username), str(password)):
session["username"] = request.form["username"] session["username"] = request.form["username"]
return response(env=get_env_info()) return response(env=get_env_info())
@ -442,7 +420,8 @@ def config_load():
return response(error=True, message=process["msg"]) return response(error=True, message=process["msg"])
if "delete" in request.form: if "delete" in request.form:
process = file_cmd.delete_file(f"{CFG_DIR}/{file_name}") file_path = Path(CFG_DIR) / file_name
process = file_cmd.delete_file(file_path)
process = ReturnCodeMapper.add_msg(process) process = ReturnCodeMapper.add_msg(process)
if process["status"]: if process["status"]:
return response(message=process["msg"]) return response(message=process["msg"])
@ -954,8 +933,9 @@ def download():
""" """
Downloads a file from the Pi to the local computer Downloads a file from the Pi to the local computer
""" """
image = request.form.get("file") file_name = request.form.get("file")
return send_file(image, as_attachment=True) server_info = ractl_cmd.get_server_info()
return send_from_directory(server_info["image_dir"], file_name, as_attachment=True)
@APP.route("/files/delete", methods=["POST"]) @APP.route("/files/delete", methods=["POST"])
@ -974,8 +954,8 @@ def delete():
(_("Image file deleted: %(file_name)s", file_name=file_name), "success")] (_("Image file deleted: %(file_name)s", file_name=file_name), "success")]
# Delete the drive properties file, if it exists # Delete the drive properties file, if it exists
prop_file_path = f"{CFG_DIR}/{file_name}.{PROPERTIES_SUFFIX}" prop_file_path = Path(CFG_DIR) / f"{file_name}.{PROPERTIES_SUFFIX}"
if Path(prop_file_path).is_file(): if prop_file_path.is_file():
process = file_cmd.delete_file(prop_file_path) process = file_cmd.delete_file(prop_file_path)
process = ReturnCodeMapper.add_msg(process) process = ReturnCodeMapper.add_msg(process)
if process["status"]: if process["status"]:
@ -1003,9 +983,9 @@ def rename():
(_("Image file renamed to: %(file_name)s", file_name=new_file_name), "success")] (_("Image file renamed to: %(file_name)s", file_name=new_file_name), "success")]
# Rename the drive properties file, if it exists # Rename the drive properties file, if it exists
prop_file_path = f"{CFG_DIR}/{file_name}.{PROPERTIES_SUFFIX}" prop_file_path = Path(CFG_DIR) / f"{file_name}.{PROPERTIES_SUFFIX}"
new_prop_file_path = f"{CFG_DIR}/{new_file_name}.{PROPERTIES_SUFFIX}" new_prop_file_path = Path(CFG_DIR) / f"{new_file_name}.{PROPERTIES_SUFFIX}"
if Path(prop_file_path).is_file(): if prop_file_path.is_file():
process = file_cmd.rename_file(prop_file_path, new_prop_file_path) process = file_cmd.rename_file(prop_file_path, new_prop_file_path)
process = ReturnCodeMapper.add_msg(process) process = ReturnCodeMapper.add_msg(process)
if process["status"]: if process["status"]:
@ -1033,9 +1013,9 @@ def copy():
(_("Copy of image file saved as: %(file_name)s", file_name=new_file_name), "success")] (_("Copy of image file saved as: %(file_name)s", file_name=new_file_name), "success")]
# Create a copy of the drive properties file, if it exists # Create a copy of the drive properties file, if it exists
prop_file_path = f"{CFG_DIR}/{file_name}.{PROPERTIES_SUFFIX}" prop_file_path = Path(CFG_DIR) / f"{file_name}.{PROPERTIES_SUFFIX}"
new_prop_file_path = f"{CFG_DIR}/{new_file_name}.{PROPERTIES_SUFFIX}" new_prop_file_path = Path(CFG_DIR) / f"{new_file_name}.{PROPERTIES_SUFFIX}"
if Path(prop_file_path).is_file(): if prop_file_path.is_file():
process = file_cmd.copy_file(prop_file_path, new_prop_file_path) process = file_cmd.copy_file(prop_file_path, new_prop_file_path)
process = ReturnCodeMapper.add_msg(process) process = ReturnCodeMapper.add_msg(process)
if process["status"]: if process["status"]:
@ -1171,8 +1151,10 @@ if __name__ == "__main__":
if process["status"]: if process["status"]:
APP.config["RASCSI_DRIVE_PROPERTIES"] = process["conf"] APP.config["RASCSI_DRIVE_PROPERTIES"] = process["conf"]
else: else:
APP.config["RASCSI_DRIVE_PROPERTIES"] = []
logging.error(process["msg"]) logging.error(process["msg"])
else: else:
APP.config["RASCSI_DRIVE_PROPERTIES"] = []
logging.warning("Could not read drive properties from %s", DRIVE_PROPERTIES_FILE) logging.warning("Could not read drive properties from %s", DRIVE_PROPERTIES_FILE)
logging.basicConfig(stream=sys.stdout, logging.basicConfig(stream=sys.stdout,

View File

@ -294,18 +294,7 @@ def upload_with_dropzonejs(image_dir):
if current_chunk + 1 == total_chunks: if current_chunk + 1 == total_chunks:
# Validate the resulting file size after writing the last chunk # Validate the resulting file size after writing the last chunk
if path.getsize(save_path) != int(request.form["dztotalfilesize"]): if path.getsize(save_path) != int(request.form["dztotalfilesize"]):
log.error( log.error("File size mismatch between the original file and transferred file.")
"Finished transferring %s, "
"but it has a size mismatch with the original file. "
"Got %s but we expected %s.",
file_object.filename,
path.getsize(save_path),
request.form['dztotalfilesize'],
)
return make_response(_("Transferred file corrupted!"), 500) return make_response(_("Transferred file corrupted!"), 500)
log.info("File %s has been uploaded successfully", file_object.filename)
log.debug("Chunk %s of %s for file %s completed.",
current_chunk + 1, total_chunks, file_object.filename)
return make_response(_("File upload successful!"), 200) return make_response(_("File upload successful!"), 200)

View File

@ -3,6 +3,7 @@ from conftest import STATUS_SUCCESS, STATUS_ERROR
# route("/login", methods=["POST"]) # route("/login", methods=["POST"])
def test_login_with_valid_credentials(pytestconfig, http_client_unauthenticated): def test_login_with_valid_credentials(pytestconfig, http_client_unauthenticated):
# Note: This test depends on the rascsi group existing and 'username' a member the group
response = http_client_unauthenticated.post( response = http_client_unauthenticated.post(
"/login", "/login",
data={ data={

View File

@ -201,7 +201,7 @@ def test_upload_file(http_client, delete_file):
def test_download_file(http_client, create_test_image): def test_download_file(http_client, create_test_image):
file_name = create_test_image() file_name = create_test_image()
response = http_client.post("/files/download", data={"file": f"{IMAGES_DIR}/{file_name}"}) response = http_client.post("/files/download", data={"file": file_name})
assert response.status_code == 200 assert response.status_code == 200
assert response.headers["content-type"] == "application/octet-stream" assert response.headers["content-type"] == "application/octet-stream"

View File

@ -42,7 +42,7 @@ def test_show_named_drive_presets(http_client):
assert response.status_code == 200 assert response.status_code == 200
assert response_data["status"] == STATUS_SUCCESS assert response_data["status"] == STATUS_SUCCESS
assert "drive_properties" in response_data["data"] assert "files" in response_data["data"]
# route("/drive/cdrom", methods=["POST"]) # route("/drive/cdrom", methods=["POST"])