Skip to content

Commit 3b7f777

Browse files
Merge branch 'feat/extensions' of https://github.com/Geode-solutions/OpenGeodeWeb-Back into feat/extensions
2 parents 5c99282 + 069cc6a commit 3b7f777

7 files changed

Lines changed: 39 additions & 19 deletions

File tree

opengeodeweb_back_schemas.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,17 @@
343343
"required": [],
344344
"additionalProperties": false
345345
},
346+
"import_extension": {
347+
"$id": "opengeodeweb_back/import_extension",
348+
"route": "/import_extension",
349+
"methods": [
350+
"POST"
351+
],
352+
"type": "object",
353+
"properties": {},
354+
"required": [],
355+
"additionalProperties": false
356+
},
346357
"geographic_coordinate_systems": {
347358
"$id": "opengeodeweb_back/geographic_coordinate_systems",
348359
"route": "/geographic_coordinate_systems",

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,3 @@ werkzeug==3.1.2
6060
# flask
6161
# flask-cors
6262

63-
opengeodeweb-microservice==1.*,>=1.0.11

src/opengeodeweb_back/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ def run_server() -> None:
147147
)
148148
args = parser.parse_args()
149149
app.config.update(DATA_FOLDER_PATH=args.data_folder_path)
150+
app.config.update(
151+
EXTENSIONS_FOLDER_PATH=os.path.join(args.data_folder_path, "extensions")
152+
)
150153
app.config.update(UPLOAD_FOLDER=args.upload_folder_path)
151154
app.config.update(MINUTES_BEFORE_TIMEOUT=args.timeout)
152155
flask_cors.CORS(app, origins=args.allowed_origins)

src/opengeodeweb_back/app_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ProdConfig(Config):
2424
MINUTES_BEFORE_TIMEOUT = "1"
2525
SECONDS_BETWEEN_SHUTDOWNS = "10"
2626
DATA_FOLDER_PATH = "/data"
27+
EXTENSIONS_FOLDER_PATH = os.path.join(DATA_FOLDER_PATH, "extensions")
2728

2829

2930
class DevConfig(Config):
@@ -33,3 +34,4 @@ class DevConfig(Config):
3334
SECONDS_BETWEEN_SHUTDOWNS = "10"
3435
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
3536
DATA_FOLDER_PATH = os.path.join(BASE_DIR, "data")
37+
EXTENSIONS_FOLDER_PATH = os.path.join(DATA_FOLDER_PATH, "extensions")

src/opengeodeweb_back/routes/blueprint_routes.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -525,11 +525,9 @@ def import_extension() -> flask.Response:
525525
flask.abort(400, "Uploaded file must be a .vext")
526526

527527
# Create extensions directory in the data folder
528-
data_folder_path: str = flask.current_app.config.get("DATA_FOLDER_PATH", "")
529-
extensions_folder = os.path.join(data_folder_path, "extensions")
528+
extensions_folder = flask.current_app.config["EXTENSIONS_FOLDER_PATH"]
530529
os.makedirs(extensions_folder, exist_ok=True)
531530

532-
# Extract extension name from filename (e.g., "vease-modeling-0.0.0.vext" -> "vease-modeling")
533531
extension_name = (
534532
filename.rsplit("-", 1)[0] if "-" in filename else filename.replace(".vext", "")
535533
)
@@ -561,23 +559,23 @@ def import_extension() -> flask.Response:
561559
if file.endswith(".es.js"):
562560
frontend_file = file_path
563561
elif not file.endswith(".js") and not file.endswith(".css"):
564-
# Assume it's the backend executable
565562
backend_executable = file_path
566-
# Make it executable
567563
os.chmod(backend_executable, 0o755)
568564

569565
if not frontend_file:
570566
flask.abort(400, "Invalid .vext file: missing frontend JavaScript")
571-
572567
if not backend_executable:
573568
flask.abort(400, "Invalid .vext file: missing backend executable")
574569

570+
assert frontend_file is not None
571+
with open(frontend_file, "r", encoding="utf-8") as f:
572+
frontend_content = f.read()
573+
575574
return flask.make_response(
576575
{
577576
"extension_name": extension_name,
578-
"frontend_path": frontend_file,
577+
"frontend_content": frontend_content,
579578
"backend_path": backend_executable,
580-
"extension_folder": extension_path,
581579
},
582580
200,
583581
)

src/opengeodeweb_back/routes/schemas/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from .kill import *
1010
from .inspect_file import *
1111
from .import_project import *
12+
from .import_extension import *
1213
from .geographic_coordinate_systems import *
1314
from .geode_objects_and_output_extensions import *
1415
from .export_project import *
1516
from .cell_attribute_names import *
1617
from .allowed_objects import *
1718
from .allowed_files import *
18-
from .import_extension import *

tests/test_models_routes.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,10 @@ def test_import_extension_route(client: FlaskClient, tmp_path: Path) -> None:
231231
"""Test importing a .vext extension file."""
232232
route = "/opengeodeweb_back/import_extension"
233233
original_data_folder = client.application.config["DATA_FOLDER_PATH"]
234-
client.application.config["DATA_FOLDER_PATH"] = os.path.join(
235-
str(tmp_path), "extension_test_data"
234+
new_data_folder = os.path.join(str(tmp_path), "extension_test_data")
235+
client.application.config["DATA_FOLDER_PATH"] = new_data_folder
236+
client.application.config["EXTENSIONS_FOLDER_PATH"] = os.path.join(
237+
new_data_folder, "extensions"
236238
)
237239
vext_path = tmp_path / "test-extension-1.0.0.vext"
238240
with zipfile.ZipFile(vext_path, "w", compression=zipfile.ZIP_DEFLATED) as zipf:
@@ -251,9 +253,8 @@ def test_import_extension_route(client: FlaskClient, tmp_path: Path) -> None:
251253
assert response.status_code == 200
252254
json_data = response.get_json()
253255
assert "extension_name" in json_data
254-
assert "frontend_path" in json_data
256+
assert "frontend_content" in json_data
255257
assert "backend_path" in json_data
256-
assert "extension_folder" in json_data
257258
assert json_data["extension_name"] == "test-extension"
258259
extensions_folder = os.path.join(
259260
client.application.config["DATA_FOLDER_PATH"], "extensions"
@@ -262,9 +263,13 @@ def test_import_extension_route(client: FlaskClient, tmp_path: Path) -> None:
262263
assert os.path.exists(extension_path)
263264
dist_path = os.path.join(extension_path, "dist")
264265
assert os.path.exists(dist_path)
265-
frontend_js = json_data["frontend_path"]
266-
assert os.path.exists(frontend_js)
267-
assert frontend_js.endswith("-extension.es.js")
266+
267+
# Verify frontend content is returned
268+
frontend_content = json_data["frontend_content"]
269+
assert isinstance(frontend_content, str)
270+
assert len(frontend_content) > 0
271+
assert "export const metadata" in frontend_content
272+
268273
backend_exec = json_data["backend_path"]
269274
assert os.path.exists(backend_exec)
270275
assert os.access(backend_exec, os.X_OK)
@@ -275,8 +280,10 @@ def test_import_extension_invalid_file(client: FlaskClient, tmp_path: Path) -> N
275280
"""Test importing an invalid .vext file (missing dist folder)."""
276281
route = "/opengeodeweb_back/import_extension"
277282
original_data_folder = client.application.config["DATA_FOLDER_PATH"]
278-
client.application.config["DATA_FOLDER_PATH"] = os.path.join(
279-
str(tmp_path), "extension_invalid_test"
283+
new_data_folder = os.path.join(str(tmp_path), "extension_invalid_test")
284+
client.application.config["DATA_FOLDER_PATH"] = new_data_folder
285+
client.application.config["EXTENSIONS_FOLDER_PATH"] = os.path.join(
286+
new_data_folder, "extensions"
280287
)
281288
vext_path = tmp_path / "invalid-extension.vext"
282289
with zipfile.ZipFile(vext_path, "w") as zipf:

0 commit comments

Comments
 (0)