Lots of adjustments from running pyl

Main change is in the ErrorDisplay.tsx to assure all error information is provided. and index.css to make it "pretty"
This commit is contained in:
Dan 2023-01-19 12:36:45 -05:00
parent d495553968
commit 628c59dde9
78 changed files with 273 additions and 233 deletions

View File

@ -57,10 +57,17 @@ function run_autoflake() {
python_dirs=$(get_python_dirs) python_dirs=$(get_python_dirs)
python_files=$(find $python_dirs -type f -name "*.py" ! -name '.null-ls*' ! -name '_null-ls*') python_files=$(find $python_dirs -type f -name "*.py" ! -name '.null-ls*' ! -name '_null-ls*')
echo Current dir: $(pwd)
echo dirs: $python_dirs
echo files: \"$python_files\"
if [ -z "$python_files" != ""]
then
autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files
autoflake --in-place --remove-all-unused-imports $python_files autoflake --in-place --remove-all-unused-imports $python_files
autopep8 --in-place $python_files autopep8 --in-place $python_files
else
echo "no files "
fi
} }
function run_pre_commmit() { function run_pre_commmit() {

View File

@ -1,9 +1,8 @@
"""Grabs tickets from csv and makes process instances.""" """Grabs tickets from csv and makes process instances."""
import csv import csv
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend import get_hacked_up_app_for_script from spiffworkflow_backend import get_hacked_up_app_for_script
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (

View File

@ -5,11 +5,10 @@ import shutil
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -9,16 +9,16 @@ import sqlalchemy
from apscheduler.schedulers.background import BackgroundScheduler # type: ignore from apscheduler.schedulers.background import BackgroundScheduler # type: ignore
from apscheduler.schedulers.base import BaseScheduler # type: ignore from apscheduler.schedulers.base import BaseScheduler # type: ignore
from flask.json.provider import DefaultJSONProvider from flask.json.provider import DefaultJSONProvider
from spiffworkflow_backend.exceptions.api_error import api_error_blueprint
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import migrate
from flask_cors import CORS # type: ignore from flask_cors import CORS # type: ignore
from flask_mail import Mail # type: ignore from flask_mail import Mail # type: ignore
from werkzeug.exceptions import NotFound from werkzeug.exceptions import NotFound
import spiffworkflow_backend.load_database_models # noqa: F401 import spiffworkflow_backend.load_database_models # noqa: F401
from spiffworkflow_backend.config import setup_config from spiffworkflow_backend.config import setup_config
from spiffworkflow_backend.exceptions.api_error import api_error_blueprint
from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import migrate
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
from spiffworkflow_backend.routes.openid_blueprint.openid_blueprint import ( from spiffworkflow_backend.routes.openid_blueprint.openid_blueprint import (
openid_blueprint, openid_blueprint,

View File

@ -17,21 +17,21 @@ def setup_database_uri(app: Flask) -> None:
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None: if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None:
database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}" database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}"
if app.config.get("SPIFF_DATABASE_TYPE") == "sqlite": if app.config.get("SPIFF_DATABASE_TYPE") == "sqlite":
app.config["SQLALCHEMY_DATABASE_URI"] = ( app.config[
f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" "SQLALCHEMY_DATABASE_URI"
) ] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3"
elif app.config.get("SPIFF_DATABASE_TYPE") == "postgres": elif app.config.get("SPIFF_DATABASE_TYPE") == "postgres":
app.config["SQLALCHEMY_DATABASE_URI"] = ( app.config[
f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" "SQLALCHEMY_DATABASE_URI"
) ] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}"
else: else:
# use pswd to trick flake8 with hardcoded passwords # use pswd to trick flake8 with hardcoded passwords
db_pswd = os.environ.get("DB_PASSWORD") db_pswd = os.environ.get("DB_PASSWORD")
if db_pswd is None: if db_pswd is None:
db_pswd = "" db_pswd = ""
app.config["SQLALCHEMY_DATABASE_URI"] = ( app.config[
f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" "SQLALCHEMY_DATABASE_URI"
) ] = f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}"
else: else:
app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get( app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get(
"SPIFFWORKFLOW_BACKEND_DATABASE_URI" "SPIFFWORKFLOW_BACKEND_DATABASE_URI"

View File

@ -102,4 +102,3 @@ permissions:
users: [] users: []
allowed_permissions: [create, read] allowed_permissions: [create, read]
uri: /v1.0/user-groups/for-current-user uri: /v1.0/user-groups/for-current-user

View File

@ -15,7 +15,8 @@ from flask import jsonify
from flask import make_response from flask import make_response
from sentry_sdk import capture_exception from sentry_sdk import capture_exception
from sentry_sdk import set_tag from sentry_sdk import set_tag
from SpiffWorkflow.exceptions import WorkflowException, WorkflowTaskException # type: ignore from SpiffWorkflow.exceptions import WorkflowException
from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.specs.base import TaskSpec # type: ignore from SpiffWorkflow.specs.base import TaskSpec # type: ignore
from SpiffWorkflow.task import Task # type: ignore from SpiffWorkflow.task import Task # type: ignore
@ -40,7 +41,7 @@ class ApiError(Exception):
task_data: dict | str | None = field(default_factory=dict) task_data: dict | str | None = field(default_factory=dict)
task_id: str = "" task_id: str = ""
task_name: str = "" task_name: str = ""
task_trace: dict | None = field(default_factory=dict) task_trace: list | None = field(default_factory=dict)
def __str__(self) -> str: def __str__(self) -> str:
"""Instructions to print instance as a string.""" """Instructions to print instance as a string."""
@ -151,7 +152,7 @@ class ApiError(Exception):
) )
else: else:
return ApiError.from_task_spec(error_code, message, exp.sender) return ApiError.from_task_spec(error_code, message, exp.task_spec)
def set_user_sentry_context() -> None: def set_user_sentry_context() -> None:
@ -176,7 +177,9 @@ def handle_exception(exception: Exception) -> flask.wrappers.Response:
if isinstance(exception, ApiError): if isinstance(exception, ApiError):
current_app.logger.info( current_app.logger.info(
f"Sending ApiError exception to sentry: {exception} with error code {exception.error_code}") f"Sending ApiError exception to sentry: {exception} with error code"
f" {exception.error_code}"
)
organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG")
project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") project_slug = current_app.config.get("SENTRY_PROJECT_SLUG")

View File

@ -2,6 +2,7 @@
import time import time
import sqlalchemy import sqlalchemy
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db

View File

@ -59,7 +59,8 @@ class SpiffworkflowBaseDBModel(db.Model): # type: ignore
def update_created_modified_on_create_listener( def update_created_modified_on_create_listener(
mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel
) -> None: ) -> None:
"""Event listener that runs before a record is updated, and sets the create/modified field accordingly.""" """Event listener that runs before a record is updated, and sets the create/modified field accordingly.
"""
if "created_at_in_seconds" in mapper.columns.keys(): if "created_at_in_seconds" in mapper.columns.keys():
target.created_at_in_seconds = round(time.time()) target.created_at_in_seconds = round(time.time())
if "updated_at_in_seconds" in mapper.columns.keys(): if "updated_at_in_seconds" in mapper.columns.keys():
@ -69,7 +70,8 @@ def update_created_modified_on_create_listener(
def update_modified_on_update_listener( def update_modified_on_update_listener(
mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel
) -> None: ) -> None:
"""Event listener that runs before a record is updated, and sets the modified field accordingly.""" """Event listener that runs before a record is updated, and sets the modified field accordingly.
"""
if "updated_at_in_seconds" in mapper.columns.keys(): if "updated_at_in_seconds" in mapper.columns.keys():
if db.session.is_modified(target, include_collections=False): if db.session.is_modified(target, include_collections=False):
target.updated_at_in_seconds = round(time.time()) target.updated_at_in_seconds = round(time.time())

View File

@ -3,9 +3,11 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from spiffworkflow_backend.models.db import db, SpiffworkflowBaseDBModel
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
if TYPE_CHECKING: if TYPE_CHECKING:
from spiffworkflow_backend.models.user_group_assignment import ( # noqa: F401 from spiffworkflow_backend.models.user_group_assignment import ( # noqa: F401
UserGroupAssignmentModel, UserGroupAssignmentModel,

View File

@ -4,12 +4,11 @@ from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import Task

View File

@ -3,11 +3,10 @@ from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -2,12 +2,11 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.message_correlation_property import ( from spiffworkflow_backend.models.message_correlation_property import (
MessageCorrelationPropertyModel, MessageCorrelationPropertyModel,
) )

View File

@ -1,11 +1,10 @@
"""Message_correlation_message_instance.""" """Message_correlation_message_instance."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel

View File

@ -1,9 +1,8 @@
"""Message_correlation_property.""" """Message_correlation_property."""
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel

View File

@ -5,15 +5,14 @@ from typing import Any
from typing import Optional from typing import Optional
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.event import listens_for from sqlalchemy.event import listens_for
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy.orm import validates from sqlalchemy.orm import validates
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel

View File

@ -3,7 +3,6 @@ from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
class MessageModel(SpiffworkflowBaseDBModel): class MessageModel(SpiffworkflowBaseDBModel):
"""MessageModel.""" """MessageModel."""

View File

@ -1,9 +1,8 @@
"""Message_correlation_property.""" """Message_correlation_property."""
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel

View File

@ -2,12 +2,11 @@
import enum import enum
from typing import Any from typing import Any
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import validates from sqlalchemy.orm import validates
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel
from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.principal import PrincipalModel

View File

@ -3,11 +3,11 @@ import re
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional from typing import Optional
from sqlalchemy.orm import validates
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy.orm import validates
class InvalidPermissionTargetUriError(Exception): class InvalidPermissionTargetUriError(Exception):
"""InvalidPermissionTargetUriError.""" """InvalidPermissionTargetUriError."""

View File

@ -1,13 +1,12 @@
"""Principal.""" """Principal."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.schema import CheckConstraint from sqlalchemy.schema import CheckConstraint
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -5,9 +5,6 @@ from typing import Any
from typing import cast from typing import cast
import marshmallow import marshmallow
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from marshmallow import INCLUDE from marshmallow import INCLUDE
from marshmallow import Schema from marshmallow import Schema
from marshmallow_enum import EnumField # type: ignore from marshmallow_enum import EnumField # type: ignore
@ -18,6 +15,8 @@ from sqlalchemy.orm import relationship
from sqlalchemy.orm import validates from sqlalchemy.orm import validates
from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import Task
from spiffworkflow_backend.models.task import TaskSchema from spiffworkflow_backend.models.task import TaskSchema
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -1,11 +1,10 @@
"""Process_instance_metadata.""" """Process_instance_metadata."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel

View File

@ -7,9 +7,6 @@ from typing import cast
from typing import Optional from typing import Optional
from typing import TypedDict from typing import TypedDict
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import deferred from sqlalchemy.orm import deferred
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
@ -17,6 +14,8 @@ from sqlalchemy.orm import relationship
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (

View File

@ -1,11 +1,11 @@
"""Refresh_token.""" """Refresh_token."""
from dataclasses import dataclass from dataclasses import dataclass
from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey
# from sqlalchemy.orm import relationship # from sqlalchemy.orm import relationship
# from spiffworkflow_backend.models.user import UserModel # from spiffworkflow_backend.models.user import UserModel

View File

@ -1,12 +1,11 @@
"""Secret_model.""" """Secret_model."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from marshmallow import Schema from marshmallow import Schema
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -1,13 +1,13 @@
"""Message_model.""" """Message_model."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from flask_marshmallow import Schema # type: ignore from flask_marshmallow import Schema # type: ignore
from marshmallow import INCLUDE from marshmallow import INCLUDE
from sqlalchemy import UniqueConstraint from sqlalchemy import UniqueConstraint
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
class SpecReferenceNotFoundError(Exception): class SpecReferenceNotFoundError(Exception):
"""SpecReferenceNotFoundError.""" """SpecReferenceNotFoundError."""
@ -38,7 +38,8 @@ class SpecReference:
class SpecReferenceCache(SpiffworkflowBaseDBModel): class SpecReferenceCache(SpiffworkflowBaseDBModel):
"""A cache of information about all the Processes and Decisions defined in all files.""" """A cache of information about all the Processes and Decisions defined in all files.
"""
__tablename__ = "spec_reference_cache" __tablename__ = "spec_reference_cache"
__table_args__ = ( __table_args__ = (

View File

@ -6,7 +6,6 @@ from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
@dataclass @dataclass
class SpiffLoggingModel(SpiffworkflowBaseDBModel): class SpiffLoggingModel(SpiffworkflowBaseDBModel):
"""SpiffLoggingModel.""" """SpiffLoggingModel."""

View File

@ -1,12 +1,11 @@
"""Spiff_step_details.""" """Spiff_step_details."""
from dataclasses import dataclass from dataclasses import dataclass
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import deferred from sqlalchemy.orm import deferred
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel

View File

@ -6,12 +6,11 @@ from dataclasses import dataclass
import jwt import jwt
import marshmallow import marshmallow
from flask import current_app from flask import current_app
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from marshmallow import Schema from marshmallow import Schema
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel

View File

@ -1,10 +1,9 @@
"""UserGroupAssignment.""" """UserGroupAssignment."""
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -1,10 +1,9 @@
"""UserGroupAssignment.""" """UserGroupAssignment."""
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel

View File

@ -9,8 +9,8 @@ from flask import g
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel

View File

@ -11,12 +11,12 @@ from flask import jsonify
from flask import make_response from flask import make_response
from flask import request from flask import request
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema

View File

@ -8,8 +8,8 @@ from flask import g
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )

View File

@ -11,12 +11,12 @@ from flask import jsonify
from flask import make_response from flask import make_response
from flask import request from flask import request
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from SpiffWorkflow.task import TaskState # type: ignore from SpiffWorkflow.task import TaskState # type: ignore
from sqlalchemy import and_ from sqlalchemy import and_
from sqlalchemy import or_ from sqlalchemy import or_
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema
@ -556,9 +556,10 @@ def process_instance_task_list(
else: else:
spiff_tasks = processor.get_all_user_tasks() spiff_tasks = processor.get_all_user_tasks()
subprocesses_by_child_task_ids, task_typename_by_task_id = ( (
processor.get_subprocesses_by_child_task_ids() subprocesses_by_child_task_ids,
) task_typename_by_task_id,
) = processor.get_subprocesses_by_child_task_ids()
processor.get_highest_level_calling_subprocesses_by_child_task_ids( processor.get_highest_level_calling_subprocesses_by_child_task_ids(
subprocesses_by_child_task_ids, task_typename_by_task_id subprocesses_by_child_task_ids, task_typename_by_task_id
) )

View File

@ -14,9 +14,9 @@ from flask import g
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from werkzeug.datastructures import FileStorage from werkzeug.datastructures import FileStorage
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.interfaces import IdToProcessGroupMapping from spiffworkflow_backend.interfaces import IdToProcessGroupMapping
from spiffworkflow_backend.models.file import FileSchema from spiffworkflow_backend.models.file import FileSchema
from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroup

View File

@ -10,10 +10,10 @@ from flask import current_app
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from lxml import etree # type: ignore from lxml import etree # type: ignore
from lxml.builder import ElementMaker # type: ignore from lxml.builder import ElementMaker # type: ignore
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.routes.process_api_blueprint import _get_process_model from spiffworkflow_backend.routes.process_api_blueprint import _get_process_model
from spiffworkflow_backend.routes.process_api_blueprint import ( from spiffworkflow_backend.routes.process_api_blueprint import (
_get_required_parameter_or_raise, _get_required_parameter_or_raise,

View File

@ -15,8 +15,6 @@ from flask import g
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from SpiffWorkflow.task import TaskState from SpiffWorkflow.task import TaskState
from sqlalchemy import and_ from sqlalchemy import and_
@ -26,6 +24,8 @@ from sqlalchemy import func
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from sqlalchemy.orm.util import AliasedClass from sqlalchemy.orm.util import AliasedClass
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel

View File

@ -14,9 +14,9 @@ from flask import current_app
from flask import g from flask import g
from flask import redirect from flask import redirect
from flask import request from flask import request
from spiffworkflow_backend.exceptions.api_error import ApiError
from werkzeug.wrappers import Response from werkzeug.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.authentication_service import AuthenticationService from spiffworkflow_backend.services.authentication_service import AuthenticationService
from spiffworkflow_backend.services.authentication_service import ( from spiffworkflow_backend.services.authentication_service import (

View File

@ -7,10 +7,10 @@ import flask.wrappers
from flask import Blueprint from flask import Blueprint
from flask import request from flask import request
from flask import Response from flask import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel

View File

@ -2,9 +2,9 @@
from time import time from time import time
from typing import Any from typing import Any
from spiffworkflow_backend.models.db import db
from sqlalchemy import or_ from sqlalchemy import or_
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.script_attributes_context import ( from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext, ScriptAttributesContext,

View File

@ -3,8 +3,8 @@ from datetime import datetime
from typing import Any from typing import Any
import pytz import pytz
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.script_attributes_context import ( from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext, ScriptAttributesContext,
) )

View File

@ -2,7 +2,6 @@
from typing import Any from typing import Any
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance_metadata import ( from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel, ProcessInstanceMetadataModel,
) )

View File

@ -9,7 +9,6 @@ from typing import Any
from typing import Callable from typing import Callable
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceNotFoundError from spiffworkflow_backend.models.process_instance import ProcessInstanceNotFoundError
from spiffworkflow_backend.models.script_attributes_context import ( from spiffworkflow_backend.models.script_attributes_context import (
@ -28,7 +27,8 @@ class ScriptUnauthorizedForUserError(Exception):
class Script: class Script:
"""Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks.""" """Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks.
"""
@abstractmethod @abstractmethod
def get_description(self) -> str: def get_description(self) -> str:

View File

@ -2,9 +2,9 @@
import time import time
from flask import current_app from flask import current_app
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.services.process_instance_service import ( from spiffworkflow_backend.services.process_instance_service import (

View File

@ -9,10 +9,10 @@ import jwt
import requests import requests
from flask import current_app from flask import current_app
from flask import redirect from flask import redirect
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from werkzeug.wrappers import Response from werkzeug.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.refresh_token import RefreshTokenModel from spiffworkflow_backend.models.refresh_token import RefreshTokenModel
@ -60,7 +60,8 @@ class AuthenticationService:
@classmethod @classmethod
def open_id_endpoint_for_name(cls, name: str) -> str: def open_id_endpoint_for_name(cls, name: str) -> str:
"""All openid systems provide a mapping of static names to the full path of that endpoint.""" """All openid systems provide a mapping of static names to the full path of that endpoint.
"""
openid_config_url = f"{cls.server_url()}/.well-known/openid-configuration" openid_config_url = f"{cls.server_url()}/.well-known/openid-configuration"
if name not in AuthenticationService.ENDPOINT_CACHE: if name not in AuthenticationService.ENDPOINT_CACHE:
response = requests.get(openid_config_url) response = requests.get(openid_config_url)
@ -200,7 +201,8 @@ class AuthenticationService:
@classmethod @classmethod
def get_auth_token_from_refresh_token(cls, refresh_token: str) -> dict: def get_auth_token_from_refresh_token(cls, refresh_token: str) -> dict:
"""Converts a refresh token to an Auth Token by calling the openid's auth endpoint.""" """Converts a refresh token to an Auth Token by calling the openid's auth endpoint.
"""
backend_basic_auth_string = f"{cls.client_id()}:{cls.secret_key()}" backend_basic_auth_string = f"{cls.client_id()}:{cls.secret_key()}"
backend_basic_auth_bytes = bytes(backend_basic_auth_string, encoding="ascii") backend_basic_auth_bytes = bytes(backend_basic_auth_string, encoding="ascii")
backend_basic_auth = base64.b64encode(backend_basic_auth_bytes) backend_basic_auth = base64.b64encode(backend_basic_auth_bytes)

View File

@ -17,13 +17,13 @@ from flask import current_app
from flask import g from flask import g
from flask import request from flask import request
from flask import scaffold from flask import scaffold
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from sqlalchemy import or_ from sqlalchemy import or_
from sqlalchemy import text from sqlalchemy import text
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel
@ -171,7 +171,8 @@ class AuthorizationService:
@classmethod @classmethod
def delete_all_permissions(cls) -> None: def delete_all_permissions(cls) -> None:
"""Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user?""" """Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user?
"""
for model in [PermissionAssignmentModel, PermissionTargetModel]: for model in [PermissionAssignmentModel, PermissionTargetModel]:
db.session.query(model).delete() db.session.query(model).delete()
@ -282,9 +283,9 @@ class AuthorizationService:
"""Find_or_create_permission_target.""" """Find_or_create_permission_target."""
uri_with_percent = re.sub(r"\*", "%", uri) uri_with_percent = re.sub(r"\*", "%", uri)
target_uri_normalized = uri_with_percent.removeprefix(V1_API_PATH_PREFIX) target_uri_normalized = uri_with_percent.removeprefix(V1_API_PATH_PREFIX)
permission_target: Optional[PermissionTargetModel] = ( permission_target: Optional[
PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first() PermissionTargetModel
) ] = PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first()
if permission_target is None: if permission_target is None:
permission_target = PermissionTargetModel(uri=target_uri_normalized) permission_target = PermissionTargetModel(uri=target_uri_normalized)
db.session.add(permission_target) db.session.add(permission_target)
@ -299,13 +300,13 @@ class AuthorizationService:
permission: str, permission: str,
) -> PermissionAssignmentModel: ) -> PermissionAssignmentModel:
"""Create_permission_for_principal.""" """Create_permission_for_principal."""
permission_assignment: Optional[PermissionAssignmentModel] = ( permission_assignment: Optional[
PermissionAssignmentModel.query.filter_by( PermissionAssignmentModel
] = PermissionAssignmentModel.query.filter_by(
principal_id=principal.id, principal_id=principal.id,
permission_target_id=permission_target.id, permission_target_id=permission_target.id,
permission=permission, permission=permission,
).first() ).first()
)
if permission_assignment is None: if permission_assignment is None:
permission_assignment = PermissionAssignmentModel( permission_assignment = PermissionAssignmentModel(
principal_id=principal.id, principal_id=principal.id,
@ -434,10 +435,8 @@ class AuthorizationService:
except jwt.InvalidTokenError as exception: except jwt.InvalidTokenError as exception:
raise ApiError( raise ApiError(
"token_invalid", "token_invalid",
(
"The Authentication token you provided is invalid. You need a new" "The Authentication token you provided is invalid. You need a new"
" token. " " token. ",
),
) from exception ) from exception
@staticmethod @staticmethod

View File

@ -15,11 +15,13 @@ class BackgroundProcessingService:
self.app = app self.app = app
def process_waiting_process_instances(self) -> None: def process_waiting_process_instances(self) -> None:
"""Since this runs in a scheduler, we need to specify the app context as well.""" """Since this runs in a scheduler, we need to specify the app context as well.
"""
with self.app.app_context(): with self.app.app_context():
ProcessInstanceService.do_waiting() ProcessInstanceService.do_waiting()
def process_message_instances_with_app_context(self) -> None: def process_message_instances_with_app_context(self) -> None:
"""Since this runs in a scheduler, we need to specify the app context as well.""" """Since this runs in a scheduler, we need to specify the app context as well.
"""
with self.app.app_context(): with self.app.app_context():
MessageService.process_message_instances() MessageService.process_message_instances()

View File

@ -1,7 +1,7 @@
"""Data_setup_service.""" """Data_setup_service."""
from flask import current_app from flask import current_app
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.spec_file_service import SpecFileService

View File

@ -5,9 +5,9 @@ from typing import Union
from flask import current_app from flask import current_app
from flask import g from flask import g
from flask.wrappers import Response from flask.wrappers import Response
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel
from spiffworkflow_backend.models.message_triggerable_process_model import ( from spiffworkflow_backend.models.message_triggerable_process_model import (
MessageTriggerableProcessModel, MessageTriggerableProcessModel,
@ -41,7 +41,8 @@ class ErrorHandlingService:
def handle_error( def handle_error(
self, _processor: ProcessInstanceProcessor, _error: Union[ApiError, Exception] self, _processor: ProcessInstanceProcessor, _error: Union[ApiError, Exception]
) -> None: ) -> None:
"""On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.""" """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.
"""
process_model = ProcessModelService.get_process_model( process_model = ProcessModelService.get_process_model(
_processor.process_model_identifier _processor.process_model_identifier
) )

View File

@ -8,8 +8,8 @@ from typing import Optional
import pytz import pytz
from flask import current_app from flask import current_app
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.file import CONTENT_TYPES from spiffworkflow_backend.models.file import CONTENT_TYPES
from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import FileType
@ -151,7 +151,8 @@ class FileSystemService:
@staticmethod @staticmethod
def _get_files(file_path: str, file_name: Optional[str] = None) -> List[File]: def _get_files(file_path: str, file_name: Optional[str] = None) -> List[File]:
"""Returns an array of File objects at the given path, can be restricted to just one file.""" """Returns an array of File objects at the given path, can be restricted to just one file.
"""
files = [] files = []
items = os.scandir(file_path) items = os.scandir(file_path)
for item in items: for item in items:

View File

@ -2,7 +2,6 @@
from typing import Optional from typing import Optional
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.user_service import UserService from spiffworkflow_backend.services.user_service import UserService

View File

@ -7,8 +7,8 @@ from typing import Optional
from flask import g from flask import g
from flask.app import Flask from flask.app import Flask
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
@ -52,7 +52,8 @@ class JsonFormatter(logging.Formatter):
self.datefmt = None self.datefmt = None
def usesTime(self) -> bool: def usesTime(self) -> bool:
"""Overwritten to look for the attribute in the format dict values instead of the fmt string.""" """Overwritten to look for the attribute in the format dict values instead of the fmt string.
"""
return "asctime" in self.fmt_dict.values() return "asctime" in self.fmt_dict.values()
# we are overriding a method that returns a string and returning a dict, hence the Any # we are overriding a method that returns a string and returning a dict, hence the Any

View File

@ -2,11 +2,11 @@
from typing import Any from typing import Any
from typing import Optional from typing import Optional
from spiffworkflow_backend.models.db import db
from sqlalchemy import and_ from sqlalchemy import and_
from sqlalchemy import or_ from sqlalchemy import or_
from sqlalchemy import select from sqlalchemy import select
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel
from spiffworkflow_backend.models.message_correlation_message_instance import ( from spiffworkflow_backend.models.message_correlation_message_instance import (
MessageCorrelationMessageInstanceModel, MessageCorrelationMessageInstanceModel,

View File

@ -22,11 +22,9 @@ from uuid import UUID
import dateparser import dateparser
import pytz import pytz
from flask import current_app from flask import current_app
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from lxml import etree # type: ignore from lxml import etree # type: ignore
from lxml.etree import XMLSyntaxError
from RestrictedPython import safe_globals # type: ignore from RestrictedPython import safe_globals # type: ignore
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore
from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
@ -40,6 +38,7 @@ from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore
from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore
from SpiffWorkflow.dmn.serializer.task_spec_converters import BusinessRuleTaskConverter # type: ignore from SpiffWorkflow.dmn.serializer.task_spec_converters import BusinessRuleTaskConverter # type: ignore
from SpiffWorkflow.exceptions import WorkflowException # type: ignore from SpiffWorkflow.exceptions import WorkflowException # type: ignore
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore
from SpiffWorkflow.spiff.serializer.task_spec_converters import BoundaryEventConverter # type: ignore from SpiffWorkflow.spiff.serializer.task_spec_converters import BoundaryEventConverter # type: ignore
from SpiffWorkflow.spiff.serializer.task_spec_converters import ( from SpiffWorkflow.spiff.serializer.task_spec_converters import (
@ -71,6 +70,8 @@ from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from SpiffWorkflow.task import TaskState from SpiffWorkflow.task import TaskState
from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
@ -217,15 +218,16 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
return super()._evaluate(expression, context, external_methods=methods) return super()._evaluate(expression, context, external_methods=methods)
except Exception as exception: except Exception as exception:
if task is None: if task is None:
raise ProcessInstanceProcessorError( raise WorkflowException(
"Error evaluating expression: '%s', exception: %s" "Error evaluating expression: '%s', %s"
% (expression, str(exception)), % (expression, str(exception)),
) from exception ) from exception
else: else:
raise WorkflowTaskException( raise WorkflowTaskException(
task,
"Error evaluating expression '%s', %s" "Error evaluating expression '%s', %s"
% (expression, str(exception)), % (expression, str(exception)),
task=task,
exception=exception,
) from exception ) from exception
def execute( def execute(
@ -240,7 +242,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
except WorkflowException as e: except WorkflowException as e:
raise e raise e
except Exception as e: except Exception as e:
raise WorkflowTaskException(task, f" {script}, {e}", e) from e raise self.create_task_exec_exception(task, script, e)
def call_service( def call_service(
self, self,
@ -297,7 +299,8 @@ class ProcessInstanceProcessor:
def __init__( def __init__(
self, process_instance_model: ProcessInstanceModel, validate_only: bool = False self, process_instance_model: ProcessInstanceModel, validate_only: bool = False
) -> None: ) -> None:
"""Create a Workflow Processor based on the serialized information available in the process_instance model.""" """Create a Workflow Processor based on the serialized information available in the process_instance model.
"""
tld = current_app.config["THREAD_LOCAL_DATA"] tld = current_app.config["THREAD_LOCAL_DATA"]
tld.process_instance_id = process_instance_model.id tld.process_instance_id = process_instance_model.id
tld.spiff_step = process_instance_model.spiff_step tld.spiff_step = process_instance_model.spiff_step
@ -403,10 +406,8 @@ class ProcessInstanceProcessor:
raise ( raise (
ApiError( ApiError(
"process_model_not_found", "process_model_not_found",
(
"The given process model was not found:" "The given process model was not found:"
f" {process_model_identifier}." f" {process_model_identifier}.",
),
) )
) )
spec_files = SpecFileService.get_files(process_model_info) spec_files = SpecFileService.get_files(process_model_info)
@ -536,11 +537,9 @@ class ProcessInstanceProcessor:
potential_owner_ids.append(lane_owner_user.id) potential_owner_ids.append(lane_owner_user.id)
self.raise_if_no_potential_owners( self.raise_if_no_potential_owners(
potential_owner_ids, potential_owner_ids,
(
"No users found in task data lane owner list for lane:" "No users found in task data lane owner list for lane:"
f" {task_lane}. The user list used:" f" {task_lane}. The user list used:"
f" {task.data['lane_owners'][task_lane]}" f" {task.data['lane_owners'][task_lane]}",
),
) )
else: else:
group_model = GroupModel.query.filter_by(identifier=task_lane).first() group_model = GroupModel.query.filter_by(identifier=task_lane).first()
@ -693,9 +692,9 @@ class ProcessInstanceProcessor:
): ):
continue continue
subprocesses_by_child_task_ids[task_id] = ( subprocesses_by_child_task_ids[
subprocesses_by_child_task_ids[subprocess_id] task_id
) ] = subprocesses_by_child_task_ids[subprocess_id]
self.get_highest_level_calling_subprocesses_by_child_task_ids( self.get_highest_level_calling_subprocesses_by_child_task_ids(
subprocesses_by_child_task_ids, task_typename_by_task_id subprocesses_by_child_task_ids, task_typename_by_task_id
) )
@ -1015,17 +1014,24 @@ class ProcessInstanceProcessor:
def get_spec( def get_spec(
files: List[File], process_model_info: ProcessModelInfo files: List[File], process_model_info: ProcessModelInfo
) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]: ) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]:
"""Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided.""" """Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided.
"""
parser = ProcessInstanceProcessor.get_parser() parser = ProcessInstanceProcessor.get_parser()
for file in files: for file in files:
data = SpecFileService.get_data(process_model_info, file.name) data = SpecFileService.get_data(process_model_info, file.name)
try:
if file.type == FileType.bpmn.value: if file.type == FileType.bpmn.value:
bpmn: etree.Element = etree.fromstring(data) bpmn: etree.Element = etree.fromstring(data)
parser.add_bpmn_xml(bpmn, filename=file.name) parser.add_bpmn_xml(bpmn, filename=file.name)
elif file.type == FileType.dmn.value: elif file.type == FileType.dmn.value:
dmn: etree.Element = etree.fromstring(data) dmn: etree.Element = etree.fromstring(data)
parser.add_dmn_xml(dmn, filename=file.name) parser.add_dmn_xml(dmn, filename=file.name)
except XMLSyntaxError as xse:
raise ApiError(
error_code="invalid_xml",
message=f"'{file.name}' is not a valid xml file." + str(xse),
)
if ( if (
process_model_info.primary_process_id is None process_model_info.primary_process_id is None
or process_model_info.primary_process_id == "" or process_model_info.primary_process_id == ""
@ -1056,7 +1062,8 @@ class ProcessInstanceProcessor:
error_code="process_instance_validation_error", error_code="process_instance_validation_error",
message="Failed to parse the Workflow Specification. " message="Failed to parse the Workflow Specification. "
+ "Error is '%s.'" % str(ve), + "Error is '%s.'" % str(ve),
file_name=ve.filename, file_name=ve.file_name,
task_name=ve.name,
task_id=ve.id, task_id=ve.id,
tag=ve.tag, tag=ve.tag,
) from ve ) from ve
@ -1097,10 +1104,8 @@ class ProcessInstanceProcessor:
if not bpmn_message.correlations: if not bpmn_message.correlations:
raise ApiError( raise ApiError(
"message_correlations_missing", "message_correlations_missing",
(
"Could not find any message correlations bpmn_message:" "Could not find any message correlations bpmn_message:"
f" {bpmn_message.name}" f" {bpmn_message.name}",
),
) )
message_correlations = [] message_correlations = []
@ -1120,10 +1125,8 @@ class ProcessInstanceProcessor:
if message_correlation_property is None: if message_correlation_property is None:
raise ApiError( raise ApiError(
"message_correlations_missing_from_process", "message_correlations_missing_from_process",
(
"Could not find a known message correlation with" "Could not find a known message correlation with"
f" identifier:{message_correlation_property_identifier}" f" identifier:{message_correlation_property_identifier}",
),
) )
message_correlations.append( message_correlations.append(
{ {
@ -1186,10 +1189,8 @@ class ProcessInstanceProcessor:
if message_model is None: if message_model is None:
raise ApiError( raise ApiError(
"invalid_message_name", "invalid_message_name",
(
"Invalid message name:" "Invalid message name:"
f" {waiting_task.task_spec.event_definition.name}." f" {waiting_task.task_spec.event_definition.name}.",
),
) )
# Ensure we are only creating one message instance for each waiting message # Ensure we are only creating one message instance for each waiting message
@ -1474,7 +1475,8 @@ class ProcessInstanceProcessor:
return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore
def get_current_user_tasks(self) -> list[SpiffTask]: def get_current_user_tasks(self) -> list[SpiffTask]:
"""Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task.""" """Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task.
"""
ready_tasks = self.bpmn_process_instance.get_ready_user_tasks() ready_tasks = self.bpmn_process_instance.get_ready_user_tasks()
additional_tasks = [] additional_tasks = []
if len(ready_tasks) > 0: if len(ready_tasks) > 0:
@ -1531,7 +1533,8 @@ class ProcessInstanceProcessor:
return None return None
def find_spec_and_field(self, spec_name: str, field_id: Union[str, int]) -> Any: def find_spec_and_field(self, spec_name: str, field_id: Union[str, int]) -> Any:
"""Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form.""" """Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form.
"""
process_instances = [self.bpmn_process_instance] process_instances = [self.bpmn_process_instance]
for task in self.bpmn_process_instance.get_ready_user_tasks(): for task in self.bpmn_process_instance.get_ready_user_tasks():
if task.process_instance not in process_instances: if task.process_instance not in process_instances:

View File

@ -6,15 +6,14 @@ from typing import Optional
from typing import Type from typing import Type
import sqlalchemy import sqlalchemy
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import and_ from sqlalchemy import and_
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy import or_ from sqlalchemy import or_
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
@ -313,9 +312,9 @@ class ProcessInstanceReportService:
process_instance_dict = process_instance["ProcessInstanceModel"].serialized process_instance_dict = process_instance["ProcessInstanceModel"].serialized
for metadata_column in metadata_columns: for metadata_column in metadata_columns:
if metadata_column["accessor"] not in process_instance_dict: if metadata_column["accessor"] not in process_instance_dict:
process_instance_dict[metadata_column["accessor"]] = ( process_instance_dict[
process_instance[metadata_column["accessor"]] metadata_column["accessor"]
) ] = process_instance[metadata_column["accessor"]]
results.append(process_instance_dict) results.append(process_instance_dict)
return results return results

View File

@ -5,10 +5,10 @@ from typing import List
from typing import Optional from typing import Optional
from flask import current_app from flask import current_app
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceApi
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
@ -224,7 +224,8 @@ class ProcessInstanceService:
@staticmethod @staticmethod
def extract_form_data(latest_data: dict, task: SpiffTask) -> dict: def extract_form_data(latest_data: dict, task: SpiffTask) -> dict:
"""Extracts data from the latest_data that is directly related to the form that is being submitted.""" """Extracts data from the latest_data that is directly related to the form that is being submitted.
"""
data = {} data = {}
if hasattr(task.task_spec, "form"): if hasattr(task.task_spec, "form"):

View File

@ -9,7 +9,6 @@ from typing import Optional
from typing import TypeVar from typing import TypeVar
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )

View File

@ -3,7 +3,6 @@ from typing import Optional
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModel
# from cryptography.fernet import Fernet # from cryptography.fernet import Fernet

View File

@ -5,10 +5,10 @@ from datetime import datetime
from typing import List from typing import List
from typing import Optional from typing import Optional
from spiffworkflow_backend.models.db import db
from lxml import etree # type: ignore from lxml import etree # type: ignore
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator # type: ignore from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator # type: ignore
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.file import SpecReference from spiffworkflow_backend.models.file import SpecReference
@ -325,7 +325,8 @@ class SpecFileService(FileSystemService):
@staticmethod @staticmethod
def update_message_cache(ref: SpecReference) -> None: def update_message_cache(ref: SpecReference) -> None:
"""Assure we have a record in the database of all possible message ids and names.""" """Assure we have a record in the database of all possible message ids and names.
"""
for message_model_identifier in ref.messages.keys(): for message_model_identifier in ref.messages.keys():
message_model = MessageModel.query.filter_by( message_model = MessageModel.query.filter_by(
identifier=message_model_identifier identifier=message_model_identifier

View File

@ -4,9 +4,9 @@ from typing import Optional
from flask import current_app from flask import current_app
from flask import g from flask import g
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel

View File

@ -9,11 +9,11 @@ from typing import Optional
from flask import current_app from flask import current_app
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from werkzeug.test import TestResponse # type: ignore from werkzeug.test import TestResponse # type: ignore
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.permission_assignment import Permission from spiffworkflow_backend.models.permission_assignment import Permission
from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel
from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroup

View File

@ -40,7 +40,8 @@ def load_test_spec(
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
process_model_source_directory: Optional[str] = None, process_model_source_directory: Optional[str] = None,
) -> ProcessModelInfo: ) -> ProcessModelInfo:
"""Loads a bpmn file into the process model dir based on a directory in tests/data.""" """Loads a bpmn file into the process model dir based on a directory in tests/data.
"""
if process_model_source_directory is None: if process_model_source_directory is None:
raise Exception("You must inclode a `process_model_source_directory`.") raise Exception("You must inclode a `process_model_source_directory`.")

View File

@ -9,13 +9,13 @@ from typing import Dict
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroup
@ -3103,7 +3103,8 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_get_process_instance_list_with_report_metadata_and_process_initator.""" """Test_can_get_process_instance_list_with_report_metadata_and_process_initator.
"""
user_one = self.create_user_with_permission(username="user_one") user_one = self.create_user_with_permission(username="user_one")
process_model = load_test_spec( process_model = load_test_spec(

View File

@ -5,10 +5,10 @@ from typing import Optional
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.exceptions.api_error import ApiError
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from werkzeug.test import TestResponse # type: ignore from werkzeug.test import TestResponse # type: ignore
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModel
from spiffworkflow_backend.models.secret_model import SecretModelSchema from spiffworkflow_backend.models.secret_model import SecretModelSchema

View File

@ -1,10 +1,10 @@
"""Test_get_localtime.""" """Test_get_localtime."""
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (

View File

@ -2,10 +2,10 @@
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.exceptions.api_error import ApiError
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,
) )

View File

@ -2,9 +2,9 @@
import pytest import pytest
from flask import Flask from flask import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel

View File

@ -1,9 +1,9 @@
"""Process Model.""" """Process Model."""
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.permission_target import ( from spiffworkflow_backend.models.permission_target import (
InvalidPermissionTargetUriError, InvalidPermissionTargetUriError,
) )

View File

@ -1,10 +1,10 @@
"""Test Permissions.""" """Test Permissions."""
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel
from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel

View File

@ -3,10 +3,10 @@ from typing import Optional
from flask import Flask from flask import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.process_instance_report import ( from spiffworkflow_backend.models.process_instance_report import (

View File

@ -1,10 +1,10 @@
"""Process Model.""" """Process Model."""
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance_metadata import ( from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel, ProcessInstanceMetadataModel,
) )

View File

@ -2,10 +2,10 @@
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.exceptions.api_error import ApiError
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,

View File

@ -4,10 +4,10 @@ import os
import pytest import pytest
from flask import Flask from flask import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.spec_reference import SpecReferenceCache
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
@ -136,7 +136,8 @@ class TestSpecFileService(BaseTest):
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""When a BPMN processes identifier is changed in a file, the old id is removed from the cache.""" """When a BPMN processes identifier is changed in a file, the old id is removed from the cache.
"""
old_identifier = "ye_old_identifier" old_identifier = "ye_old_identifier"
process_id_lookup = SpecReferenceCache( process_id_lookup = SpecReferenceCache(
identifier=old_identifier, identifier=old_identifier,

View File

@ -2,10 +2,10 @@
from decimal import Decimal from decimal import Decimal
from flask.app import Flask from flask.app import Flask
from spiffworkflow_backend.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel

View File

@ -2,6 +2,23 @@ import { useContext } from 'react';
import ErrorContext from '../contexts/ErrorContext'; import ErrorContext from '../contexts/ErrorContext';
import { Notification } from './Notification'; import { Notification } from './Notification';
function errorDetailDisplay(
errorObject: any,
propertyName: string,
title: string
) {
// Creates a bit of html for displaying a single error property if it exists.
if (propertyName in errorObject && errorObject[propertyName]) {
return (
<div className="error_info">
<span className="error_title">{title}:</span>
{errorObject[propertyName]}
</div>
);
}
return null;
}
export default function ErrorDisplay() { export default function ErrorDisplay() {
const [errorObject, setErrorObject] = (useContext as any)(ErrorContext); const [errorObject, setErrorObject] = (useContext as any)(ErrorContext);
@ -21,21 +38,24 @@ export default function ErrorDisplay() {
); );
} }
let message = <div>{errorObject.message}</div>; const message = <div>{errorObject.message}</div>;
let title = 'Error:'; const title = 'Error:';
if ('task_name' in errorObject && errorObject.task_name) { const taskName = errorDetailDisplay(errorObject, 'task_name', 'Task Name');
title = 'Error in python script:'; const taskId = errorDetailDisplay(errorObject, 'task_id', 'Task ID');
message = ( const fileName = errorDetailDisplay(errorObject, 'file_name', 'File Name');
<> const lineNumber = errorDetailDisplay(
<br /> errorObject,
<div> 'line_number',
Task: {errorObject.task_name} ({errorObject.task_id}) 'Line Number'
);
const errorLine = errorDetailDisplay(errorObject, 'error_line', 'Context');
let taskTrace = null;
if ('task_trace' in errorObject && errorObject.task_trace.length > 1) {
taskTrace = (
<div className="error_info">
<span className="error_title">Call Activity Trace:</span>
{errorObject.task_trace.reverse().join(' -> ')}
</div> </div>
<div>File name: {errorObject.file_name}</div>
<div>Line number in script task: {errorObject.line_number}</div>
<br />
<div>{errorObject.message}</div>
</>
); );
} }
@ -46,7 +66,14 @@ export default function ErrorDisplay() {
type="error" type="error"
> >
{message} {message}
<br />
{sentryLinkTag} {sentryLinkTag}
{taskName}
{taskId}
{fileName}
{lineNumber}
{errorLine}
{taskTrace}
</Notification> </Notification>
); );
} }

View File

@ -374,3 +374,12 @@ svg.notification-icon {
.tag-type-green:hover { .tag-type-green:hover {
background-color: #80ee90; background-color: #80ee90;
} }
/* Errors and notifications */
.error_info .error_title {
display: inline-block;
font-weight: lighter;
width: 100px;
text-align: right;
margin-right: 10px;
}