From 7c35b20446fe8a83589ff503b83836136af4698d Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 11 Nov 2022 11:24:35 -0500 Subject: [PATCH] Squashed 'spiffworkflow-backend/' changes from e78e32dcf..46a590749 46a590749 pulled in subtrees and resolved conflicts w/ burnettk 1dcad7262 Report URL fixes (#29) 131dbeb3c oops c50c85eda mypy fixes 3735b71e0 removed duplicate code ba08826c6 modify process_groups_list so it can process any group path, not just the root process_groups_list now takes an optional group path 1e09c9552 renamed and reordered some methods in base_test.py dfa79360c Merge branch 'main' into feature/nested-groups-2 450a8d075 Delete groups now checks for running instances in nested models also, pyl c814e991a use error as a status instead of faulted w/ burnettk 3211e7a49 fixed up the process instance show page and moved contents of scss to css file and load that last w/ burnettk git-subtree-dir: spiffworkflow-backend git-subtree-split: 46a590749dc147d0fe7250dcb65d764e87fb2200 --- bin/import_tickets_for_command_line.py | 1 - bin/start_blocking_appscheduler.py | 1 - conftest.py | 5 +- migrations/env.py | 25 +- migrations/versions/fd00c59e1f60_.py | 769 ++++++++++++------ poetry.lock | 2 +- src/spiffworkflow_backend/__init__.py | 5 +- src/spiffworkflow_backend/api.yml | 68 +- src/spiffworkflow_backend/config/__init__.py | 3 +- .../models/active_task.py | 7 +- .../models/active_task_user.py | 3 +- src/spiffworkflow_backend/models/file.py | 1 - .../models/message_correlation.py | 5 +- .../message_correlation_message_instance.py | 3 +- .../models/message_correlation_property.py | 3 +- .../models/message_instance.py | 5 +- .../message_triggerable_process_model.py | 3 +- .../models/permission_assignment.py | 5 +- src/spiffworkflow_backend/models/principal.py | 5 +- .../models/process_group.py | 1 - .../models/process_instance.py | 12 +- .../models/process_instance_report.py | 11 +- .../models/process_model.py | 1 - .../models/secret_model.py | 3 +- src/spiffworkflow_backend/models/user.py | 5 +- .../models/user_group_assignment.py | 5 +- .../routes/admin_blueprint/admin_blueprint.py | 3 +- .../routes/process_api_blueprint.py | 20 +- src/spiffworkflow_backend/routes/user.py | 7 +- .../routes/user_blueprint.py | 3 +- .../scripts/get_current_user.py | 1 - .../scripts/get_frontend_url.py | 1 - .../scripts/get_localtime.py | 1 - src/spiffworkflow_backend/scripts/script.py | 1 - .../services/acceptance_test_fixtures.py | 5 +- .../services/authentication_service.py | 3 +- .../services/authorization_service.py | 3 +- .../services/background_processing_service.py | 1 - .../services/data_setup_service.py | 1 - .../services/error_handling_service.py | 3 +- .../services/file_system_service.py | 3 +- .../services/git_service.py | 1 - .../services/group_service.py | 1 - .../services/logging_service.py | 1 - .../services/message_service.py | 7 +- .../services/process_instance_processor.py | 1 - .../services/process_instance_service.py | 3 +- .../services/process_model_service.py | 38 +- .../services/script_unit_test_runner.py | 1 - .../services/secret_service.py | 1 - .../services/service_task_service.py | 1 - .../services/spec_file_service.py | 1 - .../services/user_service.py | 1 - tests/data/simple_form/simple_form.bpmn | 63 ++ tests/data/simple_form/simple_form.json | 24 + tests/data/simple_form/simple_form_ui.json | 13 + .../helpers/base_test.py | 162 ++-- .../helpers/example_data.py | 1 - .../helpers/test_data.py | 3 +- .../integration/test_authentication.py | 3 +- .../integration/test_logging_service.py | 5 +- .../integration/test_nested_groups.py | 115 ++- .../integration/test_process_api.py | 103 ++- .../integration/test_secret_service.py | 5 +- .../scripts/test_get_group_members.py | 5 +- .../scripts/test_get_localtime.py | 5 +- .../unit/test_acceptance_test_fixtures.py | 1 - .../unit/test_authorization_service.py | 5 +- .../unit/test_dot_notation.py | 7 +- .../unit/test_environment_var_script.py | 3 +- .../unit/test_message_instance.py | 5 +- .../unit/test_message_service.py | 5 +- .../unit/test_permission_target.py | 3 +- .../unit/test_permissions.py | 5 +- .../unit/test_process_group.py | 1 - .../unit/test_process_instance_processor.py | 5 +- .../unit/test_process_instance_report.py | 3 +- .../unit/test_process_model.py | 5 +- .../unit/test_process_model_service.py | 5 +- .../unit/test_restricted_script_engine.py | 5 +- .../unit/test_script_unit_test_runner.py | 5 +- .../unit/test_service_task_delegate.py | 3 +- .../unit/test_spec_file_service.py | 13 +- .../unit/test_spiff_logging.py | 3 +- .../unit/test_various_bpmn_constructs.py | 5 +- tests/test_main.py | 1 - 86 files changed, 999 insertions(+), 666 deletions(-) create mode 100644 tests/data/simple_form/simple_form.bpmn create mode 100644 tests/data/simple_form/simple_form.json create mode 100644 tests/data/simple_form/simple_form_ui.json diff --git a/bin/import_tickets_for_command_line.py b/bin/import_tickets_for_command_line.py index 8b145dc4a..5818d438d 100644 --- a/bin/import_tickets_for_command_line.py +++ b/bin/import_tickets_for_command_line.py @@ -2,7 +2,6 @@ import csv from flask_bpmn.models.db import db - from spiffworkflow_backend import get_hacked_up_app_for_script from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel diff --git a/bin/start_blocking_appscheduler.py b/bin/start_blocking_appscheduler.py index 4af99e411..61b753f26 100755 --- a/bin/start_blocking_appscheduler.py +++ b/bin/start_blocking_appscheduler.py @@ -2,7 +2,6 @@ import time from apscheduler.schedulers.background import BlockingScheduler # type: ignore - from spiffworkflow_backend import create_app from spiffworkflow_backend import start_scheduler from spiffworkflow_backend.helpers.db_helper import try_to_connect diff --git a/conftest.py b/conftest.py index d73693c23..012f3c776 100644 --- a/conftest.py +++ b/conftest.py @@ -7,8 +7,6 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel @@ -19,6 +17,7 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest # from tests.spiffworkflow_backend.helpers.test_data import load_test_spec @@ -77,7 +76,7 @@ def setup_process_instances_for_reports( process_model_id = "sample" # bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = BaseTest().basic_test_setup( + process_model_identifier = BaseTest().create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, diff --git a/migrations/env.py b/migrations/env.py index 630e381ad..4bd0316c2 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,9 +1,8 @@ import logging from logging.config import fileConfig -from flask import current_app - from alembic import context +from flask import current_app # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -12,17 +11,17 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.get_engine().url).replace( - '%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.get_engine().url).replace("%", "%%"), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -43,9 +42,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) with context.begin_transaction(): context.run_migrations() @@ -63,20 +60,20 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") - connectable = current_app.extensions['migrate'].db.get_engine() + connectable = current_app.extensions["migrate"].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args + **current_app.extensions["migrate"].configure_args ) with context.begin_transaction(): diff --git a/migrations/versions/fd00c59e1f60_.py b/migrations/versions/fd00c59e1f60_.py index f240843ae..ed8bbeb8d 100644 --- a/migrations/versions/fd00c59e1f60_.py +++ b/migrations/versions/fd00c59e1f60_.py @@ -1,16 +1,16 @@ """empty message Revision ID: fd00c59e1f60 -Revises: +Revises: Create Date: 2022-11-09 14:04:14.169379 """ -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. -revision = 'fd00c59e1f60' +revision = "fd00c59e1f60" down_revision = None branch_labels = None depends_on = None @@ -18,291 +18,532 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - 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), - sa.Column('bpmn_file_relative_path', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id') + 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), + sa.Column("bpmn_file_relative_path", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), 'bpmn_process_id_lookup', ['bpmn_process_identifier'], unique=True) - op.create_table('group', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=255), nullable=True), - sa.Column('identifier', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_bpmn_process_id_lookup_bpmn_process_identifier"), + "bpmn_process_id_lookup", + ["bpmn_process_identifier"], + unique=True, ) - op.create_table('message_model', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=True), - sa.Column('name', sa.String(length=50), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_table( + "group", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=255), nullable=True), + sa.Column("identifier", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_model_identifier'), 'message_model', ['identifier'], unique=True) - op.create_index(op.f('ix_message_model_name'), 'message_model', ['name'], unique=True) - op.create_table('permission_target', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('uri', sa.String(length=255), nullable=False), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('uri') + op.create_table( + "message_model", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=True), + sa.Column("name", sa.String(length=50), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('spiff_logging', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=False), - sa.Column('bpmn_task_identifier', sa.String(length=255), nullable=False), - sa.Column('bpmn_task_name', sa.String(length=255), nullable=True), - sa.Column('bpmn_task_type', sa.String(length=255), nullable=True), - sa.Column('spiff_task_guid', sa.String(length=50), nullable=False), - sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), - sa.Column('message', sa.String(length=255), nullable=True), - sa.Column('current_user_id', sa.Integer(), nullable=True), - sa.Column('spiff_step', sa.Integer(), nullable=False), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_message_model_identifier"), + "message_model", + ["identifier"], + unique=True, ) - op.create_table('spiff_step_details', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('spiff_step', sa.Integer(), nullable=False), - sa.Column('task_json', sa.JSON(), nullable=False), - sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), - sa.Column('completed_by_user_id', sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_message_model_name"), "message_model", ["name"], unique=True ) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('username', sa.String(length=255), nullable=False), - sa.Column('uid', sa.String(length=50), nullable=True), - sa.Column('service', sa.String(length=50), nullable=False), - sa.Column('service_id', sa.String(length=255), nullable=False), - sa.Column('name', sa.String(length=255), nullable=True), - sa.Column('email', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('service', 'service_id', name='service_key'), - sa.UniqueConstraint('uid'), - sa.UniqueConstraint('username') + op.create_table( + "permission_target", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("uri", sa.String(length=255), nullable=False), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("uri"), ) - op.create_table('message_correlation_property', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=True), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('identifier', 'message_model_id', name='message_correlation_property_unique') + op.create_table( + "spiff_logging", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("bpmn_process_identifier", sa.String(length=255), nullable=False), + sa.Column("bpmn_task_identifier", sa.String(length=255), nullable=False), + sa.Column("bpmn_task_name", sa.String(length=255), nullable=True), + sa.Column("bpmn_task_type", sa.String(length=255), nullable=True), + sa.Column("spiff_task_guid", sa.String(length=50), nullable=False), + sa.Column("timestamp", sa.DECIMAL(precision=17, scale=6), nullable=False), + sa.Column("message", sa.String(length=255), nullable=True), + sa.Column("current_user_id", sa.Integer(), nullable=True), + sa.Column("spiff_step", sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_correlation_property_identifier'), 'message_correlation_property', ['identifier'], unique=False) - op.create_table('message_triggerable_process_model', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('process_model_identifier', sa.String(length=50), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('message_model_id') + op.create_table( + "spiff_step_details", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("spiff_step", sa.Integer(), nullable=False), + sa.Column("task_json", sa.JSON(), nullable=False), + sa.Column("timestamp", sa.DECIMAL(precision=17, scale=6), nullable=False), + sa.Column("completed_by_user_id", sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), 'message_triggerable_process_model', ['process_group_identifier'], unique=False) - op.create_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), 'message_triggerable_process_model', ['process_model_identifier'], unique=False) - op.create_table('principal', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('group_id', sa.Integer(), nullable=True), - sa.CheckConstraint('NOT(user_id IS NULL AND group_id IS NULL)'), - sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('group_id'), - sa.UniqueConstraint('user_id') + op.create_table( + "user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("username", sa.String(length=255), nullable=False), + sa.Column("uid", sa.String(length=50), nullable=True), + sa.Column("service", sa.String(length=50), nullable=False), + sa.Column("service_id", sa.String(length=255), nullable=False), + sa.Column("name", sa.String(length=255), nullable=True), + sa.Column("email", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("service", "service_id", name="service_key"), + sa.UniqueConstraint("uid"), + sa.UniqueConstraint("username"), ) - op.create_table('process_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_model_identifier', sa.String(length=255), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), - sa.Column('process_initiator_id', sa.Integer(), nullable=False), - sa.Column('bpmn_json', sa.JSON(), nullable=True), - sa.Column('start_in_seconds', sa.Integer(), nullable=True), - sa.Column('end_in_seconds', 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('status', sa.String(length=50), nullable=True), - sa.Column('bpmn_version_control_type', sa.String(length=50), nullable=True), - sa.Column('bpmn_version_control_identifier', sa.String(length=255), nullable=True), - sa.Column('spiff_step', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['process_initiator_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "message_correlation_property", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=True), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "identifier", "message_model_id", name="message_correlation_property_unique" + ), ) - op.create_index(op.f('ix_process_instance_process_group_identifier'), 'process_instance', ['process_group_identifier'], unique=False) - op.create_index(op.f('ix_process_instance_process_model_identifier'), 'process_instance', ['process_model_identifier'], unique=False) - op.create_table('process_instance_report', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=False), - sa.Column('report_metadata', sa.JSON(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=False), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('created_by_id', 'identifier', name='process_instance_report_unique') + op.create_index( + op.f("ix_message_correlation_property_identifier"), + "message_correlation_property", + ["identifier"], + unique=False, ) - op.create_index(op.f('ix_process_instance_report_created_by_id'), 'process_instance_report', ['created_by_id'], unique=False) - op.create_index(op.f('ix_process_instance_report_identifier'), 'process_instance_report', ['identifier'], unique=False) - op.create_table('refresh_token', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('token', sa.String(length=1024), nullable=False), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('user_id') + op.create_table( + "message_triggerable_process_model", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("process_model_identifier", sa.String(length=50), nullable=False), + sa.Column("process_group_identifier", sa.String(length=50), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("message_model_id"), ) - op.create_table('secret', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('key', sa.String(length=50), nullable=False), - sa.Column('value', sa.Text(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('key') + op.create_index( + op.f("ix_message_triggerable_process_model_process_group_identifier"), + "message_triggerable_process_model", + ["process_group_identifier"], + unique=False, ) - op.create_table('user_group_assignment', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('group_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('user_id', 'group_id', name='user_group_assignment_unique') + op.create_index( + op.f("ix_message_triggerable_process_model_process_model_identifier"), + "message_triggerable_process_model", + ["process_model_identifier"], + unique=False, ) - op.create_table('active_task', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('actual_owner_id', sa.Integer(), nullable=True), - sa.Column('lane_assignment_id', sa.Integer(), nullable=True), - sa.Column('form_file_name', sa.String(length=50), nullable=True), - sa.Column('ui_form_file_name', sa.String(length=50), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), 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_status', sa.String(length=50), nullable=True), - sa.Column('process_model_display_name', sa.String(length=255), nullable=True), - sa.ForeignKeyConstraint(['actual_owner_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('task_id', 'process_instance_id', name='active_task_unique') + op.create_table( + "principal", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("group_id", sa.Integer(), nullable=True), + sa.CheckConstraint("NOT(user_id IS NULL AND group_id IS NULL)"), + sa.ForeignKeyConstraint( + ["group_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("group_id"), + sa.UniqueConstraint("user_id"), ) - op.create_table('message_correlation', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('message_correlation_property_id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('value', sa.String(length=255), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_correlation_property_id'], ['message_correlation_property.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('process_instance_id', 'message_correlation_property_id', 'name', name='message_instance_id_name_unique') + op.create_table( + "process_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_model_identifier", sa.String(length=255), nullable=False), + sa.Column("process_group_identifier", sa.String(length=50), nullable=False), + sa.Column("process_initiator_id", sa.Integer(), nullable=False), + sa.Column("bpmn_json", sa.JSON(), nullable=True), + sa.Column("start_in_seconds", sa.Integer(), nullable=True), + sa.Column("end_in_seconds", 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("status", sa.String(length=50), nullable=True), + sa.Column("bpmn_version_control_type", sa.String(length=50), nullable=True), + sa.Column( + "bpmn_version_control_identifier", sa.String(length=255), nullable=True + ), + sa.Column("spiff_step", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["process_initiator_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_correlation_message_correlation_property_id'), 'message_correlation', ['message_correlation_property_id'], unique=False) - op.create_index(op.f('ix_message_correlation_name'), 'message_correlation', ['name'], unique=False) - op.create_index(op.f('ix_message_correlation_process_instance_id'), 'message_correlation', ['process_instance_id'], unique=False) - op.create_index(op.f('ix_message_correlation_value'), 'message_correlation', ['value'], unique=False) - op.create_table('message_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('message_type', sa.String(length=20), nullable=False), - sa.Column('payload', sa.JSON(), nullable=True), - sa.Column('status', sa.String(length=20), nullable=False), - sa.Column('failure_cause', sa.Text(), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_process_instance_process_group_identifier"), + "process_instance", + ["process_group_identifier"], + unique=False, ) - op.create_table('permission_assignment', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('principal_id', sa.Integer(), nullable=False), - sa.Column('permission_target_id', sa.Integer(), nullable=False), - sa.Column('grant_type', sa.String(length=50), nullable=False), - sa.Column('permission', sa.String(length=50), nullable=False), - sa.ForeignKeyConstraint(['permission_target_id'], ['permission_target.id'], ), - sa.ForeignKeyConstraint(['principal_id'], ['principal.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('principal_id', 'permission_target_id', 'permission', name='permission_assignment_uniq') + op.create_index( + op.f("ix_process_instance_process_model_identifier"), + "process_instance", + ["process_model_identifier"], + unique=False, ) - op.create_table('active_task_user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('active_task_id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['active_task_id'], ['active_task.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('active_task_id', 'user_id', name='active_task_user_unique') + op.create_table( + "process_instance_report", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=False), + sa.Column("report_metadata", sa.JSON(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=False), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "created_by_id", "identifier", name="process_instance_report_unique" + ), ) - 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('message_correlation_message_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('message_instance_id', sa.Integer(), nullable=False), - sa.Column('message_correlation_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['message_correlation_id'], ['message_correlation.id'], ), - sa.ForeignKeyConstraint(['message_instance_id'], ['message_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('message_instance_id', 'message_correlation_id', name='message_correlation_message_instance_unique') + op.create_index( + op.f("ix_process_instance_report_created_by_id"), + "process_instance_report", + ["created_by_id"], + unique=False, + ) + op.create_index( + op.f("ix_process_instance_report_identifier"), + "process_instance_report", + ["identifier"], + unique=False, + ) + op.create_table( + "refresh_token", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("token", sa.String(length=1024), nullable=False), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id"), + ) + op.create_table( + "secret", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("key", sa.String(length=50), nullable=False), + sa.Column("value", sa.Text(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("key"), + ) + op.create_table( + "user_group_assignment", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("group_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["group_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id", "group_id", name="user_group_assignment_unique"), + ) + op.create_table( + "active_task", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("actual_owner_id", sa.Integer(), nullable=True), + sa.Column("lane_assignment_id", sa.Integer(), nullable=True), + sa.Column("form_file_name", sa.String(length=50), nullable=True), + sa.Column("ui_form_file_name", sa.String(length=50), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), 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_status", sa.String(length=50), nullable=True), + sa.Column("process_model_display_name", sa.String(length=255), nullable=True), + sa.ForeignKeyConstraint( + ["actual_owner_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["lane_assignment_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "task_id", "process_instance_id", name="active_task_unique" + ), + ) + op.create_table( + "message_correlation", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("message_correlation_property_id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=255), nullable=False), + sa.Column("value", sa.String(length=255), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_correlation_property_id"], + ["message_correlation_property.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "process_instance_id", + "message_correlation_property_id", + "name", + name="message_instance_id_name_unique", + ), + ) + op.create_index( + op.f("ix_message_correlation_message_correlation_property_id"), + "message_correlation", + ["message_correlation_property_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_name"), + "message_correlation", + ["name"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_process_instance_id"), + "message_correlation", + ["process_instance_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_value"), + "message_correlation", + ["value"], + unique=False, + ) + op.create_table( + "message_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("message_type", sa.String(length=20), nullable=False), + sa.Column("payload", sa.JSON(), nullable=True), + sa.Column("status", sa.String(length=20), nullable=False), + sa.Column("failure_cause", sa.Text(), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "permission_assignment", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("principal_id", sa.Integer(), nullable=False), + sa.Column("permission_target_id", sa.Integer(), nullable=False), + sa.Column("grant_type", sa.String(length=50), nullable=False), + sa.Column("permission", sa.String(length=50), nullable=False), + sa.ForeignKeyConstraint( + ["permission_target_id"], + ["permission_target.id"], + ), + sa.ForeignKeyConstraint( + ["principal_id"], + ["principal.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "principal_id", + "permission_target_id", + "permission", + name="permission_assignment_uniq", + ), + ) + op.create_table( + "active_task_user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("active_task_id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["active_task_id"], + ["active_task.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "active_task_id", "user_id", name="active_task_user_unique" + ), + ) + 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( + "message_correlation_message_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("message_instance_id", sa.Integer(), nullable=False), + sa.Column("message_correlation_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["message_correlation_id"], + ["message_correlation.id"], + ), + sa.ForeignKeyConstraint( + ["message_instance_id"], + ["message_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "message_instance_id", + "message_correlation_id", + name="message_correlation_message_instance_unique", + ), + ) + op.create_index( + op.f("ix_message_correlation_message_instance_message_correlation_id"), + "message_correlation_message_instance", + ["message_correlation_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_message_instance_message_instance_id"), + "message_correlation_message_instance", + ["message_instance_id"], + unique=False, ) - op.create_index(op.f('ix_message_correlation_message_instance_message_correlation_id'), 'message_correlation_message_instance', ['message_correlation_id'], unique=False) - op.create_index(op.f('ix_message_correlation_message_instance_message_instance_id'), 'message_correlation_message_instance', ['message_instance_id'], unique=False) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - 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_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('permission_assignment') - op.drop_table('message_instance') - op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation') - op.drop_index(op.f('ix_message_correlation_process_instance_id'), table_name='message_correlation') - 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('active_task') - op.drop_table('user_group_assignment') - op.drop_table('secret') - op.drop_table('refresh_token') - op.drop_index(op.f('ix_process_instance_report_identifier'), table_name='process_instance_report') - op.drop_index(op.f('ix_process_instance_report_created_by_id'), table_name='process_instance_report') - op.drop_table('process_instance_report') - op.drop_index(op.f('ix_process_instance_process_model_identifier'), table_name='process_instance') - op.drop_index(op.f('ix_process_instance_process_group_identifier'), table_name='process_instance') - op.drop_table('process_instance') - op.drop_table('principal') - op.drop_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), table_name='message_triggerable_process_model') - op.drop_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), table_name='message_triggerable_process_model') - op.drop_table('message_triggerable_process_model') - op.drop_index(op.f('ix_message_correlation_property_identifier'), table_name='message_correlation_property') - op.drop_table('message_correlation_property') - op.drop_table('user') - op.drop_table('spiff_step_details') - op.drop_table('spiff_logging') - op.drop_table('permission_target') - op.drop_index(op.f('ix_message_model_name'), table_name='message_model') - op.drop_index(op.f('ix_message_model_identifier'), table_name='message_model') - op.drop_table('message_model') - 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_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_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("permission_assignment") + op.drop_table("message_instance") + op.drop_index( + op.f("ix_message_correlation_value"), table_name="message_correlation" + ) + op.drop_index( + op.f("ix_message_correlation_process_instance_id"), + table_name="message_correlation", + ) + 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("active_task") + op.drop_table("user_group_assignment") + op.drop_table("secret") + op.drop_table("refresh_token") + op.drop_index( + op.f("ix_process_instance_report_identifier"), + table_name="process_instance_report", + ) + op.drop_index( + op.f("ix_process_instance_report_created_by_id"), + table_name="process_instance_report", + ) + op.drop_table("process_instance_report") + op.drop_index( + op.f("ix_process_instance_process_model_identifier"), + table_name="process_instance", + ) + op.drop_index( + op.f("ix_process_instance_process_group_identifier"), + table_name="process_instance", + ) + op.drop_table("process_instance") + op.drop_table("principal") + op.drop_index( + op.f("ix_message_triggerable_process_model_process_model_identifier"), + table_name="message_triggerable_process_model", + ) + op.drop_index( + op.f("ix_message_triggerable_process_model_process_group_identifier"), + table_name="message_triggerable_process_model", + ) + op.drop_table("message_triggerable_process_model") + op.drop_index( + op.f("ix_message_correlation_property_identifier"), + table_name="message_correlation_property", + ) + op.drop_table("message_correlation_property") + op.drop_table("user") + op.drop_table("spiff_step_details") + op.drop_table("spiff_logging") + op.drop_table("permission_target") + op.drop_index(op.f("ix_message_model_name"), table_name="message_model") + op.drop_index(op.f("ix_message_model_identifier"), table_name="message_model") + op.drop_table("message_model") + 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") # ### end Alembic commands ### diff --git a/poetry.lock b/poetry.lock index 285f19e78..8baf76e90 100644 --- a/poetry.lock +++ b/poetry.lock @@ -643,7 +643,7 @@ werkzeug = "*" type = "git" url = "https://github.com/sartography/flask-bpmn" reference = "main" -resolved_reference = "b9d4077955e0d45406946ef07440176fb9fd12e5" +resolved_reference = "df9ab9a12078e4f908c87778371725e0af414a11" [[package]] name = "Flask-Cors" diff --git a/src/spiffworkflow_backend/__init__.py b/src/spiffworkflow_backend/__init__.py index 6ca51aef2..9f1a74e70 100644 --- a/src/spiffworkflow_backend/__init__.py +++ b/src/spiffworkflow_backend/__init__.py @@ -5,6 +5,7 @@ from typing import Any import connexion # type: ignore import flask.app import flask.json +import spiffworkflow_backend.load_database_models # noqa: F401 import sqlalchemy from apscheduler.schedulers.background import BackgroundScheduler # type: ignore from apscheduler.schedulers.base import BaseScheduler # type: ignore @@ -14,9 +15,6 @@ from flask_bpmn.models.db import db from flask_bpmn.models.db import migrate from flask_cors import CORS # type: ignore from flask_mail import Mail # type: ignore -from werkzeug.exceptions import NotFound - -import spiffworkflow_backend.load_database_models # noqa: F401 from spiffworkflow_backend.config import setup_config from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint from spiffworkflow_backend.routes.process_api_blueprint import process_api_blueprint @@ -26,6 +24,7 @@ from spiffworkflow_backend.services.authorization_service import AuthorizationSe from spiffworkflow_backend.services.background_processing_service import ( BackgroundProcessingService, ) +from werkzeug.exceptions import NotFound class MyJSONEncoder(DefaultJSONProvider): diff --git a/src/spiffworkflow_backend/api.yml b/src/spiffworkflow_backend/api.yml index 2bfa117ea..14a0e52f6 100755 --- a/src/spiffworkflow_backend/api.yml +++ b/src/spiffworkflow_backend/api.yml @@ -141,6 +141,12 @@ paths: /process-groups: parameters: + - name: process_group_identifier + in: query + required: false + description: Optional parameter to filter by a single group + schema: + type: string - name: page in: query required: false @@ -413,7 +419,7 @@ paths: - name: process_status in: query required: false - description: For filtering - not_started, user_input_required, waiting, complete, faulted, or suspended + description: For filtering - not_started, user_input_required, waiting, complete, error, or suspended schema: type: string # process_instance_list @@ -702,33 +708,6 @@ paths: type: array items: $ref: "#/components/schemas/Workflow" - - /process-models/{process_group_id}/{process_model_id}/process-instances/reports: - parameters: - - name: process_group_id - in: path - required: true - description: The unique id of an existing process group - schema: - type: string - - name: process_model_id - in: path - required: true - description: The unique id of an existing process model. - schema: - type: string - - name: page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer - - name: per_page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer post: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_create summary: Returns all process instance reports for process model @@ -776,39 +755,6 @@ paths: type: array items: $ref: "#/components/schemas/Workflow" - - /process-models/{process_group_id}/{process_model_id}/process-instances/reports/{report_identifier}: - parameters: - - name: process_group_id - in: path - required: true - description: The unique id of an existing process group - schema: - type: string - - name: process_model_id - in: path - required: true - description: The unique id of an existing process model. - schema: - type: string - - name: report_identifier - in: path - required: true - description: The unique id of an existing report - schema: - type: string - - name: page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer - - name: per_page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer put: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_update summary: Updates a process instance report diff --git a/src/spiffworkflow_backend/config/__init__.py b/src/spiffworkflow_backend/config/__init__.py index b56683ca3..082195798 100644 --- a/src/spiffworkflow_backend/config/__init__.py +++ b/src/spiffworkflow_backend/config/__init__.py @@ -3,9 +3,8 @@ import os import threading from flask.app import Flask -from werkzeug.utils import ImportStringError - from spiffworkflow_backend.services.logging_service import setup_logger +from werkzeug.utils import ImportStringError class ConfigurationError(Exception): diff --git a/src/spiffworkflow_backend/models/active_task.py b/src/spiffworkflow_backend/models/active_task.py index ea9e10552..50bd8c75b 100644 --- a/src/spiffworkflow_backend/models/active_task.py +++ b/src/spiffworkflow_backend/models/active_task.py @@ -6,14 +6,13 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import relationship -from sqlalchemy.orm import RelationshipProperty - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship +from sqlalchemy.orm import RelationshipProperty if TYPE_CHECKING: diff --git a/src/spiffworkflow_backend/models/active_task_user.py b/src/spiffworkflow_backend/models/active_task_user.py index f194c38e4..002759b1b 100644 --- a/src/spiffworkflow_backend/models/active_task_user.py +++ b/src/spiffworkflow_backend/models/active_task_user.py @@ -5,10 +5,9 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey @dataclass diff --git a/src/spiffworkflow_backend/models/file.py b/src/spiffworkflow_backend/models/file.py index 02ad5fc10..9260e1844 100644 --- a/src/spiffworkflow_backend/models/file.py +++ b/src/spiffworkflow_backend/models/file.py @@ -7,7 +7,6 @@ from typing import Optional import marshmallow from marshmallow import INCLUDE from marshmallow import Schema - from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum diff --git a/src/spiffworkflow_backend/models/message_correlation.py b/src/spiffworkflow_backend/models/message_correlation.py index baec8270a..c3338f0b1 100644 --- a/src/spiffworkflow_backend/models/message_correlation.py +++ b/src/spiffworkflow_backend/models/message_correlation.py @@ -4,13 +4,12 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import relationship - from spiffworkflow_backend.models.message_correlation_property import ( MessageCorrelationPropertyModel, ) from spiffworkflow_backend.models.process_instance import ProcessInstanceModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship if TYPE_CHECKING: from spiffworkflow_backend.models.message_correlation_message_instance import ( # noqa: F401 diff --git a/src/spiffworkflow_backend/models/message_correlation_message_instance.py b/src/spiffworkflow_backend/models/message_correlation_message_instance.py index 320dfba3e..f056aec6f 100644 --- a/src/spiffworkflow_backend/models/message_correlation_message_instance.py +++ b/src/spiffworkflow_backend/models/message_correlation_message_instance.py @@ -3,10 +3,9 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel +from sqlalchemy import ForeignKey @dataclass diff --git a/src/spiffworkflow_backend/models/message_correlation_property.py b/src/spiffworkflow_backend/models/message_correlation_property.py index b84b7140c..04acaa940 100644 --- a/src/spiffworkflow_backend/models/message_correlation_property.py +++ b/src/spiffworkflow_backend/models/message_correlation_property.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.message_model import MessageModel +from sqlalchemy import ForeignKey class MessageCorrelationPropertyModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/message_instance.py b/src/spiffworkflow_backend/models/message_instance.py index 61dd12b24..2bc9c2673 100644 --- a/src/spiffworkflow_backend/models/message_instance.py +++ b/src/spiffworkflow_backend/models/message_instance.py @@ -7,15 +7,14 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.message_model import MessageModel +from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from sqlalchemy import ForeignKey from sqlalchemy.event import listens_for from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import validates -from spiffworkflow_backend.models.message_model import MessageModel -from spiffworkflow_backend.models.process_instance import ProcessInstanceModel - if TYPE_CHECKING: from spiffworkflow_backend.models.message_correlation_message_instance import ( # noqa: F401 MessageCorrelationMessageInstanceModel, diff --git a/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/src/spiffworkflow_backend/models/message_triggerable_process_model.py index 97d54aa7d..b82580d7e 100644 --- a/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.message_model import MessageModel +from sqlalchemy import ForeignKey class MessageTriggerableProcessModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/permission_assignment.py b/src/spiffworkflow_backend/models/permission_assignment.py index 63295f74e..194341929 100644 --- a/src/spiffworkflow_backend/models/permission_assignment.py +++ b/src/spiffworkflow_backend/models/permission_assignment.py @@ -4,11 +4,10 @@ from typing import Any from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import validates - from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import validates class PermitDeny(enum.Enum): diff --git a/src/spiffworkflow_backend/models/principal.py b/src/spiffworkflow_backend/models/principal.py index c7efa8609..d43be35a4 100644 --- a/src/spiffworkflow_backend/models/principal.py +++ b/src/spiffworkflow_backend/models/principal.py @@ -3,13 +3,12 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.group import GroupModel +from spiffworkflow_backend.models.user import UserModel from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.schema import CheckConstraint -from spiffworkflow_backend.models.group import GroupModel -from spiffworkflow_backend.models.user import UserModel - class DataValidityError(Exception): """DataValidityError.""" diff --git a/src/spiffworkflow_backend/models/process_group.py b/src/spiffworkflow_backend/models/process_group.py index 9efc8cf5e..4a93c417b 100644 --- a/src/spiffworkflow_backend/models/process_group.py +++ b/src/spiffworkflow_backend/models/process_group.py @@ -9,7 +9,6 @@ from typing import Any import marshmallow from marshmallow import post_load from marshmallow import Schema - from spiffworkflow_backend.models.process_model import ProcessModelInfo diff --git a/src/spiffworkflow_backend/models/process_instance.py b/src/spiffworkflow_backend/models/process_instance.py index 37b651575..cc53623ee 100644 --- a/src/spiffworkflow_backend/models/process_instance.py +++ b/src/spiffworkflow_backend/models/process_instance.py @@ -12,16 +12,15 @@ from marshmallow import INCLUDE from marshmallow import Schema from marshmallow_enum import EnumField # type: ignore from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore -from sqlalchemy import ForeignKey -from sqlalchemy.orm import deferred -from sqlalchemy.orm import relationship -from sqlalchemy.orm import validates - from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import TaskSchema from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import deferred +from sqlalchemy.orm import relationship +from sqlalchemy.orm import validates class NavigationItemSchema(Schema): @@ -61,10 +60,9 @@ class ProcessInstanceStatus(SpiffEnum): user_input_required = "user_input_required" waiting = "waiting" complete = "complete" - faulted = "faulted" + error = "error" suspended = "suspended" terminated = "terminated" - erroring = "erroring" class ProcessInstanceModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/process_instance_report.py b/src/spiffworkflow_backend/models/process_instance_report.py index b6f16288f..c4fcbad27 100644 --- a/src/spiffworkflow_backend/models/process_instance_report.py +++ b/src/spiffworkflow_backend/models/process_instance_report.py @@ -9,10 +9,6 @@ from typing import TypedDict from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import deferred -from sqlalchemy.orm import relationship - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -21,6 +17,9 @@ from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) +from sqlalchemy import ForeignKey +from sqlalchemy.orm import deferred +from sqlalchemy.orm import relationship ReportMetadata = dict[str, Any] @@ -83,10 +82,6 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): report_metadata = { "columns": [ {"Header": "id", "accessor": "id"}, - { - "Header": "process_group_identifier", - "accessor": "process_group_identifier", - }, { "Header": "process_model_identifier", "accessor": "process_model_identifier", diff --git a/src/spiffworkflow_backend/models/process_model.py b/src/spiffworkflow_backend/models/process_model.py index d63197be2..1c82bd405 100644 --- a/src/spiffworkflow_backend/models/process_model.py +++ b/src/spiffworkflow_backend/models/process_model.py @@ -9,7 +9,6 @@ from typing import Any import marshmallow from marshmallow import Schema from marshmallow.decorators import post_load - from spiffworkflow_backend.models.file import File diff --git a/src/spiffworkflow_backend/models/secret_model.py b/src/spiffworkflow_backend/models/secret_model.py index 92fd470a3..9cc338ed2 100644 --- a/src/spiffworkflow_backend/models/secret_model.py +++ b/src/spiffworkflow_backend/models/secret_model.py @@ -4,9 +4,8 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from marshmallow import Schema -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey @dataclass() diff --git a/src/spiffworkflow_backend/models/user.py b/src/spiffworkflow_backend/models/user.py index c33a72e7a..0df4c9c21 100644 --- a/src/spiffworkflow_backend/models/user.py +++ b/src/spiffworkflow_backend/models/user.py @@ -10,13 +10,12 @@ from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from marshmallow import Schema -from sqlalchemy.orm import relationship -from sqlalchemy.orm import validates - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.services.authentication_service import ( AuthenticationProviderTypes, ) +from sqlalchemy.orm import relationship +from sqlalchemy.orm import validates class UserNotFoundError(Exception): diff --git a/src/spiffworkflow_backend/models/user_group_assignment.py b/src/spiffworkflow_backend/models/user_group_assignment.py index fa5b620c8..8cccf1d8c 100644 --- a/src/spiffworkflow_backend/models/user_group_assignment.py +++ b/src/spiffworkflow_backend/models/user_group_assignment.py @@ -1,11 +1,10 @@ """UserGroupAssignment.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import relationship - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship class UserGroupAssignmentModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py b/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py index 2e480f2a4..f13e4e073 100644 --- a/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py +++ b/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py @@ -7,8 +7,6 @@ from flask import redirect from flask import render_template from flask import request from flask import url_for -from werkzeug.wrappers import Response - from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -18,6 +16,7 @@ from spiffworkflow_backend.services.process_instance_service import ( from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.user_service import UserService +from werkzeug.wrappers import Response admin_blueprint = Blueprint( "admin", __name__, template_folder="templates", static_folder="static" diff --git a/src/spiffworkflow_backend/routes/process_api_blueprint.py b/src/spiffworkflow_backend/routes/process_api_blueprint.py index e37f2d0bd..260da3788 100644 --- a/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -28,9 +28,6 @@ from lxml import etree # type: ignore from lxml.builder import ElementMaker # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState -from sqlalchemy import asc -from sqlalchemy import desc - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -78,6 +75,8 @@ from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.service_task_service import ServiceTaskService from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.user_service import UserService +from sqlalchemy import asc +from sqlalchemy import desc class TaskDataSelectOption(TypedDict): @@ -162,7 +161,9 @@ def process_group_delete(modified_process_group_id: str) -> flask.wrappers.Respo return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") -def process_group_update(modified_process_group_id: str, body: dict) -> flask.wrappers.Response: +def process_group_update( + modified_process_group_id: str, body: dict +) -> flask.wrappers.Response: """Process Group Update.""" body_include_list = ["display_name", "description"] body_filtered = { @@ -177,9 +178,12 @@ def process_group_update(modified_process_group_id: str, body: dict) -> flask.wr return make_response(jsonify(process_group), 200) -def process_groups_list(page: int = 1, per_page: int = 100) -> flask.wrappers.Response: +def process_groups_list(process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100) -> flask.wrappers.Response: """Process_groups_list.""" - process_groups = ProcessModelService().get_process_groups() + if process_group_identifier is not None: + process_groups = ProcessModelService().get_process_groups(process_group_identifier) + else: + process_groups = ProcessModelService().get_process_groups() batch = ProcessModelService().get_batch( items=process_groups, page=page, per_page=per_page ) @@ -230,7 +234,9 @@ def process_model_add( ) modified_process_model_id = process_model_info.id - unmodified_process_model_id = un_modify_modified_process_model_id(modified_process_model_id) + unmodified_process_model_id = un_modify_modified_process_model_id( + modified_process_model_id + ) process_model_info.id = unmodified_process_model_id process_group_id, _ = os.path.split(process_model_info.id) process_model_service = ProcessModelService() diff --git a/src/spiffworkflow_backend/routes/user.py b/src/spiffworkflow_backend/routes/user.py index ed5961418..45d7c2ae5 100644 --- a/src/spiffworkflow_backend/routes/user.py +++ b/src/spiffworkflow_backend/routes/user.py @@ -12,14 +12,13 @@ from flask import g from flask import redirect from flask import request from flask_bpmn.api.api_error import ApiError -from werkzeug.wrappers import Response - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authentication_service import ( AuthenticationService, ) from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.user_service import UserService +from werkzeug.wrappers import Response """ .. module:: crc.api.user @@ -125,7 +124,9 @@ def verify_token( # no user_info else: raise ApiError( - error_code="no_user_info", message="Cannot retrieve user info", status_code=401 + error_code="no_user_info", + message="Cannot retrieve user info", + status_code=401, ) else: diff --git a/src/spiffworkflow_backend/routes/user_blueprint.py b/src/spiffworkflow_backend/routes/user_blueprint.py index 29bbddcd1..9520dfc85 100644 --- a/src/spiffworkflow_backend/routes/user_blueprint.py +++ b/src/spiffworkflow_backend/routes/user_blueprint.py @@ -9,11 +9,10 @@ from flask import request from flask import Response from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db -from sqlalchemy.exc import IntegrityError - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel +from sqlalchemy.exc import IntegrityError APPLICATION_JSON: Final = "application/json" diff --git a/src/spiffworkflow_backend/scripts/get_current_user.py b/src/spiffworkflow_backend/scripts/get_current_user.py index a1a1b47e9..4cdcdc37c 100644 --- a/src/spiffworkflow_backend/scripts/get_current_user.py +++ b/src/spiffworkflow_backend/scripts/get_current_user.py @@ -2,7 +2,6 @@ from typing import Any from flask import g - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/scripts/get_frontend_url.py b/src/spiffworkflow_backend/scripts/get_frontend_url.py index 9490df95a..6930c57e0 100644 --- a/src/spiffworkflow_backend/scripts/get_frontend_url.py +++ b/src/spiffworkflow_backend/scripts/get_frontend_url.py @@ -2,7 +2,6 @@ from typing import Any from flask import current_app - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/scripts/get_localtime.py b/src/spiffworkflow_backend/scripts/get_localtime.py index 689b86d8c..16b9bf577 100644 --- a/src/spiffworkflow_backend/scripts/get_localtime.py +++ b/src/spiffworkflow_backend/scripts/get_localtime.py @@ -4,7 +4,6 @@ from typing import Any import pytz from flask_bpmn.api.api_error import ApiError - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/scripts/script.py b/src/spiffworkflow_backend/scripts/script.py index b744694a2..7ed745d6e 100644 --- a/src/spiffworkflow_backend/scripts/script.py +++ b/src/spiffworkflow_backend/scripts/script.py @@ -9,7 +9,6 @@ from typing import Any from typing import Callable from flask_bpmn.api.api_error import ApiError - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index c6c1b578a..c71e6069e 100644 --- a/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -4,10 +4,9 @@ import time from flask import current_app from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus +from tests.spiffworkflow_backend.helpers.base_test import BaseTest def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: @@ -24,7 +23,7 @@ def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: # user_input_required - 2 hours ago # waiting - 3 hourse ago # complete - 4 hours ago - # faulted - 5 hours ago + # error - 5 hours ago # suspended - 6 hours ago process_instances = [] for i in range(len(statuses)): diff --git a/src/spiffworkflow_backend/services/authentication_service.py b/src/spiffworkflow_backend/services/authentication_service.py index 18f08d0f3..1ec35ae15 100644 --- a/src/spiffworkflow_backend/services/authentication_service.py +++ b/src/spiffworkflow_backend/services/authentication_service.py @@ -11,9 +11,8 @@ from flask import current_app from flask import redirect from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db -from werkzeug.wrappers import Response - from spiffworkflow_backend.models.refresh_token import RefreshTokenModel +from werkzeug.wrappers import Response class AuthenticationProviderTypes(enum.Enum): diff --git a/src/spiffworkflow_backend/services/authorization_service.py b/src/spiffworkflow_backend/services/authorization_service.py index 75c17ab86..7c654609c 100644 --- a/src/spiffworkflow_backend/services/authorization_service.py +++ b/src/spiffworkflow_backend/services/authorization_service.py @@ -11,8 +11,6 @@ from flask import request 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 sqlalchemy import text - from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel @@ -27,6 +25,7 @@ from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.user_service import UserService +from sqlalchemy import text class PermissionsFileNotSetError(Exception): diff --git a/src/spiffworkflow_backend/services/background_processing_service.py b/src/spiffworkflow_backend/services/background_processing_service.py index 08a2b02df..8c4fee6e7 100644 --- a/src/spiffworkflow_backend/services/background_processing_service.py +++ b/src/spiffworkflow_backend/services/background_processing_service.py @@ -1,6 +1,5 @@ """Background_processing_service.""" import flask - from spiffworkflow_backend.services.message_service import MessageService from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, diff --git a/src/spiffworkflow_backend/services/data_setup_service.py b/src/spiffworkflow_backend/services/data_setup_service.py index 23df25f34..226003c46 100644 --- a/src/spiffworkflow_backend/services/data_setup_service.py +++ b/src/spiffworkflow_backend/services/data_setup_service.py @@ -1,6 +1,5 @@ """Data_setup_service.""" from flask import current_app - from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/src/spiffworkflow_backend/services/error_handling_service.py b/src/spiffworkflow_backend/services/error_handling_service.py index 3f1622a47..8bf377bdc 100644 --- a/src/spiffworkflow_backend/services/error_handling_service.py +++ b/src/spiffworkflow_backend/services/error_handling_service.py @@ -5,7 +5,6 @@ from typing import Union from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db - from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.services.email_service import EmailService @@ -46,7 +45,7 @@ class ErrorHandlingService: # fault is the default self.set_instance_status( _processor.process_instance_model.id, - ProcessInstanceStatus.faulted.value, + ProcessInstanceStatus.error.value, ) if len(process_model.exception_notification_addresses) > 0: diff --git a/src/spiffworkflow_backend/services/file_system_service.py b/src/spiffworkflow_backend/services/file_system_service.py index a4a01b836..f6091de09 100644 --- a/src/spiffworkflow_backend/services/file_system_service.py +++ b/src/spiffworkflow_backend/services/file_system_service.py @@ -7,7 +7,6 @@ from typing import Optional import pytz from flask import current_app from flask_bpmn.api.api_error import ApiError - from spiffworkflow_backend.models.file import CONTENT_TYPES from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType @@ -34,7 +33,7 @@ class FileSystemService: @staticmethod def process_group_path(name: str) -> str: """Category_path.""" - return os.path.join(FileSystemService.root_path(), name) + return os.path.abspath(os.path.join(FileSystemService.root_path(), name)) @staticmethod def full_path_from_relative_path(relative_path: str) -> str: diff --git a/src/spiffworkflow_backend/services/git_service.py b/src/spiffworkflow_backend/services/git_service.py index 815e4cadc..08f45386d 100644 --- a/src/spiffworkflow_backend/services/git_service.py +++ b/src/spiffworkflow_backend/services/git_service.py @@ -2,7 +2,6 @@ import os from flask import current_app - from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.file_system_service import FileSystemService diff --git a/src/spiffworkflow_backend/services/group_service.py b/src/spiffworkflow_backend/services/group_service.py index aa560009e..a2e54460a 100644 --- a/src/spiffworkflow_backend/services/group_service.py +++ b/src/spiffworkflow_backend/services/group_service.py @@ -2,7 +2,6 @@ from typing import Optional from flask_bpmn.models.db import db - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.services.user_service import UserService diff --git a/src/spiffworkflow_backend/services/logging_service.py b/src/spiffworkflow_backend/services/logging_service.py index c4e8c8ae9..201a7e5c2 100644 --- a/src/spiffworkflow_backend/services/logging_service.py +++ b/src/spiffworkflow_backend/services/logging_service.py @@ -8,7 +8,6 @@ from typing import Optional from flask import g from flask.app import Flask from flask_bpmn.models.db import db - from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel diff --git a/src/spiffworkflow_backend/services/message_service.py b/src/spiffworkflow_backend/services/message_service.py index 216a66a58..190eaaa41 100644 --- a/src/spiffworkflow_backend/services/message_service.py +++ b/src/spiffworkflow_backend/services/message_service.py @@ -3,10 +3,6 @@ from typing import Any from typing import Optional from flask_bpmn.models.db import db -from sqlalchemy import and_ -from sqlalchemy import or_ -from sqlalchemy import select - from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation_message_instance import ( MessageCorrelationMessageInstanceModel, @@ -23,6 +19,9 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) +from sqlalchemy import and_ +from sqlalchemy import or_ +from sqlalchemy import select class MessageServiceError(Exception): diff --git a/src/spiffworkflow_backend/services/process_instance_processor.py b/src/spiffworkflow_backend/services/process_instance_processor.py index a9f7ac661..fb59960be 100644 --- a/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/src/spiffworkflow_backend/services/process_instance_processor.py @@ -65,7 +65,6 @@ from SpiffWorkflow.spiff.serializer.task_spec_converters import UserTaskConverte from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore - from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup diff --git a/src/spiffworkflow_backend/services/process_instance_service.py b/src/spiffworkflow_backend/services/process_instance_service.py index 7854537e3..f5c5128cc 100644 --- a/src/spiffworkflow_backend/services/process_instance_service.py +++ b/src/spiffworkflow_backend/services/process_instance_service.py @@ -7,7 +7,6 @@ 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_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus @@ -64,7 +63,7 @@ class ProcessInstanceService: processor.do_engine_steps(save=True) except Exception as e: db.session.rollback() # in case the above left the database with a bad transaction - process_instance.status = ProcessInstanceStatus.erroring.value + process_instance.status = ProcessInstanceStatus.error.value db.session.add(process_instance) db.session.commit() error_message = ( diff --git a/src/spiffworkflow_backend/services/process_model_service.py b/src/spiffworkflow_backend/services/process_model_service.py index d64596cb8..d8fe12033 100644 --- a/src/spiffworkflow_backend/services/process_model_service.py +++ b/src/spiffworkflow_backend/services/process_model_service.py @@ -8,7 +8,6 @@ from typing import Optional from typing import TypeVar from flask_bpmn.api.api_error import ApiError - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -161,9 +160,9 @@ class ProcessModelService(FileSystemService): process_models.sort() return process_models - def get_process_groups(self) -> list[ProcessGroup]: + def get_process_groups(self, process_group_id: Optional[str] = None) -> list[ProcessGroup]: """Returns the process_groups as a list in display order.""" - process_groups = self.__scan_process_groups() + process_groups = self.__scan_process_groups(process_group_id) process_groups.sort() return process_groups @@ -213,10 +212,35 @@ class ProcessModelService(FileSystemService): ) return process_group + def __get_all_nested_models(self, group_path: str) -> list: + """__get_all_nested_models.""" + all_nested_models = [] + for root, dirs, files in os.walk(group_path): + for dir in dirs: + model_dir = os.path.join(group_path, dir) + if ProcessModelService().is_model(model_dir): + process_model = self.get_process_model(model_dir) + all_nested_models.append(process_model) + return all_nested_models + def process_group_delete(self, process_group_id: str) -> None: """Delete_process_group.""" + problem_models = [] path = self.process_group_path(process_group_id) if os.path.exists(path): + nested_models = self.__get_all_nested_models(path) + for process_model in nested_models: + instances = ProcessInstanceModel.query.filter( + ProcessInstanceModel.process_model_identifier == process_model.id + ).all() + if len(instances) > 0: + problem_models.append(process_model) + if len(problem_models) > 0: + raise ApiError( + error_code="existing_instances", + message=f"We cannot delete the group `{process_group_id}`, " + f"there are models with existing instances inside the group. {problem_models}", + ) shutil.rmtree(path) self.cleanup_process_group_display_order() @@ -230,12 +254,16 @@ class ProcessModelService(FileSystemService): index += 1 return process_groups - def __scan_process_groups(self) -> list[ProcessGroup]: + def __scan_process_groups(self, process_group_id: Optional[str] = None) -> list[ProcessGroup]: """__scan_process_groups.""" if not os.path.exists(FileSystemService.root_path()): return [] # Nothing to scan yet. There are no files. + if process_group_id is not None: + scan_path = os.path.join(FileSystemService.root_path(), process_group_id) + else: + scan_path = FileSystemService.root_path() - with os.scandir(FileSystemService.root_path()) as directory_items: + with os.scandir(scan_path) as directory_items: process_groups = [] for item in directory_items: # if item.is_dir() and not item.name[0] == ".": diff --git a/src/spiffworkflow_backend/services/script_unit_test_runner.py b/src/spiffworkflow_backend/services/script_unit_test_runner.py index 9112e20f0..b9ec129ec 100644 --- a/src/spiffworkflow_backend/services/script_unit_test_runner.py +++ b/src/spiffworkflow_backend/services/script_unit_test_runner.py @@ -8,7 +8,6 @@ from typing import Optional from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore - from spiffworkflow_backend.services.process_instance_processor import ( CustomBpmnScriptEngine, ) diff --git a/src/spiffworkflow_backend/services/secret_service.py b/src/spiffworkflow_backend/services/secret_service.py index 42f401c18..332644995 100644 --- a/src/spiffworkflow_backend/services/secret_service.py +++ b/src/spiffworkflow_backend/services/secret_service.py @@ -3,7 +3,6 @@ from typing import Optional from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db - from spiffworkflow_backend.models.secret_model import SecretModel # from cryptography.fernet import Fernet diff --git a/src/spiffworkflow_backend/services/service_task_service.py b/src/spiffworkflow_backend/services/service_task_service.py index 97ce1495a..fb2961f56 100644 --- a/src/spiffworkflow_backend/services/service_task_service.py +++ b/src/spiffworkflow_backend/services/service_task_service.py @@ -5,7 +5,6 @@ from typing import Any import requests from flask import current_app from flask import g - from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.secret_service import SecretService diff --git a/src/spiffworkflow_backend/services/spec_file_service.py b/src/spiffworkflow_backend/services/spec_file_service.py index 92e905bf3..757a259d6 100644 --- a/src/spiffworkflow_backend/services/spec_file_service.py +++ b/src/spiffworkflow_backend/services/spec_file_service.py @@ -12,7 +12,6 @@ from lxml import etree # type: ignore from lxml.etree import _Element # type: ignore from lxml.etree import Element as EtreeElement from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore - from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileReference diff --git a/src/spiffworkflow_backend/services/user_service.py b/src/spiffworkflow_backend/services/user_service.py index 0e8e65c2c..c65c48873 100644 --- a/src/spiffworkflow_backend/services/user_service.py +++ b/src/spiffworkflow_backend/services/user_service.py @@ -6,7 +6,6 @@ from flask import current_app from flask import g from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db - from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.group import GroupModel diff --git a/tests/data/simple_form/simple_form.bpmn b/tests/data/simple_form/simple_form.bpmn new file mode 100644 index 000000000..410561738 --- /dev/null +++ b/tests/data/simple_form/simple_form.bpmn @@ -0,0 +1,63 @@ + + + + + Flow_0smvjir + + + + Flow_1boyhcj + + + + + Hello {{ name }} +Department: {{ department }} + + + Flow_1ly1khd + Flow_1boyhcj + + + + + + + + + + Flow_0smvjir + Flow_1ly1khd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/data/simple_form/simple_form.json b/tests/data/simple_form/simple_form.json new file mode 100644 index 000000000..ded388eb2 --- /dev/null +++ b/tests/data/simple_form/simple_form.json @@ -0,0 +1,24 @@ +{ + "title": "Simple form", + "description": "A simple form example.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "title": "Name", + "default": "World" + }, + "department": { + "type": "string", + "title": "Department", + "enum": [ + "Finance", + "HR", + "IT" + ] + } + } +} \ No newline at end of file diff --git a/tests/data/simple_form/simple_form_ui.json b/tests/data/simple_form/simple_form_ui.json new file mode 100644 index 000000000..e6788536e --- /dev/null +++ b/tests/data/simple_form/simple_form_ui.json @@ -0,0 +1,13 @@ +{ + "name": { + "ui:title": "Name", + "ui:description": "(Your name)" + }, + "department": { + "ui:title": "Department", + "ui:description": "(Your department)" + }, + "ui:order": ["name", "department"] +} + + diff --git a/tests/spiffworkflow_backend/helpers/base_test.py b/tests/spiffworkflow_backend/helpers/base_test.py index 794e1cea6..0d30df0a2 100644 --- a/tests/spiffworkflow_backend/helpers/base_test.py +++ b/tests/spiffworkflow_backend/helpers/base_test.py @@ -12,9 +12,6 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec -from werkzeug.test import TestResponse # type: ignore - from spiffworkflow_backend.models.permission_assignment import Permission from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.process_group import ProcessGroup @@ -28,6 +25,8 @@ from spiffworkflow_backend.services.authorization_service import AuthorizationSe from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.user_service import UserService +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from werkzeug.test import TestResponse # type: ignore # from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers @@ -35,7 +34,30 @@ from spiffworkflow_backend.services.user_service import UserService class BaseTest: """BaseTest.""" - def basic_test_setup( + @staticmethod + def find_or_create_user(username: str = "test_user_1") -> UserModel: + """Find_or_create_user.""" + user = UserModel.query.filter_by(username=username).first() + if isinstance(user, UserModel): + return user + + user = UserService.create_user("internal", username, username=username) + if isinstance(user, UserModel): + return user + + raise ApiError( + error_code="create_user_error", + message=f"Cannot find or create user: {username}", + ) + + @staticmethod + def logged_in_headers( + user: UserModel, _redirect_url: str = "http://some/frontend/url" + ) -> Dict[str, str]: + """Logged_in_headers.""" + return dict(Authorization="Bearer " + user.encode_auth_token()) + + def create_group_and_model_with_bpmn( self, client: FlaskClient, user: UserModel, @@ -75,56 +97,27 @@ class BaseTest: return process_model_identifier - @staticmethod - def find_or_create_user(username: str = "test_user_1") -> UserModel: - """Find_or_create_user.""" - user = UserModel.query.filter_by(username=username).first() - if isinstance(user, UserModel): - return user - - user = UserService.create_user("internal", username, username=username) - if isinstance(user, UserModel): - return user - - raise ApiError( - error_code="create_user_error", - message=f"Cannot find or create user: {username}", - ) - - @staticmethod - def get_open_id_constants(app: Flask) -> tuple: - """Get_open_id_constants.""" - open_id_server_url = app.config["OPEN_ID_SERVER_URL"] - open_id_client_id = app.config["OPEN_ID_CLIENT_ID"] - open_id_realm_name = app.config["OPEN_ID_REALM_NAME"] - open_id_client_secret_key = app.config[ - "OPEN_ID_CLIENT_SECRET_KEY" - ] # noqa: S105 - - return ( - open_id_server_url, - open_id_client_id, - open_id_realm_name, - open_id_client_secret_key, - ) - - @staticmethod - def create_process_instance( + def create_process_group( + self, client: FlaskClient, - test_process_model_id: str, - headers: Dict[str, str], - ) -> TestResponse: - """Create_process_instance. - - There must be an existing process model to instantiate. - """ - modified_process_model_id = test_process_model_id.replace("/", ":") + user: Any, + process_group_id: str, + display_name: str = "", + ) -> str: + """Create_process_group.""" + process_group = ProcessGroup( + id=process_group_id, display_name=display_name, display_order=0, admin=False + ) response = client.post( - f"/v1.0/process-models/{modified_process_model_id}/process-instances", - headers=headers, + "/v1.0/process-groups", + headers=self.logged_in_headers(user), + content_type="application/json", + data=json.dumps(ProcessGroupSchema().dump(process_group)), ) assert response.status_code == 201 - return response + assert response.json is not None + assert response.json["id"] == process_group_id + return process_group_id def create_process_model_with_api( self, @@ -178,6 +171,22 @@ class BaseTest: "You must include the process_model_id, which must be a path to the model" ) + def get_test_data_file_contents( + self, file_name: str, process_model_test_data_dir: str + ) -> bytes: + """Get_test_data_file_contents.""" + file_full_path = os.path.join( + current_app.instance_path, + "..", + "..", + "tests", + "data", + process_model_test_data_dir, + file_name, + ) + with open(file_full_path, "rb") as file: + return file.read() + def create_spec_file( self, client: FlaskClient, @@ -230,27 +239,23 @@ class BaseTest: assert file["file_contents"] == file2["file_contents"] return file - def create_process_group( - self, + @staticmethod + def create_process_instance_from_process_model_id( client: FlaskClient, - user: Any, - process_group_id: str, - display_name: str = "", - ) -> str: - """Create_process_group.""" - process_group = ProcessGroup( - id=process_group_id, display_name=display_name, display_order=0, admin=False - ) + test_process_model_id: str, + headers: Dict[str, str], + ) -> TestResponse: + """Create_process_instance. + + There must be an existing process model to instantiate. + """ + modified_process_model_id = test_process_model_id.replace("/", ":") response = client.post( - "/v1.0/process-groups", - headers=self.logged_in_headers(user), - content_type="application/json", - data=json.dumps(ProcessGroupSchema().dump(process_group)), + f"/v1.0/process-models/{modified_process_model_id}/process-instances", + headers=headers, ) assert response.status_code == 201 - assert response.json is not None - assert response.json["id"] == process_group_id - return process_group_id + return response # @staticmethod # def get_public_access_token(username: str, password: str) -> dict: @@ -324,29 +329,6 @@ class BaseTest: ) return user - @staticmethod - def logged_in_headers( - user: UserModel, _redirect_url: str = "http://some/frontend/url" - ) -> Dict[str, str]: - """Logged_in_headers.""" - return dict(Authorization="Bearer " + user.encode_auth_token()) - - def get_test_data_file_contents( - self, file_name: str, process_model_test_data_dir: str - ) -> bytes: - """Get_test_data_file_contents.""" - file_full_path = os.path.join( - current_app.instance_path, - "..", - "..", - "tests", - "data", - process_model_test_data_dir, - file_name, - ) - with open(file_full_path, "rb") as file: - return file.read() - def assert_user_has_permission( self, user: UserModel, diff --git a/tests/spiffworkflow_backend/helpers/example_data.py b/tests/spiffworkflow_backend/helpers/example_data.py index 251ba19c8..c5e5c9bce 100644 --- a/tests/spiffworkflow_backend/helpers/example_data.py +++ b/tests/spiffworkflow_backend/helpers/example_data.py @@ -4,7 +4,6 @@ import os from typing import Optional from flask import current_app - from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/tests/spiffworkflow_backend/helpers/test_data.py b/tests/spiffworkflow_backend/helpers/test_data.py index d6b4f730c..0ce535d1e 100644 --- a/tests/spiffworkflow_backend/helpers/test_data.py +++ b/tests/spiffworkflow_backend/helpers/test_data.py @@ -1,14 +1,13 @@ """User.""" from typing import Optional -from tests.spiffworkflow_backend.helpers.example_data import ExampleDataLoader - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.example_data import ExampleDataLoader def assure_process_group_exists(process_group_id: Optional[str] = None) -> ProcessGroup: diff --git a/tests/spiffworkflow_backend/integration/test_authentication.py b/tests/spiffworkflow_backend/integration/test_authentication.py index 34e4d71bc..537943480 100644 --- a/tests/spiffworkflow_backend/integration/test_authentication.py +++ b/tests/spiffworkflow_backend/integration/test_authentication.py @@ -2,11 +2,10 @@ import ast import base64 -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.services.authentication_service import ( AuthenticationService, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestAuthentication(BaseTest): diff --git a/tests/spiffworkflow_backend/integration/test_logging_service.py b/tests/spiffworkflow_backend/integration/test_logging_service.py index 02d8ade17..a5e3e36dc 100644 --- a/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -1,9 +1,8 @@ """Test_logging_service.""" from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.user import UserModel +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestLoggingService(BaseTest): @@ -45,7 +44,7 @@ class TestLoggingService(BaseTest): user=with_super_admin_user, ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None diff --git a/tests/spiffworkflow_backend/integration/test_nested_groups.py b/tests/spiffworkflow_backend/integration/test_nested_groups.py index ef89a561a..c5d38b4fa 100644 --- a/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -3,18 +3,129 @@ import json from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroupSchema from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.services.process_instance_service import ( + ProcessInstanceService, +) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestNestedGroups(BaseTest): """TestNestedGroups.""" + def test_delete_group_with_running_instance( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_delete_group_with_running_instance.""" + process_group_id = "test_group" + process_model_id = "manual_task" + bpmn_file_name = "manual_task.bpmn" + bpmn_file_location = "manual_task" + process_model_identifier = self.create_group_and_model_with_bpmn( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location, + ) + response = self.create_process_instance_from_process_model_id( + client, + process_model_identifier, + self.logged_in_headers(with_super_admin_user), + ) + process_instance_id = response.json["id"] + + client.post( + f"/v1.0/process-instances/{process_instance_id}/run", + headers=self.logged_in_headers(with_super_admin_user), + ) + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance + modified_process_group_id = process_group_id.replace("/", ":") + response = client.delete( + f"/v1.0/process-groups/{modified_process_group_id}", + headers=self.logged_in_headers(with_super_admin_user), + ) + assert response.status_code == 400 + assert response.json["error_code"] == "existing_instances" + assert "We cannot delete the group" in response.json["message"] + assert ( + "there are models with existing instances inside the group" + in response.json["message"] + ) + + def test_delete_group_with_running_instance_in_nested_group( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_delete_group_with_running_instance_in_nested_group.""" + process_group_a = ProcessGroup( + id="group_a", + display_name="Group A", + display_order=0, + admin=False, + ) + response_a = client.post( # noqa: F841 + "/v1.0/process-groups", + headers=self.logged_in_headers(with_super_admin_user), + content_type="application/json", + data=json.dumps(ProcessGroupSchema().dump(process_group_a)), + ) + + process_group_id = "group_a/test_group" + process_model_id = "manual_task" + bpmn_file_name = "manual_task.bpmn" + bpmn_file_location = "manual_task" + process_model_identifier = self.create_group_and_model_with_bpmn( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location, + ) + response = self.create_process_instance_from_process_model_id( + client, + process_model_identifier, + self.logged_in_headers(with_super_admin_user), + ) + process_instance_id = response.json["id"] + + client.post( + f"/v1.0/process-instances/{process_instance_id}/run", + headers=self.logged_in_headers(with_super_admin_user), + ) + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance + modified_process_group_id = process_group_id.replace("/", ":") + response = client.delete( + f"/v1.0/process-groups/{modified_process_group_id}", + headers=self.logged_in_headers(with_super_admin_user), + ) + assert response.status_code == 400 + assert response.json["error_code"] == "existing_instances" + assert "We cannot delete the group" in response.json["message"] + assert ( + "there are models with existing instances inside the group" + in response.json["message"] + ) + def test_nested_groups( self, app: Flask, diff --git a/tests/spiffworkflow_backend/integration/test_process_api.py b/tests/spiffworkflow_backend/integration/test_process_api.py index 91355e0e0..a860eaab8 100644 --- a/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,9 +9,6 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -35,6 +32,8 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec # from spiffworkflow_backend.services.git_service import GitService @@ -286,7 +285,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) # create an instance from a model - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) @@ -623,7 +622,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"key1": "THIS DATA"} @@ -647,7 +646,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"file": (io.BytesIO(b""), "random_fact.svg")} @@ -723,7 +722,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) # self.create_spec_file(client, user=with_super_admin_user) # process_model = load_test_spec("random_fact") @@ -749,7 +748,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -770,7 +769,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -797,7 +796,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_file.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.get( @@ -817,7 +816,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_workflow_from_workflow_spec.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.post( @@ -852,7 +851,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_groups_when_there_are_some.""" - self.basic_test_setup(client, with_super_admin_user) + self.create_group_and_model_with_bpmn(client, with_super_admin_user) response = client.get( "/v1.0/process-groups", headers=self.logged_in_headers(with_super_admin_user), @@ -872,7 +871,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_group_when_found.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) process_group_id, process_model_id = os.path.split(process_model_identifier) response = client.get( @@ -893,7 +892,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_model_when_found.""" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, bpmn_file_name="random_fact.bpmn" ) modified_process_model_identifier = process_model_identifier.replace("/", ":") @@ -938,7 +937,7 @@ class TestProcessApi(BaseTest): """Test_process_instance_create.""" test_process_model_id = "runs_without_input/sample" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance(client, test_process_model_id, headers) + response = self.create_process_instance_from_process_model_id(client, test_process_model_id, headers) assert response.json is not None assert response.json["updated_at_in_seconds"] is not None assert response.json["status"] == "not_started" @@ -956,7 +955,7 @@ class TestProcessApi(BaseTest): ) -> None: """Test_process_instance_run.""" # process_model_id = "runs_without_input/sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id="runs_without_input", @@ -966,7 +965,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -998,7 +997,7 @@ class TestProcessApi(BaseTest): """Test_process_instance_show.""" process_group_id = "simple_script" process_model_id = "simple_script" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1006,7 +1005,7 @@ class TestProcessApi(BaseTest): ) modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) - create_response = self.create_process_instance( + create_response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert create_response.json is not None @@ -1041,7 +1040,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_receiver" bpmn_file_name = "message_receiver.bpmn" bpmn_file_location = "message_send_one_conversation" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1089,7 +1088,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_sender" bpmn_file_name = "message_sender.bpmn" bpmn_file_location = "message_send_one_conversation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1106,7 +1105,7 @@ class TestProcessApi(BaseTest): "andThis": "another_item_non_key", } } - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, self.logged_in_headers(with_super_admin_user), @@ -1157,7 +1156,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_sender" bpmn_file_name = "message_sender.bpmn" bpmn_file_location = "message_send_one_conversation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1166,7 +1165,7 @@ class TestProcessApi(BaseTest): bpmn_file_location=bpmn_file_location, ) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, self.logged_in_headers(with_super_admin_user), @@ -1206,7 +1205,7 @@ class TestProcessApi(BaseTest): process_model_id = "user_task" bpmn_file_name = "user_task.bpmn" bpmn_file_location = "user_task" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1216,7 +1215,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -1245,7 +1244,7 @@ class TestProcessApi(BaseTest): process_group_id = "my_process_group" process_model_id = "dynamic_enum_select_fields" bpmn_file_location = "dynamic_enum_select_fields" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1255,7 +1254,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -1297,7 +1296,7 @@ class TestProcessApi(BaseTest): process_group_id = "runs_without_input" process_model_id = "sample" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1306,7 +1305,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) response = client.get( "/v1.0/process-instances", @@ -1342,7 +1341,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1351,11 +1350,11 @@ class TestProcessApi(BaseTest): bpmn_file_location=bpmn_file_location, ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) response = client.get( "/v1.0/process-instances?per_page=2&page=3", @@ -1391,7 +1390,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1504,7 +1503,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( # noqa: F841 + process_model_identifier = self.create_group_and_model_with_bpmn( # noqa: F841 client, with_super_admin_user, process_group_id=process_group_id, @@ -1544,7 +1543,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" # bpmn_file_name = "sample.bpmn" # bpmn_file_location = "sample" - # process_model_identifier = self.basic_test_setup( + # process_model_identifier = self.create_group_and_model_with_bpmn( # client, # with_super_admin_user, # process_group_id=process_group_id, @@ -1658,7 +1657,7 @@ class TestProcessApi(BaseTest): ) -> Any: """Setup_testing_instance.""" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance(client, process_model_id, headers) + response = self.create_process_instance_from_process_model_id(client, process_model_id, headers) process_instance = response.json assert isinstance(process_instance, dict) process_instance_id = process_instance["id"] @@ -1676,7 +1675,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1716,7 +1715,7 @@ class TestProcessApi(BaseTest): .first() ) assert process is not None - assert process.status == "faulted" + assert process.status == "error" def test_error_handler_suspend( self, @@ -1730,7 +1729,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1784,7 +1783,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1827,7 +1826,7 @@ class TestProcessApi(BaseTest): .first() ) assert process is not None - assert process.status == "faulted" + assert process.status == "error" def test_process_model_file_create( self, @@ -1843,7 +1842,7 @@ class TestProcessApi(BaseTest): file_data = b"abc123" bpmn_file_name = "hello_world.bpmn" bpmn_file_location = "hello_world" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1876,7 +1875,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_receiver" bpmn_file_name = "message_receiver.bpmn" bpmn_file_location = "message_send_one_conversation" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1968,7 +1967,7 @@ class TestProcessApi(BaseTest): process_model_id = "model_with_lanes" bpmn_file_name = "lanes.bpmn" bpmn_file_location = "model_with_lanes" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1983,7 +1982,7 @@ class TestProcessApi(BaseTest): # process_group_id="finance", # ) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, # process_model.process_group_id, process_model_identifier, @@ -2171,7 +2170,7 @@ class TestProcessApi(BaseTest): """Test_process_instance_suspend.""" bpmn_file_name = "manual_task.bpmn" bpmn_file_location = "manual_task" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_model_id="manual_task", @@ -2192,7 +2191,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -2239,7 +2238,7 @@ class TestProcessApi(BaseTest): process_model_id = "simple_script" bpmn_file_name = "simple_script.bpmn" bpmn_file_location = "simple_script" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/integration/test_secret_service.py b/tests/spiffworkflow_backend/integration/test_secret_service.py index 071ef6ccd..ea1a486e5 100644 --- a/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -6,15 +6,14 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from werkzeug.test import TestResponse # type: ignore - from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModelSchema from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.secret_service import SecretService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from werkzeug.test import TestResponse # type: ignore class SecretServiceTestHelpers(BaseTest): diff --git a/tests/spiffworkflow_backend/scripts/test_get_group_members.py b/tests/spiffworkflow_backend/scripts/test_get_group_members.py index 8a6046b5b..b38296be2 100644 --- a/tests/spiffworkflow_backend/scripts/test_get_group_members.py +++ b/tests/spiffworkflow_backend/scripts/test_get_group_members.py @@ -2,15 +2,14 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.user_service import UserService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestGetGroupMembers(BaseTest): diff --git a/tests/spiffworkflow_backend/scripts/test_get_localtime.py b/tests/spiffworkflow_backend/scripts/test_get_localtime.py index 9e65b9707..b04e93f5f 100644 --- a/tests/spiffworkflow_backend/scripts/test_get_localtime.py +++ b/tests/spiffworkflow_backend/scripts/test_get_localtime.py @@ -4,9 +4,6 @@ import datetime import pytz from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) @@ -17,6 +14,8 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestGetLocaltime(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py b/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py index 1d5157123..a9305a04c 100644 --- a/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py +++ b/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py @@ -1,6 +1,5 @@ """Test_acceptance_test_fixtures.""" from flask.app import Flask - from spiffworkflow_backend.services.acceptance_test_fixtures import ( load_acceptance_test_fixtures, ) diff --git a/tests/spiffworkflow_backend/unit/test_authorization_service.py b/tests/spiffworkflow_backend/unit/test_authorization_service.py index 5d0a10be1..25bce349c 100644 --- a/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -2,8 +2,6 @@ import pytest from flask import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserNotFoundError from spiffworkflow_backend.services.authorization_service import AuthorizationService @@ -14,6 +12,7 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestAuthorizationService(BaseTest): @@ -104,7 +103,7 @@ class TestAuthorizationService(BaseTest): self.find_or_create_user("testuser1") AuthorizationService.import_permissions_from_yaml_file() - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id="test_group", diff --git a/tests/spiffworkflow_backend/unit/test_dot_notation.py b/tests/spiffworkflow_backend/unit/test_dot_notation.py index ff37c3b5f..2e3f432f2 100644 --- a/tests/spiffworkflow_backend/unit/test_dot_notation.py +++ b/tests/spiffworkflow_backend/unit/test_dot_notation.py @@ -1,8 +1,6 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -10,6 +8,7 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestDotNotation(BaseTest): @@ -27,7 +26,7 @@ class TestDotNotation(BaseTest): process_model_id = "test_dot_notation" bpmn_file_name = "diagram.bpmn" bpmn_file_location = "dot_notation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -37,7 +36,7 @@ class TestDotNotation(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) process_instance_id = response.json["id"] diff --git a/tests/spiffworkflow_backend/unit/test_environment_var_script.py b/tests/spiffworkflow_backend/unit/test_environment_var_script.py index ac96e7e4d..e00fb7708 100644 --- a/tests/spiffworkflow_backend/unit/test_environment_var_script.py +++ b/tests/spiffworkflow_backend/unit/test_environment_var_script.py @@ -1,10 +1,9 @@ """Test_environment_var_script.""" from flask import Flask -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestEnvironmentVarScript(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_message_instance.py b/tests/spiffworkflow_backend/unit/test_message_instance.py index 39b37f2c2..f91290e55 100644 --- a/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -3,12 +3,11 @@ import pytest from flask import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestMessageInstance(BaseTest): @@ -20,7 +19,7 @@ class TestMessageInstance(BaseTest): process_model_id = "hello_world" bpmn_file_name = "hello_world.bpmn" bpmn_file_location = "hello_world" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/unit/test_message_service.py b/tests/spiffworkflow_backend/unit/test_message_service.py index aa1f28053..46b98c4af 100644 --- a/tests/spiffworkflow_backend/unit/test_message_service.py +++ b/tests/spiffworkflow_backend/unit/test_message_service.py @@ -1,9 +1,6 @@ """Test_message_service.""" from flask import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation_message_instance import ( MessageCorrelationMessageInstanceModel, @@ -18,6 +15,8 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestMessageService(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_permission_target.py b/tests/spiffworkflow_backend/unit/test_permission_target.py index 567681428..a6fefd682 100644 --- a/tests/spiffworkflow_backend/unit/test_permission_target.py +++ b/tests/spiffworkflow_backend/unit/test_permission_target.py @@ -2,12 +2,11 @@ import pytest from flask.app import Flask from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.permission_target import ( InvalidPermissionTargetUriError, ) from spiffworkflow_backend.models.permission_target import PermissionTargetModel +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestPermissionTarget(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_permissions.py b/tests/spiffworkflow_backend/unit/test_permissions.py index 117fd0af5..0973bb4cb 100644 --- a/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/tests/spiffworkflow_backend/unit/test_permissions.py @@ -2,15 +2,14 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.user_service import UserService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec # we think we can get the list of roles for a user. diff --git a/tests/spiffworkflow_backend/unit/test_process_group.py b/tests/spiffworkflow_backend/unit/test_process_group.py index 6c3ad0ade..b2cf3c444 100644 --- a/tests/spiffworkflow_backend/unit/test_process_group.py +++ b/tests/spiffworkflow_backend/unit/test_process_group.py @@ -1,6 +1,5 @@ """Process Model.""" from flask.app import Flask - from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.services.process_model_service import ProcessModelService diff --git a/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index ad7aefe34..20b47b0cc 100644 --- a/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -3,9 +3,6 @@ import pytest from flask import g from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.user import UserModel @@ -19,6 +16,8 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestProcessInstanceProcessor(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_process_instance_report.py b/tests/spiffworkflow_backend/unit/test_process_instance_report.py index 482395076..ccfb088f6 100644 --- a/tests/spiffworkflow_backend/unit/test_process_instance_report.py +++ b/tests/spiffworkflow_backend/unit/test_process_instance_report.py @@ -2,12 +2,11 @@ from typing import Optional from flask.app import Flask -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance_report import ( ProcessInstanceReportModel, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest # from tests.spiffworkflow_backend.helpers.test_data import find_or_create_process_group # from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel diff --git a/tests/spiffworkflow_backend/unit/test_process_model.py b/tests/spiffworkflow_backend/unit/test_process_model.py index 5b5b9f256..4154be5df 100644 --- a/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/tests/spiffworkflow_backend/unit/test_process_model.py @@ -2,15 +2,14 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestProcessModel(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_process_model_service.py b/tests/spiffworkflow_backend/unit/test_process_model_service.py index 438ef89d9..bd981e1c5 100644 --- a/tests/spiffworkflow_backend/unit/test_process_model_service.py +++ b/tests/spiffworkflow_backend/unit/test_process_model_service.py @@ -1,11 +1,10 @@ """Test_process_model_service.""" from flask import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestProcessModelService(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index d31ea424f..46f88e749 100644 --- a/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -3,13 +3,12 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestOpenFile(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py b/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py index 9ece043a5..38a03c116 100644 --- a/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py +++ b/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py @@ -1,15 +1,14 @@ """Test Permissions.""" from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.script_unit_test_runner import PythonScriptContext from spiffworkflow_backend.services.script_unit_test_runner import ScriptUnitTestRunner +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestScriptUnitTestRunner(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_service_task_delegate.py b/tests/spiffworkflow_backend/unit/test_service_task_delegate.py index 95b557560..647db1759 100644 --- a/tests/spiffworkflow_backend/unit/test_service_task_delegate.py +++ b/tests/spiffworkflow_backend/unit/test_service_task_delegate.py @@ -1,9 +1,8 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.service_task_service import ServiceTaskDelegate +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestServiceTaskDelegate(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/tests/spiffworkflow_backend/unit/test_spec_file_service.py index d74acb47b..630ae5951 100644 --- a/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -7,13 +7,12 @@ from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestSpecFileService(BaseTest): @@ -35,7 +34,7 @@ class TestSpecFileService(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_can_store_process_ids_for_lookup.""" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -60,7 +59,7 @@ class TestSpecFileService(BaseTest): ) -> None: """Test_fails_to_save_duplicate_process_id.""" bpmn_process_identifier = "Level1" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -104,7 +103,7 @@ class TestSpecFileService(BaseTest): db.session.add(process_id_lookup) db.session.commit() - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -144,7 +143,7 @@ class TestSpecFileService(BaseTest): """ process_group_id = "test_group" process_model_id = "call_activity_nested" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/unit/test_spiff_logging.py b/tests/spiffworkflow_backend/unit/test_spiff_logging.py index d8680b719..fe5c8afef 100644 --- a/tests/spiffworkflow_backend/unit/test_spiff_logging.py +++ b/tests/spiffworkflow_backend/unit/test_spiff_logging.py @@ -3,11 +3,10 @@ from decimal import Decimal from flask.app import Flask from flask_bpmn.models.db import db +from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec -from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel - class TestSpiffLogging(BaseTest): """TestSpiffLogging.""" diff --git a/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index c655d3ffd..9ff299074 100644 --- a/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -1,13 +1,12 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask from flask.testing import FlaskClient -from tests.spiffworkflow_backend.helpers.base_test import BaseTest - from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService +from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestVariousBpmnConstructs(BaseTest): @@ -21,7 +20,7 @@ class TestVariousBpmnConstructs(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_running_process_with_timer_intermediate_catch_event.""" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, "test_group", diff --git a/tests/test_main.py b/tests/test_main.py index 7917a970d..001dbcc6d 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,7 +1,6 @@ """Test cases for the __main__ module.""" import pytest from click.testing import CliRunner - from spiffworkflow_backend import __main__