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 06b2b562..c474c696 100644
--- a/spiffworkflow-backend/poetry.lock
+++ b/spiffworkflow-backend/poetry.lock
@@ -1873,7 +1873,7 @@ pytz = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
-resolved_reference = "5cdb881edc4621502bfd61ce67565cf1148199f0"
+resolved_reference = "a6392d19061f623394f5705fb78af23673d3940d"
[[package]]
name = "SQLAlchemy"
@@ -2621,6 +2621,7 @@ greenlet = [
{file = "greenlet-1.1.3.post0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win32.whl", hash = "sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"},
+ {file = "greenlet-1.1.3.post0.tar.gz", hash = "sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c"},
]
gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
@@ -2945,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"},
@@ -3058,18 +3062,7 @@ py = [
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
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-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"},
]
pycodestyle = [
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 f0a93fd9..0523ad25 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()
@@ -1123,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/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
index b499081f..fecde1b9 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
@@ -79,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
@@ -419,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
@@ -433,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,