mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add comments
This commit is contained in:
parent
407ca4c0bb
commit
0aae82448b
@ -5,6 +5,7 @@ import pathlib
|
|||||||
import tempfile
|
import tempfile
|
||||||
import zipfile
|
import zipfile
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from typing import BinaryIO
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
||||||
import urllib.request
|
import urllib.request
|
||||||
@ -150,7 +151,11 @@ class FileHelpers:
|
|||||||
return m_type
|
return m_type
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_file_hash(file_path):
|
def calculate_file_hash(file_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Takes one parameter of file path.
|
||||||
|
It will generate a SHA256 hash for the path and return it.
|
||||||
|
"""
|
||||||
sha256_hash = hashlib.sha256()
|
sha256_hash = hashlib.sha256()
|
||||||
with open(file_path, "rb") as f:
|
with open(file_path, "rb") as f:
|
||||||
for byte_block in iter(lambda: f.read(4096), b""):
|
for byte_block in iter(lambda: f.read(4096), b""):
|
||||||
@ -158,7 +163,11 @@ class FileHelpers:
|
|||||||
return sha256_hash.hexdigest()
|
return sha256_hash.hexdigest()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_buffer_hash(buffer):
|
def calculate_buffer_hash(buffer: BinaryIO) -> str:
|
||||||
|
"""
|
||||||
|
Takes one argument of a stream buffer. Will return a
|
||||||
|
sha256 hash of the buffer
|
||||||
|
"""
|
||||||
sha256_hash = hashlib.sha256()
|
sha256_hash = hashlib.sha256()
|
||||||
sha256_hash.update(buffer)
|
sha256_hash.update(buffer)
|
||||||
return sha256_hash.hexdigest()
|
return sha256_hash.hexdigest()
|
||||||
|
@ -43,6 +43,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
accepted_types = []
|
accepted_types = []
|
||||||
|
|
||||||
if server_id:
|
if server_id:
|
||||||
|
# Check to make sure user is authorized for the server
|
||||||
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
|
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
|
||||||
# if the user doesn't have access to the server, return an error
|
# if the user doesn't have access to the server, return an error
|
||||||
return self.finish_json(
|
return self.finish_json(
|
||||||
@ -54,6 +55,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
),
|
),
|
||||||
auth_data[5],
|
auth_data[5],
|
||||||
)
|
)
|
||||||
|
# Make sure user has file access for the server
|
||||||
server_permissions = self.controller.server_perms.get_permissions(mask)
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
if EnumPermissionsServer.FILES not in server_permissions:
|
if EnumPermissionsServer.FILES not in server_permissions:
|
||||||
# if the user doesn't have Files permission, return an error
|
# if the user doesn't have Files permission, return an error
|
||||||
@ -62,6 +64,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
u_type = "server_upload"
|
u_type = "server_upload"
|
||||||
|
# Make sure user is a super user if they're changing panel settings
|
||||||
elif auth_data[4]["superuser"] and upload_type == "background":
|
elif auth_data[4]["superuser"] and upload_type == "background":
|
||||||
u_type = "admin_config"
|
u_type = "admin_config"
|
||||||
self.upload_dir = os.path.join(
|
self.upload_dir = os.path.join(
|
||||||
@ -70,6 +73,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
)
|
)
|
||||||
accepted_types = IMAGE_MIME_TYPES
|
accepted_types = IMAGE_MIME_TYPES
|
||||||
elif upload_type == "import":
|
elif upload_type == "import":
|
||||||
|
# Check that user can make servers
|
||||||
if (
|
if (
|
||||||
not self.controller.crafty_perms.can_create_server(
|
not self.controller.crafty_perms.can_create_server(
|
||||||
auth_data[4]["user_id"]
|
auth_data[4]["user_id"]
|
||||||
@ -84,6 +88,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
"data": {"message": ""},
|
"data": {"message": ""},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
# Set directory to upload import dir
|
||||||
self.upload_dir = os.path.join(
|
self.upload_dir = os.path.join(
|
||||||
self.controller.project_root, "import", "upload"
|
self.controller.project_root, "import", "upload"
|
||||||
)
|
)
|
||||||
@ -117,8 +122,11 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
self.temp_dir = os.path.join(self.controller.project_root, "temp", self.file_id)
|
self.temp_dir = os.path.join(self.controller.project_root, "temp", self.file_id)
|
||||||
|
|
||||||
if u_type == "server_upload":
|
if u_type == "server_upload":
|
||||||
|
# If this is an upload from a server the path will be what
|
||||||
|
# Is requested
|
||||||
full_path = os.path.join(self.upload_dir, self.filename)
|
full_path = os.path.join(self.upload_dir, self.filename)
|
||||||
|
|
||||||
|
# Check to make sure the requested path is inside the server's directory
|
||||||
if not self.helper.is_subdir(
|
if not self.helper.is_subdir(
|
||||||
full_path,
|
full_path,
|
||||||
Helpers.get_os_understandable_path(
|
Helpers.get_os_understandable_path(
|
||||||
@ -133,7 +141,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
"data": {"message": "Traversal detected"},
|
"data": {"message": "Traversal detected"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
# Check to make sure the file type we're being sent is what we're expecting
|
||||||
if (
|
if (
|
||||||
self.file_helper.check_mime_types(self.filename) not in accepted_types
|
self.file_helper.check_mime_types(self.filename) not in accepted_types
|
||||||
and u_type != "server_upload"
|
and u_type != "server_upload"
|
||||||
@ -166,20 +174,29 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
return self.finish_json(
|
return self.finish_json(
|
||||||
200, {"status": "ok", "data": {"file-id": self.file_id}}
|
200, {"status": "ok", "data": {"file-id": self.file_id}}
|
||||||
)
|
)
|
||||||
|
# Create the upload and temp directories if they don't exist
|
||||||
|
os.makedirs(self.upload_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# Check for chunked header. We will handle this request differently
|
||||||
|
# if it doesn't exist
|
||||||
if not self.chunked:
|
if not self.chunked:
|
||||||
|
# Write the file directly to the upload dir
|
||||||
with open(os.path.join(self.upload_dir, self.filename), "wb") as file:
|
with open(os.path.join(self.upload_dir, self.filename), "wb") as file:
|
||||||
while True:
|
while True:
|
||||||
chunk = self.request.body
|
chunk = self.request.body
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
break
|
||||||
file.write(chunk)
|
file.write(chunk)
|
||||||
|
# We'll check the file hash against the sent hash once the file is
|
||||||
|
# written. We cannot check this buffer.
|
||||||
if (
|
if (
|
||||||
self.file_helper.calculate_file_hash(
|
self.file_helper.calculate_file_hash(
|
||||||
os.path.join(self.upload_dir, self.filename)
|
os.path.join(self.upload_dir, self.filename)
|
||||||
)
|
)
|
||||||
!= self.file_hash
|
!= self.file_hash
|
||||||
):
|
):
|
||||||
|
# If the hash is bad we'll delete the malformed file and send
|
||||||
|
# a warning
|
||||||
os.remove(os.path.join(self.upload_dir, self.filename))
|
os.remove(os.path.join(self.upload_dir, self.filename))
|
||||||
logger.error(
|
logger.error(
|
||||||
f"File upload failed. Filename: {self.filename}"
|
f"File upload failed. Filename: {self.filename}"
|
||||||
@ -206,9 +223,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
"data": {"message": "File uploaded successfully"},
|
"data": {"message": "File uploaded successfully"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
# Since this is a chunked upload we'll create the temp dir for parts.
|
||||||
# Create the upload and temp directories if they don't exist
|
|
||||||
os.makedirs(self.upload_dir, exist_ok=True)
|
|
||||||
os.makedirs(self.temp_dir, exist_ok=True)
|
os.makedirs(self.temp_dir, exist_ok=True)
|
||||||
|
|
||||||
# Read headers and query parameters
|
# Read headers and query parameters
|
||||||
@ -227,6 +242,8 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# At this point filename, chunk index and total chunks are required
|
||||||
|
# in the request
|
||||||
if not self.filename or self.chunk_index is None or total_chunks is None:
|
if not self.filename or self.chunk_index is None or total_chunks is None:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"File upload failed. Filename: {self.filename}"
|
f"File upload failed. Filename: {self.filename}"
|
||||||
@ -244,6 +261,7 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Calculate the hash of the buffer and compare it against the expected hash
|
||||||
calculated_hash = self.file_helper.calculate_buffer_hash(self.request.body)
|
calculated_hash = self.file_helper.calculate_buffer_hash(self.request.body)
|
||||||
if str(self.chunk_hash) != str(calculated_hash):
|
if str(self.chunk_hash) != str(calculated_hash):
|
||||||
logger.error(
|
logger.error(
|
||||||
@ -278,6 +296,8 @@ class ApiFilesUploadHandler(BaseApiHandler):
|
|||||||
for f in os.listdir(self.temp_dir)
|
for f in os.listdir(self.temp_dir)
|
||||||
if f.startswith(f"{self.filename}.part")
|
if f.startswith(f"{self.filename}.part")
|
||||||
]
|
]
|
||||||
|
# When we've reached the total chunks we'll
|
||||||
|
# Compare the hash and write the file
|
||||||
if len(received_chunks) == total_chunks:
|
if len(received_chunks) == total_chunks:
|
||||||
with open(file_path, "wb") as outfile:
|
with open(file_path, "wb") as outfile:
|
||||||
for i in range(total_chunks):
|
for i in range(total_chunks):
|
||||||
|
Loading…
Reference in New Issue
Block a user