Squashed 'spiffworkflow-backend/' changes from ffb6d366..d0336039

d0336039 added api endpoint to get the auth list from connector proxy w/ burnettk
ca13f0ca Merge pull request #142 from sartography/bugfix/clean_up_non_existant_workflow_types_and_libraries
304ee66b lint
935c883b migration.
1f99264c Remove all references to the MasterWorkflow, standalone workflows, and libraries, as these concepts should no longer exist.
a7a83a97 Merge branch 'main' of github.com:sartography/spiffworkflow-backend
6ce1cdb0 updated flask-bpmn for new ApiError. w/ burnettk
796735e8 Merge pull request #141 from sartography/bugfix/allow-strptime-in-scripts
5e13a239 Remove the "master_spec"
7e52204f fix bs issue
8cc59eb3 add strptime to script engine

git-subtree-dir: spiffworkflow-backend
git-subtree-split: d0336039c556bf5f19f8db2f32d9b37228e9f057
This commit is contained in:
jasquat 2022-10-18 16:41:10 -04:00
parent aa22f4b397
commit 64e7049c9a
16 changed files with 82 additions and 173 deletions

View File

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: 07ff3fbef405 Revision ID: b41f0d35641a
Revises: Revises:
Create Date: 2022-10-13 07:56:01.234090 Create Date: 2022-10-18 16:16:23.575571
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '07ff3fbef405' revision = 'b41f0d35641a'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None

57
poetry.lock generated
View File

@ -95,7 +95,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]] [[package]]
name = "Babel" name = "Babel"
@ -268,7 +268,7 @@ optional = false
python-versions = ">=3.6.0" python-versions = ">=3.6.0"
[package.extras] [package.extras]
unicode_backport = ["unicodedata2"] unicode-backport = ["unicodedata2"]
[[package]] [[package]]
name = "classify-imports" name = "classify-imports"
@ -639,7 +639,7 @@ werkzeug = "*"
type = "git" type = "git"
url = "https://github.com/sartography/flask-bpmn" url = "https://github.com/sartography/flask-bpmn"
reference = "main" reference = "main"
resolved_reference = "f3fc539423a3522d142146d2a039c0cd49badaf5" resolved_reference = "42cebab51fe469ab9dcb45672917d34c1f30987a"
[[package]] [[package]]
name = "Flask-Cors" name = "Flask-Cors"
@ -1512,7 +1512,7 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras] [package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]] [[package]]
name = "requests-toolbelt" name = "requests-toolbelt"
@ -1625,7 +1625,7 @@ falcon = ["falcon (>=1.4)"]
fastapi = ["fastapi (>=0.79.0)"] fastapi = ["fastapi (>=0.79.0)"]
flask = ["blinker (>=1.1)", "flask (>=0.11)"] flask = ["blinker (>=1.1)", "flask (>=0.11)"]
httpx = ["httpx (>=0.16.0)"] httpx = ["httpx (>=0.16.0)"]
pure_eval = ["asttokens", "executing", "pure-eval"] pure-eval = ["asttokens", "executing", "pure-eval"]
pyspark = ["pyspark (>=2.4.4)"] pyspark = ["pyspark (>=2.4.4)"]
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
rq = ["rq (>=0.6)"] rq = ["rq (>=0.6)"]
@ -1884,19 +1884,19 @@ aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"] asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"]
mariadb_connector = ["mariadb (>=1.0.1,!=1.1.2)"] mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"]
mssql = ["pyodbc"] mssql = ["pyodbc"]
mssql_pymssql = ["pymssql"] mssql-pymssql = ["pymssql"]
mssql_pyodbc = ["pyodbc"] mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"]
mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"]
mysql_connector = ["mysql-connector-python"] mysql-connector = ["mysql-connector-python"]
oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"] oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"]
postgresql = ["psycopg2 (>=2.7)"] postgresql = ["psycopg2 (>=2.7)"]
postgresql_asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql_pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"]
postgresql_psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql_psycopg2cffi = ["psycopg2cffi"] postgresql-psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"] pymysql = ["pymysql", "pymysql (<1)"]
sqlcipher = ["sqlcipher3_binary"] sqlcipher = ["sqlcipher3_binary"]
@ -1982,7 +1982,7 @@ test = ["mypy", "pytest", "typing-extensions"]
name = "types-click" name = "types-click"
version = "7.1.8" version = "7.1.8"
description = "Typing stubs for click" description = "Typing stubs for click"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -1990,7 +1990,7 @@ python-versions = "*"
name = "types-Flask" name = "types-Flask"
version = "1.1.6" version = "1.1.6"
description = "Typing stubs for Flask" description = "Typing stubs for Flask"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2003,7 +2003,7 @@ types-Werkzeug = "*"
name = "types-Jinja2" name = "types-Jinja2"
version = "2.11.9" version = "2.11.9"
description = "Typing stubs for Jinja2" description = "Typing stubs for Jinja2"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2014,7 +2014,7 @@ types-MarkupSafe = "*"
name = "types-MarkupSafe" name = "types-MarkupSafe"
version = "1.1.10" version = "1.1.10"
description = "Typing stubs for MarkupSafe" description = "Typing stubs for MarkupSafe"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2022,7 +2022,7 @@ python-versions = "*"
name = "types-pytz" name = "types-pytz"
version = "2022.4.0.0" version = "2022.4.0.0"
description = "Typing stubs for pytz" description = "Typing stubs for pytz"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2030,7 +2030,7 @@ python-versions = "*"
name = "types-PyYAML" name = "types-PyYAML"
version = "6.0.12" version = "6.0.12"
description = "Typing stubs for PyYAML" description = "Typing stubs for PyYAML"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2038,7 +2038,7 @@ python-versions = "*"
name = "types-requests" name = "types-requests"
version = "2.28.11.1" version = "2.28.11.1"
description = "Typing stubs for requests" description = "Typing stubs for requests"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2049,7 +2049,7 @@ types-urllib3 = "<1.27"
name = "types-urllib3" name = "types-urllib3"
version = "1.26.25" version = "1.26.25"
description = "Typing stubs for urllib3" description = "Typing stubs for urllib3"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2057,7 +2057,7 @@ python-versions = "*"
name = "types-Werkzeug" name = "types-Werkzeug"
version = "1.0.9" version = "1.0.9"
description = "Typing stubs for Werkzeug" description = "Typing stubs for Werkzeug"
category = "main" category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -2234,7 +2234,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.9,<3.11" python-versions = ">=3.9,<3.11"
content-hash = "80df3106c84ea30cfbad3e6d708e136e07b6390c4d0c622aced0abf052d11300" content-hash = "cff4bcfd10157833f1a0f0bb806c3543267c3e99cc13f311b328d101c30ac553"
[metadata.files] [metadata.files]
alabaster = [ alabaster = [
@ -3013,18 +3013,7 @@ py = [
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
] ]
pyasn1 = [ pyasn1 = [
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
{file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"},
{file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"},
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
{file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"},
{file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"},
{file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"},
{file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"},
{file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"},
{file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"},
{file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"},
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
] ]
pycodestyle = [ pycodestyle = [

View File

@ -937,6 +937,20 @@ paths:
schema: schema:
$ref: "#/components/schemas/ServiceTask" $ref: "#/components/schemas/ServiceTask"
/authentications:
get:
tags:
- Authentications
operationId: spiffworkflow_backend.routes.process_api_blueprint.authentication_list
summary: Gets all available authentications from connector proxy
responses:
"200":
description: All authentications
content:
application/json:
schema:
$ref: "#/components/schemas/ServiceTask"
/tasks/{process_instance_id}/{task_id}: /tasks/{process_instance_id}/{task_id}:
parameters: parameters:
- name: task_id - name: task_id

View File

@ -22,6 +22,10 @@ SPIFFWORKFLOW_FRONTEND_URL = environ.get(
SPIFFWORKFLOW_BACKEND_URL = environ.get( SPIFFWORKFLOW_BACKEND_URL = environ.get(
"SPIFFWORKFLOW_BACKEND_URL", default="http://localhost:7000" "SPIFFWORKFLOW_BACKEND_URL", default="http://localhost:7000"
) )
# service task connector proxy
CONNECTOR_PROXY_URL = environ.get(
"CONNECTOR_PROXY_URL", default="http://localhost:7004"
)
GIT_COMMIT_ON_SAVE = environ.get("GIT_COMMIT_ON_SAVE", default="false") == "true" GIT_COMMIT_ON_SAVE = environ.get("GIT_COMMIT_ON_SAVE", default="false") == "true"
@ -37,11 +41,6 @@ SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="false") == "true" environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="false") == "true"
) )
# service task connector proxy
CONNECTOR_PROXY_URL = environ.get(
"CONNECTOR_PROXY_URL", default="http://localhost:7004"
)
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get( SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(
"SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME" "SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME"
) )

View File

@ -31,12 +31,8 @@ class ProcessModelInfo:
description: str description: str
process_group_id: str = "" process_group_id: str = ""
process_group: Any | None = None process_group: Any | None = None
is_master_spec: bool | None = False
standalone: bool | None = False
library: bool | None = False
primary_file_name: str | None = None primary_file_name: str | None = None
primary_process_id: str | None = None primary_process_id: str | None = None
libraries: list[str] = field(default_factory=list)
display_order: int | None = 0 display_order: int | None = 0
is_review: bool = False is_review: bool = False
files: list[File] | None = field(default_factory=list[File]) files: list[File] | None = field(default_factory=list[File])
@ -67,15 +63,11 @@ class ProcessModelInfoSchema(Schema):
id = marshmallow.fields.String(required=True) id = marshmallow.fields.String(required=True)
display_name = marshmallow.fields.String(required=True) display_name = marshmallow.fields.String(required=True)
description = marshmallow.fields.String() description = marshmallow.fields.String()
is_master_spec = marshmallow.fields.Boolean(required=True)
standalone = marshmallow.fields.Boolean(required=True)
library = marshmallow.fields.Boolean(required=True)
display_order = marshmallow.fields.Integer(allow_none=True) display_order = marshmallow.fields.Integer(allow_none=True)
primary_file_name = marshmallow.fields.String(allow_none=True) primary_file_name = marshmallow.fields.String(allow_none=True)
primary_process_id = marshmallow.fields.String(allow_none=True) primary_process_id = marshmallow.fields.String(allow_none=True)
is_review = marshmallow.fields.Boolean(allow_none=True) is_review = marshmallow.fields.Boolean(allow_none=True)
process_group_id = marshmallow.fields.String(allow_none=True) process_group_id = marshmallow.fields.String(allow_none=True)
libraries = marshmallow.fields.List(marshmallow.fields.String(), allow_none=True)
files = marshmallow.fields.List(marshmallow.fields.Nested("FileSchema")) files = marshmallow.fields.List(marshmallow.fields.Nested("FileSchema"))
fault_or_suspend_on_exception = marshmallow.fields.String() fault_or_suspend_on_exception = marshmallow.fields.String()
exception_notification_addresses = marshmallow.fields.List( exception_notification_addresses = marshmallow.fields.List(

View File

@ -774,6 +774,17 @@ def service_tasks_show() -> flask.wrappers.Response:
) )
def authentication_list() -> flask.wrappers.Response:
"""Authentication_list."""
available_authentications = ServiceTaskService.authentication_list()
response_json = {
"results": available_authentications,
"connector_proxy_base_url": current_app.config["CONNECTOR_PROXY_URL"],
}
return Response(json.dumps(response_json), status=200, mimetype="application/json")
def process_instance_report_show( def process_instance_report_show(
process_group_id: str, process_group_id: str,
process_model_id: str, process_model_id: str,

View File

@ -20,11 +20,6 @@ class FileSystemService:
""" Simple Service meant for extension that provides some useful """ Simple Service meant for extension that provides some useful
methods for dealing with the File system. methods for dealing with the File system.
""" """
LIBRARY_SPECS = "Library Specs"
STAND_ALONE_SPECS = "Stand Alone"
MASTER_SPECIFICATION = "Master Specification"
REFERENCE_FILES = "Reference Files"
SPECIAL_FOLDERS = [LIBRARY_SPECS, MASTER_SPECIFICATION, REFERENCE_FILES]
CAT_JSON_FILE = "process_group.json" CAT_JSON_FILE = "process_group.json"
WF_JSON_FILE = "workflow.json" WF_JSON_FILE = "workflow.json"
@ -41,13 +36,6 @@ class FileSystemService:
"""Category_path.""" """Category_path."""
return os.path.join(FileSystemService.root_path(), name) return os.path.join(FileSystemService.root_path(), name)
@staticmethod
def library_path(name: str) -> str:
"""Library_path."""
return os.path.join(
FileSystemService.root_path(), FileSystemService.LIBRARY_SPECS, name
)
@staticmethod @staticmethod
def full_path_from_relative_path(relative_path: str) -> str: def full_path_from_relative_path(relative_path: str) -> str:
"""Full_path_from_relative_path.""" """Full_path_from_relative_path."""
@ -66,32 +54,13 @@ class FileSystemService:
@staticmethod @staticmethod
def process_group_path_for_spec(spec: ProcessModelInfo) -> str: def process_group_path_for_spec(spec: ProcessModelInfo) -> str:
"""Category_path_for_spec.""" """Category_path_for_spec."""
if spec.is_master_spec: return FileSystemService.process_group_path(spec.process_group_id)
return os.path.join(FileSystemService.root_path())
elif spec.library:
process_group_path = FileSystemService.process_group_path(
FileSystemService.LIBRARY_SPECS
)
elif spec.standalone:
process_group_path = FileSystemService.process_group_path(
FileSystemService.STAND_ALONE_SPECS
)
else:
process_group_path = FileSystemService.process_group_path(
spec.process_group_id
)
return process_group_path
@staticmethod @staticmethod
def workflow_path(spec: ProcessModelInfo) -> str: def workflow_path(spec: ProcessModelInfo) -> str:
"""Workflow_path.""" """Workflow_path."""
if spec.is_master_spec: process_group_path = FileSystemService.process_group_path_for_spec(spec)
return os.path.join( return os.path.join(process_group_path, spec.id)
FileSystemService.root_path(), FileSystemService.MASTER_SPECIFICATION
)
else:
process_group_path = FileSystemService.process_group_path_for_spec(spec)
return os.path.join(process_group_path, spec.id)
@staticmethod @staticmethod
def full_path_to_process_model_file(spec: ProcessModelInfo, file_name: str) -> str: def full_path_to_process_model_file(spec: ProcessModelInfo, file_name: str) -> str:

View File

@ -1,4 +1,5 @@
"""Process_instance_processor.""" """Process_instance_processor."""
import _strptime # type: ignore
import decimal import decimal
import json import json
import logging import logging
@ -95,6 +96,7 @@ DEFAULT_GLOBALS.update(
"datetime": datetime, "datetime": datetime,
"time": time, "time": time,
"decimal": decimal, "decimal": decimal,
"_strptime": _strptime,
} }
) )
# This will overwrite the standard builtins # This will overwrite the standard builtins
@ -343,9 +345,7 @@ class ProcessInstanceProcessor:
f"The given process model was not found: {process_group_identifier}/{process_model_identifier}.", f"The given process model was not found: {process_group_identifier}/{process_model_identifier}.",
) )
) )
spec_files = SpecFileService.get_files( spec_files = SpecFileService.get_files(process_model_info)
process_model_info, include_libraries=True
)
return cls.get_spec(spec_files, process_model_info) return cls.get_spec(spec_files, process_model_info)
@classmethod @classmethod

View File

@ -217,9 +217,6 @@ class ProcessInstanceService:
message="A process instance must have a user_id.", message="A process instance must have a user_id.",
task=spiff_task, task=spiff_task,
) )
# # Standalone workflow - we only care about the current user
# elif processor.workflow_model.study_id is None and processor.workflow_model.user_id is not None:
# return [processor.workflow_model.user_id]
# Workflow associated with a study - get all the users # Workflow associated with a study - get all the users
else: else:

View File

@ -63,12 +63,6 @@ class ProcessModelService(FileSystemService):
def save_process_model(self, process_model: ProcessModelInfo) -> None: def save_process_model(self, process_model: ProcessModelInfo) -> None:
"""Save_process_model.""" """Save_process_model."""
spec_path = self.workflow_path(process_model) spec_path = self.workflow_path(process_model)
if (
process_model.is_master_spec
or process_model.library
or process_model.standalone
):
process_model.process_group_id = ""
os.makedirs(spec_path, exist_ok=True) os.makedirs(spec_path, exist_ok=True)
json_path = os.path.join(spec_path, self.WF_JSON_FILE) json_path = os.path.join(spec_path, self.WF_JSON_FILE)
with open(json_path, "w") as wf_json: with open(json_path, "w") as wf_json:
@ -90,20 +84,6 @@ class ProcessModelService(FileSystemService):
path = self.workflow_path(process_model) path = self.workflow_path(process_model)
shutil.rmtree(path) shutil.rmtree(path)
@property
def master_spec(self) -> Optional[ProcessModelInfo]:
"""Master_spec."""
return self.get_master_spec()
def get_master_spec(self) -> Optional[ProcessModelInfo]:
"""Get_master_spec."""
path = os.path.join(
FileSystemService.root_path(), FileSystemService.MASTER_SPECIFICATION
)
if os.path.exists(path):
return self.__scan_spec(path, FileSystemService.MASTER_SPECIFICATION)
return None
@classmethod @classmethod
def get_process_model_from_relative_path( def get_process_model_from_relative_path(
cls, relative_path: str cls, relative_path: str
@ -121,9 +101,6 @@ class ProcessModelService(FileSystemService):
if not os.path.exists(FileSystemService.root_path()): if not os.path.exists(FileSystemService.root_path()):
raise ProcessEntityNotFoundError("process_model_not_found") raise ProcessEntityNotFoundError("process_model_not_found")
master_spec = self.get_master_spec()
if master_spec and master_spec.id == process_model_id:
return master_spec
if group_id is not None: if group_id is not None:
process_group = self.get_process_group(group_id) process_group = self.get_process_group(group_id)
if process_group is not None: if process_group is not None:
@ -168,20 +145,6 @@ class ProcessModelService(FileSystemService):
process_groups.sort() process_groups.sort()
return process_groups return process_groups
def get_libraries(self) -> List[ProcessModelInfo]:
"""Get_libraries."""
process_group = self.get_process_group(self.LIBRARY_SPECS)
if not process_group:
return []
return process_group.process_models
def get_standalones(self) -> List[ProcessModelInfo]:
"""Get_standalones."""
process_group = self.get_process_group(self.STAND_ALONE_SPECS)
if not process_group:
return []
return process_group.process_models
def get_process_group(self, process_group_id: str) -> ProcessGroup: def get_process_group(self, process_group_id: str) -> ProcessGroup:
"""Look for a given process_group, and return it.""" """Look for a given process_group, and return it."""
if os.path.exists(FileSystemService.root_path()): if os.path.exists(FileSystemService.root_path()):
@ -240,14 +203,6 @@ class ProcessModelService(FileSystemService):
process_groups = [] process_groups = []
for item in directory_items: for item in directory_items:
if item.is_dir() and not item.name[0] == ".": if item.is_dir() and not item.name[0] == ".":
# if item.name == self.REFERENCE_FILES:
# continue
# elif item.name == self.MASTER_SPECIFICATION:
# continue
# elif item.name == self.LIBRARY_SPECS:
# continue
# elif item.name == self.STAND_ALONE_SPECS:
# continue
process_groups.append(self.__scan_process_group(item)) process_groups.append(self.__scan_process_group(item))
return process_groups return process_groups
@ -292,7 +247,6 @@ class ProcessModelService(FileSystemService):
) -> ProcessModelInfo: ) -> ProcessModelInfo:
"""__scan_spec.""" """__scan_spec."""
spec_path = os.path.join(path, self.WF_JSON_FILE) spec_path = os.path.join(path, self.WF_JSON_FILE)
is_master = FileSystemService.MASTER_SPECIFICATION in spec_path
if os.path.exists(spec_path): if os.path.exists(spec_path):
with open(spec_path) as wf_json: with open(spec_path) as wf_json:
@ -312,14 +266,10 @@ class ProcessModelService(FileSystemService):
spec = ProcessModelInfo( spec = ProcessModelInfo(
id=name, id=name,
library=False,
standalone=False,
is_master_spec=is_master,
display_name=name, display_name=name,
description="", description="",
display_order=0, display_order=0,
is_review=False, is_review=False,
libraries=[],
) )
with open(spec_path, "w") as wf_json: with open(spec_path, "w") as wf_json:
json.dump(self.WF_SCHEMA.dump(spec), wf_json, indent=4) json.dump(self.WF_SCHEMA.dump(spec), wf_json, indent=4)

View File

@ -9,6 +9,10 @@ from spiffworkflow_backend.services.file_system_service import FileSystemService
from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.secret_service import SecretService
class ConnectorProxyError(Exception):
"""ConnectorProxyError."""
def connector_proxy_url() -> Any: def connector_proxy_url() -> Any:
"""Returns the connector proxy url.""" """Returns the connector proxy url."""
return current_app.config["CONNECTOR_PROXY_URL"] return current_app.config["CONNECTOR_PROXY_URL"]
@ -73,3 +77,18 @@ class ServiceTaskService:
except Exception as e: except Exception as e:
print(e) print(e)
return [] return []
@staticmethod
def authentication_list() -> Any:
"""Returns a list of available authentications."""
try:
response = requests.get(f"{connector_proxy_url()}/v1/auths")
if response.status_code != 200:
return []
parsed_response = json.loads(response.text)
return parsed_response
except Exception as exception:
current_app.logger.error(exception)
raise ConnectorProxyError(exception.__class__.__name__) from exception

View File

@ -39,22 +39,15 @@ class SpecFileService(FileSystemService):
def get_files( def get_files(
process_model_info: ProcessModelInfo, process_model_info: ProcessModelInfo,
file_name: Optional[str] = None, file_name: Optional[str] = None,
include_libraries: bool = False,
extension_filter: str = "", extension_filter: str = "",
) -> List[File]: ) -> List[File]:
"""Return all files associated with a workflow specification.""" """Return all files associated with a workflow specification."""
path = SpecFileService.workflow_path(process_model_info) path = SpecFileService.workflow_path(process_model_info)
files = SpecFileService._get_files(path, file_name) files = SpecFileService._get_files(path, file_name)
if include_libraries:
for lib_name in process_model_info.libraries:
lib_path = SpecFileService.library_path(lib_name)
files.extend(SpecFileService._get_files(lib_path, file_name))
if extension_filter != "": if extension_filter != "":
files = list( files = list(
filter(lambda file: file.name.endswith(extension_filter), files) filter(lambda file: file.name.endswith(extension_filter), files)
) )
return files return files
@staticmethod @staticmethod
@ -96,13 +89,6 @@ class SpecFileService(FileSystemService):
def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes: def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes:
"""Get_data.""" """Get_data."""
file_path = SpecFileService.file_path(process_model_info, file_name) file_path = SpecFileService.file_path(process_model_info, file_name)
if not os.path.exists(file_path):
# If the file isn't here, it may be in a library
for lib in process_model_info.libraries:
file_path = SpecFileService.library_path(lib)
file_path = os.path.join(file_path, file_name)
if os.path.exists(file_path):
break
if not os.path.exists(file_path): if not os.path.exists(file_path):
raise ApiError( raise ApiError(
"unknown_file", "unknown_file",

View File

@ -115,11 +115,7 @@ class BaseTest:
display_name=process_model_display_name, display_name=process_model_display_name,
description=process_model_description, description=process_model_description,
process_group_id=process_group.id, process_group_id=process_group.id,
standalone=False,
is_review=False, is_review=False,
is_master_spec=False,
libraries=[],
library=False,
primary_process_id=primary_process_id, primary_process_id=primary_process_id,
primary_file_name=primary_file_name, primary_file_name=primary_file_name,
fault_or_suspend_on_exception=fault_or_suspend_on_exception, fault_or_suspend_on_exception=fault_or_suspend_on_exception,

View File

@ -18,12 +18,9 @@ class ExampleDataLoader:
process_model_id: str, process_model_id: str,
display_name: str = "", display_name: str = "",
description: str = "", description: str = "",
master_spec: bool = False,
process_group_id: str = "", process_group_id: str = "",
display_order: int = 0, display_order: int = 0,
from_tests: bool = False, from_tests: bool = False,
standalone: bool = False,
library: bool = False,
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
process_model_source_directory: Optional[str] = None, process_model_source_directory: Optional[str] = None,
) -> ProcessModelInfo: ) -> ProcessModelInfo:
@ -38,11 +35,7 @@ class ExampleDataLoader:
description=description, description=description,
process_group_id=process_group_id, process_group_id=process_group_id,
display_order=display_order, display_order=display_order,
is_master_spec=master_spec,
standalone=standalone,
library=library,
is_review=False, is_review=False,
libraries=[],
) )
workflow_spec_service = ProcessModelService() workflow_spec_service = ProcessModelService()
workflow_spec_service.add_spec(spec) workflow_spec_service.add_spec(spec)

View File

@ -37,9 +37,7 @@ def assure_process_group_exists(process_group_id: Optional[str] = None) -> Proce
def load_test_spec( def load_test_spec(
process_model_id: str, process_model_id: str,
master_spec: bool = False,
process_group_id: Optional[str] = None, process_group_id: Optional[str] = None,
library: bool = False,
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
process_model_source_directory: Optional[str] = None, process_model_source_directory: Optional[str] = None,
) -> ProcessModelInfo: ) -> ProcessModelInfo:
@ -48,9 +46,8 @@ def load_test_spec(
process_model_service = ProcessModelService() process_model_service = ProcessModelService()
if process_group_id is None: if process_group_id is None:
process_group_id = "test_process_group_id" process_group_id = "test_process_group_id"
if not master_spec and not library: process_group = assure_process_group_exists(process_group_id)
process_group = assure_process_group_exists(process_group_id) process_group_id = process_group.id
process_group_id = process_group.id
try: try:
return process_model_service.get_process_model( return process_model_service.get_process_model(
@ -59,11 +56,9 @@ def load_test_spec(
except ProcessEntityNotFoundError: except ProcessEntityNotFoundError:
spec = ExampleDataLoader().create_spec( spec = ExampleDataLoader().create_spec(
process_model_id=process_model_id, process_model_id=process_model_id,
master_spec=master_spec,
from_tests=True, from_tests=True,
display_name=process_model_id, display_name=process_model_id,
process_group_id=process_group_id, process_group_id=process_group_id,
library=library,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
process_model_source_directory=process_model_source_directory, process_model_source_directory=process_model_source_directory,
) )

View File

@ -20,7 +20,6 @@ class TestProcessModel(BaseTest):
id="model_one", display_name="Model One" id="model_one", display_name="Model One"
) )
assert process_model_one.files == [] assert process_model_one.files == []
assert process_model_one.libraries == []
def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory( def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory(
self, app: Flask, with_db_and_bpmn_file_cleanup: None self, app: Flask, with_db_and_bpmn_file_cleanup: None