From c122926e012a5da5fbc3c1a6e237392e416b2c54 Mon Sep 17 00:00:00 2001 From: jbirddog <100367399+jbirddog@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:37:24 -0500 Subject: [PATCH] Support creating unique top level keys for KKV data store (#613) --- .../create_unique_kkv_top_level_key.py | 33 +++++++++++++++++ .../test_create_unique_kkv_top_level_key.py | 36 +++++++++++++++++++ spiffworkflow-frontend/package-lock.json | 5 ++- 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/scripts/create_unique_kkv_top_level_key.py create mode 100644 spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_create_unique_kkv_top_level_key.py diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/create_unique_kkv_top_level_key.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/create_unique_kkv_top_level_key.py new file mode 100644 index 00000000..4a7025ff --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/create_unique_kkv_top_level_key.py @@ -0,0 +1,33 @@ +from typing import Any + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.kkv_data_store import KKVDataStoreModel +from spiffworkflow_backend.models.script_attributes_context import ScriptAttributesContext +from spiffworkflow_backend.scripts.script import Script + + +class CreateUniqueKKVTopLevelKey(Script): + @staticmethod + def requires_privileged_permissions() -> bool: + """We have deemed this function safe to run without elevated permissions.""" + return False + + def get_description(self) -> str: + return ( + "Creates a new unique KKV top level key using the provided prefix. " + "This allows for a safe construction of incrementing keys, such as study1, study2." + ) + + def run(self, script_attributes_context: ScriptAttributesContext, *args: Any, **kwargs: Any) -> Any: + top_level_key_prefix = args[0] + + model = KKVDataStoreModel(top_level_key="", secondary_key="", value={}) + db.session.add(model) + db.session.commit() + + top_level_key = f"{top_level_key_prefix}{model.id}" + + db.session.delete(model) + db.session.commit() + + return top_level_key diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_create_unique_kkv_top_level_key.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_create_unique_kkv_top_level_key.py new file mode 100644 index 00000000..fc1a9649 --- /dev/null +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_create_unique_kkv_top_level_key.py @@ -0,0 +1,36 @@ +from collections.abc import Generator + +import pytest +from flask.app import Flask +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.kkv_data_store import KKVDataStoreModel +from spiffworkflow_backend.scripts.create_unique_kkv_top_level_key import CreateUniqueKKVTopLevelKey + +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + + +@pytest.fixture() +def with_clean_data_store(app: Flask, with_db_and_bpmn_file_cleanup: None) -> Generator[None, None, None]: + db.session.query(KKVDataStoreModel).delete() + db.session.commit() + yield + + +class TestCreateUniqueKKVTopLevelKey(BaseTest): + """Infer from class name.""" + + # TODO: skipped due to sqlite handling of rowid - https://www.sqlite.org/autoinc.html + # since the immediate use case does not require sqlite will defer the fix until needed + def skip_test_creates_unique_top_level_keys(self, with_clean_data_store: None) -> None: + prefix = "study_" + ids = [ + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + CreateUniqueKKVTopLevelKey().run(None, prefix), # type: ignore + ] + unique_ids = set(ids) + assert len(ids) == len(unique_ids) diff --git a/spiffworkflow-frontend/package-lock.json b/spiffworkflow-frontend/package-lock.json index 4737ab1d..1207346e 100644 --- a/spiffworkflow-frontend/package-lock.json +++ b/spiffworkflow-frontend/package-lock.json @@ -50179,7 +50179,7 @@ "@csstools/postcss-text-decoration-shorthand": "^1.0.0", "@csstools/postcss-trigonometric-functions": "^1.0.2", "@csstools/postcss-unset-value": "^1.0.2", - "autoprefixer": "10.4.5", + "autoprefixer": "^10.4.13", "browserslist": "^4.21.4", "css-blank-pseudo": "^3.0.3", "css-has-pseudo": "^3.0.4", @@ -50217,8 +50217,7 @@ }, "dependencies": { "autoprefixer": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz", + "version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz", "integrity": "sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw==", "requires": { "browserslist": "^4.20.2",