diff --git a/flask-bpmn/poetry.lock b/flask-bpmn/poetry.lock
index bf863b37..7a63efc6 100644
--- a/flask-bpmn/poetry.lock
+++ b/flask-bpmn/poetry.lock
@@ -667,7 +667,7 @@ SQLAlchemy = ">=0.8.0"
[[package]]
name = "furo"
-version = "2022.6.21"
+version = "2022.9.29"
description = "A clean customisable Sphinx documentation theme."
category = "dev"
optional = false
@@ -675,7 +675,7 @@ python-versions = ">=3.7"
[package.dependencies]
beautifulsoup4 = "*"
-pygments = "*"
+pygments = ">=2.7"
sphinx = ">=4.0,<6.0"
sphinx-basic-ng = "*"
@@ -1206,7 +1206,7 @@ tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]]
name = "pyupgrade"
-version = "3.1.0"
+version = "3.2.0"
description = "A tool to automatically upgrade syntax for newer versions."
category = "dev"
optional = false
@@ -1578,7 +1578,7 @@ pytz = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
-resolved_reference = "2d3bd00854ab483e823c4b386430abc9267f536b"
+resolved_reference = "5cdb881edc4621502bfd61ce67565cf1148199f0"
[[package]]
name = "sqlalchemy"
@@ -1853,7 +1853,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
-content-hash = "f5c0fcc30ff491c23da05e4d24c2dc9c66f43a2dfde028345f9dffd5e91f3f0a"
+content-hash = "7d1d5e13f2546566277c6f0b5935753c89804db2abb7a1e76498b582f40f9a01"
[metadata.files]
alabaster = [
@@ -2191,8 +2191,8 @@ flask-sqlalchemy = [
{file = "Flask_SQLAlchemy-2.5.1-py2.py3-none-any.whl", hash = "sha256:f12c3d4cc5cc7fdcc148b9527ea05671718c3ea45d50c7e732cceb33f574b390"},
]
furo = [
- {file = "furo-2022.6.21-py3-none-any.whl", hash = "sha256:061b68e323345e27fcba024cf33a1e77f3dfd8d9987410be822749a706e2add6"},
- {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"},
+ {file = "furo-2022.9.29-py3-none-any.whl", hash = "sha256:559ee17999c0f52728481dcf6b1b0cf8c9743e68c5e3a18cb45a7992747869a9"},
+ {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"},
]
gitdb = [
{file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
@@ -2608,8 +2608,8 @@ pytz-deprecation-shim = [
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
]
pyupgrade = [
- {file = "pyupgrade-3.1.0-py2.py3-none-any.whl", hash = "sha256:77c6101a710be3e24804891e43388cedbee617258e93b09c8c5e58de08617758"},
- {file = "pyupgrade-3.1.0.tar.gz", hash = "sha256:7a8d393d85e15e0e2753e90b7b2e173b9d29dfd71e61f93d93e985b242627ed3"},
+ {file = "pyupgrade-3.2.0-py2.py3-none-any.whl", hash = "sha256:2aa6c40e49ea5a350e6e45b8c7847b1741aef274a35d4f0b2bf91731ec8ab796"},
+ {file = "pyupgrade-3.2.0.tar.gz", hash = "sha256:70e1ac1e6b34a90fb21f5cada1907ef035b12dfc1d9f13cefd367acf3b530310"},
]
pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
diff --git a/flask-bpmn/pyproject.toml b/flask-bpmn/pyproject.toml
index a5a2ff3f..352cd2dd 100644
--- a/flask-bpmn/pyproject.toml
+++ b/flask-bpmn/pyproject.toml
@@ -61,7 +61,7 @@ reorder-python-imports = "^3.9.0"
pre-commit-hooks = "^4.3.0"
sphinx-click = "^4.3.0"
Pygments = "^2.13.0"
-pyupgrade = "^3.1.0"
+pyupgrade = "^3.2.0"
furo = ">=2021.11.12"
MonkeyType = "^22.2.0"
diff --git a/spiffworkflow-backend/migrations/versions/3bd6b0b1b8ae_.py b/spiffworkflow-backend/migrations/versions/bdd1d64689db_.py
similarity index 83%
rename from spiffworkflow-backend/migrations/versions/3bd6b0b1b8ae_.py
rename to spiffworkflow-backend/migrations/versions/bdd1d64689db_.py
index 80c47958..55566149 100644
--- a/spiffworkflow-backend/migrations/versions/3bd6b0b1b8ae_.py
+++ b/spiffworkflow-backend/migrations/versions/bdd1d64689db_.py
@@ -1,8 +1,8 @@
"""empty message
-Revision ID: 3bd6b0b1b8ae
+Revision ID: bdd1d64689db
Revises:
-Create Date: 2022-10-25 12:31:50.177599
+Create Date: 2022-11-02 11:31:50.606843
"""
from alembic import op
@@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
-revision = '3bd6b0b1b8ae'
+revision = 'bdd1d64689db'
down_revision = None
branch_labels = None
depends_on = None
@@ -18,13 +18,6 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
- op.create_table('admin_session',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('token', sa.String(length=50), nullable=True),
- sa.Column('admin_impersonate_uid', sa.String(length=50), nullable=True),
- sa.PrimaryKeyConstraint('id'),
- sa.UniqueConstraint('token')
- )
op.create_table('bpmn_process_id_lookup',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=True),
@@ -183,25 +176,6 @@ def upgrade():
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('task_id', 'process_instance_id', name='active_task_unique')
)
- op.create_table('file',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('name', sa.String(length=50), nullable=False),
- sa.Column('type', sa.String(length=50), nullable=False),
- sa.Column('content_type', sa.String(length=50), nullable=False),
- sa.Column('process_instance_id', sa.Integer(), nullable=True),
- sa.Column('task_spec', sa.String(length=50), nullable=True),
- sa.Column('irb_doc_code', sa.String(length=50), nullable=False),
- sa.Column('md5_hash', sa.String(length=50), nullable=False),
- sa.Column('data', sa.LargeBinary(), nullable=True),
- sa.Column('size', sa.Integer(), nullable=True),
- sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True),
- sa.Column('created_at_in_seconds', sa.Integer(), nullable=True),
- sa.Column('user_uid', sa.String(length=50), nullable=True),
- sa.Column('archived', sa.Boolean(), nullable=True),
- sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
- sa.ForeignKeyConstraint(['user_uid'], ['user.uid'], ),
- sa.PrimaryKeyConstraint('id')
- )
op.create_table('message_correlation',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False),
@@ -259,28 +233,6 @@ def upgrade():
sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
sa.PrimaryKeyConstraint('id')
)
- op.create_table('task_event',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('user_id', sa.Integer(), nullable=False),
- sa.Column('process_instance_id', sa.Integer(), nullable=False),
- sa.Column('spec_version', sa.String(length=50), nullable=True),
- sa.Column('action', sa.String(length=50), nullable=True),
- sa.Column('task_id', sa.String(length=50), nullable=True),
- sa.Column('task_name', sa.String(length=50), nullable=True),
- sa.Column('task_title', sa.String(length=50), nullable=True),
- sa.Column('task_type', sa.String(length=50), nullable=True),
- sa.Column('task_state', sa.String(length=50), nullable=True),
- sa.Column('task_lane', sa.String(length=50), nullable=True),
- sa.Column('form_data', sa.JSON(), nullable=True),
- sa.Column('mi_type', sa.String(length=50), nullable=True),
- sa.Column('mi_count', sa.Integer(), nullable=True),
- sa.Column('mi_index', sa.Integer(), nullable=True),
- sa.Column('process_name', sa.String(length=50), nullable=True),
- sa.Column('date', sa.DateTime(timezone=True), nullable=True),
- sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
- sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
- sa.PrimaryKeyConstraint('id')
- )
op.create_table('active_task_user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('active_task_id', sa.Integer(), nullable=False),
@@ -292,19 +244,6 @@ def upgrade():
)
op.create_index(op.f('ix_active_task_user_active_task_id'), 'active_task_user', ['active_task_id'], unique=False)
op.create_index(op.f('ix_active_task_user_user_id'), 'active_task_user', ['user_id'], unique=False)
- op.create_table('data_store',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True),
- sa.Column('key', sa.String(length=50), nullable=False),
- sa.Column('process_instance_id', sa.Integer(), nullable=True),
- sa.Column('task_spec', sa.String(length=50), nullable=True),
- sa.Column('spec_id', sa.String(length=50), nullable=True),
- sa.Column('user_id', sa.String(length=50), nullable=True),
- sa.Column('file_id', sa.Integer(), nullable=True),
- sa.Column('value', sa.String(length=50), nullable=True),
- sa.ForeignKeyConstraint(['file_id'], ['file.id'], ),
- sa.PrimaryKeyConstraint('id')
- )
op.create_table('message_correlation_message_instance',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('message_instance_id', sa.Integer(), nullable=False),
@@ -324,11 +263,9 @@ def downgrade():
op.drop_index(op.f('ix_message_correlation_message_instance_message_instance_id'), table_name='message_correlation_message_instance')
op.drop_index(op.f('ix_message_correlation_message_instance_message_correlation_id'), table_name='message_correlation_message_instance')
op.drop_table('message_correlation_message_instance')
- op.drop_table('data_store')
op.drop_index(op.f('ix_active_task_user_user_id'), table_name='active_task_user')
op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user')
op.drop_table('active_task_user')
- op.drop_table('task_event')
op.drop_table('spiff_logging')
op.drop_table('permission_assignment')
op.drop_table('message_instance')
@@ -337,7 +274,6 @@ def downgrade():
op.drop_index(op.f('ix_message_correlation_name'), table_name='message_correlation')
op.drop_index(op.f('ix_message_correlation_message_correlation_property_id'), table_name='message_correlation')
op.drop_table('message_correlation')
- op.drop_table('file')
op.drop_table('active_task')
op.drop_table('user_group_assignment')
op.drop_table('secret')
@@ -363,5 +299,4 @@ def downgrade():
op.drop_table('group')
op.drop_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), table_name='bpmn_process_id_lookup')
op.drop_table('bpmn_process_id_lookup')
- op.drop_table('admin_session')
# ### end Alembic commands ###
diff --git a/spiffworkflow-backend/poetry.lock b/spiffworkflow-backend/poetry.lock
index 0fd209b3..c474c696 100644
--- a/spiffworkflow-backend/poetry.lock
+++ b/spiffworkflow-backend/poetry.lock
@@ -410,7 +410,7 @@ python-versions = ">=3.6,<4.0"
[[package]]
name = "dateparser"
-version = "1.1.1"
+version = "1.1.2"
description = "Date parsing library designed to parse dates from HTML pages"
category = "main"
optional = false
@@ -639,7 +639,7 @@ werkzeug = "*"
type = "git"
url = "https://github.com/sartography/flask-bpmn"
reference = "main"
-resolved_reference = "cedc5253add81a18a274f2cd3289fe36bb138f8b"
+resolved_reference = "191f0f32798720c9ce1e5307732c90ac26433298"
[[package]]
name = "Flask-Cors"
@@ -820,7 +820,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "importlib-metadata"
-version = "5.0.0"
+version = "4.13.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
@@ -1441,7 +1441,7 @@ docs = ["Sphinx (>=5.0.2,<6.0.0)", "alabaster (>=0.7.12,<0.8.0)", "commonmark (>
[[package]]
name = "pytz"
-version = "2022.5"
+version = "2022.6"
description = "World timezone definitions, modern and historical"
category = "main"
optional = false
@@ -1873,7 +1873,7 @@ pytz = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
-resolved_reference = "2d3bd00854ab483e823c4b386430abc9267f536b"
+resolved_reference = "a6392d19061f623394f5705fb78af23673d3940d"
[[package]]
name = "SQLAlchemy"
@@ -2000,6 +2000,14 @@ category = "main"
optional = false
python-versions = "*"
+[[package]]
+name = "types-dateparser"
+version = "1.1.4.1"
+description = "Typing stubs for dateparser"
+category = "main"
+optional = false
+python-versions = "*"
+
[[package]]
name = "types-Flask"
version = "1.1.6"
@@ -2248,7 +2256,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata]
lock-version = "1.1"
python-versions = ">=3.9,<3.11"
-content-hash = "bfb51ebc4ef76d4a74f670f44dc4d7ca7e91874b096f56521c2776f1837f6a63"
+content-hash = "995be3a9a60b515b281f017ff32ff27a52ca178b1980611b348dccac6afb6b89"
[metadata.files]
alabaster = [
@@ -2454,8 +2462,8 @@ darglint = [
{file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
]
dateparser = [
- {file = "dateparser-1.1.1-py2.py3-none-any.whl", hash = "sha256:9600874312ff28a41f96ec7ccdc73be1d1c44435719da47fea3339d55ff5a628"},
- {file = "dateparser-1.1.1.tar.gz", hash = "sha256:038196b1f12c7397e38aad3d61588833257f6f552baa63a1499e6987fa8d42d9"},
+ {file = "dateparser-1.1.2-py2.py3-none-any.whl", hash = "sha256:d31659dc806a7d88e2b510b2c74f68b525ae531f145c62a57a99bd616b7f90cf"},
+ {file = "dateparser-1.1.2.tar.gz", hash = "sha256:3821bf191f95b2658c4abd91571c09821ce7a2bc179bf6cefd8b4515c3ccf9ef"},
]
distlib = [
{file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"},
@@ -2632,8 +2640,8 @@ imagesize = [
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
]
importlib-metadata = [
- {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"},
- {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"},
+ {file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"},
+ {file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"},
]
inflection = [
{file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
@@ -2938,7 +2946,10 @@ orjson = [
{file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"},
{file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"},
{file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"},
+ {file = "orjson-3.8.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:200eae21c33f1f8b02a11f5d88d76950cd6fd986d88f1afe497a8ae2627c49aa"},
+ {file = "orjson-3.8.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9529990f3eab54b976d327360aa1ff244a4b12cb5e4c5b3712fcdd96e8fe56d4"},
{file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"},
+ {file = "orjson-3.8.0-cp311-none-win_amd64.whl", hash = "sha256:b21c7af0ff6228ca7105f54f0800636eb49201133e15ddb80ac20c1ce973ef07"},
{file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"},
{file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"},
{file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"},
@@ -3130,8 +3141,8 @@ python-keycloak = [
{file = "python_keycloak-2.6.0-py3-none-any.whl", hash = "sha256:a1ce102b978beb56d385319b3ca20992b915c2c12d15a2d0c23f1104882f3fb6"},
]
pytz = [
- {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"},
- {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"},
+ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
+ {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
]
pytz-deprecation-shim = [
{file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"},
@@ -3539,6 +3550,10 @@ types-click = [
{file = "types-click-7.1.8.tar.gz", hash = "sha256:b6604968be6401dc516311ca50708a0a28baa7a0cb840efd7412f0dbbff4e092"},
{file = "types_click-7.1.8-py3-none-any.whl", hash = "sha256:8cb030a669e2e927461be9827375f83c16b8178c365852c060a34e24871e7e81"},
]
+types-dateparser = [
+ {file = "types-dateparser-1.1.4.1.tar.gz", hash = "sha256:0f76578bbae15c8b8701b5efd94db98a97ce0a27aedfe6f14a531170de6db97d"},
+ {file = "types_dateparser-1.1.4.1-py3-none-any.whl", hash = "sha256:dd7b2343bb06225c0e358533609b66a8edfb95e5426d8f658664e7d0f27dea68"},
+]
types-Flask = [
{file = "types-Flask-1.1.6.tar.gz", hash = "sha256:aac777b3abfff9436e6b01f6d08171cf23ea6e5be71cbf773aaabb1c5763e9cf"},
{file = "types_Flask-1.1.6-py3-none-any.whl", hash = "sha256:6ab8a9a5e258b76539d652f6341408867298550b19b81f0e41e916825fc39087"},
diff --git a/spiffworkflow-backend/pyproject.toml b/spiffworkflow-backend/pyproject.toml
index a4741447..7f2d09a4 100644
--- a/spiffworkflow-backend/pyproject.toml
+++ b/spiffworkflow-backend/pyproject.toml
@@ -28,6 +28,7 @@ flask-migrate = "*"
flask-restful = "*"
werkzeug = "*"
SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
+#SpiffWorkflow = {develop = true, path = "../SpiffWorkflow" }
sentry-sdk = "^1.10"
sphinx-autoapi = "^2.0"
flask-bpmn = {git = "https://github.com/sartography/flask-bpmn", rev = "main"}
@@ -68,6 +69,9 @@ types-pytz = "^2022.1.1"
# for now use my fork
sqlalchemy-stubs = { git = "https://github.com/burnettk/sqlalchemy-stubs.git", rev = "scoped-session-delete" }
simplejson = "^3.17.6"
+pytz = "^2022.6"
+dateparser = "^1.1.2"
+types-dateparser = "^1.1.4.1"
[tool.poetry.dev-dependencies]
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py
index 12b33a7e..7283b19b 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py
@@ -21,8 +21,6 @@ from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F4
from spiffworkflow_backend.models.bpmn_process_id_lookup import (
BpmnProcessIdLookup,
) # noqa: F401
-from spiffworkflow_backend.models.data_store import DataStoreModel # noqa: F401
-from spiffworkflow_backend.models.file import FileModel # noqa: F401
from spiffworkflow_backend.models.message_correlation_property import (
MessageCorrelationPropertyModel,
) # noqa: F401
@@ -48,7 +46,6 @@ from spiffworkflow_backend.models.process_instance_report import (
from spiffworkflow_backend.models.refresh_token import RefreshTokenModel # noqa: F401
from spiffworkflow_backend.models.secret_model import SecretModel # noqa: F401
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel # noqa: F401
-from spiffworkflow_backend.models.task_event import TaskEventModel # noqa: F401
from spiffworkflow_backend.models.user import UserModel # noqa: F401
from spiffworkflow_backend.models.group import GroupModel # noqa: F401
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/data_store.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/data_store.py
deleted file mode 100644
index abbfcf34..00000000
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/data_store.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""Data_store."""
-from flask_bpmn.models.db import db
-from flask_bpmn.models.db import SpiffworkflowBaseDBModel
-from flask_marshmallow.sqla import SQLAlchemyAutoSchema # type: ignore
-
-
-class DataStoreModel(SpiffworkflowBaseDBModel):
- """DataStoreModel."""
-
- __tablename__ = "data_store"
- id = db.Column(db.Integer, primary_key=True)
- updated_at_in_seconds = db.Column(db.Integer)
- key = db.Column(db.String(50), nullable=False)
- process_instance_id = db.Column(db.Integer)
- task_spec = db.Column(db.String(50))
- spec_id = db.Column(db.String(50))
- user_id = db.Column(db.String(50), nullable=True)
- file_id = db.Column(db.Integer, db.ForeignKey("file.id"), nullable=True)
- value = db.Column(db.String(50))
-
-
-class DataStoreSchema(SQLAlchemyAutoSchema): # type: ignore
- """DataStoreSchema."""
-
- class Meta:
- """Meta."""
-
- model = DataStoreModel
- load_instance = True
- include_fk = True
- sqla_session = db.session
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py
index eb49b873..0c844766 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py
@@ -4,40 +4,10 @@ from dataclasses import field
from datetime import datetime
from typing import Optional
-from flask_bpmn.models.db import db
-from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from marshmallow import INCLUDE
from marshmallow import Schema
-from sqlalchemy.orm import deferred
-from sqlalchemy.orm import relationship
from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum
-from spiffworkflow_backend.models.data_store import DataStoreModel
-
-
-class FileModel(SpiffworkflowBaseDBModel):
- """FileModel."""
-
- __tablename__ = "file"
- id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.String(50), nullable=False)
- type = db.Column(db.String(50), nullable=False)
- content_type = db.Column(db.String(50), nullable=False)
- process_instance_id = db.Column(
- db.Integer, db.ForeignKey("process_instance.id"), nullable=True
- )
- task_spec = db.Column(db.String(50), nullable=True)
- irb_doc_code = db.Column(
- db.String(50), nullable=False
- ) # Code reference to the documents.xlsx reference file.
- data_stores = relationship(DataStoreModel, cascade="all,delete", backref="file")
- md5_hash = db.Column(db.String(50), unique=False, nullable=False)
- data = deferred(db.Column(db.LargeBinary)) # type: ignore
- size = db.Column(db.Integer, default=0)
- updated_at_in_seconds = db.Column(db.Integer)
- created_at_in_seconds = db.Column(db.Integer)
- user_uid = db.Column(db.String(50), db.ForeignKey("user.uid"), nullable=True)
- archived = db.Column(db.Boolean, default=False)
class FileType(SpiffEnum):
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py
index d1d117c8..1c2098e9 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py
@@ -78,7 +78,6 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
process_initiator = relationship("UserModel")
active_tasks = relationship("ActiveTaskModel", cascade="delete") # type: ignore
- task_events = relationship("TaskEventModel", cascade="delete") # type: ignore
spiff_logs = relationship("SpiffLoggingModel", cascade="delete") # type: ignore
message_instances = relationship("MessageInstanceModel", cascade="delete") # type: ignore
message_correlations = relationship("MessageCorrelationModel", cascade="delete") # type: ignore
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_event.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_event.py
deleted file mode 100644
index 5bb668b4..00000000
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_event.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""Task_event."""
-from __future__ import annotations
-
-import enum
-from typing import TYPE_CHECKING
-
-from flask_bpmn.models.db import db
-from flask_bpmn.models.db import SpiffworkflowBaseDBModel
-from marshmallow import fields
-from marshmallow import INCLUDE
-from marshmallow import Schema
-from sqlalchemy import func
-
-
-if TYPE_CHECKING:
- from spiffworkflow_backend.models.process_instance import (
- ProcessInstanceModel,
- ) # noqa: F401
-
-
-class TaskAction(enum.Enum):
- """TaskAction."""
-
- COMPLETE = "COMPLETE"
- TOKEN_RESET = "TOKEN_RESET" # noqa: S105
- HARD_RESET = "HARD_RESET"
- SOFT_RESET = "SOFT_RESET"
- ASSIGNMENT = "ASSIGNMENT" # Whenever the lane changes between tasks we assign the task to specific user.
-
-
-class TaskEventModel(SpiffworkflowBaseDBModel):
- """TaskEventModel."""
-
- __tablename__ = "task_event"
- id = db.Column(db.Integer, primary_key=True)
- user_id = db.Column(
- db.Integer, db.ForeignKey("user.id"), nullable=False
- ) # In some cases the unique user id may not exist in the db yet.
- process_instance_id = db.Column(
- db.Integer, db.ForeignKey("process_instance.id"), nullable=False
- )
- spec_version = db.Column(db.String(50))
- action = db.Column(db.String(50))
- task_id = db.Column(db.String(50))
- task_name = db.Column(db.String(50))
- task_title = db.Column(db.String(50))
- task_type = db.Column(db.String(50))
- task_state = db.Column(db.String(50))
- task_lane = db.Column(db.String(50))
- form_data = db.Column(
- db.JSON
- ) # And form data submitted when the task was completed.
- mi_type = db.Column(db.String(50))
- mi_count = db.Column(db.Integer)
- mi_index = db.Column(db.Integer)
- process_name = db.Column(db.String(50))
- date = db.Column(db.DateTime(timezone=True), default=func.now())
-
-
-class TaskEvent:
- """TaskEvent."""
-
- def __init__(self, model: TaskEventModel, process_instance: ProcessInstanceModel):
- """__init__."""
- self.id = model.id
- self.process_instance = process_instance
- self.user_id = model.user_id
- self.action = model.action
- self.task_id = model.task_id
- self.task_title = model.task_title
- self.task_name = model.task_name
- self.task_type = model.task_type
- self.task_state = model.task_state
- self.task_lane = model.task_lane
- self.date = model.date
-
-
-class TaskEventSchema(Schema):
- """TaskEventSchema."""
-
- process_instance = fields.Nested("ProcessInstanceMetadataSchema", dump_only=True)
- task_lane = fields.String(allow_none=True, required=False)
-
- class Meta:
- """Meta."""
-
- model = TaskEvent
- additional = [
- "id",
- "user_id",
- "action",
- "task_id",
- "task_title",
- "task_name",
- "task_type",
- "task_state",
- "task_lane",
- "date",
- ]
- unknown = INCLUDE
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py
index 22cdfb69..c33a72e7 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py
@@ -112,12 +112,3 @@ class UserModelSchema(Schema):
id = marshmallow.fields.String(required=True)
username = marshmallow.fields.String(required=True)
-
-
-class AdminSessionModel(SpiffworkflowBaseDBModel):
- """AdminSessionModel."""
-
- __tablename__ = "admin_session"
- id = db.Column(db.Integer, primary_key=True)
- token = db.Column(db.String(50), unique=True)
- admin_impersonate_uid = db.Column(db.String(50))
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
index 012cb52f..fd20341c 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
@@ -424,7 +424,6 @@ def process_instance_run(
task=task,
) from e
processor.save()
- ProcessInstanceService.update_task_assignments(processor)
if not current_app.config["RUN_BACKGROUND_SCHEDULER"]:
MessageService.process_message_instances()
@@ -1071,7 +1070,9 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
task.form_ui_schema = ui_form_contents
if task.properties and task.data and "instructionsForEndUser" in task.properties:
- print(f"task.properties['instructionsForEndUser']: {task.properties['instructionsForEndUser']}")
+ print(
+ f"task.properties['instructionsForEndUser']: {task.properties['instructionsForEndUser']}"
+ )
if task.properties["instructionsForEndUser"]:
task.properties["instructionsForEndUser"] = render_jinja_template(
task.properties["instructionsForEndUser"], task.data
@@ -1121,8 +1122,6 @@ def task_submit(
# last_index = next_task.task_info()["mi_index"]
# next_task = processor.next_task()
- ProcessInstanceService.update_task_assignments(processor)
-
next_active_task_assigned_to_me = (
ActiveTaskModel.query.filter_by(process_instance_id=process_instance_id)
.order_by(asc(ActiveTaskModel.id)) # type: ignore
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py
index 40dc482c..9490df95 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py
@@ -1,5 +1,6 @@
"""Get_env."""
from typing import Any
+
from flask import current_app
from spiffworkflow_backend.models.script_attributes_context import (
@@ -22,4 +23,4 @@ class GetFrontendUrl(Script):
**kwargs: Any
) -> Any:
"""Run."""
- return current_app.config['SPIFFWORKFLOW_FRONTEND_URL']
+ return current_app.config["SPIFFWORKFLOW_FRONTEND_URL"]
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
index d82d8063..fecde1b9 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
@@ -7,6 +7,7 @@ import os
import re
import time
from datetime import datetime
+from datetime import timedelta
from typing import Any
from typing import Callable
from typing import Dict
@@ -17,6 +18,8 @@ from typing import Tuple
from typing import TypedDict
from typing import Union
+import dateparser
+import pytz
from flask import current_app
from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db
@@ -25,7 +28,6 @@ from RestrictedPython import safe_globals # type: ignore
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore
from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore
from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore
-from SpiffWorkflow.bpmn.PythonScriptEngine import DEFAULT_GLOBALS
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.serializer import BpmnWorkflowSerializer # type: ignore
from SpiffWorkflow.bpmn.specs.BpmnProcessSpec import BpmnProcessSpec # type: ignore
@@ -77,8 +79,6 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
-from spiffworkflow_backend.models.task_event import TaskAction
-from spiffworkflow_backend.models.task_event import TaskEventModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user import UserModelSchema
from spiffworkflow_backend.scripts.script import Script
@@ -98,19 +98,6 @@ def _import(name: str, glbls: Dict[str, Any], *args: Any) -> None:
raise ImportError(f"Import not allowed: {name}", name=name)
-DEFAULT_GLOBALS.update(
- {
- "datetime": datetime,
- "time": time,
- "decimal": decimal,
- "_strptime": _strptime,
- }
-)
-# This will overwrite the standard builtins
-DEFAULT_GLOBALS.update(safe_globals)
-DEFAULT_GLOBALS["__builtins__"]["__import__"] = _import
-
-
class PotentialOwnerIdList(TypedDict):
"""PotentialOwnerIdList."""
@@ -143,7 +130,21 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
def __init__(self) -> None:
"""__init__."""
- super().__init__(default_globals=DEFAULT_GLOBALS)
+ default_globals = {
+ "timedelta": timedelta,
+ "datetime": datetime,
+ "dateparser": dateparser,
+ "pytz": pytz,
+ "time": time,
+ "decimal": decimal,
+ "_strptime": _strptime,
+ }
+
+ # This will overwrite the standard builtins
+ default_globals.update(safe_globals)
+ default_globals["__builtins__"]["__import__"] = _import
+
+ super().__init__(default_globals=default_globals)
def __get_augment_methods(self, task: SpiffTask) -> Dict[str, Callable]:
"""__get_augment_methods."""
@@ -416,7 +417,7 @@ class ProcessInstanceProcessor:
"""Add_user_info_to_process_instance."""
current_user = None
if UserService.has_user():
- current_user = UserService.current_user(allow_admin_impersonate=True)
+ current_user = UserService.current_user()
# fall back to initiator if g.user is not set
# this is for background processes when there will not be a user
@@ -430,59 +431,6 @@ class ProcessInstanceProcessor:
for task in tasks:
task.data["current_user"] = current_user_data
- @staticmethod
- def reset(
- process_instance_model: ProcessInstanceModel, clear_data: bool = False
- ) -> None:
- """Resets the process_instance back to an unstarted state - where nothing has happened yet.
-
- If clear_data is set to false, then the information
- previously used in forms will be re-populated when the form is re-
- displayed, and any files that were updated will remain in place, otherwise
- files will also be cleared out.
- """
- # Try to execute a cancel notify
- try:
- bpmn_process_instance = (
- ProcessInstanceProcessor.__get_bpmn_process_instance(
- process_instance_model
- )
- )
- ProcessInstanceProcessor.__cancel_notify(bpmn_process_instance)
- except Exception as e:
- db.session.rollback() # in case the above left the database with a bad transaction
- current_app.logger.error(
- "Unable to send a cancel notify for process_instance %s during a reset."
- " Continuing with the reset anyway so we don't get in an unresolvable"
- " state. An %s error occured with the following information: %s"
- % (process_instance_model.id, e.__class__.__name__, str(e))
- )
- process_instance_model.bpmn_json = None
- process_instance_model.status = ProcessInstanceStatus.not_started.value
-
- # clear out any task assignments
- db.session.query(TaskEventModel).filter(
- TaskEventModel.process_instance_id == process_instance_model.id
- ).filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).delete()
-
- if clear_data:
- # Clear out data in previous task events
- task_events = (
- db.session.query(TaskEventModel)
- .filter(TaskEventModel.process_instance_id == process_instance_model.id)
- .all()
- )
- for task_event in task_events:
- task_event.form_data = {}
- db.session.add(task_event)
- # Remove any uploaded files.
-
- # TODO: grab UserFileService
- # files = FileModel.query.filter(FileModel.process_instance_id == process_instance_model.id).all()
- # for file in files:
- # UserFileService().delete_file(file.id)
- db.session.commit()
-
@staticmethod
def get_bpmn_process_instance_from_workflow_spec(
spec: BpmnProcessSpec,
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
index f3d080a8..062d0ef7 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
@@ -1,7 +1,6 @@
"""Process_instance_service."""
import time
from typing import Any
-from typing import Dict
from typing import List
from typing import Optional
@@ -9,15 +8,12 @@ from flask import current_app
from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
-from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.task import MultiInstanceType
from spiffworkflow_backend.models.task import Task
-from spiffworkflow_backend.models.task_event import TaskAction
-from spiffworkflow_backend.models.task_event import TaskEventModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.git_service import GitService
@@ -108,70 +104,9 @@ class ProcessInstanceService:
is_review=is_review_value,
title=title_value,
)
- next_task_trying_again = next_task
- if (
- not next_task
- ): # The Next Task can be requested to be a certain task, useful for parallel tasks.
- # This may or may not work, sometimes there is no next task to complete.
- next_task_trying_again = processor.next_task()
-
- if next_task_trying_again is not None:
- previous_form_data = ProcessInstanceService.get_previously_submitted_data(
- processor.process_instance_model.id, next_task_trying_again
- )
- # DeepMerge.merge(next_task_trying_again.data, previous_form_data)
- next_task_trying_again.data = DeepMerge.merge(
- previous_form_data, next_task_trying_again.data
- )
-
- process_instance_api.next_task = (
- ProcessInstanceService.spiff_task_to_api_task(
- next_task_trying_again, add_docs_and_forms=True
- )
- )
- # TODO: Hack for now, until we decide how to implment forms
- process_instance_api.next_task.form = None
-
- # Update the state of the task to locked if the current user does not own the task.
- # user_uids = WorkflowService.get_users_assigned_to_task(processor, next_task)
- # if not UserService.in_list(user_uids, allow_admin_impersonate=True):
- # workflow_api.next_task.state = WorkflowService.TASK_STATE_LOCKED
return process_instance_api
- @staticmethod
- def get_previously_submitted_data(
- process_instance_id: int, spiff_task: SpiffTask
- ) -> Dict[Any, Any]:
- """If the user has completed this task previously, find the form data for the last submission."""
- query = (
- db.session.query(TaskEventModel)
- .filter_by(process_instance_id=process_instance_id)
- .filter_by(task_name=spiff_task.task_spec.name)
- .filter_by(action=TaskAction.COMPLETE.value)
- )
-
- if (
- hasattr(spiff_task, "internal_data")
- and "runtimes" in spiff_task.internal_data
- ):
- query = query.filter_by(mi_index=spiff_task.internal_data["runtimes"])
-
- latest_event = query.order_by(TaskEventModel.date.desc()).first()
- if latest_event:
- if latest_event.form_data is not None:
- return latest_event.form_data # type: ignore
- else:
- missing_form_error = (
- f"We have lost data for workflow {process_instance_id}, "
- f"task {spiff_task.task_spec.name}, it is not in the task event model, "
- f"and it should be."
- )
- current_app.logger.exception("missing_form_data", missing_form_error)
- return {}
- else:
- return {}
-
def get_process_instance(self, process_instance_id: int) -> Any:
"""Get_process_instance."""
result = (
@@ -181,30 +116,6 @@ class ProcessInstanceService:
)
return result
- @staticmethod
- def update_task_assignments(processor: ProcessInstanceProcessor) -> None:
- """For every upcoming user task, log a task action that connects the assigned user(s) to that task.
-
- All existing assignment actions for this workflow are removed from the database,
- so that only the current valid actions are available. update_task_assignments
- should be called whenever progress is made on a workflow.
- """
- db.session.query(TaskEventModel).filter(
- TaskEventModel.process_instance_id == processor.process_instance_model.id
- ).filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).delete()
- db.session.commit()
-
- tasks = processor.get_current_user_tasks()
- for task in tasks:
- user_ids = ProcessInstanceService.get_users_assigned_to_task(
- processor, task
- )
-
- for user_id in user_ids:
- ProcessInstanceService().log_task_action(
- user_id, processor, task, TaskAction.ASSIGNMENT.value
- )
-
@staticmethod
def get_users_assigned_to_task(
processor: ProcessInstanceProcessor, spiff_task: SpiffTask
@@ -279,52 +190,8 @@ class ProcessInstanceService:
spiff_task.update_data(dot_dct)
# ProcessInstanceService.post_process_form(spiff_task) # some properties may update the data store.
processor.complete_task(spiff_task)
- # Log the action before doing the engine steps, as doing so could effect the state of the task
- # the workflow could wrap around in the ngine steps, and the task could jump from being completed to
- # another state. What we are logging here is the completion.
- ProcessInstanceService.log_task_action(
- user.id, processor, spiff_task, TaskAction.COMPLETE.value
- )
processor.do_engine_steps(save=True)
- @staticmethod
- def log_task_action(
- user_id: int,
- processor: ProcessInstanceProcessor,
- spiff_task: SpiffTask,
- action: str,
- ) -> None:
- """Log_task_action."""
- task = ProcessInstanceService.spiff_task_to_api_task(spiff_task)
- form_data = ProcessInstanceService.extract_form_data(
- spiff_task.data, spiff_task
- )
- multi_instance_type_value = ""
- if task.multi_instance_type:
- multi_instance_type_value = task.multi_instance_type.value
-
- task_event = TaskEventModel(
- # study_id=processor.workflow_model.study_id,
- user_id=user_id,
- process_instance_id=processor.process_instance_model.id,
- # workflow_spec_id=processor.workflow_model.workflow_spec_id,
- action=action,
- task_id=str(task.id),
- task_name=task.name,
- task_title=task.title,
- task_type=str(task.type),
- task_state=task.state,
- task_lane=task.lane,
- form_data=form_data,
- mi_type=multi_instance_type_value, # Some tasks have a repeat behavior.
- mi_count=task.multi_instance_count, # This is the number of times the task could repeat.
- mi_index=task.multi_instance_index, # And the index of the currently repeating task.
- process_name=task.process_name,
- # date=datetime.utcnow(), <=== For future reference, NEVER do this. Let the database set the time.
- )
- db.session.add(task_event)
- db.session.commit()
-
@staticmethod
def extract_form_data(latest_data: dict, task: SpiffTask) -> dict:
"""Extracts data from the latest_data that is directly related to the form that is being submitted."""
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py
index d4749e01..0e8e65c2 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py
@@ -11,7 +11,6 @@ from spiffworkflow_backend.models.active_task import ActiveTaskModel
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.principal import PrincipalModel
-from spiffworkflow_backend.models.user import AdminSessionModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel
@@ -103,27 +102,6 @@ class UserService:
"""Has_user."""
return "token" in g and bool(g.token) and "user" in g and bool(g.user)
- # Returns true if the current user is an admin.
- @staticmethod
- def user_is_admin() -> bool:
- """User_is_admin."""
- return UserService.has_user() and g.user.is_admin()
-
- # Returns true if the current admin user is impersonating another user.
- @staticmethod
- def admin_is_impersonating() -> bool:
- """Admin_is_impersonating."""
- if UserService.user_is_admin():
- admin_session = UserService.get_admin_session()
- return admin_session is not None
-
- else:
- raise ApiError(
- "unauthorized",
- "You do not have permissions to do this.",
- status_code=403,
- )
-
# Returns true if the given user uid is different from the current user's uid.
@staticmethod
def is_different_user(uid: str) -> bool:
@@ -131,84 +109,16 @@ class UserService:
return UserService.has_user() and uid is not None and uid is not g.user.uid
@staticmethod
- def current_user(allow_admin_impersonate: bool = False) -> Any:
+ def current_user() -> Any:
"""Current_user."""
if not UserService.has_user():
raise ApiError(
"logged_out", "You are no longer logged in.", status_code=401
)
-
- # Admins can pretend to be different users and act on a user's behalf in
- # some circumstances.
- if (
- UserService.user_is_admin()
- and allow_admin_impersonate
- and UserService.admin_is_impersonating()
- ):
- return UserService.get_admin_session_user()
- else:
- return g.user
-
- # Admins can pretend to be different users and act on a user's behalf in some circumstances.
- # This method allows an admin user to start impersonating another user with the given uid.
- # Stops impersonating if the uid is None or invalid.
- @staticmethod
- def start_impersonating(uid: Optional[str] = None) -> None:
- """Start_impersonating."""
- if not UserService.has_user():
- raise ApiError(
- "logged_out", "You are no longer logged in.", status_code=401
- )
-
- if not UserService.user_is_admin():
- raise ApiError(
- "unauthorized",
- "You do not have permissions to do this.",
- status_code=403,
- )
-
- if uid is None:
- raise ApiError("invalid_uid", "Please provide a valid user uid.")
-
- if UserService.is_different_user(uid):
- # Impersonate the user if the given uid is valid.
- impersonate_user = (
- db.session.query(UserModel).filter(UserModel.uid == uid).first()
- )
-
- if impersonate_user is not None:
- g.impersonate_user = impersonate_user
-
- # Store the uid and user session token.
- db.session.query(AdminSessionModel).filter(
- AdminSessionModel.token == g.token
- ).delete()
- db.session.add(
- AdminSessionModel(token=g.token, admin_impersonate_uid=uid)
- )
- db.session.commit()
- else:
- raise ApiError("invalid_uid", "The uid provided is not valid.")
+ return g.user
@staticmethod
- def stop_impersonating() -> None:
- """Stop_impersonating."""
- if not UserService.has_user():
- raise ApiError(
- "logged_out", "You are no longer logged in.", status_code=401
- )
-
- # Clear out the current impersonating user.
- if "impersonate_user" in g:
- del g.impersonate_user
-
- admin_session = UserService.get_admin_session()
- if admin_session:
- db.session.delete(admin_session)
- db.session.commit()
-
- @staticmethod
- def in_list(uids: list[str], allow_admin_impersonate: bool = False) -> bool:
+ def in_list(uids: list[str]) -> bool:
"""Returns true if the current user's id is in the given list of ids.
False if there is no user, or the user is not in the list.
@@ -216,46 +126,11 @@ class UserService:
if (
UserService.has_user()
): # If someone is logged in, lock tasks that don't belong to them.
- user = UserService.current_user(allow_admin_impersonate)
+ user = UserService.current_user()
if user.uid in uids:
return True
return False
- @staticmethod
- def get_admin_session() -> Any:
- """Get_admin_session."""
- if UserService.user_is_admin():
- return (
- db.session.query(AdminSessionModel)
- .filter(AdminSessionModel.token == g.token)
- .first()
- )
- else:
- raise ApiError(
- "unauthorized",
- "You do not have permissions to do this.",
- status_code=403,
- )
-
- @staticmethod
- def get_admin_session_user() -> Any:
- """Get_admin_session_user."""
- if UserService.user_is_admin():
- admin_session = UserService.get_admin_session()
-
- if admin_session is not None:
- return (
- db.session.query(UserModel)
- .filter(UserModel.uid == admin_session.admin_impersonate_uid)
- .first()
- )
- else:
- raise ApiError(
- "unauthorized",
- "You do not have permissions to do this.",
- status_code=403,
- )
-
@staticmethod
def get_principal_by_user_id(user_id: int) -> PrincipalModel:
"""Get_principal_by_user_id."""
diff --git a/spiffworkflow-backend/tests/data/get_group_members/get_group_members.bpmn b/spiffworkflow-backend/tests/data/get_group_members/get_group_members.bpmn
index 23f6df07..b6e849ba 100644
--- a/spiffworkflow-backend/tests/data/get_group_members/get_group_members.bpmn
+++ b/spiffworkflow-backend/tests/data/get_group_members/get_group_members.bpmn
@@ -11,13 +11,13 @@
Flow_1j4jzft
Flow_10xyk22
- members_a = get_group_members("GroupA")
+ members_a = get_group_members("groupA")
Flow_10xyk22
Flow_01xr2ac
- members_b = get_group_members("GroupB")
+ members_b = get_group_members("groupB")
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py
index b7d2c5d7..a573e8a3 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py
@@ -275,25 +275,6 @@ class BaseTest:
user: UserModel, _redirect_url: str = "http://some/frontend/url"
) -> Dict[str, str]:
"""Logged_in_headers."""
- # if user is None:
- # uid = 'test_user'
- # user_info = {'uid': 'test_user'}
- # else:
- # uid = user.uid
- # user_info = {'uid': user.uid}
-
- # query_string = user_info_to_query_string(user_info, redirect_url)
- # rv = self.app.get("/v1.0/login%s" % query_string, follow_redirects=False)
- # self.assertTrue(rv.status_code == 302)
- # self.assertTrue(str.startswith(rv.location, redirect_url))
- #
- # user_model = session.query(UserModel).filter_by(uid=uid).first()
- # self.assertIsNotNone(user_model.ldap_info.display_name)
- # self.assertEqual(user_model.uid, uid)
- # self.assertTrue('user' in g, 'User should be in Flask globals')
- # user = UserService.current_user(allow_admin_impersonate=True)
- # self.assertEqual(uid, user.uid, 'Logged in user should match given user uid')
-
return dict(Authorization="Bearer " + user.encode_auth_token())
def get_test_data_file_contents(
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py
index 2d79b652..9a923b97 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py
@@ -25,7 +25,6 @@ from spiffworkflow_backend.models.process_instance_report import (
)
from spiffworkflow_backend.models.process_model import NotificationType
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
-from spiffworkflow_backend.models.task_event import TaskEventModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.file_system_service import FileSystemService
@@ -1088,16 +1087,7 @@ class TestProcessApi(BaseTest):
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
headers=self.logged_in_headers(with_super_admin_user),
)
-
assert response.json is not None
- task_events = (
- db.session.query(TaskEventModel)
- .filter(TaskEventModel.process_instance_id == process_instance_id)
- .all()
- )
- assert len(task_events) == 1
- task_event = task_events[0]
- assert task_event.user_id == with_super_admin_user.id
delete_response = client.delete(
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}",
@@ -1105,40 +1095,6 @@ class TestProcessApi(BaseTest):
)
assert delete_response.status_code == 200
- def test_process_instance_run_user_task_creates_task_event(
- self,
- app: Flask,
- client: FlaskClient,
- with_db_and_bpmn_file_cleanup: None,
- with_super_admin_user: UserModel,
- ) -> None:
- """Test_process_instance_run_user_task."""
- process_group_id = "my_process_group"
- process_model_id = "user_task"
-
- headers = self.logged_in_headers(with_super_admin_user)
- response = self.create_process_instance(
- client, process_group_id, process_model_id, headers
- )
- assert response.json is not None
- process_instance_id = response.json["id"]
-
- response = client.post(
- f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
- headers=self.logged_in_headers(with_super_admin_user),
- )
-
- assert response.json is not None
- task_events = (
- db.session.query(TaskEventModel)
- .filter(TaskEventModel.process_instance_id == process_instance_id)
- .all()
- )
- assert len(task_events) == 1
- task_event = task_events[0]
- assert task_event.user_id == with_super_admin_user.id
- # TODO: When user tasks work, we need to add some more assertions for action, task_state, etc.
-
def test_task_show(
self,
app: Flask,