From 7f9f7afe7332dbc09c0467aa1a62eff4b98fdacc Mon Sep 17 00:00:00 2001 From: supersonik12 Date: Fri, 10 Oct 2025 09:23:40 -0600 Subject: [PATCH 1/5] Changed XDC process in upload_sbs --- sbs_server/app/views.py | 105 ++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 70 deletions(-) diff --git a/sbs_server/app/views.py b/sbs_server/app/views.py index f83ccee..db4d89b 100644 --- a/sbs_server/app/views.py +++ b/sbs_server/app/views.py @@ -23,33 +23,60 @@ def get_data(): @app.route('/api/upload_sbs', methods = ['POST']) def upload_file_from_sbs_post(): + # Check Metadata excel template if 'Metadata' not in request.files: print(request) return 'No file part', 400 file = request.files['Metadata'] if file.filename == '': return 'No selected file', 400 - file_contents = file.read() + if not file.filename.contains('xlsx', 'xlsm'): + return 'Invalid Metadata file', 400 + + # # Experimental results to upload to SBH + # if 'Attachments' in request.files: + # attachments = request.files['Attachments'] + # # add to template somehow (?) + # # attachments = result + # else: + # attachments = None + + # # Plate reader data to upload to FJ + # if 'Experimental_Data' in request.files: + # data = request.files['Experimental_Data'] + # # Run XDE to add data to template (?) + # # data = result + # else: + # data = None + + # Check params from frontend if 'Params' not in request.files: return 'No Params file part', 400 params_file = request.files['Params'] if params_file.filename == '': return 'No selected Params file', 400 params_from_request = json.loads(params_file.read()) - expected_params = ['fj_url', 'fj_token', 'sbh_url', 'sbh_token', 'sbh_collec', 'sbh_collec_desc', 'sbh_overwrite', 'fj_overwrite'] - for param in expected_params: + required_params = ['sbh_url', 'sbh_token', 'sbh_user', 'sbh_pass', + 'fj_url', 'fj_token', 'fj_user', 'fj_pass', + 'sbh_collec', 'sbh_collec_desc', + 'sbh_overwrite', 'fj_overwrite'] + for param in required_params: if param not in params_from_request: return 'Parameter ' + param + ' not found in request', 400 + if (params_from_request['sbh_token'] is None and + params_from_request['sbh_user'] is None and + params_from_request['sbh_pass'] is None): + return 'No SBH credentials provided', 400 # instantiate the XDC class using the params_from_request dictionary print(request.files['Metadata']) xdc = tricahue.XDC(input_excel_path = request.files['Metadata'], fj_url = params_from_request['fj_url'], - fj_user = None, - fj_pass = None, + fj_user = params_from_request['fj_user'], + fj_pass = params_from_request['fj_pass'], sbh_url = params_from_request['sbh_url'], - sbh_user = None, - sbh_pass = None, + sbh_user = params_from_request['sbh_user'], + sbh_pass = params_from_request['sbh_pass'], sbh_collection = params_from_request['sbh_collec'], sbh_collection_description = params_from_request['sbh_collec_desc'], sbh_overwrite = params_from_request['sbh_overwrite'], @@ -60,13 +87,7 @@ def upload_file_from_sbs_post(): ) try: - xdc.initialize() - xdc.log_in_sbh() - xdc.log_in_fj() - xdc.convert_to_sbol() - xdc.generate_sbol_hash_map() - sbh_url = xdc.upload_to_sbh() - xdc.upload_to_fj() + sbh_url = xdc.run() except AttributeError as e: return jsonify({"error": str(e)}), 400 @@ -76,62 +97,6 @@ def upload_file_from_sbs_post(): } return jsonify(sbs_upload_response_dict) -@app.route('/api/upload_sbs_up', methods = ['POST']) -def upload_file_from_sbs_post_up(): - if 'Metadata' not in request.files: - print(request) - return 'No file part', 400 - file = request.files['Metadata'] - if file.filename == '': - return 'No selected file', 400 - file_contents = file.read() - if 'Params' not in request.files: - return 'No Params file part', 400 - params_file = request.files['Params'] - if params_file.filename == '': - return 'No selected Params file', 400 - params_from_request = json.loads(params_file.read()) - expected_params = ['fj_url', 'fj_user', 'fj_pass', 'sbh_url', 'sbh_user', 'sbh_pass', 'sbh_collec', 'sbh_collec_desc', 'sbh_overwrite', 'fj_overwrite'] - for param in expected_params: - if param not in params_from_request: - return 'Parameter ' + param + ' not found in request', 400 - - # instantiate the XDC class using the params_from_request dictionary - print(request.files['Metadata']) - xdc = tricahue.XDC(input_excel_path = request.files['Metadata'], - fj_url = params_from_request['fj_url'], - fj_user = params_from_request['fj_user'], - fj_pass = params_from_request['fj_pass'], - sbh_url = params_from_request['sbh_url'], - sbh_user = params_from_request['sbh_user'], - sbh_pass = params_from_request['sbh_pass'], - sbh_collection = params_from_request['sbh_collec'], - sbh_collection_description = params_from_request['sbh_collec_desc'], - sbh_overwrite = params_from_request['sbh_overwrite'], - fj_overwrite = params_from_request['fj_overwrite'], - fj_token = None, - sbh_token = None, - homespace = "https://synbiohub.org/gonza10v" - ) - - try: - xdc.initialize() - xdc.log_in_fj() - xdc.log_in_sbh() - xdc.convert_to_sbol() - xdc.generate_sbol_hash_map() - sbh_url = xdc.upload_to_sbh() - xdc.upload_to_fj() - except AttributeError as e: - return jsonify({"error": str(e)}), 400 - - sbs_upload_response_dict = { - "sbh_url": sbh_url, - "status": "success" - } - return jsonify(sbs_upload_response_dict) - - @app.route('/sbol_2_build_golden_gate', methods=['POST']) def sbol_2_build_golden_gate(): From b4a86175a15d37053b1b234889ce249a4d358652 Mon Sep 17 00:00:00 2001 From: supersonik12 Date: Fri, 24 Oct 2025 12:19:02 -0600 Subject: [PATCH 2/5] Added SBH attachment option to upload_sbs route --- Dockerfile | 2 +- requirements.txt | 2 +- sbs_server/app/views.py | 28 +++++++++++++++++----------- sbs_server/files/sbs_params.json | 20 +++++++++++++------- sbs_server/files/sbs_params_up.json | 12 ------------ 5 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 sbs_server/files/sbs_params_up.json diff --git a/Dockerfile b/Dockerfile index e960b84..395fbf3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ EXPOSE 5003 # Install requirements COPY requirements.txt /app/ RUN /usr/local/bin/python -m pip install --upgrade pip -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install -r requirements.txt # Create uploads directory RUN mkdir -p /app/uploads && \ diff --git a/requirements.txt b/requirements.txt index a89f062..7664a14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ pandas==1.3.3 pyflapjack @ git+https://github.com/flapjacksynbio/pyFlapjack@xdc_features2 excel2flapjack==1.0.11 # tricahue==0.0b5 -tricahue @ git+https://github.com/MyersResearchGroup/Tricahue/@dev +tricahue @ git+https://github.com/MyersResearchGroup/Tricahue/@saanika_dev sbol2build flask_swagger_ui xlsxwriter diff --git a/sbs_server/app/views.py b/sbs_server/app/views.py index db4d89b..84fc225 100644 --- a/sbs_server/app/views.py +++ b/sbs_server/app/views.py @@ -30,17 +30,10 @@ def upload_file_from_sbs_post(): file = request.files['Metadata'] if file.filename == '': return 'No selected file', 400 - if not file.filename.contains('xlsx', 'xlsm'): - return 'Invalid Metadata file', 400 + root, extension = os.path.splitext(file.filename) + if not extension == '.xlsx' and not extension == '.xlsm': + return 'Invalid Metadata file format', 400 - # # Experimental results to upload to SBH - # if 'Attachments' in request.files: - # attachments = request.files['Attachments'] - # # add to template somehow (?) - # # attachments = result - # else: - # attachments = None - # # Plate reader data to upload to FJ # if 'Experimental_Data' in request.files: # data = request.files['Experimental_Data'] @@ -68,6 +61,17 @@ def upload_file_from_sbs_post(): params_from_request['sbh_pass'] is None): return 'No SBH credentials provided', 400 + # Attachment files to upload to SBH + if 'Attachments' in request.files and 'attachTo' in params_from_request: + attachments = [] + for file in request.files.getlist('Attachments'): + print(file.filename) + attachments.append(file) + attachTo = params_from_request['attachTo'] + else: + attachments = None + attachTo = None + # instantiate the XDC class using the params_from_request dictionary print(request.files['Metadata']) xdc = tricahue.XDC(input_excel_path = request.files['Metadata'], @@ -83,7 +87,9 @@ def upload_file_from_sbs_post(): fj_overwrite = params_from_request['fj_overwrite'], fj_token = params_from_request['fj_token'], sbh_token = params_from_request['sbh_token'], - homespace = "https://synbiohub.org/gonza10v" + homespace = "https://example.org/", + attachments = attachments, + attachTo = attachTo ) try: diff --git a/sbs_server/files/sbs_params.json b/sbs_server/files/sbs_params.json index db25b44..2dae8d9 100644 --- a/sbs_server/files/sbs_params.json +++ b/sbs_server/files/sbs_params.json @@ -1,10 +1,16 @@ { - "fj_url": "charmmefj-api.synbiohub.org", - "fj_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzU0NDE1ODYyLCJqdGkiOiI0ZDk5NmI0MjkxMjM0YzdmOGNlNTIzMTZlMGMzZmMwNSIsInVzZXJfaWQiOjJ9.Jc3g4aHGR-OfTrA6nM6b1PDsxx0yigfZvyTPRKcgX4w", "sbh_url": "https://synbiohub.org", - "sbh_token": "3e293de1-6181-47d3-a104-4312182fb675", - "sbh_collec": "xdc_sbs_test_uploader_file", - "sbh_collec_desc": "xdc_sbs_test_uploader_file_description", - "fj_overwrite": false, - "sbh_overwrite": false + "sbh_token": null, + "sbh_user": "synbiotest", + "sbh_pass": "test123", + "fj_url": "charmmefj-api.synbiohub.org", + "fj_token": null, + "fj_user": null, + "fj_pass": null, + "sbh_collec": "sbs_backend_test", + "sbh_collec_desc": "Uploaded via SBS_server using XDC to SBH", + "sbh_overwrite": 1, + "fj_overwrite": 1, + "version": "", + "attachTo": "ExampleMedia" } \ No newline at end of file diff --git a/sbs_server/files/sbs_params_up.json b/sbs_server/files/sbs_params_up.json deleted file mode 100644 index debe8fe..0000000 --- a/sbs_server/files/sbs_params_up.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "fj_url": "charmmefj-api.synbiohub.org", - "fj_user": "test", - "fj_pass": "test123", - "sbh_url": "https://synbiohub.org", - "sbh_user": "test@test.test", - "sbh_pass": "test123", - "sbh_collec": "xdc_sbs_test_uploader_file", - "sbh_collec_desc": "xdc_sbs_test_uploader_file_description", - "fj_overwrite": false, - "sbh_overwrite": false -} \ No newline at end of file From 32c6703f5be581adae3a3a1d13127484065451dd Mon Sep 17 00:00:00 2001 From: supersonik12 Date: Fri, 14 Nov 2025 10:02:29 -0700 Subject: [PATCH 3/5] uploadResource and uploadExperiment endpoints --- requirements.txt | 2 +- sbs_server/app/views.py | 55 ++++++++++++++++---------------- sbs_server/files/sbs_params.json | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7664a14..e75ec2a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ pandas==1.3.3 pyflapjack @ git+https://github.com/flapjacksynbio/pyFlapjack@xdc_features2 excel2flapjack==1.0.11 # tricahue==0.0b5 -tricahue @ git+https://github.com/MyersResearchGroup/Tricahue/@saanika_dev +tricahue @ git+https://github.com/MyersResearchGroup/Tricahue sbol2build flask_swagger_ui xlsxwriter diff --git a/sbs_server/app/views.py b/sbs_server/app/views.py index 84fc225..5c4ceb4 100644 --- a/sbs_server/app/views.py +++ b/sbs_server/app/views.py @@ -17,35 +17,41 @@ def pin(): return jsonify({"status": "working"}), 200 -@app.route("/api/data") -def get_data(): - return app.send_static_file("data.json") - -@app.route('/api/upload_sbs', methods = ['POST']) -def upload_file_from_sbs_post(): - # Check Metadata excel template - if 'Metadata' not in request.files: +@app.route('/api/uploadResource', methods = ['POST']) +def upload_resource(): + return sbh_fj_upload(request.files) + +@app.route('/api/uploadExperiment', methods = ['POST']) +def upload_experiment(): + return sbh_fj_upload(request.files) + +''' +Helper function to upload to SynBioHub and Flapjack using XDC/XDE +''' +def sbh_fj_upload(files): + + if 'Metadata' not in files: print(request) return 'No file part', 400 - file = request.files['Metadata'] - if file.filename == '': + metadata_file = files['Metadata'] + if metadata_file.filename == '': return 'No selected file', 400 - root, extension = os.path.splitext(file.filename) + root, extension = os.path.splitext(metadata_file.filename) if not extension == '.xlsx' and not extension == '.xlsm': return 'Invalid Metadata file format', 400 # # Plate reader data to upload to FJ # if 'Experimental_Data' in request.files: - # data = request.files['Experimental_Data'] + # experimental = request.files['Experimental_Data'] # # Run XDE to add data to template (?) - # # data = result + # # experimental = result # else: - # data = None + # experimental = None # Check params from frontend - if 'Params' not in request.files: + if 'Params' not in files: return 'No Params file part', 400 - params_file = request.files['Params'] + params_file = files['Params'] if params_file.filename == '': return 'No selected Params file', 400 params_from_request = json.loads(params_file.read()) @@ -62,19 +68,15 @@ def upload_file_from_sbs_post(): return 'No SBH credentials provided', 400 # Attachment files to upload to SBH - if 'Attachments' in request.files and 'attachTo' in params_from_request: - attachments = [] - for file in request.files.getlist('Attachments'): - print(file.filename) - attachments.append(file) - attachTo = params_from_request['attachTo'] + if 'Attachments' in files and 'attachments' in params_from_request: + attachment_files = files.getlist("Attachments") + attachments = {params_from_request['attachments'][file.filename] : file for file in attachment_files} + print(attachments) else: attachments = None - attachTo = None # instantiate the XDC class using the params_from_request dictionary - print(request.files['Metadata']) - xdc = tricahue.XDC(input_excel_path = request.files['Metadata'], + xdc = tricahue.XDC(input_excel_path = files['Metadata'], fj_url = params_from_request['fj_url'], fj_user = params_from_request['fj_user'], fj_pass = params_from_request['fj_pass'], @@ -88,8 +90,7 @@ def upload_file_from_sbs_post(): fj_token = params_from_request['fj_token'], sbh_token = params_from_request['sbh_token'], homespace = "https://example.org/", - attachments = attachments, - attachTo = attachTo + attachments = attachments ) try: diff --git a/sbs_server/files/sbs_params.json b/sbs_server/files/sbs_params.json index 2dae8d9..543a08e 100644 --- a/sbs_server/files/sbs_params.json +++ b/sbs_server/files/sbs_params.json @@ -12,5 +12,5 @@ "sbh_overwrite": 1, "fj_overwrite": 1, "version": "", - "attachTo": "ExampleMedia" + "attachments": {"example.jpg":"ExampleMedia", "ExpNOTs_GFP_trans.xlsx":"LB"} } \ No newline at end of file From 129e94bee873a5d6ded731bd9e2d74f83ada5f36 Mon Sep 17 00:00:00 2001 From: supersonik12 Date: Fri, 14 Nov 2025 10:11:56 -0700 Subject: [PATCH 4/5] Not yet implemented endpoints --- sbs_server/app/views.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sbs_server/app/views.py b/sbs_server/app/views.py index 5c4ceb4..bb36c63 100644 --- a/sbs_server/app/views.py +++ b/sbs_server/app/views.py @@ -21,6 +21,14 @@ def pin(): def upload_resource(): return sbh_fj_upload(request.files) +@app.route('/api/uploadAssembly', methods = ['POST']) +def upload_assembly(): + return 'Not implemented yet', 501 + +@app.route('/api/uploadTransformation', methods = ['POST']) +def upload_transformation(): + return 'Not implemented yet', 501 + @app.route('/api/uploadExperiment', methods = ['POST']) def upload_experiment(): return sbh_fj_upload(request.files) From 2deabb6e167e5aff93fc08a0a2118b3291b5d9d4 Mon Sep 17 00:00:00 2001 From: Gonzalo Vidal <35148159+Gonza10V@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:39:11 -0700 Subject: [PATCH 5/5] Validate attachment metadata before upload --- sbs_server/app/views.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/sbs_server/app/views.py b/sbs_server/app/views.py index 2a8b109..3f8ed3e 100644 --- a/sbs_server/app/views.py +++ b/sbs_server/app/views.py @@ -78,12 +78,26 @@ def sbh_fj_upload(files): return 'No SBH credentials provided', 400 # Attachment files to upload to SBH - if 'Attachments' in files and 'attachments' in params_from_request: + attachments = None + if 'Attachments' in files: attachment_files = files.getlist("Attachments") - attachments = {params_from_request['attachments'][file.filename] : file for file in attachment_files} + attachment_metadata = params_from_request.get('attachments') + + if attachment_metadata is None: + return 'Attachment metadata not provided', 400 + if not isinstance(attachment_metadata, dict): + return 'Attachment metadata must be a JSON object keyed by filename', 400 + + attachments = {} + missing_metadata = [file.filename for file in attachment_files if file.filename not in attachment_metadata] + if missing_metadata: + missing_list = ', '.join(missing_metadata) + return f'Missing attachment metadata for files: {missing_list}', 400 + + for file in attachment_files: + attachments[attachment_metadata[file.filename]] = file + print(attachments) - else: - attachments = None # instantiate the XDC class using the params_from_request dictionary xdc = tricahue.XDC(input_excel_path = files['Metadata'],