Skip to content

Commit e90175a

Browse files
committed
ask database for data entries to generate the zip file
1 parent c6ad376 commit e90175a

File tree

1 file changed

+59
-33
lines changed

1 file changed

+59
-33
lines changed

src/opengeodeweb_back/routes/blueprint_routes.py

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Standard library imports
2+
from posixpath import relpath
23
import os
34
import time
45
import shutil
@@ -14,6 +15,8 @@
1415
from opengeodeweb_back import geode_functions, utils_functions
1516
from .models import blueprint_models
1617
from . import schemas
18+
from opengeodeweb_microservice.database.data import Data
19+
from opengeodeweb_microservice.database.connection import get_session
1720

1821
routes = flask.Blueprint("routes", __name__, url_prefix="/opengeodeweb_back")
1922

@@ -280,22 +283,46 @@ def export_project() -> flask.Response:
280283
utils_functions.validate_request(flask.request, schemas_dict["export_project"])
281284
params = schemas.ExportProject.from_dict(flask.request.get_json())
282285

283-
data_folder_path: str = flask.current_app.config["DATA_FOLDER_PATH"]
284-
upload_folder: str = flask.current_app.config["UPLOAD_FOLDER"]
285-
os.makedirs(upload_folder, exist_ok=True)
286+
project_folder: str = flask.current_app.config["DATA_FOLDER_PATH"]
287+
os.makedirs(project_folder, exist_ok=True)
288+
289+
if not params.filename:
290+
flask.abort(400, "filename is required")
291+
filename: str = werkzeug.utils.secure_filename(os.path.basename(params.filename))
292+
export_zip_path = os.path.join(project_folder, filename)
293+
294+
with get_session() as session:
295+
entries = [
296+
{
297+
"id": entry.id,
298+
"input_file": entry.input_file,
299+
"additional_files": entry.additional_files,
300+
}
301+
for entry in session.query(Data).all()
302+
]
303+
304+
with zipfile.ZipFile(export_zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_file:
305+
database_root_path = os.path.join(project_folder, "project.db")
306+
if os.path.isfile(database_root_path):
307+
zip_file.write(database_root_path, "project.db")
308+
309+
for entry in entries:
310+
base_dir = os.path.join(project_folder, entry["id"])
311+
312+
input_file = entry["input_file"]
313+
if input_file:
314+
in_path = os.path.join(base_dir, input_file)
315+
if os.path.isfile(in_path):
316+
zip_file.write(in_path, os.path.join(entry["id"], input_file))
317+
318+
for relative_path in entry["additional_files"] or []:
319+
add_path = os.path.join(base_dir, relative_path)
320+
if os.path.isfile(add_path):
321+
zip_file.write(add_path, os.path.join(entry["id"], relative_path))
286322

287-
filename: str = params.filename or f"project_{int(time.time())}.zip"
288-
export_zip_path = os.path.join(upload_folder, filename)
289-
290-
with zipfile.ZipFile(export_zip_path, "w", compression=8) as zip_file:
291-
pattern = os.path.join(data_folder_path, "**", "*")
292-
for full_path in glob.glob(pattern, recursive=True):
293-
if os.path.isfile(full_path):
294-
archive_name = os.path.relpath(full_path, start=data_folder_path)
295-
zip_file.write(full_path, archive_name)
296323
zip_file.writestr("snapshot.json", flask.json.dumps(params.snapshot))
297324

298-
return utils_functions.send_file(upload_folder, [export_zip_path], filename)
325+
return utils_functions.send_file(project_folder, [export_zip_path], filename)
299326

300327

301328
@routes.route(
@@ -313,31 +340,30 @@ def import_project() -> flask.Response:
313340
if not filename.lower().endswith(".zip"):
314341
flask.abort(400, "Uploaded file must be a .zip")
315342

316-
data_folder_path: str = flask.current_app.config["DATA_FOLDER_PATH"]
317-
os.makedirs(data_folder_path, exist_ok=True)
318-
for entry in os.listdir(data_folder_path):
319-
entry_path = os.path.join(data_folder_path, entry)
320-
try:
321-
if os.path.isdir(entry_path):
322-
shutil.rmtree(entry_path, ignore_errors=True)
323-
else:
324-
os.remove(entry_path)
325-
except FileNotFoundError:
326-
pass
327-
except PermissionError:
328-
flask.abort(423, "Project files are locked; cannot overwrite")
343+
project_folder_path: str = flask.current_app.config["DATA_FOLDER_PATH"]
344+
try:
345+
if os.path.exists(project_folder_path):
346+
shutil.rmtree(project_folder_path)
347+
os.makedirs(project_folder_path, exist_ok=True)
348+
except PermissionError:
349+
flask.abort(423, "Project files are locked; cannot overwrite")
329350

330351
zip_file.stream.seek(0)
331-
with zipfile.ZipFile(zip_file.stream) as zf:
332-
base = os.path.abspath(data_folder_path)
333-
for member in zf.namelist():
334-
target = os.path.abspath(os.path.normpath(os.path.join(base, member)))
335-
if not (target == base or target.startswith(base + os.sep)):
352+
with zipfile.ZipFile(zip_file.stream) as zip_archive:
353+
project_folder = os.path.abspath(project_folder_path)
354+
for member in zip_archive.namelist():
355+
target = os.path.abspath(os.path.normpath(os.path.join(project_folder, member)))
356+
if not (target == project_folder or target.startswith(project_folder + os.sep)):
336357
flask.abort(400, "Zip contains unsafe paths")
337-
zf.extractall(data_folder_path)
358+
zip_archive.extractall(project_folder)
359+
360+
database_root_path = os.path.join(project_folder, "project.db")
361+
if not os.path.isfile(database_root_path):
362+
flask.abort(400, "Missing project.db at project root")
363+
338364
snapshot = {}
339365
try:
340-
raw = zf.read("snapshot.json").decode("utf-8")
366+
raw = zip_archive.read("snapshot.json").decode("utf-8")
341367
snapshot = flask.json.loads(raw)
342368
except KeyError:
343369
snapshot = {}

0 commit comments

Comments
 (0)