diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 167158de..f90f61f3 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -190,7 +190,7 @@ jobs: Compress-Archive -Path "${{env.ARTIFACTS_DIR_WIN}}\*.dll","${{env.ARTIFACTS_DIR_WIN}}\*.exe" -DestinationPath "${{env.ARTIFACTS_DIR_WIN}}\artifacts-${{matrix.os}}.zip" -Verbose -Force - name: Upload Artifacts - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: ${{ matrix.os }}-artifacts path: ${{ env.ARTIFACTS_DIR }}/artifacts-${{matrix.os}}.zip @@ -216,7 +216,7 @@ jobs: # download the artifacts - name: "Download artifacts" - uses: "actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110" # v4.1.0 + uses: "actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935" # v4.1.1 with: path: ${{ github.workspace }}/artifacts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 601142b9..e4622d47 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/init@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 with: languages: ${{ matrix.language }} config-file: ${{ github.workspace }}/.github/codeql-config.yml @@ -78,6 +78,6 @@ jobs: run: cmake --build --preset linux-release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/analyze@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 31d2af0c..523c7326 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -25,6 +25,6 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: 'Dependency Review' - uses: actions/dependency-review-action@01bc87099ba56df1e897b6874784491ea6309bc4 # v3.1.4 + uses: actions/dependency-review-action@c74b580d73376b7750d3d2a50bfb8adc2c937507 # v3.1.5 with: comment-summary-in-pr: true diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 9655f2bd..a3a31c58 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -71,7 +71,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@9dc751fe249ad99385a2583ee0d084c400eee04e + uses: docker/metadata-action@dbef88086f6cef02e264edb7dbf63250c17cef6c with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | diff --git a/.github/workflows/docker-scout-scan.yml b/.github/workflows/docker-scout-scan.yml index dcfdda77..5c5fd544 100644 --- a/.github/workflows/docker-scout-scan.yml +++ b/.github/workflows/docker-scout-scan.yml @@ -83,7 +83,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@9dc751fe249ad99385a2583ee0d084c400eee04e + uses: docker/metadata-action@dbef88086f6cef02e264edb7dbf63250c17cef6c with: images: ${{ env.IMAGE_NAME }} tags: | @@ -138,7 +138,7 @@ jobs: - name: Upload SARIF result id: upload-sarif - uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/upload-sarif@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 with: sarif_file: sarif.output.json diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 164b028b..a66355a2 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -61,7 +61,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: SARIF file path: results.sarif @@ -69,6 +69,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/upload-sarif@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 with: sarif_file: results.sarif diff --git a/Dockerfile b/Dockerfile index 30a7d720..3515d544 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bookworm-20231218@sha256:bac353db4cc04bc672b14029964e686cd7bad56fe34b51f432c1a1304b9928da AS build +FROM debian:bookworm-20240110@sha256:b16cef8cbcb20935c0f052e37fc3d38dc92bfec0bcfb894c328547f81e932d67 AS build ARG OWNER=nam20485 ARG GITHUB_TOKEN="PASSWORD" @@ -66,7 +66,7 @@ RUN cmake --build --preset linux-release # RUN cmake --build --preset linux-debug # much smaller runtime image -FROM debian:bookworm-20231218-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 AS run +FROM debian:bookworm-20240110-slim@sha256:f4a83aa865a2b4a064ff142aa91c713180df9fcb86ce676b5de2981029379c37 AS run LABEL org.opencontainers.image.source=https://github.com/nam20485/OdbDesign LABEL org.opencontainers.image.authors=https://github.com/nam20485 LABEL org.opencontainers.image.description="The OdbDesign Docker image runs the OdbDesignServer REST API server executable, listening on port 8888." diff --git a/Dockerfile (exe) b/Dockerfile (exe) index 9475189c..2f1a1960 100644 --- a/Dockerfile (exe) +++ b/Dockerfile (exe) @@ -1,4 +1,4 @@ -FROM debian:bookworm-20231218-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 AS build +FROM debian:bookworm-20240110-slim@sha256:f4a83aa865a2b4a064ff142aa91c713180df9fcb86ce676b5de2981029379c37 AS build # install dependencies RUN apt-get update && \ @@ -52,7 +52,7 @@ RUN cp /src/OdbDesign/out/build/linux-release/OdbDesignLib/libOdbDesign.so ./_Py #RUN python3 -m build # much smaller runtime image -FROM debian:bookworm-20231218-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 AS run +FROM debian:bookworm-20240110-slim@sha256:f4a83aa865a2b4a064ff142aa91c713180df9fcb86ce676b5de2981029379c37 AS run RUN mkdir /OdbDesign WORKDIR /OdbDesign diff --git a/Dockerfile_PyOdbDesignServer b/Dockerfile_PyOdbDesignServer index 6560dc4c..f6ba739c 100644 --- a/Dockerfile_PyOdbDesignServer +++ b/Dockerfile_PyOdbDesignServer @@ -1,4 +1,4 @@ -FROM debian:bookworm-20231218-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 AS build +FROM debian:bookworm-20240110-slim@sha256:f4a83aa865a2b4a064ff142aa91c713180df9fcb86ce676b5de2981029379c37 AS build # install dependencies RUN apt-get update && \ @@ -44,7 +44,7 @@ RUN cmake --build --preset python-linux-release # much smaller runtime image #FROM python:3.11.4-bullseye AS run -FROM debian:bookworm-20231218-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 as run +FROM debian:bookworm-20240110-slim@sha256:f4a83aa865a2b4a064ff142aa91c713180df9fcb86ce676b5de2981029379c37 as run # copy PyOdbDesignServer files COPY --from=build /src/OdbDesign/PyOdbDesignServer PyOdbDesignServer diff --git a/OdbDesignLib/App/IOdbServerApp.h b/OdbDesignLib/App/IOdbServerApp.h index 44b1b1a3..2830dc06 100644 --- a/OdbDesignLib/App/IOdbServerApp.h +++ b/OdbDesignLib/App/IOdbServerApp.h @@ -10,7 +10,7 @@ namespace Odb::Lib::App public: virtual ~IOdbServerApp() {} - virtual crow::SimpleApp& crow_app() = 0; + virtual CrowApp& crow_app() = 0; protected: IOdbServerApp() = default; diff --git a/OdbDesignLib/App/OdbServerAppBase.cpp b/OdbDesignLib/App/OdbServerAppBase.cpp index 1f47b3e9..8306505c 100644 --- a/OdbDesignLib/App/OdbServerAppBase.cpp +++ b/OdbDesignLib/App/OdbServerAppBase.cpp @@ -77,7 +77,7 @@ namespace Odb::Lib::App return ExitCode::Success; } - crow::SimpleApp& OdbServerAppBase::crow_app() + CrowApp& OdbServerAppBase::crow_app() { return m_crowApp; } diff --git a/OdbDesignLib/App/OdbServerAppBase.h b/OdbDesignLib/App/OdbServerAppBase.h index da0c1828..ae62ba1a 100644 --- a/OdbDesignLib/App/OdbServerAppBase.h +++ b/OdbDesignLib/App/OdbServerAppBase.h @@ -13,7 +13,7 @@ namespace Odb::Lib::App OdbServerAppBase(int argc, char* argv[]); virtual ~OdbServerAppBase(); - crow::SimpleApp& crow_app() override; + CrowApp& crow_app() override; Utils::ExitCode Run() override; @@ -24,7 +24,8 @@ namespace Odb::Lib::App virtual void add_controllers() = 0; private: - crow::SimpleApp m_crowApp; + CrowApp m_crowApp; + //crow::SimpleApp m_crowApp; void register_routes(); diff --git a/OdbDesignLib/FileModel/Design/AttrListFile.cpp b/OdbDesignLib/FileModel/Design/AttrListFile.cpp index 344dadb8..4b29ffbf 100644 --- a/OdbDesignLib/FileModel/Design/AttrListFile.cpp +++ b/OdbDesignLib/FileModel/Design/AttrListFile.cpp @@ -44,7 +44,7 @@ namespace Odb::Lib::FileModel::Design loginfo("checking for extraction..."); std::filesystem::path featuresFilePath; - for (const std::string& featuresFilename : ATTRLIST_FILENAMES) + for (const std::string featuresFilename : ATTRLIST_FILENAMES) { loginfo("trying attrlist file: [" + featuresFilename + "]..."); diff --git a/OdbDesignLib/FileModel/Design/ComponentsFile.cpp b/OdbDesignLib/FileModel/Design/ComponentsFile.cpp index f5f4a32d..a255c747 100644 --- a/OdbDesignLib/FileModel/Design/ComponentsFile.cpp +++ b/OdbDesignLib/FileModel/Design/ComponentsFile.cpp @@ -311,7 +311,7 @@ namespace Odb::Lib::FileModel::Design loginfo("checking for extraction..."); std::filesystem::path componentsFilePath; - for (const std::string& componentsFilename : COMPONENTS_FILENAMES) + for (const std::string componentsFilename : COMPONENTS_FILENAMES) { loginfo("trying components file: [" + componentsFilename + "]..."); diff --git a/OdbDesignLib/FileModel/Design/FeaturesFile.cpp b/OdbDesignLib/FileModel/Design/FeaturesFile.cpp index 02d18c3d..ec241482 100644 --- a/OdbDesignLib/FileModel/Design/FeaturesFile.cpp +++ b/OdbDesignLib/FileModel/Design/FeaturesFile.cpp @@ -53,7 +53,7 @@ namespace Odb::Lib::FileModel::Design } std::filesystem::path featuresFilePath; - for (const std::string& featuresFilename : filenames) + for (const std::string featuresFilename : filenames) { loginfo("trying features file: [" + featuresFilename + "]..."); diff --git a/OdbDesignServer/Controllers/FileModelController.cpp b/OdbDesignServer/Controllers/FileModelController.cpp index cd7e30cb..c5a753b0 100644 --- a/OdbDesignServer/Controllers/FileModelController.cpp +++ b/OdbDesignServer/Controllers/FileModelController.cpp @@ -14,18 +14,172 @@ namespace Odb::App::Server { } + ////FileArchive * + ////StepDirectory::StringMap m_stepsByName; //* + ////LayerDirectory::StringMap m_layersByName; //* + //// ComponentsFile m_componentsFile; + //// FeaturesFile m_featuresFile; + //// AttrListFile m_attrListFile; + ////Netlist//File::StringMap m_netlistsByName; //* + + ////EdaDataFile m_edaData; + ////AttrListFile m_attrListFile; + ////FeaturesFile m_profileFile; + ////StepHdrFile m_stepHdrFile; + + ////SymbolsDirectory::StringMap m_symbolsDirectoriesByName; //* + //// AttrList file + //// features file + + ////MiscInfoFile m_miscInfoFile; + ////MatrixFile m_matrixFile; + ////StandardFontsFile m_standardFontsFile; + ////AttrListFile m_miscAttrListFile; + + // * need endpoints to list of keys of maps, i.e. available names to fetch + void FileModelController::register_routes() { + CROW_ROUTE(m_serverApp.crow_app(), "/filemodels") + ([&](const crow::request& req) + { + return this->designs_list_route_handler(req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel/") + ([&](const crow::request& req, std::string designName) + { + return this->designs_route_handler(designName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps/") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps") + ([&](const crow::request& req, std::string designName) + { + return this->steps_list_route_handler(designName, req); + }); + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//eda_data") ([&](const crow::request& req, std::string designName, std::string stepName) { return this->steps_edadata_route_handler(designName, stepName, req); }); - CROW_ROUTE(m_serverApp.crow_app(), "/filemodel/") + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//attrlist") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_attrlist_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//profile") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_profile_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//stephdr") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_stephdr_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//netlists/") + ([&](const crow::request& req, std::string designName, std::string stepName, std::string netlistName) + { + return this->steps_netlists_route_handler(designName, stepName, netlistName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//netlists") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_netlists_list_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//layers/") + ([&](const crow::request& req, std::string designName, std::string stepName, std::string layerName) + { + return this->steps_layers_route_handler(designName, stepName, layerName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//layers") + ([&](const crow::request& req, std::string designName, std::string stepName) + { + return this->steps_layers_list_route_handler(designName, stepName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//layer//components") + ([&](const crow::request& req, std::string designName, std::string stepName, std::string layerName) + { + return this->steps_layers_components_route_handler(designName, stepName, layerName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//layers//features") + ([&](const crow::request& req, std::string designName, std::string stepName, std::string layerName) + { + return this->steps_layers_features_route_handler(designName, stepName, layerName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//steps//layers//attrlist") + ([&](const crow::request& req, std::string designName, std::string stepName, std::string layerName) + { + return this->steps_layers_attrlist_route_handler(designName, stepName, layerName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//symbols/") + ([&](const crow::request& req, std::string designName, std::string symbolName) + { + return this->symbols_route_handler(designName, symbolName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//symbols//features") + ([&](const crow::request& req, std::string designName, std::string symbolName) + { + return this->symbols_features_route_handler(designName, symbolName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//symbols//attrlist") + ([&](const crow::request& req, std::string designName, std::string symbolName) + { + return this->symbols_attrlist_route_handler(designName, symbolName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//symbols") ([&](const crow::request& req, std::string designName) { - return this->designs_route_handler(designName, req); + return this->symbols_list_route_handler(designName, req); + }); + + //register_route_handler("/filemodel/misc/attrlist", std::bind(&FileModelController::misc_attrlist_route_handler, this, std::placeholders::_1)); + //register_route_handler("/filemodel/matrix/matrix", std::bind(&FileModelController::matrix_matrix_route_handler, this, std::placeholders::_1)); + //register_route_handler("/filemodel/misc/info", std::bind(&FileModelController::misc_info_route_handler, this, std::placeholders::_1)); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//misc/attrlist") + ([&](const crow::request& req, std::string designName) + { + return this->misc_attrlist_route_handler(designName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//matrix/matrix") + ([&](const crow::request& req, std::string designName) + { + return this->matrix_matrix_route_handler(designName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//misc/info") + ([&](const crow::request& req, std::string designName) + { + return this->misc_info_route_handler(designName, req); + }); + + CROW_ROUTE(m_serverApp.crow_app(), "/filemodel//fonts/standard") + ([&](const crow::request& req, std::string designName) + { + return this->fonts_standard_route_handler(designName, req); }); } @@ -67,7 +221,7 @@ namespace Odb::App::Server return crow::response(JsonCrowReturnable(edaDataFile)); } - crow::response FileModelController::designs_route_handler(const std::string& designName, const crow::request& req) + crow::response FileModelController::steps_attrlist_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) { auto designNameDecoded = UrlEncoding::decode(designName); if (designNameDecoded.empty()) @@ -75,6 +229,12 @@ namespace Odb::App::Server return crow::response(crow::status::BAD_REQUEST, "design name not specified"); } + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); if (pFileArchive == nullptr) { @@ -83,6 +243,747 @@ namespace Odb::App::Server return crow::response(crow::status::NOT_FOUND, ss.str()); } - return crow::response(JsonCrowReturnable(*pFileArchive)); + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& step = findIt->second; + auto& attrListFile = step->GetAttrListFile(); + return crow::response(JsonCrowReturnable(attrListFile)); + } + + crow::response FileModelController::steps_profile_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& step = findIt->second; + auto& profileFile = step->GetProfileFile(); + return crow::response(JsonCrowReturnable(profileFile)); + } + + crow::response FileModelController::steps_stephdr_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& step = findIt->second; + auto& stepHdrFile = step->GetStepHdrFile(); + return crow::response(JsonCrowReturnable(stepHdrFile)); + } + + crow::response FileModelController::steps_netlists_route_handler(const std::string& designName, const std::string& stepName, const std::string& netlistName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto netlistNameDecoded = UrlEncoding::decode(netlistName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "netlist name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& netlistsByName = step->GetNetlistsByName(); + auto findIt2 = netlistsByName.find(netlistNameDecoded); + if (findIt2 == netlistsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\"" << " netlist: \"" << netlistNameDecoded << "\"" << " not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& netlist = findIt2->second; + + return crow::response(JsonCrowReturnable(*netlist)); + } + + crow::response FileModelController::steps_netlists_list_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& netlistsByName = step->GetNetlistsByName(); + crow::json::wvalue::list netlistNames; + for (const auto& kvNetlists : netlistsByName) + { + netlistNames.push_back(kvNetlists.first); + } + + crow::json::wvalue jsonResponse; + jsonResponse["netlists"] = std::move(netlistNames); + return crow::response(jsonResponse); + } + + crow::response FileModelController::steps_list_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + crow::json::wvalue::list stepNames; + for (const auto& kvSteps : stepsByName) + { + stepNames.push_back(kvSteps.first); + } + + crow::json::wvalue jsonResponse; + jsonResponse["steps"] = std::move(stepNames); + return crow::response(jsonResponse); + } + + crow::response FileModelController::steps_layers_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto layerNameDecoded = UrlEncoding::decode(layerName); + if (layerNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "layer name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& layersByName = step->GetLayersByName(); + auto findIt2 = layersByName.find(layerNameDecoded); + if (findIt2 == layersByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\"" << " layer: \"" << layerNameDecoded << "\"" << " not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& layer = findIt2->second; + + return crow::response(JsonCrowReturnable(*layer)); + } + + crow::response FileModelController::steps_layers_components_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto layerNameDecoded = UrlEncoding::decode(layerName); + if (layerNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "layer name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& layersByName = step->GetLayersByName(); + auto findIt2 = layersByName.find(layerNameDecoded); + if (findIt2 == layersByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\"" << " layer: \"" << layerNameDecoded << "\"" << " not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& layer = findIt2->second; + + auto& componentsFile = layer->GetComponentsFile(); + return crow::response(JsonCrowReturnable(componentsFile)); + } + + crow::response FileModelController::steps_layers_features_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto layerNameDecoded = UrlEncoding::decode(layerName); + if (layerNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "layer name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& layersByName = step->GetLayersByName(); + auto findIt2 = layersByName.find(layerNameDecoded); + if (findIt2 == layersByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\"" << " layer: \"" << layerNameDecoded << "\"" << " not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& layer = findIt2->second; + + auto& featuresFile = layer->GetFeaturesFile(); + return crow::response(JsonCrowReturnable(featuresFile)); + } + + crow::response FileModelController::steps_layers_attrlist_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto layerNameDecoded = UrlEncoding::decode(layerName); + if (layerNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "layer name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& layersByName = step->GetLayersByName(); + auto findIt2 = layersByName.find(layerNameDecoded); + if (findIt2 == layersByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\"" << " layer: \"" << layerNameDecoded << "\"" << " not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& layer = findIt2->second; + + auto& attrlistFile = layer->GetAttrListFile(); + return crow::response(JsonCrowReturnable(attrlistFile)); + } + + crow::response FileModelController::steps_layers_list_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& step = findIt->second; + + auto& layersByName = step->GetLayersByName(); + crow::json::wvalue::list layerNames; + for (const auto& kvLayers : layersByName) + { + layerNames.push_back(kvLayers.first); + } + + crow::json::wvalue jsonResponse; + jsonResponse["layers"] = std::move(layerNames); + return crow::response(jsonResponse); + } + + crow::response FileModelController::steps_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto stepNameDecoded = UrlEncoding::decode(stepName); + if (stepNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& stepsByName = pFileArchive->GetStepsByName(); + auto findIt = stepsByName.find(stepNameDecoded); + if (findIt == stepsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " step: \"" << stepNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& step = findIt->second; + return crow::response(JsonCrowReturnable(*step)); + } + + crow::response FileModelController::symbols_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto symbolNameDecoded = UrlEncoding::decode(symbolName); + if (symbolNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& symbolsByName = pFileArchive->GetSymbolsDirectoriesByName(); + auto findIt = symbolsByName.find(symbolNameDecoded); + if (findIt == symbolsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " symbol: \"" << symbolNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& symbol = findIt->second; + return crow::response(JsonCrowReturnable(*symbol)); + } + + crow::response FileModelController::symbols_features_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto symbolNameDecoded = UrlEncoding::decode(symbolName); + if (symbolNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& symbolsByName = pFileArchive->GetSymbolsDirectoriesByName(); + auto findIt = symbolsByName.find(symbolNameDecoded); + if (findIt == symbolsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " symbol: \"" << symbolNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& symbol = findIt->second; + + auto& featuresFile = symbol->GetFeaturesFile(); + return crow::response(JsonCrowReturnable(featuresFile)); + } + + crow::response FileModelController::symbols_attrlist_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto symbolNameDecoded = UrlEncoding::decode(symbolName); + if (symbolNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "step name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& symbolsByName = pFileArchive->GetSymbolsDirectoriesByName(); + auto findIt = symbolsByName.find(symbolNameDecoded); + if (findIt == symbolsByName.end()) + { + std::stringstream ss; + ss << "(design: \"" << designNameDecoded << "\")" << " symbol: \"" << symbolNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + auto& symbol = findIt->second; + + auto& attrlistFile = symbol->GetAttrListFile(); + return crow::response(JsonCrowReturnable(attrlistFile)); + } + + crow::response FileModelController::symbols_list_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& symbolsByName = pFileArchive->GetSymbolsDirectoriesByName(); + crow::json::wvalue::list symbolNames; + for (const auto& kvSymbols : symbolsByName) + { + symbolNames.push_back(kvSymbols.first); + } + + crow::json::wvalue jsonResponse; + jsonResponse["symbols"] = std::move(symbolNames); + return crow::response(jsonResponse); + } + + crow::response FileModelController::designs_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + return crow::response(JsonCrowReturnable(*pFileArchive)); + } + + crow::response FileModelController::designs_list_route_handler(const crow::request& req) + { + const auto& fileArchives = m_serverApp.designs().getUnloadedDesignNames(); + + crow::json::wvalue::list designNames; + for (const auto& designName : fileArchives) + { + designNames.push_back(designName); + } + + crow::json::wvalue jsonResponse; + jsonResponse["designs"] = std::move(designNames); + return crow::response(jsonResponse); + } + + crow::response FileModelController::misc_attrlist_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& miscAttrListFile = pFileArchive->GetMiscAttrListFile(); + return crow::response(JsonCrowReturnable(miscAttrListFile)); + } + + crow::response FileModelController::matrix_matrix_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& matrixFile = pFileArchive->GetMatrixFile(); + return crow::response(JsonCrowReturnable(matrixFile)); + } + + crow::response FileModelController::misc_info_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& miscInfoFile = pFileArchive->GetMiscInfoFile(); + return crow::response(JsonCrowReturnable(miscInfoFile)); + } + + crow::response FileModelController::fonts_standard_route_handler(const std::string& designName, const crow::request& req) + { + auto designNameDecoded = UrlEncoding::decode(designName); + if (designNameDecoded.empty()) + { + return crow::response(crow::status::BAD_REQUEST, "design name not specified"); + } + + auto pFileArchive = m_serverApp.designs().GetFileArchive(designNameDecoded); + if (pFileArchive == nullptr) + { + std::stringstream ss; + ss << "design: \"" << designNameDecoded << "\" not found"; + return crow::response(crow::status::NOT_FOUND, ss.str()); + } + + auto& standardFontsFile = pFileArchive->GetStandardFontsFile(); + return crow::response(JsonCrowReturnable(standardFontsFile)); } } \ No newline at end of file diff --git a/OdbDesignServer/Controllers/FileModelController.h b/OdbDesignServer/Controllers/FileModelController.h index fee483ca..da6404d7 100644 --- a/OdbDesignServer/Controllers/FileModelController.h +++ b/OdbDesignServer/Controllers/FileModelController.h @@ -14,8 +14,33 @@ namespace Odb::App::Server virtual void register_routes() override; private: - crow::response steps_edadata_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); crow::response designs_route_handler(const std::string& designName, const crow::request& req); + crow::response designs_list_route_handler(const crow::request& req); + + crow::response steps_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_edadata_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_attrlist_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_profile_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_stephdr_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_netlists_route_handler(const std::string& designName, const std::string& stepName, const std::string& netlistName, const crow::request& req); + crow::response steps_netlists_list_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + crow::response steps_list_route_handler(const std::string& designName, const crow::request& req); + + crow::response steps_layers_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req); + crow::response steps_layers_components_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req); + crow::response steps_layers_features_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req); + crow::response steps_layers_attrlist_route_handler(const std::string& designName, const std::string& stepName, const std::string& layerName, const crow::request& req); + crow::response steps_layers_list_route_handler(const std::string& designName, const std::string& stepName, const crow::request& req); + + crow::response symbols_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req); + crow::response symbols_features_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req); + crow::response symbols_attrlist_route_handler(const std::string& designName, const std::string& symbolName, const crow::request& req); + crow::response symbols_list_route_handler(const std::string& designName, const crow::request& req); + + crow::response misc_attrlist_route_handler(const std::string& designName, const crow::request& req); + crow::response matrix_matrix_route_handler(const std::string& designName, const crow::request& req); + crow::response misc_info_route_handler(const std::string& designName, const crow::request& req); + crow::response fonts_standard_route_handler(const std::string& designName, const crow::request& req); }; } diff --git a/OdbDesignServer/OdbDesignServerApp.cpp b/OdbDesignServer/OdbDesignServerApp.cpp index d9f72a4e..0ea772aa 100644 --- a/OdbDesignServer/OdbDesignServerApp.cpp +++ b/OdbDesignServer/OdbDesignServerApp.cpp @@ -4,6 +4,7 @@ #include "Controllers/FileUploadController.h" #include "Controllers/FileModelController.h" #include "Controllers/HealthCheckController.h" +#include "macros.h" namespace Odb::App::Server @@ -17,18 +18,35 @@ namespace Odb::App::Server //{ //} - //Utils::ExitCode OdbDesignServerApp::Run() - //{ - // // - // // do any initialization here - // // + Utils::ExitCode OdbDesignServerApp::Run() + { + // + // do any initialization here + // - // return OdbServerAppBase::Run(); + // CORS + auto& cors = crow_app().get_middleware(); + if (Utils::IsProduction()) + { + cors.global().headers("*"); + //cors.global().methods(crow::HTTPMethod::Get, crow::HTTPMethod::Post); + cors.global().origin("*"); + //cors.global().origin("73.157.184.219"); + } + else + { + cors.global().headers("*"); + //cors.global().methods(crow::HTTPMethod::Get); + cors.global().origin("*"); + //cors.global().origin("73.157.184.219"); + } - // // - // // do any cleanup here - // // - //} + return OdbServerAppBase::Run(); + + // + // do any cleanup here + // + } void OdbDesignServerApp::add_controllers() { diff --git a/OdbDesignServer/OdbDesignServerApp.h b/OdbDesignServer/OdbDesignServerApp.h index 0fb34d9f..c5b5ab21 100644 --- a/OdbDesignServer/OdbDesignServerApp.h +++ b/OdbDesignServer/OdbDesignServerApp.h @@ -12,7 +12,7 @@ namespace Odb::App::Server OdbDesignServerApp(int argc, char* argv[]); //~OdbDesignServerApp(); - //ExitCode Run() override; + Utils::ExitCode Run() override; protected: void add_controllers() override; diff --git a/Utils/crow_win.h b/Utils/crow_win.h index fce2e362..0b9131d8 100644 --- a/Utils/crow_win.h +++ b/Utils/crow_win.h @@ -2,3 +2,7 @@ #include "win.h" #include "crow.h" +#include "crow/middlewares/cors.h" + + +using CrowApp = crow::Crow; \ No newline at end of file diff --git a/Utils/macros.h b/Utils/macros.h index 6f6654cf..928f541a 100644 --- a/Utils/macros.h +++ b/Utils/macros.h @@ -1,7 +1,10 @@ #pragma once +#include +#include "str_utils.h" -namespace Odb::Lib + +namespace Utils { constexpr static inline bool IsMsvc() { @@ -21,6 +24,43 @@ namespace Odb::Lib #endif } + constexpr static inline bool IsRelease() + { + return !IsDebug(); + } + + constexpr static const char ENVIRONMENT_VARIABLE[] = "Environment"; + + static inline bool IsEnvironment(const std::string& environmentName) + { + auto envValue = std::getenv("ENVIRONMENT_VARIABLE"); + if (envValue == nullptr) return false; + + return Utils::str_to_lower_copy(envValue) == + Utils::str_to_lower_copy(environmentName); + } + + static inline bool IsDevelopment() + { + return IsEnvironment("Development"); + } + + static inline bool IsTesting() + { + return IsEnvironment("Testing"); + } + + static inline bool IsStaging() + { + return IsEnvironment("Staging"); + } + + static inline bool IsProduction() + { + return IsEnvironment("Production"); + } + + #ifndef ARRAY_COUNT # define ARRAY_COUNT(array_) (sizeof(array_)/sizeof((array_)[0])) #endif diff --git a/docs/README.md b/docs/README.md index 3b01ba89..95efb644 100644 --- a/docs/README.md +++ b/docs/README.md @@ -31,6 +31,8 @@ The maintainer has well over a decade of experience in the PCB Manufacturing and All code, dependency packages, and Docker images are scanned for security vulnerabilities, using extended security scanning rule profiles (these are more secure than the default base scanning rule profiles). +>The project has earned a high score on the [OpenSSF Security Scorecard](https://securityscorecards.dev/#what-is-openssf-scorecard). Details can be seen in the [Project Security](#project-security) section below. + It is built using the latest available version of the C++ standard and is compiled with the latest available compiler versions. The parser is also built using the latest available versions of all of its dependencies and is regularly updated to use the latest versions of those dependencies as they are released. >These checks are run against all branches starting with development, so there is no chance of a security vulnerability being introduced into the main and release branches. Docker's Scout Suite is used to scan the Docker image for security vulnerabilities, and GitHub's CodeQL is used to scan the code for security vulnerabilities. @@ -39,11 +41,11 @@ It is built using the latest available version of the C++ standard and is compil ### Current Implementation State -The diagram describes the current state of parser implementation and data availability. Green color describes areas of the ODB++ archive file that are implemented and have their data available for use. Red color describes areas that are not parsed so their data is not yet available. +The diagram describes the current state of parser implementation and data availability. Green color describes areas of the ODB++ archive file that are implemented and have their data available for use. ~~Red color describes areas that are not parsed so their data is not yet available.~~ **All areas of the file are now parsed, and have their data available for use.** -![image](https://github.com/nam20485/OdbDesign/assets/1829396/d55d0ea8-6ad9-446a-8659-9157636e1c9f) +![ODB++ file hierarchy implementation state diagram]() -### CI/CD Build +### Project Security #### OpenSSF Security Scorecard @@ -51,7 +53,9 @@ The diagram describes the current state of parser implementation and data availa [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/nam20485/OdbDesign/badge)](https://securityscorecards.dev/viewer/?uri=github.com/nam20485/OdbDesign) ->90% of tested projects have a score of less than 4.0/10, so OdbDesign's 7.2 score represents a remarkably high level of security. +>The majority of tested projects have a muc lower score, so OdbDesign's 7.8 score represents a remarkably high level of security. + +### CI/CD Build #### Branches @@ -186,6 +190,12 @@ Data objects returned from the parser library support serialization to and from >The protocol buffer definitions are included in the library so they can be used to generate code for other languages - currently C++ bindings are built and used in the library. +## Contributing + +The project is happy to accept pull requests if you would like to contribute. Please open an issue to discuss your proposed changes before submitting a pull request. Pull requests are accepted against the `development` branch. Please make sure your pull request is up to date with the latest changes in the `development` branch before submitting it. + +All contributed code must be covered by accompanying test cases. Please make sure your changes are covered by test cases before submitting a pull request. + ## License This project is free and open source under the MIT [license](https://github.com/nam20485/OdbDesign/blob/c0c8b6e4b93e1c7d4d5e65c7ad25157c883f8bfb/LICENSE). diff --git a/docs/odb++ file hierarchy (implemented).png b/docs/odb++ file hierarchy (implemented).png new file mode 100644 index 00000000..2595c360 Binary files /dev/null and b/docs/odb++ file hierarchy (implemented).png differ diff --git a/scripts/create-k3d-cluster.ps1 b/scripts/create-k3d-cluster.ps1 index 983a510b..e0fea396 100644 --- a/scripts/create-k3d-cluster.ps1 +++ b/scripts/create-k3d-cluster.ps1 @@ -1,9 +1,16 @@ -# When set to true, the cluster will be deleted first -param( - [string]$ClusterName = "k3dcluster", +param( + # Cluster name + [Parameter(Mandatory=$true)] + [string]$ClusterName = "k3dcluster", + # Number of agents to create + [Parameter(Mandatory=$true)] [int]$NumAgents = 3, + # Ingress host port + [Parameter(Mandatory=$true)] [int]$IngressHostPort = 8081, + # When set to true, the cluster will be deleted first [switch]$DeleteClusterFirst = $false, + # When set to true, the cluster will be deleted without asking for confirmation [switch]$ForceDelete = $false ) diff --git a/scripts/deploy.ps1 b/scripts/deploy.ps1 index 8d0d690d..9ec1af25 100644 --- a/scripts/deploy.ps1 +++ b/scripts/deploy.ps1 @@ -1,13 +1,21 @@ - -$clusterName = "k3d-k3dcluster" -$deploymentName = "odbdesign-server-v1" +param( + # Cluster name + [Parameter(Mandatory=$true)] + [string]$ClusterName, + # Deployment name + [Parameter(Mandatory=$true)] + [string]$DeploymentName +) + +#$clusterName = "k3d-k3dcluster" +#$deploymentName = "odbdesign-server-v1" #$serviceName = "odbdesign-server-service" #$ingressName = "odbdesign-server-ingress" #$image = "ghcr.io/nam20485/odbdesign:nam20485-latest" # set kubeconfig -kubectl config use-context $clusterName +kubectl config use-context $ClusterName if ($LASTEXITCODE -ne 0) { Exit 1 } @@ -30,7 +38,7 @@ if ($LASTEXITCODE -ne 0) { # kubectl set image deployment/$deploymentName odbdesign-server=$image # initiate rolling update -kubectl rollout restart deployment/$deploymentName +kubectl rollout restart deployment/$DeploymentName # wait for kubectl deployment to finish -kubectl rollout status deployment/$deploymentName +kubectl rollout status deployment/$DeploymentName