Merge remote-tracking branch 'origin/main' into feature/typeahead_in_custom_widgets

This commit is contained in:
jasquat 2023-06-01 10:43:37 -04:00
commit 27bd66d93b
No known key found for this signature in database
123 changed files with 69 additions and 695 deletions

View File

@ -49,7 +49,7 @@ function run_pre_commmit() {
for react_project in "${react_projects[@]}" ; do
# if pre, only do stuff when there are changes
if [[ "$subcommand" != "pre" ]] || [[ -n "$(git status --porcelain "$react_project")" ]]; then
if [[ -n "$(git status --porcelain "$react_project")" ]]; then
pushd "$react_project"
npm run lint:fix
popd
@ -57,6 +57,7 @@ for react_project in "${react_projects[@]}" ; do
done
for python_project in "${python_projects[@]}" ; do
# if pre, only do stuff when there are changes
if [[ "$subcommand" != "pre" ]] || [[ -n "$(git status --porcelain "$python_project")" ]]; then
pushd "$python_project"
run_autofixers || run_autofixers

View File

@ -35,37 +35,44 @@ matches_filename_pattern() {
remove_useless_comments() {
local file_name="$1"
echo "grepping"
matches=$(ggrep --group-separator=HOTSEP -B 1 -E '^\s*"""' "$file_name" || echo '')
if [[ -n "$matches" ]]; then
matches="${matches}\nHOTSEP"
echo -e "$matches"
while read -d'HOTSEP' -r match || [ -n "$match" ]; do
echo "match: ${match}"
if [[ -n "$match" ]]; then
code_line_of_match=$(head -n 1 <<< "$match")
comment_line_of_match=$(sed -n '2 p' <<< "$match")
echo "code_line_of_match: ${code_line_of_match}"
comment_line_of_match=$(sed -n '2 p' <<< "$match")
echo "comment_line_of_match: ${comment_line_of_match}"
comment_contents=$(hot_sed -E 's/^\s*"""(.*)\.""".*$/\1/' <<< "$comment_line_of_match")
echo "comment_contents: ${comment_contents}"
if grep -Eiq "^\s*(def|class) ${comment_contents}\(" <<< "$code_line_of_match"; then
# Remove line from file matching comment_line
hot_sed -i "/${comment_line_of_match}/d" "$file_name"
fi
fi
done <<< $matches
fi
# echo "grepping"
# matches=$(grep --group-separator=HOTSEP -B 1 -E '^\s*"""' "$file_name" || echo '')
# if [[ -n "$matches" ]]; then
# matches="${matches}\nHOTSEP"
# echo -e "$matches"
# while read -d'HOTSEP' -r match || [ -n "$match" ]; do
# echo "match: ${match}"
# if [[ -n "$match" ]]; then
# code_line_of_match=$(head -n 1 <<< "$match")
# echo "code_line_of_match: ${code_line_of_match}"
# comment_line_of_match=$(sed -n '2 p' <<< "$match")
# echo "comment_line_of_match: ${comment_line_of_match}"
# comment_contents=$(hot_sed -E 's/^\s*"""(.*)\.""".*$/\1/' <<< "$comment_line_of_match")
# echo "comment_contents: ${comment_contents}"
# if grep -Eiq "^class.*${comment_contents}\(Exception\)" <<< "$code_line_of_match"; then
# hot_sed -i "s/^(\s*)[^\s]*${comment_line_of_match}.*/\1pass/" "$file_name"
# fi
# # if grep -Eiq "^\s*(def|class) ${comment_contents}\(" <<< "$code_line_of_match"; then
# # # Remove line from file matching comment_line
# # hot_sed -i "/${comment_line_of_match}/d" "$file_name"
# # fi
# fi
# done <<< $matches
# fi
# matches=$(grep -E '\s*(def|class) ' "$file_name" || echo '')
# if [[ -n "$matches" ]]; then
# fi
sed -Ei 's/^(\s*)"""[A-Z]\w*Error\."""/\1pass/' "$file_name"
sed -Ei '/^\s*"""[A-Z]\w*\."""/d' "$file_name"
}
# Process each Python file in the "src" and "tests" directories
for file in $(find src tests -type f -name '*.py'); do
# Read the first line of the file
if grep -Eq '/logging_service' <<< "$file"; then
# if grep -Eq '/logging_service' <<< "$file"; then
echo "processing file that we hand picked for debugging: ${file}"
remove_useless_comments "$file"
fi
# fi
# this is already done
# if [ -s "$file" ]; then

View File

@ -33,10 +33,7 @@ from spiffworkflow_backend.services.background_processing_service import Backgro
class MyJSONEncoder(DefaultJSONProvider):
"""MyJSONEncoder."""
def default(self, obj: Any) -> Any:
"""Default."""
if hasattr(obj, "serialized"):
return obj.serialized
elif isinstance(obj, sqlalchemy.engine.row.Row): # type: ignore
@ -56,13 +53,11 @@ class MyJSONEncoder(DefaultJSONProvider):
return super().default(obj)
def dumps(self, obj: Any, **kwargs: Any) -> Any:
"""Dumps."""
kwargs.setdefault("default", self.default)
return super().dumps(obj, **kwargs)
def start_scheduler(app: flask.app.Flask, scheduler_class: BaseScheduler = BackgroundScheduler) -> None:
"""Start_scheduler."""
scheduler = scheduler_class()
# TODO: polling intervals for messages job
@ -120,7 +115,6 @@ class NoOpCipher:
def create_app() -> flask.app.Flask:
"""Create_app."""
faulthandler.enable()
# We need to create the sqlite database in a known location.
@ -207,7 +201,6 @@ def _setup_prometheus_metrics(app: flask.app.Flask, connexion_app: connexion.app
def get_hacked_up_app_for_script() -> flask.app.Flask:
"""Get_hacked_up_app_for_script."""
os.environ["SPIFFWORKFLOW_BACKEND_ENV"] = "local_development"
flask_env_key = "FLASK_SESSION_SECRET_KEY"
os.environ[flask_env_key] = "whatevs"
@ -245,13 +238,11 @@ def traces_sampler(sampling_context: Any) -> Any:
def configure_sentry(app: flask.app.Flask) -> None:
"""Configure_sentry."""
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
# get rid of NotFound errors
def before_send(event: Any, hint: Any) -> Any:
"""Before_send."""
if "exc_info" in hint:
_exc_type, exc_value, _tb = hint["exc_info"]
# NotFound is mostly from web crawlers

View File

@ -59,7 +59,6 @@ def setup_database_configs(app: Flask) -> None:
def load_config_file(app: Flask, env_config_module: str) -> None:
"""Load_config_file."""
try:
app.config.from_object(env_config_module)
print(f"loaded config: {env_config_module}")
@ -119,7 +118,6 @@ def _check_for_incompatible_frontend_and_backend_urls(app: Flask) -> None:
def setup_config(app: Flask) -> None:
"""Setup_config."""
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)

View File

@ -1,4 +1,3 @@
"""Development."""
from os import environ
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(

View File

@ -216,7 +216,6 @@ class ApiError(Exception):
def set_user_sentry_context() -> None:
"""Set_user_sentry_context."""
try:
username = g.user.username
except Exception:

View File

@ -1,5 +1,2 @@
"""Process_entity_not_found."""
class ProcessEntityNotFoundError(Exception):
"""ProcessEntityNotFoundError."""
pass

View File

@ -10,14 +10,10 @@ IdToProcessGroupMapping = NewType("IdToProcessGroupMapping", dict[str, "ProcessG
class ProcessGroupLite(TypedDict):
"""ProcessGroupLite."""
id: str
display_name: str
class ProcessGroupLitesWithCache(TypedDict):
"""ProcessGroupLitesWithCache."""
cache: dict[str, "ProcessGroup"]
process_groups: list[ProcessGroupLite]

View File

@ -1,4 +1,3 @@
"""Message_correlation."""
from dataclasses import dataclass
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel

View File

@ -15,8 +15,6 @@ migrate = Migrate()
class SpiffworkflowBaseDBModel(db.Model): # type: ignore
"""SpiffworkflowBaseDBModel."""
__abstract__ = True
@classmethod
@ -39,7 +37,6 @@ class SpiffworkflowBaseDBModel(db.Model): # type: ignore
return result
def validate_enum_field(self, key: str, value: Any, enum_variable: enum.EnumMeta) -> Any:
"""Validate_enum_field."""
try:
m_type = getattr(enum_variable, value, None)
except Exception as e:

View File

@ -10,8 +10,6 @@ from spiffworkflow_backend.models.spec_reference import SpecReference
class FileType(SpiffEnum):
"""FileType."""
bpmn = "bpmn"
csv = "csv"
dmn = "dmn"
@ -62,8 +60,6 @@ CONTENT_TYPES = {
@dataclass(order=True)
class File:
"""File."""
sort_index: str = field(init=False)
content_type: str
@ -89,7 +85,6 @@ class File:
last_modified: datetime,
file_size: int,
) -> File:
"""From_file_system."""
instance = cls(
name=file_name,
content_type=content_type,

View File

@ -21,8 +21,6 @@ if TYPE_CHECKING:
@dataclass
class HumanTaskModel(SpiffworkflowBaseDBModel):
"""HumanTaskModel."""
__tablename__ = "human_task"
id: int = db.Column(db.Integer, primary_key=True)
@ -65,7 +63,6 @@ class HumanTaskModel(SpiffworkflowBaseDBModel):
@classmethod
def to_task(cls, task: HumanTaskModel) -> Task:
"""To_task."""
can_complete = False
for user in task.human_task_users:
if user.user_id == g.user.id:

View File

@ -13,8 +13,6 @@ from spiffworkflow_backend.models.user import UserModel
@dataclass
class HumanTaskUserModel(SpiffworkflowBaseDBModel):
"""HumanTaskUserModel."""
__tablename__ = "human_task_user"
__table_args__ = (

View File

@ -23,15 +23,11 @@ if TYPE_CHECKING:
class MessageTypes(enum.Enum):
"""MessageTypes."""
send = "send"
receive = "receive"
class MessageStatuses(enum.Enum):
"""MessageStatuses."""
ready = "ready"
running = "running"
completed = "completed"
@ -67,12 +63,10 @@ class MessageInstanceModel(SpiffworkflowBaseDBModel):
@validates("message_type")
def validate_message_type(self, key: str, value: Any) -> Any:
"""Validate_message_type."""
return self.validate_enum_field(key, value, MessageTypes)
@validates("status")
def validate_status(self, key: str, value: Any) -> Any:
"""Validate_status."""
return self.validate_enum_field(key, value, MessageStatuses)
def correlates(self, other: Any, expression_engine: PythonScriptEngine) -> bool:
@ -151,7 +145,6 @@ class MessageInstanceModel(SpiffworkflowBaseDBModel):
def ensure_failure_cause_is_set_if_message_instance_failed(
session: Any, _flush_context: Any | None, _instances: Any | None
) -> None:
"""Ensure_failure_cause_is_set_if_message_instance_failed."""
for instance in session.new:
if isinstance(instance, MessageInstanceModel):
if instance.status == "failed" and instance.failure_cause is None:

View File

@ -1,4 +1,3 @@
"""Message_correlation."""
from dataclasses import dataclass
from sqlalchemy import ForeignKey

View File

@ -1,11 +1,8 @@
"""Message_correlation_property."""
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.db import db
class MessageTriggerableProcessModel(SpiffworkflowBaseDBModel):
"""MessageTriggerableProcessModel."""
__tablename__ = "message_triggerable_process_model"
id = db.Column(db.Integer, primary_key=True)

View File

@ -1,4 +1,3 @@
"""PermissionAssignment."""
import enum
from typing import Any
@ -12,16 +11,12 @@ from spiffworkflow_backend.models.principal import PrincipalModel
class PermitDeny(enum.Enum):
"""PermitDeny."""
# permit, aka grant
permit = "permit"
deny = "deny"
class Permission(enum.Enum):
"""Permission."""
# from original requirements
# instantiate = 1
# administer = 2
@ -34,8 +29,6 @@ class Permission(enum.Enum):
class PermissionAssignmentModel(SpiffworkflowBaseDBModel):
"""PermissionAssignmentModel."""
__tablename__ = "permission_assignment"
__table_args__ = (
db.UniqueConstraint(
@ -53,10 +46,8 @@ class PermissionAssignmentModel(SpiffworkflowBaseDBModel):
@validates("grant_type")
def validate_grant_type(self, key: str, value: str) -> Any:
"""Validate_grant_type."""
return self.validate_enum_field(key, value, PermitDeny)
@validates("permission")
def validate_permission(self, key: str, value: str) -> Any:
"""Validate_permission."""
return self.validate_enum_field(key, value, Permission)

View File

@ -1,4 +1,3 @@
"""PermissionTarget."""
import re
from dataclasses import dataclass
@ -9,13 +8,11 @@ from spiffworkflow_backend.models.db import db
class InvalidPermissionTargetUriError(Exception):
"""InvalidPermissionTargetUriError."""
pass
@dataclass
class PermissionTargetModel(SpiffworkflowBaseDBModel):
"""PermissionTargetModel."""
URI_ALL = "/%"
__tablename__ = "permission_target"
@ -32,7 +29,6 @@ class PermissionTargetModel(SpiffworkflowBaseDBModel):
@validates("uri")
def validate_uri(self, key: str, value: str) -> str:
"""Validate_uri."""
if re.search(r"%.", value):
raise InvalidPermissionTargetUriError(f"Wildcard must appear at end: {value}")
return value

View File

@ -11,17 +11,15 @@ from spiffworkflow_backend.models.user import UserModel
class DataValidityError(Exception):
"""DataValidityError."""
pass
class MissingPrincipalError(DataValidityError):
"""MissingPrincipalError."""
pass
@dataclass
class PrincipalModel(SpiffworkflowBaseDBModel):
"""PrincipalModel."""
__tablename__ = "principal"
__table_args__ = (CheckConstraint("NOT(user_id IS NULL AND group_id IS NULL)"),)

View File

@ -1,4 +1,3 @@
"""ProcessCaller_model."""
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.db import db

View File

@ -16,8 +16,6 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
@dataclass(order=True)
class ProcessGroup:
"""ProcessGroup."""
sort_index: str = field(init=False)
id: str # A unique string name, lower case, under scores (ie, 'my_group')
@ -43,22 +41,16 @@ class ProcessGroup:
@property
def serialized(self) -> dict:
"""Serialized."""
original_dict = dataclasses.asdict(self)
return {x: original_dict[x] for x in original_dict if x not in ["sort_index"]}
# for use with os.path.join, so it can work on windows
def id_for_file_path(self) -> str:
"""Id_for_file_path."""
return self.id.replace("/", os.sep)
class ProcessGroupSchema(Schema):
"""ProcessGroupSchema."""
class Meta:
"""Meta."""
model = ProcessGroup
fields = [
"id",
@ -79,5 +71,4 @@ class ProcessGroupSchema(Schema):
@post_load
def make_process_group(self, data: dict[str, str | bool | int], **kwargs: dict) -> ProcessGroup:
"""Make_process_group."""
return ProcessGroup(**data) # type: ignore

View File

@ -23,20 +23,18 @@ from spiffworkflow_backend.models.user import UserModel
class ProcessInstanceNotFoundError(Exception):
"""ProcessInstanceNotFoundError."""
pass
class ProcessInstanceTaskDataCannotBeUpdatedError(Exception):
"""ProcessInstanceTaskDataCannotBeUpdatedError."""
pass
class ProcessInstanceCannotBeDeletedError(Exception):
"""ProcessInstanceCannotBeDeletedError."""
pass
class ProcessInstanceStatus(SpiffEnum):
"""ProcessInstanceStatus."""
not_started = "not_started"
user_input_required = "user_input_required"
waiting = "waiting"
@ -47,8 +45,6 @@ class ProcessInstanceStatus(SpiffEnum):
class ProcessInstanceModel(SpiffworkflowBaseDBModel):
"""ProcessInstanceModel."""
__tablename__ = "process_instance"
__allow_unmapped__ = True
id: int = db.Column(db.Integer, primary_key=True)
@ -144,11 +140,9 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
@validates("status")
def validate_status(self, key: str, value: Any) -> Any:
"""Validate_status."""
return self.validate_enum_field(key, value, ProcessInstanceStatus)
def can_submit_task(self) -> bool:
"""Can_submit_task."""
return not self.has_terminal_status() and self.status != "suspended"
def can_receive_message(self) -> bool:
@ -156,7 +150,6 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
return not self.has_terminal_status() and self.status != "suspended"
def has_terminal_status(self) -> bool:
"""Has_terminal_status."""
return self.status in self.terminal_statuses()
@classmethod
@ -174,11 +167,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
class ProcessInstanceModelSchema(Schema):
"""ProcessInstanceModelSchema."""
class Meta:
"""Meta."""
model = ProcessInstanceModel
fields = [
"id",
@ -196,13 +185,10 @@ class ProcessInstanceModelSchema(Schema):
status = marshmallow.fields.Method("get_status", dump_only=True)
def get_status(self, obj: ProcessInstanceModel) -> str:
"""Get_status."""
return obj.status
class ProcessInstanceApi:
"""ProcessInstanceApi."""
def __init__(
self,
id: int,
@ -222,11 +208,7 @@ class ProcessInstanceApi:
class ProcessInstanceApiSchema(Schema):
"""ProcessInstanceApiSchema."""
class Meta:
"""Meta."""
model = ProcessInstanceApi
fields = [
"id",
@ -243,7 +225,6 @@ class ProcessInstanceApiSchema(Schema):
@marshmallow.post_load
def make_process_instance(self, data: dict[str, Any], **kwargs: dict) -> ProcessInstanceApi:
"""Make_process_instance."""
keys = [
"id",
"status",

View File

@ -9,8 +9,6 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
@dataclass
class ProcessInstanceQueueModel(SpiffworkflowBaseDBModel):
"""ProcessInstanceQueueModel."""
__tablename__ = "process_instance_queue"
id: int = db.Column(db.Integer, primary_key=True)

View File

@ -1,4 +1,3 @@
"""Process_instance."""
from __future__ import annotations
import sys
@ -48,20 +47,16 @@ class Report(TypedDict):
class ProcessInstanceReportAlreadyExistsError(Exception):
"""ProcessInstanceReportAlreadyExistsError."""
pass
class ProcessInstanceReportResult(TypedDict):
"""ProcessInstanceReportResult."""
report_metadata: ReportMetadata
results: list[dict]
# https://stackoverflow.com/a/56842689/6090676
class Reversor:
"""Reversor."""
def __init__(self, obj: Any):
"""__init__."""
self.obj = obj
@ -77,8 +72,6 @@ class Reversor:
@dataclass
class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
"""ProcessInstanceReportModel."""
__tablename__ = "process_instance_report"
__table_args__ = (
db.UniqueConstraint(
@ -105,7 +98,6 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
@classmethod
def default_order_by(cls) -> list[str]:
"""Default_order_by."""
return ["-start_in_seconds", "-id"]
@classmethod

View File

@ -15,16 +15,12 @@ from spiffworkflow_backend.models.file import File
class NotificationType(enum.Enum):
"""NotificationType."""
fault = "fault"
suspend = "suspend"
@dataclass(order=True)
class ProcessModelInfo:
"""ProcessModelInfo."""
sort_index: str = field(init=False)
id: str
@ -60,12 +56,10 @@ class ProcessModelInfo:
# this is because we have to store ids in the database, and we want the same
# database snapshot to work on any OS.
def id_for_file_path(self) -> str:
"""Id_for_file_path."""
return self.id.replace("/", os.sep)
@classmethod
def modify_process_identifier_for_path_param(cls, identifier: str) -> str:
"""Identifier."""
if "\\" in identifier:
raise Exception(f"Found backslash in identifier: {identifier}")
@ -73,11 +67,7 @@ class ProcessModelInfo:
class ProcessModelInfoSchema(Schema):
"""ProcessModelInfoSchema."""
class Meta:
"""Meta."""
model = ProcessModelInfo
id = marshmallow.fields.String(required=True)
@ -99,5 +89,4 @@ class ProcessModelInfoSchema(Schema):
@post_load
def make_spec(self, data: dict[str, str | bool | int | NotificationType], **_: Any) -> ProcessModelInfo:
"""Make_spec."""
return ProcessModelInfo(**data) # type: ignore

View File

@ -6,8 +6,6 @@ from spiffworkflow_backend.models.db import db
@dataclass
class ProcessModelCycleModel(SpiffworkflowBaseDBModel):
"""ProcessInstanceQueueModel."""
__tablename__ = "process_model_cycle"
id: int = db.Column(db.Integer, primary_key=True)

View File

@ -12,8 +12,6 @@ from spiffworkflow_backend.models.db import db
@dataclass()
class RefreshTokenModel(SpiffworkflowBaseDBModel):
"""RefreshTokenModel."""
__tablename__ = "refresh_token"
id: int = db.Column(db.Integer, primary_key=True)

View File

@ -11,8 +11,6 @@ from spiffworkflow_backend.models.user import UserModel
@dataclass()
class SecretModel(SpiffworkflowBaseDBModel):
"""SecretModel."""
__tablename__ = "secret"
id: int = db.Column(db.Integer, primary_key=True)
key: str = db.Column(db.String(50), unique=True, nullable=False)
@ -32,10 +30,6 @@ class SecretModel(SpiffworkflowBaseDBModel):
class SecretModelSchema(Schema):
"""SecretModelSchema."""
class Meta:
"""Meta."""
model = SecretModel
fields = ["key", "value", "user_id"]

View File

@ -1,4 +1,3 @@
"""Message_model."""
from dataclasses import dataclass
from flask_marshmallow import Schema # type: ignore
@ -10,7 +9,7 @@ from spiffworkflow_backend.models.db import db
class SpecReferenceNotFoundError(Exception):
"""SpecReferenceNotFoundError."""
pass
@dataclass()
@ -56,7 +55,6 @@ class SpecReferenceCache(SpiffworkflowBaseDBModel):
@classmethod
def from_spec_reference(cls, ref: SpecReference) -> "SpecReferenceCache":
"""From_spec_reference."""
return cls(
identifier=ref.identifier,
display_name=ref.display_name,
@ -71,11 +69,7 @@ class SpecReferenceCache(SpiffworkflowBaseDBModel):
class SpecReferenceSchema(Schema): # type: ignore
"""FileSchema."""
class Meta:
"""Meta."""
model = SpecReference
fields = [
"identifier",

View File

@ -25,8 +25,6 @@ class TaskNotFoundError(Exception):
class MultiInstanceType(enum.Enum):
"""MultiInstanceType."""
none = "none"
looping = "looping"
parallel = "parallel"
@ -93,8 +91,6 @@ class TaskModel(SpiffworkflowBaseDBModel):
class Task:
"""Task."""
HUMAN_TASK_TYPES = ["User Task", "Manual Task"]
def __init__(
@ -212,38 +208,22 @@ class Task:
class OptionSchema(Schema):
"""OptionSchema."""
class Meta:
"""Meta."""
fields = ["id", "name", "data"]
class ValidationSchema(Schema):
"""ValidationSchema."""
class Meta:
"""Meta."""
fields = ["name", "config"]
class FormFieldPropertySchema(Schema):
"""FormFieldPropertySchema."""
class Meta:
"""Meta."""
fields = ["id", "value"]
class FormFieldSchema(Schema):
"""FormFieldSchema."""
class Meta:
"""Meta."""
fields = [
"id",
"type",
@ -269,11 +249,7 @@ class FormFieldSchema(Schema):
class TaskSchema(Schema):
"""TaskSchema."""
class Meta:
"""Meta."""
fields = [
"id",
"name",
@ -304,5 +280,4 @@ class TaskSchema(Schema):
@marshmallow.post_load
def make_task(self, data: dict[str, Any], **kwargs: dict) -> Task:
"""Make_task."""
return Task(**data)

View File

@ -94,11 +94,7 @@ class UserModel(SpiffworkflowBaseDBModel):
class UserModelSchema(Schema):
"""UserModelSchema."""
class Meta:
"""Meta."""
model = UserModel
# load_instance = True
# include_relationships = False

View File

@ -1,4 +1,3 @@
"""UserGroupAssignment."""
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
@ -9,8 +8,6 @@ from spiffworkflow_backend.models.user import UserModel
class UserGroupAssignmentModel(SpiffworkflowBaseDBModel):
"""UserGroupAssignmentModel."""
__tablename__ = "user_group_assignment"
__table_args__ = (db.UniqueConstraint("user_id", "group_id", name="user_group_assignment_unique"),)

View File

@ -1,4 +1,3 @@
"""UserGroupAssignment."""
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
@ -24,7 +23,6 @@ class UserGroupAssignmentWaitingModel(SpiffworkflowBaseDBModel):
group = relationship("GroupModel", overlaps="groups,user_group_assignments_waiting,users") # type: ignore
def is_match_all(self) -> bool:
"""Is_match_all."""
if self.username == self.MATCH_ALL_USERS:
return True
return False

View File

@ -6,6 +6,5 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
def status() -> Response:
"""Status."""
ProcessInstanceModel.query.filter().first()
return make_response({"ok": True}, 200)

View File

@ -21,7 +21,6 @@ def message_instance_list(
page: int = 1,
per_page: int = 100,
) -> flask.wrappers.Response:
"""Message_instance_list."""
# to make sure the process instance exists
message_instances_query = MessageInstanceModel.query

View File

@ -122,7 +122,6 @@ def token() -> dict:
@openid_blueprint.route("/end_session", methods=["GET"])
def end_session() -> Response:
"""Logout."""
redirect_url = request.args.get("post_logout_redirect_uri", "http://localhost")
request.args.get("id_token_hint")
return redirect(redirect_url)
@ -130,7 +129,6 @@ def end_session() -> Response:
@openid_blueprint.route("/refresh", methods=["POST"])
def refresh() -> str:
"""Refresh."""
return ""

View File

@ -30,7 +30,6 @@ process_api_blueprint = Blueprint("process_api", __name__)
def permissions_check(body: dict[str, dict[str, list[str]]]) -> flask.wrappers.Response:
"""Permissions_check."""
if "requests_to_check" not in body:
raise (
ApiError(
@ -82,7 +81,6 @@ def _process_data_fetcher(
process_data_identifier: str,
download_file_data: bool,
) -> flask.wrappers.Response:
"""Process_data_show."""
if download_file_data:
file_data = ProcessInstanceFileDataModel.query.filter_by(
digest=process_data_identifier,
@ -128,7 +126,6 @@ def process_data_show(
process_data_identifier: str,
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_data_show."""
return _process_data_fetcher(
process_instance_id,
process_data_identifier,
@ -141,7 +138,6 @@ def process_data_file_download(
process_data_identifier: str,
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_data_file_download."""
return _process_data_fetcher(
process_instance_id,
process_data_identifier,
@ -155,7 +151,6 @@ def process_data_file_download(
# test with: ngrok http 7000
# where 7000 is the port the app is running on locally
def github_webhook_receive(body: dict) -> Response:
"""Github_webhook_receive."""
auth_header = request.headers.get("X-Hub-Signature-256")
AuthorizationService.verify_sha256_token(auth_header)
result = GitService.handle_web_hook(body)
@ -163,7 +158,6 @@ def github_webhook_receive(body: dict) -> Response:
def _get_required_parameter_or_raise(parameter: str, post_body: dict[str, Any]) -> Any:
"""Get_required_parameter_or_raise."""
return_value = None
if parameter in post_body:
return_value = post_body[parameter]
@ -181,7 +175,6 @@ def _get_required_parameter_or_raise(parameter: str, post_body: dict[str, Any])
def _commit_and_push_to_git(message: str) -> None:
"""Commit_and_push_to_git."""
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE"]:
git_output = GitService.commit(message=message)
current_app.logger.info(f"git output: {git_output}")
@ -190,14 +183,12 @@ def _commit_and_push_to_git(message: str) -> None:
def _un_modify_modified_process_model_id(modified_process_model_identifier: str) -> str:
"""Un_modify_modified_process_model_id."""
return modified_process_model_identifier.replace(":", "/")
def _find_process_instance_by_id_or_raise(
process_instance_id: int,
) -> ProcessInstanceModel:
"""Find_process_instance_by_id_or_raise."""
process_instance_query = ProcessInstanceModel.query.filter_by(id=process_instance_id)
# we had a frustrating session trying to do joins and access columns from two tables. here's some notes for our future selves:
@ -222,7 +213,6 @@ def _find_process_instance_by_id_or_raise(
# process_model_id uses forward slashes on all OSes
# this seems to return an object where process_model.id has backslashes on windows
def _get_process_model(process_model_id: str) -> ProcessModelInfo:
"""Get_process_model."""
process_model = None
try:
process_model = ProcessModelService.get_process_model(process_model_id)
@ -239,7 +229,6 @@ def _get_process_model(process_model_id: str) -> ProcessModelInfo:
def _find_principal_or_raise() -> PrincipalModel:
"""Find_principal_or_raise."""
principal = PrincipalModel.query.filter_by(user_id=g.user.id).first()
if principal is None:
raise (

View File

@ -19,7 +19,6 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelWit
def process_group_create(body: dict) -> flask.wrappers.Response:
"""Add_process_group."""
process_group = ProcessGroup(**body)
if ProcessModelService.is_process_model_identifier(process_group.id):
@ -42,7 +41,6 @@ def process_group_create(body: dict) -> flask.wrappers.Response:
def process_group_delete(modified_process_group_id: str) -> flask.wrappers.Response:
"""Process_group_delete."""
process_group_id = _un_modify_modified_process_model_id(modified_process_group_id)
try:
@ -101,7 +99,6 @@ def process_group_list(
def process_group_show(
modified_process_group_id: str,
) -> Any:
"""Process_group_show."""
process_group_id = _un_modify_modified_process_model_id(modified_process_group_id)
try:
process_group = ProcessModelService.get_process_group(process_group_id)
@ -119,7 +116,6 @@ def process_group_show(
def process_group_move(modified_process_group_identifier: str, new_location: str) -> flask.wrappers.Response:
"""Process_group_move."""
original_process_group_id = _un_modify_modified_process_model_id(modified_process_group_identifier)
new_process_group = ProcessModelService.process_group_move(original_process_group_id, new_location)
_commit_and_push_to_git(

View File

@ -58,7 +58,6 @@ from spiffworkflow_backend.services.task_service import TaskService
def process_instance_create(
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Create_process_instance."""
process_model_identifier = _un_modify_modified_process_model_id(modified_process_model_identifier)
process_model = _get_process_model(process_model_identifier)
@ -86,7 +85,6 @@ def process_instance_run(
modified_process_model_identifier: str,
process_instance_id: int,
) -> flask.wrappers.Response:
"""Process_instance_run."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
if process_instance.status != "not_started":
raise ApiError(
@ -140,7 +138,6 @@ def process_instance_terminate(
process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_instance_run."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
processor = ProcessInstanceProcessor(process_instance)
@ -161,7 +158,6 @@ def process_instance_suspend(
process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_instance_suspend."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
processor = ProcessInstanceProcessor(process_instance)
@ -182,7 +178,6 @@ def process_instance_resume(
process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_instance_resume."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
processor = ProcessInstanceProcessor(process_instance)
@ -297,7 +292,6 @@ def process_instance_show_for_me(
process_instance_id: int,
process_identifier: str | None = None,
) -> flask.wrappers.Response:
"""Process_instance_show_for_me."""
process_instance = _find_process_instance_for_me_or_raise(process_instance_id)
return _get_process_instance(
process_instance=process_instance,
@ -311,7 +305,6 @@ def process_instance_show(
process_instance_id: int,
process_identifier: str | None = None,
) -> flask.wrappers.Response:
"""Create_process_instance."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
return _get_process_instance(
process_instance=process_instance,
@ -323,7 +316,6 @@ def process_instance_show(
def process_instance_delete(
process_instance_id: int, modified_process_model_identifier: str
) -> flask.wrappers.Response:
"""Create_process_instance."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
if not process_instance.has_terminal_status():
@ -362,7 +354,6 @@ def process_instance_report_update(
report_id: int,
body: dict[str, Any],
) -> flask.wrappers.Response:
"""Process_instance_report_update."""
process_instance_report = ProcessInstanceReportModel.query.filter_by(
id=report_id,
created_by_id=g.user.id,
@ -383,7 +374,6 @@ def process_instance_report_update(
def process_instance_report_delete(
report_id: int,
) -> flask.wrappers.Response:
"""Process_instance_report_delete."""
process_instance_report = ProcessInstanceReportModel.query.filter_by(
id=report_id,
created_by_id=g.user.id,
@ -408,7 +398,6 @@ def process_instance_task_list_without_task_data_for_me(
bpmn_process_guid: str | None = None,
to_task_guid: str | None = None,
) -> flask.wrappers.Response:
"""Process_instance_task_list_without_task_data_for_me."""
process_instance = _find_process_instance_for_me_or_raise(process_instance_id)
return process_instance_task_list(
_modified_process_model_identifier=modified_process_model_identifier,
@ -426,7 +415,6 @@ def process_instance_task_list_without_task_data(
bpmn_process_guid: str | None = None,
to_task_guid: str | None = None,
) -> flask.wrappers.Response:
"""Process_instance_task_list_without_task_data."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
return process_instance_task_list(
_modified_process_model_identifier=modified_process_model_identifier,
@ -444,7 +432,6 @@ def process_instance_task_list(
to_task_guid: str | None = None,
most_recent_tasks_only: bool = False,
) -> flask.wrappers.Response:
"""Process_instance_task_list."""
bpmn_process_ids = []
if bpmn_process_guid:
bpmn_process = BpmnProcessModel.query.filter_by(guid=bpmn_process_guid).first()
@ -592,7 +579,6 @@ def process_instance_reset(
def process_instance_find_by_id(
process_instance_id: int,
) -> flask.wrappers.Response:
"""Process_instance_find_by_id."""
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
modified_process_model_identifier = ProcessModelInfo.modify_process_identifier_for_path_param(
process_instance.process_model_identifier

View File

@ -39,7 +39,6 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
def process_model_create(
modified_process_group_id: str, body: dict[str, str | bool | int | None | list]
) -> flask.wrappers.Response:
"""Process_model_create."""
body_include_list = [
"id",
"display_name",
@ -88,7 +87,6 @@ def process_model_create(
def process_model_delete(
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_model_delete."""
process_model_identifier = modified_process_model_identifier.replace(":", "/")
try:
ProcessModelService.process_model_delete(process_model_identifier)
@ -107,7 +105,6 @@ def process_model_update(
modified_process_model_identifier: str,
body: dict[str, str | bool | int | None | list],
) -> Any:
"""Process_model_update."""
process_model_identifier = modified_process_model_identifier.replace(":", "/")
body_include_list = [
"display_name",
@ -143,7 +140,6 @@ def process_model_update(
def process_model_show(modified_process_model_identifier: str, include_file_references: bool = False) -> Any:
"""Process_model_show."""
process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = _get_process_model(process_model_identifier)
files = sorted(
@ -167,7 +163,6 @@ def process_model_show(modified_process_model_identifier: str, include_file_refe
def process_model_move(modified_process_model_identifier: str, new_location: str) -> flask.wrappers.Response:
"""Process_model_move."""
original_process_model_id = _un_modify_modified_process_model_id(modified_process_model_identifier)
new_process_model = ProcessModelService.process_model_move(original_process_model_id, new_location)
_commit_and_push_to_git(
@ -179,7 +174,6 @@ def process_model_move(modified_process_model_identifier: str, new_location: str
def process_model_publish(
modified_process_model_identifier: str, branch_to_update: str | None = None
) -> flask.wrappers.Response:
"""Process_model_publish."""
if branch_to_update is None:
branch_to_update = current_app.config["SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_TARGET_BRANCH"]
if branch_to_update is None:
@ -241,7 +235,6 @@ def process_model_file_update(
def process_model_file_delete(modified_process_model_identifier: str, file_name: str) -> flask.wrappers.Response:
"""Process_model_file_delete."""
process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = _get_process_model(process_model_identifier)
@ -276,7 +269,6 @@ def process_model_file_delete(modified_process_model_identifier: str, file_name:
def process_model_file_create(
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Process_model_file_create."""
message = f"User: {g.user.username} added process model file"
return _create_or_update_process_model_file(modified_process_model_identifier, message, 201)
@ -331,7 +323,6 @@ def process_model_test_run(
def process_model_create_with_natural_language(
modified_process_group_id: str, body: dict[str, str]
) -> flask.wrappers.Response:
"""Process_model_create_with_natural_language."""
pattern = re.compile(
r"Create a (?P<pm_name>.*?) process model with a (?P<form_name>.*?) form that" r" collects (?P<columns>.*)"
)
@ -448,7 +439,6 @@ def process_model_create_with_natural_language(
def _get_file_from_request() -> FileStorage:
"""Get_file_from_request."""
request_file: FileStorage | None = connexion.request.files.get("file")
if not request_file:
raise ApiError(

View File

@ -21,7 +21,6 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
def script_unit_test_create(
modified_process_model_identifier: str, body: dict[str, str | bool | int]
) -> flask.wrappers.Response:
"""Script_unit_test_create."""
bpmn_task_identifier = _get_required_parameter_or_raise("bpmn_task_identifier", body)
input_json = _get_required_parameter_or_raise("input_json", body)
expected_output_json = _get_required_parameter_or_raise("expected_output_json", body)
@ -95,7 +94,6 @@ def script_unit_test_create(
def script_unit_test_run(
modified_process_model_identifier: str, body: dict[str, str | bool | int]
) -> flask.wrappers.Response:
"""Script_unit_test_run."""
# FIXME: We should probably clear this somewhere else but this works
current_app.config["THREAD_LOCAL_DATA"].process_instance_id = None

View File

@ -14,7 +14,6 @@ from spiffworkflow_backend.services.user_service import UserService
def secret_show(key: str) -> Response:
"""Secret_show."""
secret = SecretService.get_secret(key)
# normal serialization does not include the secret value, but this is the one endpoint where we want to return the goods
@ -28,7 +27,6 @@ def secret_list(
page: int = 1,
per_page: int = 100,
) -> Response:
"""Secret_list."""
secrets = (
SecretModel.query.order_by(SecretModel.key)
.join(UserModel)

View File

@ -15,13 +15,11 @@ from spiffworkflow_backend.services.service_task_service import ServiceTaskServi
def service_task_list() -> flask.wrappers.Response:
"""Service_task_list."""
available_connectors = ServiceTaskService.available_connectors()
return Response(json.dumps(available_connectors), status=200, mimetype="application/json")
def authentication_list() -> flask.wrappers.Response:
"""Authentication_list."""
available_authentications = ServiceTaskService.authentication_list()
response_json = {
"results": available_authentications,
@ -36,7 +34,6 @@ def authentication_callback(
service: str,
auth_method: str,
) -> werkzeug.wrappers.Response:
"""Authentication_callback."""
verify_token(request.args.get("token"), force_run=True)
response = request.args["response"]
SecretService.update_secret(f"{service}/{auth_method}", response, g.user.id, create_if_not_exists=True)

View File

@ -61,15 +61,11 @@ from spiffworkflow_backend.services.task_service import TaskService
class TaskDataSelectOption(TypedDict):
"""TaskDataSelectOption."""
value: str
label: str
class ReactJsonSchemaSelectOption(TypedDict):
"""ReactJsonSchemaSelectOption."""
type: str
title: str
enum: list[str]
@ -78,7 +74,6 @@ class ReactJsonSchemaSelectOption(TypedDict):
def task_list_my_tasks(
process_instance_id: int | None = None, page: int = 1, per_page: int = 100
) -> flask.wrappers.Response:
"""Task_list_my_tasks."""
principal = _find_principal_or_raise()
assigned_user = aliased(UserModel)
process_initiator_user = aliased(UserModel)
@ -142,12 +137,10 @@ def task_list_my_tasks(
def task_list_for_my_open_processes(page: int = 1, per_page: int = 100) -> flask.wrappers.Response:
"""Task_list_for_my_open_processes."""
return _get_tasks(page=page, per_page=per_page)
def task_list_for_me(page: int = 1, per_page: int = 100) -> flask.wrappers.Response:
"""Task_list_for_me."""
return _get_tasks(
processes_started_by_user=False,
has_lane_assignment_id=False,
@ -159,7 +152,6 @@ def task_list_for_me(page: int = 1, per_page: int = 100) -> flask.wrappers.Respo
def task_list_for_my_groups(
user_group_identifier: str | None = None, page: int = 1, per_page: int = 100
) -> flask.wrappers.Response:
"""Task_list_for_my_groups."""
return _get_tasks(
user_group_identifier=user_group_identifier,
processes_started_by_user=False,
@ -575,7 +567,6 @@ def task_submit(
body: dict[str, Any],
save_as_draft: bool = False,
) -> flask.wrappers.Response:
"""Task_submit_user_data."""
with sentry_sdk.start_span(op="controller_action", description="tasks_controller.task_submit"):
return _task_submit_shared(process_instance_id, task_guid, body, save_as_draft)
@ -587,7 +578,6 @@ def _get_tasks(
per_page: int = 100,
user_group_identifier: str | None = None,
) -> flask.wrappers.Response:
"""Get_tasks."""
user_id = g.user.id
# use distinct to ensure we only get one row per human task otherwise
@ -680,7 +670,6 @@ def _get_tasks(
def _prepare_form_data(form_file: str, task_model: TaskModel, process_model: ProcessModelInfo) -> dict:
"""Prepare_form_data."""
if task_model.data is None:
return {}
@ -707,7 +696,6 @@ def _prepare_form_data(form_file: str, task_model: TaskModel, process_model: Pro
def _render_jinja_template(unprocessed_template: str, task_model: TaskModel) -> str:
"""Render_jinja_template."""
jinja_environment = jinja2.Environment(autoescape=True, lstrip_blocks=True, trim_blocks=True)
try:
template = jinja_environment.from_string(unprocessed_template)
@ -736,7 +724,6 @@ def _get_spiff_task_from_process_instance(
process_instance: ProcessInstanceModel,
processor: ProcessInstanceProcessor | None = None,
) -> SpiffTask:
"""Get_spiff_task_from_process_instance."""
if processor is None:
processor = ProcessInstanceProcessor(process_instance)
task_uuid = uuid.UUID(task_guid)
@ -755,7 +742,6 @@ def _get_spiff_task_from_process_instance(
# originally from: https://bitcoden.com/answers/python-nested-dictionary-update-value-where-any-nested-key-matches
def _update_form_schema_with_task_data_as_needed(in_dict: dict, task_model: TaskModel) -> None:
"""Update_nested."""
if task_model.data is None:
return None
@ -787,7 +773,6 @@ def _update_form_schema_with_task_data_as_needed(in_dict: dict, task_model: Task
def map_function(
task_data_select_option: TaskDataSelectOption,
) -> ReactJsonSchemaSelectOption:
"""Map_function."""
return {
"type": "string",
"enum": [task_data_select_option["value"]],

View File

@ -296,7 +296,6 @@ def login_with_access_token(access_token: str) -> Response:
def login_api() -> Response:
"""Login_api."""
redirect_url = "/v1.0/login_api_return"
state = AuthenticationService.generate_state(redirect_url)
login_redirect_url = AuthenticationService().get_login_redirect_url(state.decode("UTF-8"), redirect_url)
@ -316,7 +315,6 @@ def login_api_return(code: str, state: str, session_state: str) -> str:
def logout(id_token: str, redirect_url: str | None) -> Response:
"""Logout."""
if redirect_url is None:
redirect_url = ""
tld = current_app.config["THREAD_LOCAL_DATA"]
@ -325,13 +323,11 @@ def logout(id_token: str, redirect_url: str | None) -> Response:
def logout_return() -> Response:
"""Logout_return."""
frontend_url = str(current_app.config["SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND"])
return redirect(f"{frontend_url}/")
def get_decoded_token(token: str) -> dict | None:
"""Get_token_type."""
try:
decoded_token = jwt.decode(token, options={"verify_signature": False})
except Exception as e:
@ -348,7 +344,6 @@ def get_decoded_token(token: str) -> dict | None:
def get_scope(token: str) -> str:
"""Get_scope."""
scope = ""
decoded_token = jwt.decode(token, options={"verify_signature": False})
if "scope" in decoded_token:
@ -357,7 +352,6 @@ def get_scope(token: str) -> str:
def get_user_from_decoded_internal_token(decoded_token: dict) -> UserModel | None:
"""Get_user_from_decoded_internal_token."""
sub = decoded_token["sub"]
parts = sub.split("::")
service = parts[0].split(":")[1]

View File

@ -1,4 +1,3 @@
"""Main."""
import json
from typing import Any
from typing import Final
@ -64,7 +63,6 @@ user_blueprint = Blueprint("main", __name__)
#
@user_blueprint.route("/user/<username>", methods=["DELETE"])
def delete_user(username: str) -> flask.wrappers.Response:
"""Delete_user."""
user = UserModel.query.filter_by(username=username).first()
if user is None:
raise (
@ -83,7 +81,6 @@ def delete_user(username: str) -> flask.wrappers.Response:
@user_blueprint.route("/group/<group_name>", methods=["GET"])
def create_group(group_name: str) -> flask.wrappers.Response:
"""Create_group."""
group = GroupModel.query.filter_by(name=group_name).first()
if group is not None:
raise (
@ -106,7 +103,6 @@ def create_group(group_name: str) -> flask.wrappers.Response:
@user_blueprint.route("/group/<group_name>", methods=["DELETE"])
def delete_group(group_name: str) -> flask.wrappers.Response:
"""Delete_group."""
group = GroupModel.query.filter_by(name=group_name).first()
if group is None:
raise (
@ -125,7 +121,6 @@ def delete_group(group_name: str) -> flask.wrappers.Response:
@user_blueprint.route("/assign_user_to_group", methods=["POST"])
def assign_user_to_group() -> flask.wrappers.Response:
"""Assign_user_to_group."""
user = get_user_from_request()
group = get_group_from_request()
@ -152,7 +147,6 @@ def assign_user_to_group() -> flask.wrappers.Response:
@user_blueprint.route("/remove_user_from_group", methods=["POST"])
def remove_user_from_group() -> flask.wrappers.Response:
"""Remove_user_from_group."""
user = get_user_from_request()
group = get_group_from_request()
@ -177,14 +171,12 @@ def remove_user_from_group() -> flask.wrappers.Response:
def get_value_from_request_json(key: str) -> Any:
"""Get_value_from_request_json."""
if request.json is None:
return None
return request.json.get(key)
def get_user_from_request() -> Any:
"""Get_user_from_request."""
user_id = get_value_from_request_json("user_id")
if user_id is None:
@ -209,7 +201,6 @@ def get_user_from_request() -> Any:
def get_group_from_request() -> Any:
"""Get_group_from_request."""
group_id = get_value_from_request_json("group_id")
if group_id is None:

View File

@ -23,7 +23,6 @@ def user_exists_by_username(body: dict[str, Any]) -> flask.wrappers.Response:
def user_search(username_prefix: str) -> flask.wrappers.Response:
"""User_search."""
found_users = UserModel.query.filter(UserModel.username.like(f"{username_prefix}%")).all() # type: ignore
response_json = {
@ -34,7 +33,6 @@ def user_search(username_prefix: str) -> flask.wrappers.Response:
def user_group_list_for_current_user() -> flask.wrappers.Response:
"""User_group_list_for_current_user."""
groups = g.user.groups
# TODO: filter out the default group and have a way to know what is the default group
group_identifiers = [

View File

@ -9,10 +9,7 @@ from sqlalchemy import or_
class DeleteProcessInstancesWithCriteria(Script):
"""DeleteProcessInstancesWithCriteria."""
def get_description(self) -> str:
"""Get_description."""
return "Delete process instances that match the provided criteria,"
def run(
@ -21,7 +18,6 @@ class DeleteProcessInstancesWithCriteria(Script):
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
criteria_list = args[0]
delete_criteria = []

View File

@ -5,20 +5,16 @@ from spiffworkflow_backend.scripts.script import Script
class FactService(Script):
"""FactService."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Just your basic class that can pull in data from a few api endpoints and
do a basic task."""
def run(self, script_attributes_context: ScriptAttributesContext, *args: Any, **kwargs: Any) -> Any:
"""Run."""
if "type" not in kwargs:
raise Exception("Please specify a 'type' of fact as a keyword argument.")
else:

View File

@ -1,4 +1,3 @@
"""Get_env."""
from collections import OrderedDict
from typing import Any
@ -11,10 +10,7 @@ from spiffworkflow_backend.scripts.script import Script
class GetAllPermissions(Script):
"""GetAllPermissions."""
def get_description(self) -> str:
"""Get_description."""
return """Get all permissions currently in the system."""
def run(
@ -23,7 +19,6 @@ class GetAllPermissions(Script):
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
permission_assignments = (
PermissionAssignmentModel.query.join(
PrincipalModel,
@ -46,14 +41,12 @@ class GetAllPermissions(Script):
permissions.setdefault((pa.group_identifier, pa.uri), []).append(pa.permission)
def replace_suffix(string: str, old: str, new: str) -> str:
"""Replace_suffix."""
if string.endswith(old):
return string[: -len(old)] + new
return string
# sort list of strings based on a specific order
def sort_by_order(string_list: list, order: list) -> list:
"""Sort_by_order."""
return sorted(string_list, key=lambda x: order.index(x))
return [

View File

@ -14,11 +14,9 @@ class GetCurrentUser(Script):
return False
def get_description(self) -> str:
"""Get_description."""
return """Return the current user."""
def run(self, script_attributes_context: ScriptAttributesContext, *_args: Any, **kwargs: Any) -> Any:
"""Run."""
# dump the user using our json encoder and then load it back up as a dict
# to remove unwanted field types
user_as_json_string = current_app.json.dumps(g.user)

View File

@ -10,20 +10,16 @@ class TaskNotGivenToScriptError(Exception):
class GetDataSizes(Script):
"""GetDataSizes."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Returns a dictionary of information about the size of task data and
the python environment for the currently running process."""
def run(self, script_attributes_context: ScriptAttributesContext, *_args: Any, **kwargs: Any) -> Any:
"""Run."""
if script_attributes_context.task is None:
raise TaskNotGivenToScriptError(
"The task was not given to script 'get_data_sizes'. "

View File

@ -7,15 +7,12 @@ from spiffworkflow_backend.scripts.script import Script
class GetEncodedFileData(Script):
"""GetEncodedFileData."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Returns a string which is the encoded file data. This is a very expensive call."""
def run(
@ -24,7 +21,6 @@ class GetEncodedFileData(Script):
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
# example input:
# "data:some/mimetype;name=testing.txt;base64,spifffiledatadigest+7a2051ffefd1eaf475dbef9fda019cb3d4a10eb8aea4c2c2a84a50a797a541bf" # noqa: B950,E501
digest_reference = args[0]

View File

@ -5,17 +5,13 @@ from spiffworkflow_backend.scripts.script import Script
class GetEnv(Script):
"""GetEnv."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Returns the current environment - ie testing, staging, production."""
def run(self, script_attributes_context: ScriptAttributesContext, *_args: Any, **kwargs: Any) -> Any:
"""Run."""
return script_attributes_context.environment_identifier

View File

@ -1,4 +1,3 @@
"""Get_env."""
from typing import Any
from flask import current_app
@ -7,17 +6,13 @@ from spiffworkflow_backend.scripts.script import Script
class GetFrontendUrl(Script):
"""GetFrontendUrl."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Return the url to the frontend."""
def run(self, script_attributes_context: ScriptAttributesContext, *args: Any, **kwargs: Any) -> Any:
"""Run."""
return current_app.config["SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND"]

View File

@ -1,4 +1,3 @@
"""Get_env."""
from typing import Any
from spiffworkflow_backend.models.group import GroupModel
@ -8,15 +7,12 @@ from spiffworkflow_backend.scripts.script import Script
class GetGroupMembers(Script):
"""GetGroupMembers."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Return the list of usernames of the users in the given group."""
def run(
@ -25,7 +21,6 @@ class GetGroupMembers(Script):
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
group_identifier = args[0]
group = GroupModel.query.filter_by(identifier=group_identifier).first()
if group is None:

View File

@ -22,7 +22,6 @@ class GetLastUserCompletingTask(Script):
*_args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
# dump the user using our json encoder and then load it back up as a dict
# to remove unwanted field types
if len(_args) == 2:

View File

@ -8,20 +8,16 @@ from spiffworkflow_backend.scripts.script import Script
class GetLocaltime(Script):
"""GetLocaltime."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Converts a Datetime object into a Datetime object for a specific timezone.
Defaults to US/Eastern."""
def run(self, script_attributes_context: ScriptAttributesContext, *args: Any, **kwargs: Any) -> datetime:
"""Run."""
if len(args) > 0 or "datetime" in kwargs:
if "datetime" in kwargs:
date_time = kwargs["datetime"]

View File

@ -22,7 +22,6 @@ class GetProcessInitiatorUser(Script):
*_args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
process_instance = (
ProcessInstanceModel.query.filter_by(id=script_attributes_context.process_instance_id)
.join(UserModel, UserModel.id == ProcessInstanceModel.process_initiator_id)

View File

@ -6,12 +6,8 @@ from spiffworkflow_backend.services.secret_service import SecretService
class GetSecret(Script):
"""GetSecret."""
def get_description(self) -> str:
"""Get_description."""
return """Returns the value for a previously configured secret."""
def run(self, script_attributes_context: ScriptAttributesContext, *args: Any, **kwargs: Any) -> Any:
"""Run."""
return SecretService.get_secret(args[0]).value

View File

@ -1,4 +1,3 @@
"""Get_process_info."""
from typing import Any
from spiffworkflow_backend.models.script_attributes_context import ScriptAttributesContext
@ -6,19 +5,15 @@ from spiffworkflow_backend.scripts.script import Script
class GetToplevelProcessInfo(Script):
"""GetProcessInfo."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Returns a dictionary of information about the currently running process."""
def run(self, script_attributes_context: ScriptAttributesContext, *_args: Any, **kwargs: Any) -> Any:
"""Run."""
return {
"process_instance_id": script_attributes_context.process_instance_id,
"process_model_identifier": script_attributes_context.process_model_identifier,

View File

@ -7,15 +7,12 @@ from spiffworkflow_backend.scripts.script import Script
class GetMarkdownFileDownloadLink(Script):
"""GetMarkdownFileDownloadLink."""
@staticmethod
def requires_privileged_permissions() -> bool:
"""We have deemed this function safe to run without elevated permissions."""
return False
def get_description(self) -> str:
"""Get_description."""
return """Returns a string which is a string in markdown format."""
def run(
@ -24,7 +21,6 @@ class GetMarkdownFileDownloadLink(Script):
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
# example input:
# "data:some/mimetype;name=testing.txt;base64,spifffiledatadigest+7a2051ffefd1eaf475dbef9fda019cb3d4a10eb8aea4c2c2a84a50a797a541bf" # noqa: B950,E501
digest_reference = args[0]

View File

@ -1,4 +1,3 @@
"""Get_env."""
from typing import Any
from spiffworkflow_backend.models.script_attributes_context import ScriptAttributesContext
@ -7,10 +6,7 @@ from spiffworkflow_backend.services.authorization_service import AuthorizationSe
class RefreshPermissions(Script):
"""RefreshPermissions."""
def get_description(self) -> str:
"""Get_description."""
return """Add permissions using a dict.
group_info: [
{

View File

@ -20,7 +20,7 @@ SCRIPT_SUB_CLASSES = None
class ScriptUnauthorizedForUserError(Exception):
"""ScriptUnauthorizedForUserError."""
pass
class ProcessInstanceIdMissingError(Exception):
@ -36,7 +36,6 @@ class Script:
@abstractmethod
def get_description(self) -> str:
"""Get_description."""
raise ApiError("invalid_script", "This script does not supply a description.")
@abstractmethod
@ -46,7 +45,6 @@ class Script:
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
raise ApiError(
"invalid_script",
"This is an internal error. The script you are trying to execute '%s' " % self.__class__.__name__
@ -108,7 +106,6 @@ class Script:
instance = subclass()
def check_script_permission() -> None:
"""Check_script_permission."""
if subclass.requires_privileged_permissions():
script_function_name = get_script_function_name(subclass)
uri = f"/can-run-privileged-script/{script_function_name}"
@ -132,7 +129,6 @@ class Script:
)
def run_script_if_allowed(*ar: Any, **kw: Any) -> Any:
"""Run_script_if_allowed."""
check_script_permission()
return subclass.run(
instance,
@ -144,7 +140,6 @@ class Script:
return run_script_if_allowed
def get_script_function_name(subclass: type[Script]) -> str:
"""Get_script_function_name."""
return subclass.__module__.split(".")[-1]
execlist = {}
@ -158,7 +153,6 @@ class Script:
@classmethod
def get_all_subclasses(cls) -> list[type[Script]]:
"""Get_all_subclasses."""
# This is expensive to generate, never changes after we load up.
global SCRIPT_SUB_CLASSES # noqa: PLW0603, allow global for performance
if not SCRIPT_SUB_CLASSES:

View File

@ -10,7 +10,6 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]:
"""Load_fixtures."""
current_app.logger.debug("load_acceptance_test_fixtures() start")
test_process_model_id = "misc/acceptance-tests-group-one/acceptance-tests-model-1"
user = BaseTest.find_or_create_user()

View File

@ -54,8 +54,6 @@ class AuthenticationProviderTypes(enum.Enum):
class AuthenticationService:
"""AuthenticationService."""
ENDPOINT_CACHE: dict = {} # We only need to find the openid endpoints once, then we can cache them.
@staticmethod
@ -89,11 +87,9 @@ class AuthenticationService:
@staticmethod
def get_backend_url() -> str:
"""Get_backend_url."""
return str(current_app.config["SPIFFWORKFLOW_BACKEND_URL"])
def logout(self, id_token: str, redirect_url: str | None = None) -> Response:
"""Logout."""
if redirect_url is None:
redirect_url = f"{self.get_backend_url()}/v1.0/logout_return"
request_url = (
@ -106,12 +102,10 @@ class AuthenticationService:
@staticmethod
def generate_state(redirect_url: str) -> bytes:
"""Generate_state."""
state = base64.b64encode(bytes(str({"redirect_url": redirect_url}), "UTF-8"))
return state
def get_login_redirect_url(self, state: str, redirect_url: str = "/v1.0/login_return") -> str:
"""Get_login_redirect_url."""
return_redirect_url = f"{self.get_backend_url()}{redirect_url}"
login_redirect_url = (
self.open_id_endpoint_for_name("authorization_endpoint")
@ -124,7 +118,6 @@ class AuthenticationService:
return login_redirect_url
def get_auth_token_object(self, code: str, redirect_url: str = "/v1.0/login_return") -> dict:
"""Get_auth_token_object."""
backend_basic_auth_string = f"{self.client_id()}:{self.secret_key()}"
backend_basic_auth_bytes = bytes(backend_basic_auth_string, encoding="ascii")
backend_basic_auth = base64.b64encode(backend_basic_auth_bytes)
@ -200,7 +193,6 @@ class AuthenticationService:
@staticmethod
def store_refresh_token(user_id: int, refresh_token: str) -> None:
"""Store_refresh_token."""
refresh_token_model = RefreshTokenModel.query.filter(RefreshTokenModel.user_id == user_id).first()
if refresh_token_model:
refresh_token_model.token = refresh_token
@ -217,7 +209,6 @@ class AuthenticationService:
@staticmethod
def get_refresh_token(user_id: int) -> str | None:
"""Get_refresh_token."""
refresh_token_object: RefreshTokenModel = RefreshTokenModel.query.filter(
RefreshTokenModel.user_id == user_id
).first()

View File

@ -5,11 +5,8 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
class DataSetupService:
"""DataSetupService."""
@classmethod
def run_setup(cls) -> list:
"""Run_setup."""
return cls.save_all_process_models()
@classmethod

View File

@ -13,11 +13,11 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
class FileSystemService:
"""FileSystemService."""
""" Simple Service meant for extension that provides some useful
"""Simple Service meant for extension that provides some useful
methods for dealing with the File system.
"""
PROCESS_GROUP_JSON_FILE = "process_group.json"
PROCESS_MODEL_JSON_FILE = "process_model.json"
@ -25,7 +25,6 @@ class FileSystemService:
@staticmethod
@contextmanager
def cd(newdir: str) -> Generator:
"""Cd."""
prevdir = os.getcwd()
os.chdir(os.path.expanduser(newdir))
try:
@ -35,14 +34,12 @@ class FileSystemService:
@staticmethod
def root_path() -> str:
"""Root_path."""
dir_name = current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
# ensure this is a string - thanks mypy...
return os.path.abspath(os.path.join(dir_name, ""))
@staticmethod
def id_string_to_relative_path(id_string: str) -> str:
"""Id_string_to_relative_path."""
return id_string.replace("/", os.sep)
@classmethod
@ -56,7 +53,6 @@ class FileSystemService:
@staticmethod
def full_path_from_relative_path(relative_path: str) -> str:
"""Full_path_from_relative_path."""
return os.path.join(FileSystemService.root_path(), relative_path)
@staticmethod
@ -81,13 +77,11 @@ class FileSystemService:
@staticmethod
def full_path_to_process_model_file(process_model: ProcessModelInfo) -> str:
"""Full_path_to_process_model_file."""
return os.path.join(
FileSystemService.process_model_full_path(process_model), process_model.primary_file_name # type: ignore
)
def next_display_order(self, process_model: ProcessModelInfo) -> int:
"""Next_display_order."""
path = self.process_group_path_for_spec(process_model)
if os.path.exists(path):
return len(next(os.walk(path))[1])
@ -96,20 +90,17 @@ class FileSystemService:
@staticmethod
def write_file_data_to_system(file_path: str, file_data: bytes) -> None:
"""Write_file_data_to_system."""
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "wb") as f_handle:
f_handle.write(file_data)
@staticmethod
def get_extension(file_name: str) -> str:
"""Get_extension."""
_, file_extension = os.path.splitext(file_name)
return file_extension.lower().strip()[1:]
@staticmethod
def assert_valid_file_name(file_name: str) -> None:
"""Assert_valid_file_name."""
file_extension = FileSystemService.get_extension(file_name)
if file_extension not in FileType.list():
raise ApiError(
@ -134,7 +125,6 @@ class FileSystemService:
@staticmethod
def file_type(file_name: str) -> FileType:
"""File_type."""
extension = FileSystemService.get_extension(file_name)
return FileType[extension]
@ -157,7 +147,6 @@ class FileSystemService:
@staticmethod
def to_file_object(file_name: str, file_path: str) -> File:
"""To_file_object."""
file_type = FileSystemService.file_type(file_name)
content_type = CONTENT_TYPES[file_type.name]
last_modified = FileSystemService._last_modified(file_path)
@ -167,7 +156,6 @@ class FileSystemService:
@staticmethod
def to_file_object_from_dir_entry(item: os.DirEntry) -> File:
"""To_file_object_from_dir_entry."""
extension = FileSystemService.get_extension(item.name)
try:
file_type = FileType[extension]

View File

@ -12,28 +12,25 @@ from spiffworkflow_backend.services.file_system_service import FileSystemService
class MissingGitConfigsError(Exception):
"""MissingGitConfigsError."""
pass
class InvalidGitWebhookBodyError(Exception):
"""InvalidGitWebhookBodyError."""
pass
class GitCloneUrlMismatchError(Exception):
"""GitCloneUrlMismatchError."""
pass
class GitCommandError(Exception):
"""GitCommandError."""
pass
# TOOD: check for the existence of git and configs on bootup if publishing is enabled
class GitService:
"""GitService."""
@classmethod
def get_current_revision(cls) -> str:
"""Get_current_revision."""
bpmn_spec_absolute_dir = current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
# The value includes a carriage return character at the end, so we don't grab the last character
with FileSystemService.cd(bpmn_spec_absolute_dir):
@ -46,7 +43,6 @@ class GitService:
revision: str,
file_name: str | None = None,
) -> str:
"""Get_instance_file_contents_for_revision."""
bpmn_spec_absolute_dir = current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
process_model_relative_path = FileSystemService.process_model_relative_path(process_model)
file_name_to_use = file_name
@ -67,7 +63,6 @@ class GitService:
repo_path: str | None = None,
branch_name: str | None = None,
) -> str:
"""Commit."""
cls.check_for_basic_configs()
branch_name_to_use = branch_name
if branch_name_to_use is None:
@ -89,7 +84,6 @@ class GitService:
@classmethod
def check_for_basic_configs(cls) -> None:
"""Check_for_basic_configs."""
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_SOURCE_BRANCH"] is None:
raise MissingGitConfigsError(
"Missing config for SPIFFWORKFLOW_BACKEND_GIT_SOURCE_BRANCH. "
@ -98,7 +92,6 @@ class GitService:
@classmethod
def check_for_publish_configs(cls) -> None:
"""Check_for_configs."""
cls.check_for_basic_configs()
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_TARGET_BRANCH"] is None:
raise MissingGitConfigsError(
@ -113,14 +106,12 @@ class GitService:
@classmethod
def run_shell_command_as_boolean(cls, command: list[str]) -> bool:
"""Run_shell_command_as_boolean."""
# we know result will be a bool here
result: bool = cls.run_shell_command(command, return_success_state=True) # type: ignore
return result
@classmethod
def run_shell_command_to_get_stdout(cls, command: list[str]) -> str:
"""Run_shell_command_to_get_stdout."""
# we know result will be a CompletedProcess here
result: subprocess.CompletedProcess[bytes] = cls.run_shell_command(
command, return_success_state=False
@ -131,7 +122,6 @@ class GitService:
def run_shell_command(
cls, command: list[str], return_success_state: bool = False
) -> subprocess.CompletedProcess[bytes] | bool:
"""Run_shell_command."""
my_env = os.environ.copy()
my_env["GIT_COMMITTER_NAME"] = current_app.config.get("SPIFFWORKFLOW_BACKEND_GIT_USERNAME") or "unknown"
@ -162,7 +152,6 @@ class GitService:
# only supports github right now
@classmethod
def handle_web_hook(cls, webhook: dict) -> bool:
"""Handle_web_hook."""
cls.check_for_publish_configs()
if "repository" not in webhook or "clone_url" not in webhook["repository"]:
@ -203,7 +192,6 @@ class GitService:
@classmethod
def publish(cls, process_model_id: str, branch_to_update: str) -> str:
"""Publish."""
cls.check_for_publish_configs()
source_process_model_root = FileSystemService.root_path()
source_process_model_path = os.path.join(source_process_model_root, process_model_id)

View File

@ -19,7 +19,7 @@ from flask.app import Flask
class InvalidLogLevelError(Exception):
"""InvalidLogLevelError."""
pass
# originally from https://stackoverflow.com/a/70223539/6090676
@ -87,7 +87,6 @@ class JsonFormatter(logging.Formatter):
def setup_logger(app: Flask) -> None:
"""Setup_logger."""
upper_log_level_string = app.config["SPIFFWORKFLOW_BACKEND_LOG_LEVEL"].upper()
log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]

View File

@ -10,12 +10,10 @@ from spiffworkflow_backend.services.process_instance_service import ProcessInsta
class MessageServiceError(Exception):
"""MessageServiceError."""
pass
class MessageService:
"""MessageService."""
@classmethod
def correlate_send_message(cls, message_instance_send: MessageInstanceModel) -> MessageInstanceModel | None:
"""Connects the given send message to a 'receive' message if possible.

View File

@ -95,31 +95,28 @@ def _import(name: str, glbls: dict[str, Any], *args: Any) -> None:
class PotentialOwnerIdList(TypedDict):
"""PotentialOwnerIdList."""
potential_owner_ids: list[int]
lane_assignment_id: int | None
class ProcessInstanceProcessorError(Exception):
"""ProcessInstanceProcessorError."""
pass
class NoPotentialOwnersForTaskError(Exception):
"""NoPotentialOwnersForTaskError."""
pass
class PotentialOwnerUserNotFoundError(Exception):
"""PotentialOwnerUserNotFoundError."""
pass
class MissingProcessInfoError(Exception):
"""MissingProcessInfoError."""
pass
class BoxedTaskDataBasedScriptEngineEnvironment(BoxedTaskDataEnvironment): # type: ignore
def __init__(self, environment_globals: dict[str, Any]):
"""BoxedTaskDataBasedScriptEngineEnvironment."""
self._last_result: dict[str, Any] = {}
super().__init__(environment_globals)
@ -159,7 +156,6 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
PYTHON_ENVIRONMENT_STATE_KEY = "spiff__python_env_state"
def __init__(self, environment_globals: dict[str, Any]):
"""NonTaskDataBasedScriptEngineEnvironment."""
self.state: dict[str, Any] = {}
self.non_user_defined_keys = set([*environment_globals.keys()] + ["__builtins__"])
super().__init__(environment_globals)
@ -368,8 +364,6 @@ IdToBpmnProcessSpecMapping = NewType("IdToBpmnProcessSpecMapping", dict[str, Bpm
class ProcessInstanceProcessor:
"""ProcessInstanceProcessor."""
_script_engine = CustomBpmnScriptEngine()
SERIALIZER_VERSION = "1.0-spiffworkflow-backend"
@ -453,7 +447,6 @@ class ProcessInstanceProcessor:
def get_process_model_and_subprocesses(
cls, process_model_identifier: str
) -> tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]:
"""Get_process_model_and_subprocesses."""
process_model_info = ProcessModelService.get_process_model(process_model_identifier)
if process_model_info is None:
raise (
@ -467,7 +460,6 @@ class ProcessInstanceProcessor:
@classmethod
def get_bpmn_process_instance_from_process_model(cls, process_model_identifier: str) -> BpmnWorkflow:
"""Get_all_bpmn_process_identifiers_for_process_model."""
(bpmn_process_spec, subprocesses) = cls.get_process_model_and_subprocesses(
process_model_identifier,
)
@ -684,7 +676,6 @@ class ProcessInstanceProcessor:
return spiff_bpmn_process_dict
def current_user(self) -> Any:
"""Current_user."""
current_user = None
if UserService.has_user():
current_user = UserService.current_user()
@ -702,7 +693,6 @@ class ProcessInstanceProcessor:
spec: BpmnProcessSpec,
subprocesses: IdToBpmnProcessSpecMapping | None = None,
) -> BpmnWorkflow:
"""Get_bpmn_process_instance_from_workflow_spec."""
bpmn_process_instance = BpmnWorkflow(
spec,
subprocess_specs=subprocesses,
@ -752,18 +742,15 @@ class ProcessInstanceProcessor:
)
def slam_in_data(self, data: dict) -> None:
"""Slam_in_data."""
self.bpmn_process_instance.data = DeepMerge.merge(self.bpmn_process_instance.data, data)
self.save()
def raise_if_no_potential_owners(self, potential_owner_ids: list[int], message: str) -> None:
"""Raise_if_no_potential_owners."""
if not potential_owner_ids:
raise NoPotentialOwnersForTaskError(message)
def get_potential_owner_ids_from_task(self, task: SpiffTask) -> PotentialOwnerIdList:
"""Get_potential_owner_ids_from_task."""
task_spec = task.task_spec
task_lane = "process_initiator"
if task_spec.lane is not None and task_spec.lane != "":
@ -803,7 +790,6 @@ class ProcessInstanceProcessor:
}
def extract_metadata(self, process_model_info: ProcessModelInfo) -> None:
"""Extract_metadata."""
metadata_extraction_paths = process_model_info.metadata_extraction_paths
if metadata_extraction_paths is None:
return
@ -1156,7 +1142,6 @@ class ProcessInstanceProcessor:
@staticmethod
def get_parser() -> MyCustomParser:
"""Get_parser."""
parser = MyCustomParser()
return parser
@ -1164,7 +1149,6 @@ class ProcessInstanceProcessor:
def backfill_missing_spec_reference_records(
bpmn_process_identifier: str,
) -> str | None:
"""Backfill_missing_spec_reference_records."""
process_models = ProcessModelService.get_process_models(recursive=True)
for process_model in process_models:
try:
@ -1181,7 +1165,6 @@ class ProcessInstanceProcessor:
def bpmn_file_full_path_from_bpmn_process_identifier(
bpmn_process_identifier: str,
) -> str:
"""Bpmn_file_full_path_from_bpmn_process_identifier."""
if bpmn_process_identifier is None:
raise ValueError(
"bpmn_file_full_path_from_bpmn_process_identifier: bpmn_process_identifier is unexpectedly None"
@ -1213,7 +1196,6 @@ class ProcessInstanceProcessor:
parser: SpiffBpmnParser,
processed_identifiers: set[str] | None = None,
) -> None:
"""Update_spiff_parser_with_all_process_dependency_files."""
if processed_identifiers is None:
processed_identifiers = set()
processor_dependencies = parser.get_process_dependencies()
@ -1292,7 +1274,6 @@ class ProcessInstanceProcessor:
@staticmethod
def status_of(bpmn_process_instance: BpmnWorkflow) -> ProcessInstanceStatus:
"""Status_of."""
if bpmn_process_instance.is_completed():
return ProcessInstanceStatus.complete
user_tasks = bpmn_process_instance.get_ready_user_tasks()
@ -1312,7 +1293,6 @@ class ProcessInstanceProcessor:
return ProcessInstanceStatus.waiting
def get_status(self) -> ProcessInstanceStatus:
"""Get_status."""
the_status = self.status_of(self.bpmn_process_instance)
# current_app.logger.debug(f"the_status: {the_status} for instance {self.process_instance_model.id}")
return the_status
@ -1430,7 +1410,6 @@ class ProcessInstanceProcessor:
return 0
def check_task_data_size(self) -> None:
"""CheckTaskDataSize."""
task_data_len = self.get_task_data_size(self.bpmn_process_instance)
# Not sure what the number here should be but this now matches the mysql
@ -1446,13 +1425,11 @@ class ProcessInstanceProcessor:
)
def serialize(self) -> dict:
"""Serialize."""
self.check_task_data_size()
self.preserve_script_engine_state()
return self._serializer.workflow_to_dict(self.bpmn_process_instance) # type: ignore
def next_user_tasks(self) -> list[SpiffTask]:
"""Next_user_tasks."""
return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore
def next_task(self) -> SpiffTask:
@ -1523,7 +1500,6 @@ class ProcessInstanceProcessor:
return next_task_to_return
def completed_user_tasks(self) -> list[SpiffTask]:
"""Completed_user_tasks."""
user_tasks = self.bpmn_process_instance.get_tasks(TaskState.COMPLETED)
user_tasks.reverse()
user_tasks = list(
@ -1545,7 +1521,6 @@ class ProcessInstanceProcessor:
return task_json
def complete_task(self, spiff_task: SpiffTask, human_task: HumanTaskModel, user: UserModel) -> None:
"""Complete_task."""
task_model = TaskModel.query.filter_by(guid=human_task.task_id).first()
if task_model is None:
raise TaskNotFoundError(
@ -1581,7 +1556,6 @@ class ProcessInstanceProcessor:
self.save()
def get_data(self) -> dict[str, Any]:
"""Get_data."""
return self.bpmn_process_instance.data # type: ignore
def get_current_data(self) -> dict[str, Any]:
@ -1606,11 +1580,9 @@ class ProcessInstanceProcessor:
return {}
def get_process_instance_id(self) -> int:
"""Get_process_instance_id."""
return self.process_instance_model.id
def get_ready_user_tasks(self) -> list[SpiffTask]:
"""Get_ready_user_tasks."""
return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore
def get_current_user_tasks(self) -> list[SpiffTask]:
@ -1624,7 +1596,6 @@ class ProcessInstanceProcessor:
return ready_tasks + additional_tasks # type: ignore
def get_all_user_tasks(self) -> list[SpiffTask]:
"""Get_all_user_tasks."""
all_tasks = self.bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
return [t for t in all_tasks if t.task_spec.manual]
@ -1633,12 +1604,10 @@ class ProcessInstanceProcessor:
return [t for t in all_tasks if t.task_spec.manual and t.state in [TaskState.COMPLETED, TaskState.CANCELLED]]
def get_all_waiting_tasks(self) -> list[SpiffTask]:
"""Get_all_ready_or_waiting_tasks."""
all_tasks = self.bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
return [t for t in all_tasks if t.state in [TaskState.WAITING]]
def get_all_ready_or_waiting_tasks(self) -> list[SpiffTask]:
"""Get_all_ready_or_waiting_tasks."""
all_tasks = self.bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
return [t for t in all_tasks if t.state in [TaskState.WAITING, TaskState.READY]]
@ -1649,7 +1618,6 @@ class ProcessInstanceProcessor:
def get_task_by_bpmn_identifier(
cls, bpmn_task_identifier: str, bpmn_process_instance: BpmnWorkflow
) -> SpiffTask | None:
"""Get_task_by_id."""
all_tasks = bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
for task in all_tasks:
if task.task_spec.name == bpmn_task_identifier:
@ -1691,7 +1659,6 @@ class ProcessInstanceProcessor:
db.session.commit()
def suspend(self) -> None:
"""Suspend."""
self.process_instance_model.status = ProcessInstanceStatus.suspended.value
db.session.add(self.process_instance_model)
ProcessInstanceTmpService.add_event_to_process_instance(
@ -1700,7 +1667,6 @@ class ProcessInstanceProcessor:
db.session.commit()
def resume(self) -> None:
"""Resume."""
self.process_instance_model.status = ProcessInstanceStatus.waiting.value
db.session.add(self.process_instance_model)
ProcessInstanceTmpService.add_event_to_process_instance(

View File

@ -36,8 +36,6 @@ class ProcessInstanceReportMetadataInvalidError(Exception):
class ProcessInstanceReportService:
"""ProcessInstanceReportService."""
@classmethod
def system_metadata_map(cls, metadata_key: str) -> ReportMetadata | None:
# TODO replace with system reports that are loaded on launch (or similar)
@ -231,7 +229,6 @@ class ProcessInstanceReportService:
process_instance_sqlalchemy_rows: list[sqlalchemy.engine.row.Row], # type: ignore
metadata_columns: list[ReportMetadataColumn],
) -> list[dict]:
"""Add_metadata_columns_to_process_instance."""
results = []
cls.non_metadata_columns()
for process_instance_row in process_instance_sqlalchemy_rows:
@ -301,7 +298,6 @@ class ProcessInstanceReportService:
@classmethod
def get_column_names_for_model(cls, model: type[SpiffworkflowBaseDBModel]) -> list[str]:
"""Get_column_names_for_model."""
return [i.name for i in model.__table__.columns]
@classmethod

View File

@ -38,8 +38,6 @@ from spiffworkflow_backend.specs.start_event import StartConfiguration
class ProcessInstanceService:
"""ProcessInstanceService."""
FILE_DATA_DIGEST_PREFIX = "spifffiledatadigest+"
TASK_STATE_LOCKED = "locked"
@ -65,7 +63,6 @@ class ProcessInstanceService:
user: UserModel,
start_configuration: StartConfiguration | None = None,
) -> tuple[ProcessInstanceModel, StartConfiguration]:
"""Get_process_instance_from_spec."""
db.session.commit()
try:
current_git_revision = GitService.get_current_revision()
@ -96,7 +93,6 @@ class ProcessInstanceService:
process_model_identifier: str,
user: UserModel,
) -> ProcessInstanceModel:
"""Create_process_instance_from_process_model_identifier."""
process_model = ProcessModelService.get_process_model(process_model_identifier)
process_instance_model, (cycle_count, _, duration_in_seconds) = cls.create_process_instance(
process_model, user
@ -190,7 +186,6 @@ class ProcessInstanceService:
@classmethod
def do_waiting(cls, status_value: str) -> None:
"""Do_waiting."""
run_at_in_seconds_threshold = round(time.time())
process_instance_ids_to_check = ProcessInstanceQueueService.peek_many(
status_value, run_at_in_seconds_threshold
@ -275,13 +270,11 @@ class ProcessInstanceService:
return process_instance_api
def get_process_instance(self, process_instance_id: int) -> Any:
"""Get_process_instance."""
result = db.session.query(ProcessInstanceModel).filter(ProcessInstanceModel.id == process_instance_id).first()
return result
@staticmethod
def get_users_assigned_to_task(processor: ProcessInstanceProcessor, spiff_task: SpiffTask) -> list[int]:
"""Get_users_assigned_to_task."""
if processor.process_instance_model.process_initiator_id is None:
raise ApiError.from_task(
error_code="invalid_workflow",
@ -464,7 +457,6 @@ class ProcessInstanceService:
@staticmethod
def create_dot_dict(data: dict) -> dict[str, Any]:
"""Create_dot_dict."""
dot_dict: dict[str, Any] = {}
for key, value in data.items():
ProcessInstanceService.set_dot_value(key, value, dot_dict)
@ -472,7 +464,6 @@ class ProcessInstanceService:
@staticmethod
def get_dot_value(path: str, source: dict) -> Any:
"""Get_dot_value."""
# Given a path in dot notation, uas as 'fruit.type' tries to find that value in
# the source, but looking deep in the dictionary.
paths = path.split(".") # [a,b,c]
@ -491,7 +482,6 @@ class ProcessInstanceService:
@staticmethod
def set_dot_value(path: str, value: Any, target: dict) -> dict:
"""Set_dot_value."""
# Given a path in dot notation, such as "fruit.type", and a value "apple", will
# set the value in the target dictionary, as target["fruit"]["type"]="apple"
destination = target

View File

@ -23,17 +23,16 @@ T = TypeVar("T")
class ProcessModelWithInstancesNotDeletableError(Exception):
"""ProcessModelWithInstancesNotDeletableError."""
pass
class ProcessModelService(FileSystemService):
"""ProcessModelService."""
"""This is a way of persisting json files to the file system in a way that mimics the data
as it would have been stored in the database. This is specific to Workflow Specifications, and
Workflow Specification process_groups.
We do this, so we can easily drop in a new configuration on the file system, and change all
the workflow process_models at once, or manage those file in a git repository. """
the workflow process_models at once, or manage those file in a git repository."""
GROUP_SCHEMA = ProcessGroupSchema()
PROCESS_MODEL_SCHEMA = ProcessModelInfoSchema()
@ -45,7 +44,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def is_process_group(cls, path: str) -> bool:
"""Is_group."""
group_json_path = os.path.join(path, cls.PROCESS_GROUP_JSON_FILE)
if os.path.exists(group_json_path):
return True
@ -53,7 +51,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def is_process_group_identifier(cls, process_group_identifier: str) -> bool:
"""Is_process_group_identifier."""
if os.path.exists(FileSystemService.root_path()):
process_group_path = FileSystemService.full_path_from_id(process_group_identifier)
return cls.is_process_group(process_group_path)
@ -62,7 +59,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def is_process_model(cls, path: str) -> bool:
"""Is_process_model."""
model_json_path = os.path.join(path, cls.PROCESS_MODEL_JSON_FILE)
if os.path.exists(model_json_path):
return True
@ -70,7 +66,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def is_process_model_identifier(cls, process_model_identifier: str) -> bool:
"""Is_process_model_identifier."""
if os.path.exists(FileSystemService.root_path()):
process_model_path = FileSystemService.full_path_from_id(process_model_identifier)
return cls.is_process_model(process_model_path)
@ -95,12 +90,10 @@ class ProcessModelService(FileSystemService):
@classmethod
def add_process_model(cls, process_model: ProcessModelInfo) -> None:
"""Add_spec."""
cls.save_process_model(process_model)
@classmethod
def update_process_model(cls, process_model: ProcessModelInfo, attributes_to_update: dict) -> None:
"""Update_spec."""
for atu_key, atu_value in attributes_to_update.items():
if hasattr(process_model, atu_key):
setattr(process_model, atu_key, atu_value)
@ -108,7 +101,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def save_process_model(cls, process_model: ProcessModelInfo) -> None:
"""Save_process_model."""
process_model_path = os.path.abspath(
os.path.join(FileSystemService.root_path(), process_model.id_for_file_path())
)
@ -149,7 +141,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def get_process_model_from_relative_path(cls, relative_path: str) -> ProcessModelInfo:
"""Get_process_model_from_relative_path."""
path = os.path.join(FileSystemService.root_path(), relative_path)
return cls.__scan_process_model(path)
@ -231,7 +222,6 @@ class ProcessModelService(FileSystemService):
def get_parent_group_array_and_cache_it(
cls, process_identifier: str, process_group_cache: dict[str, ProcessGroup]
) -> ProcessGroupLitesWithCache:
"""Get_parent_group_array."""
full_group_id_path = None
parent_group_array: list[ProcessGroupLite] = []
for process_group_id_segment in process_identifier.split("/")[0:-1]:
@ -251,7 +241,6 @@ class ProcessModelService(FileSystemService):
@classmethod
def get_parent_group_array(cls, process_identifier: str) -> list[ProcessGroupLite]:
"""Get_parent_group_array."""
parent_group_lites_with_cache = cls.get_parent_group_array_and_cache_it(process_identifier, {})
return parent_group_lites_with_cache["process_groups"]

View File

@ -1,4 +1,3 @@
"""Process_instance_processor."""
import json
import sys
import traceback
@ -14,8 +13,6 @@ PythonScriptContext = dict[str, Any]
@dataclass
class ScriptUnitTestResult:
"""ScriptUnitTestResult."""
result: bool
context: PythonScriptContext | None = None
error: str | None = None
@ -24,8 +21,6 @@ class ScriptUnitTestResult:
class ScriptUnitTestRunner:
"""ScriptUnitTestRunner."""
_script_engine = CustomBpmnScriptEngine()
@classmethod
@ -35,7 +30,6 @@ class ScriptUnitTestRunner:
input_context: PythonScriptContext,
expected_output_context: PythonScriptContext,
) -> ScriptUnitTestResult:
"""Run_task."""
# make a new variable just for clarity, since we are going to update this dict in place
# with the output variables from the script.
context = input_context.copy()
@ -86,7 +80,6 @@ class ScriptUnitTestRunner:
task: SpiffTask,
test_identifier: str,
) -> ScriptUnitTestResult:
"""Run_test."""
# this is totally made up, but hopefully resembles what spiffworkflow ultimately does
unit_tests = task.task_spec.extensions["unitTests"]
unit_test = [unit_test for unit_test in unit_tests if unit_test["id"] == test_identifier][0]

View File

@ -5,8 +5,6 @@ from spiffworkflow_backend.models.secret_model import SecretModel
class SecretService:
"""SecretService."""
CIPHER_ENCODING = "ascii"
@classmethod
@ -33,7 +31,6 @@ class SecretService:
value: str,
user_id: int,
) -> SecretModel:
"""Add_secret."""
value = cls._encrypt(value)
secret_model = SecretModel(key=key, value=value, user_id=user_id)
db.session.add(secret_model)
@ -51,7 +48,6 @@ class SecretService:
@staticmethod
def get_secret(key: str) -> SecretModel:
"""Get_secret."""
secret = db.session.query(SecretModel).filter(SecretModel.key == key).first()
if isinstance(secret, SecretModel):
return secret

View File

@ -1,4 +1,3 @@
"""ServiceTask_service."""
import json
from typing import Any
@ -13,7 +12,7 @@ from spiffworkflow_backend.services.user_service import UserService
class ConnectorProxyError(Exception):
"""ConnectorProxyError."""
pass
def connector_proxy_url() -> Any:
@ -22,11 +21,8 @@ def connector_proxy_url() -> Any:
class ServiceTaskDelegate:
"""ServiceTaskDelegate."""
@staticmethod
def check_prefixes(value: Any) -> Any:
"""Check_prefixes."""
if isinstance(value, str):
secret_prefix = "secret:" # noqa: S105
if value.startswith(secret_prefix):
@ -123,8 +119,6 @@ class ServiceTaskDelegate:
class ServiceTaskService:
"""ServiceTaskService."""
@staticmethod
def available_connectors() -> Any:
"""Returns a list of available connectors."""

View File

@ -19,19 +19,18 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelSer
class ProcessModelFileNotFoundError(Exception):
"""ProcessModelFileNotFoundError."""
pass
class ProcessModelFileInvalidError(Exception):
"""ProcessModelFileInvalidError."""
pass
class SpecFileService(FileSystemService):
"""SpecFileService."""
"""We store spec files on the file system. This allows us to take advantage of Git for
syncing and versioning.
The files are stored in a directory whose path is determined by the category and spec names.
syncing and versioning.
The files are stored in a directory whose path is determined by the category and spec names.
"""
@staticmethod
@ -59,7 +58,6 @@ class SpecFileService(FileSystemService):
def get_references_for_process(
process_model_info: ProcessModelInfo,
) -> list[SpecReference]:
"""Get_references_for_process."""
files = SpecFileService.get_files(process_model_info)
references = []
for file in files:
@ -68,7 +66,6 @@ class SpecFileService(FileSystemService):
@classmethod
def get_references_for_file(cls, file: File, process_model_info: ProcessModelInfo) -> list[SpecReference]:
"""Get_references_for_file."""
full_file_path = SpecFileService.full_file_path(process_model_info, file.name)
file_contents: bytes = b""
with open(full_file_path) as f:
@ -77,7 +74,6 @@ class SpecFileService(FileSystemService):
@classmethod
def get_etree_from_xml_bytes(cls, binary_data: bytes) -> etree.Element:
"""Get_etree_from_xml_bytes."""
etree_xml_parser = etree.XMLParser(resolve_entities=False)
return etree.fromstring(binary_data, parser=etree_xml_parser) # noqa: S320
@ -147,13 +143,11 @@ class SpecFileService(FileSystemService):
@staticmethod
def add_file(process_model_info: ProcessModelInfo, file_name: str, binary_data: bytes) -> File:
"""Add_file."""
# Same as update
return SpecFileService.update_file(process_model_info, file_name, binary_data)
@classmethod
def validate_bpmn_xml(cls, file_name: str, binary_data: bytes) -> None:
"""Validate_bpmn_xml."""
file_type = FileSystemService.file_type(file_name)
if file_type.value == FileType.bpmn.value:
BpmnValidator()
@ -202,7 +196,6 @@ class SpecFileService(FileSystemService):
@staticmethod
def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes:
"""Get_data."""
full_file_path = SpecFileService.full_file_path(process_model_info, file_name)
if not os.path.exists(full_file_path):
raise ProcessModelFileNotFoundError(
@ -214,24 +207,20 @@ class SpecFileService(FileSystemService):
@staticmethod
def full_file_path(process_model: ProcessModelInfo, file_name: str) -> str:
"""File_path."""
return os.path.abspath(os.path.join(SpecFileService.process_model_full_path(process_model), file_name))
@staticmethod
def last_modified(process_model: ProcessModelInfo, file_name: str) -> datetime:
"""Last_modified."""
full_file_path = SpecFileService.full_file_path(process_model, file_name)
return FileSystemService._last_modified(full_file_path)
@staticmethod
def timestamp(process_model: ProcessModelInfo, file_name: str) -> float:
"""Timestamp."""
full_file_path = SpecFileService.full_file_path(process_model, file_name)
return FileSystemService._timestamp(full_file_path)
@staticmethod
def delete_file(process_model: ProcessModelInfo, file_name: str) -> None:
"""Delete_file."""
# Fixme: Remember to remove the lookup files when the process_model file is removed.
# lookup_files = session.query(LookupFileModel).filter_by(file_model_id=file_id).all()
# for lf in lookup_files:
@ -242,7 +231,6 @@ class SpecFileService(FileSystemService):
@staticmethod
def delete_all_files(process_model: ProcessModelInfo) -> None:
"""Delete_all_files."""
dir_path = SpecFileService.process_model_full_path(process_model)
if os.path.exists(dir_path):
shutil.rmtree(dir_path)
@ -251,7 +239,6 @@ class SpecFileService(FileSystemService):
@staticmethod
def update_caches(ref: SpecReference) -> None:
"""Update_caches."""
SpecFileService.update_process_cache(ref)
SpecFileService.update_process_caller_cache(ref)
SpecFileService.update_message_cache(ref)
@ -279,14 +266,12 @@ class SpecFileService(FileSystemService):
@staticmethod
def clear_caches() -> None:
"""Clear_caches."""
db.session.query(SpecReferenceCache).delete()
ProcessCallerService.clear_cache()
# fixme: likely the other caches should be cleared as well, but we don't have a clean way to do so yet.
@staticmethod
def update_process_cache(ref: SpecReference) -> None:
"""Update_process_cache."""
process_id_lookup = (
SpecReferenceCache.query.filter_by(identifier=ref.identifier).filter_by(type=ref.type).first()
)
@ -350,7 +335,6 @@ class SpecFileService(FileSystemService):
@staticmethod
def update_correlation_cache(ref: SpecReference) -> None:
"""Update_correlation_cache."""
for name in ref.correlations.keys():
correlation_property_retrieval_expressions = ref.correlations[name]["retrieval_expressions"]

View File

@ -74,19 +74,16 @@ class UserService:
# Returns true if the current user is logged in.
@staticmethod
def has_user() -> bool:
"""Has_user."""
return "token" in g and bool(g.token) and "user" in g and bool(g.user)
@staticmethod
def current_user() -> Any:
"""Current_user."""
if not UserService.has_user():
raise ApiError("logged_out", "You are no longer logged in.", status_code=401)
return g.user
@staticmethod
def get_principal_by_user_id(user_id: int) -> PrincipalModel:
"""Get_principal_by_user_id."""
principal = db.session.query(PrincipalModel).filter(PrincipalModel.user_id == user_id).first()
if isinstance(principal, PrincipalModel):
return principal
@ -97,7 +94,6 @@ class UserService:
@classmethod
def create_principal(cls, child_id: int, id_column_name: str = "user_id") -> PrincipalModel:
"""Create_principal."""
column = PrincipalModel.__table__.columns[id_column_name]
principal: PrincipalModel | None = PrincipalModel.query.filter(column == child_id).first()
if principal is None:
@ -117,7 +113,6 @@ class UserService:
@classmethod
def add_user_to_group(cls, user: UserModel, group: GroupModel) -> None:
"""Add_user_to_group."""
exists = UserGroupAssignmentModel().query.filter_by(user_id=user.id).filter_by(group_id=group.id).count()
if not exists:
ugam = UserGroupAssignmentModel(user_id=user.id, group_id=group.id)
@ -126,7 +121,6 @@ class UserService:
@classmethod
def add_waiting_group_assignment(cls, username: str, group: GroupModel) -> None:
"""Add_waiting_group_assignment."""
wugam = (
UserGroupAssignmentWaitingModel().query.filter_by(username=username).filter_by(group_id=group.id).first()
)
@ -140,7 +134,6 @@ class UserService:
@classmethod
def apply_waiting_group_assignments(cls, user: UserModel) -> None:
"""Apply_waiting_group_assignments."""
waiting = (
UserGroupAssignmentWaitingModel()
.query.filter(UserGroupAssignmentWaitingModel.username == user.username)
@ -160,7 +153,6 @@ class UserService:
@staticmethod
def get_user_by_service_and_service_id(service: str, service_id: str) -> UserModel | None:
"""Get_user_by_service_and_service_id."""
user: UserModel = (
UserModel.query.filter(UserModel.service == service).filter(UserModel.service_id == service_id).first()
)
@ -170,7 +162,6 @@ class UserService:
@classmethod
def add_user_to_human_tasks_if_appropriate(cls, user: UserModel) -> None:
"""Add_user_to_human_tasks_if_appropriate."""
group_ids = [g.id for g in user.groups]
human_tasks = HumanTaskModel.query.filter(
HumanTaskModel.lane_assignment_id.in_(group_ids) # type: ignore

View File

@ -388,7 +388,6 @@ class WorkflowExecutionService:
# execution_strategy.spiff_run
# spiff.[some_run_task_method]
def run_and_save(self, exit_at: None = None, save: bool = False) -> None:
"""Do_engine_steps."""
with safe_assertion(ProcessInstanceLockService.has_lock(self.process_instance_model.id)) as tripped:
if tripped:
raise AssertionError(

View File

@ -8,8 +8,6 @@ from spiffworkflow_backend.specs.start_event import StartEvent
class WorkflowService:
"""WorkflowService."""
@classmethod
def future_start_events(cls, workflow: BpmnWorkflow) -> list[SpiffTask]:
return [t for t in workflow.get_tasks(TaskState.FUTURE) if isinstance(t.task_spec, StartEvent)]

View File

@ -34,11 +34,8 @@ from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
class BaseTest:
"""BaseTest."""
@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
@ -99,7 +96,6 @@ class BaseTest:
process_group_id: str,
display_name: str = "",
) -> ProcessGroup:
"""Create_process_group."""
process_group = ProcessGroup(id=process_group_id, display_name=display_name, display_order=0, admin=False)
return ProcessModelService.add_process_group(process_group)
@ -171,7 +167,6 @@ class BaseTest:
raise Exception("You must include the process_model_id, which must be a path to the model")
def get_test_data_file_full_path(self, file_name: str, process_model_test_data_dir: str) -> str:
"""Get_test_data_file_contents."""
return os.path.join(
current_app.instance_path,
"..",
@ -183,7 +178,6 @@ class BaseTest:
)
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 = self.get_test_data_file_full_path(file_name, process_model_test_data_dir)
with open(file_full_path, "rb") as file:
return file.read()
@ -283,7 +277,6 @@ class BaseTest:
status: str | None = "not_started",
user: UserModel | None = None,
) -> ProcessInstanceModel:
"""Create_process_instance_from_process_model."""
if user is None:
user = self.find_or_create_user()
@ -342,7 +335,6 @@ class BaseTest:
target_uri: str,
expected_result: bool = True,
) -> None:
"""Assert_user_has_permission."""
has_permission = AuthorizationService.user_has_permission(
user=user,
permission=permission,
@ -351,11 +343,9 @@ class BaseTest:
assert has_permission is expected_result
def modify_process_identifier_for_path_param(self, identifier: str) -> str:
"""Modify_process_identifier_for_path_param."""
return ProcessModelInfo.modify_process_identifier_for_path_param(identifier)
def un_modify_modified_process_identifier_for_path_param(self, modified_identifier: str) -> str:
"""Un_modify_modified_process_model_id."""
return modified_identifier.replace(":", "/")
def create_process_model_with_metadata(self) -> ProcessModelInfo:

View File

@ -8,8 +8,6 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
class ExampleDataLoader:
"""ExampleDataLoader."""
@staticmethod
def create_spec(
process_model_id: str,

View File

@ -1,5 +1,3 @@
"""User."""
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

View File

@ -7,10 +7,7 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
class TestAuthentication(BaseTest):
"""TestAuthentication."""
def test_get_login_state(self) -> None:
"""Test_get_login_state."""
redirect_url = "http://example.com/"
state = AuthenticationService.generate_state(redirect_url)
state_dict = ast.literal_eval(base64.b64decode(state).decode("utf-8"))

View File

@ -2,8 +2,7 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
class TestAuthorization(BaseTest):
"""TestAuthorization."""
pass
# def test_get_bearer_token(self, app: Flask) -> None:
# """Test_get_bearer_token."""
# for user_id in ("user_1", "user_2", "admin_1", "admin_2"):

View File

@ -1,4 +1,3 @@
"""Test_various_bpmn_constructs."""
from typing import Any
from flask.app import Flask
@ -53,7 +52,6 @@ class TestForGoodErrors(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_task_data_is_set_even_if_process_instance_errors."""
process_model = load_test_spec(
process_model_id="group/end_user_instructions_error",
bpmn_file_name="instructions_error.bpmn",

View File

@ -13,8 +13,6 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
class TestNestedGroups(BaseTest):
"""TestNestedGroups."""
def test_delete_group_with_running_instance(
self,
app: Flask,
@ -22,7 +20,6 @@ class TestNestedGroups(BaseTest):
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"
@ -65,7 +62,6 @@ class TestNestedGroups(BaseTest):
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",
@ -120,7 +116,6 @@ class TestNestedGroups(BaseTest):
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_nested_groups."""
# /process-groups/{process_group_path}/show
target_uri = "/v1.0/process-groups/group_a,group_b"
user = self.find_or_create_user()
@ -134,7 +129,6 @@ class TestNestedGroups(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_add_nested_group."""
process_group_a = ProcessGroup(
id="group_a",
display_name="Group A",
@ -179,7 +173,6 @@ class TestNestedGroups(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_create."""
process_group_a = ProcessGroup(
id="group_a",
display_name="Group A",
@ -226,7 +219,6 @@ class TestNestedGroups(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_group_show."""
# target_uri = "/process-groups/{process_group_id}"
# user = self.find_or_create_user("testadmin1")
# self.add_permissions_to_user(

View File

@ -1,4 +1,3 @@
"""Test_authentication."""
import base64
import jwt
@ -46,7 +45,6 @@ class TestFlaskOpenId(BaseTest):
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_get_token."""
code = "testadmin1:1234123412341234"
"""It should be possible to get a token."""

View File

@ -40,15 +40,12 @@ from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
class TestProcessApi(BaseTest):
"""TestProcessAPi."""
def test_returns_403_if_user_does_not_have_permission(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_returns_403_if_user_does_not_have_permission."""
user = self.find_or_create_user()
response = client.get(
"/v1.0/process-groups",
@ -75,7 +72,6 @@ class TestProcessApi(BaseTest):
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_permissions_check."""
user = self.find_or_create_user()
self.add_permissions_to_user(user, target_uri="/v1.0/process-groups", permission_names=["read"])
request_body = {
@ -107,7 +103,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_create."""
process_group_id = "test_process_group"
process_group_display_name = "Test Process Group"
# creates the group directory, and the json file
@ -157,7 +152,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_create_with_natural_language."""
process_group_id = "test_process_group"
process_group_description = "Test Process Group"
process_model_id = "sample"
@ -268,7 +262,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_delete."""
process_group_id = "test_process_group"
process_model_id = "sample"
process_model_identifier = f"{process_group_id}/{process_model_id}"
@ -299,7 +292,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_delete_with_instances."""
test_process_group_id = "runs_without_input"
test_process_model_id = "sample"
bpmn_file_name = "sample.bpmn"
@ -350,7 +342,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_update."""
self.create_process_group_with_api(client, with_super_admin_user, "test_process_group", "Test Process Group")
process_model_identifier = "test_process_group/make_cookies"
self.create_process_model_with_api(
@ -390,7 +381,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_list_all."""
group_id = "test_group/test_sub_group"
self.create_process_group_with_api(client, with_super_admin_user, group_id)
@ -425,7 +415,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_list."""
# create a group
group_id = "test_group"
self.create_process_group_with_api(client, with_super_admin_user, group_id)
@ -592,7 +581,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_add_process_group."""
process_group = ProcessGroup(
id="test",
display_name="Another Test Category",
@ -629,7 +617,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_group_delete."""
process_group_id = "test"
process_group_display_name = "My Process Group"
@ -851,7 +838,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_file_update."""
process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user)
bad_process_model_identifier = f"x{process_model_identifier}"
modified_bad_process_model_identifier = bad_process_model_identifier.replace("/", ":")
@ -872,7 +858,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_file_update."""
process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user)
modified_process_model_identifier = process_model_identifier.replace("/", ":")
@ -914,7 +899,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_file_update."""
process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user)
modified_process_model_identifier = process_model_identifier.replace("/", ":")
@ -949,7 +933,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_file."""
process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user)
modified_process_model_identifier = process_model_identifier.replace("/", ":")
@ -969,7 +952,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_workflow_from_workflow_spec."""
process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user)
modified_process_model_identifier = process_model_identifier.replace("/", ":")
@ -1100,7 +1082,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_process_group_when_found."""
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)
@ -1122,7 +1103,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_process_group_show_when_nested."""
self.create_group_and_model_with_bpmn(
client=client,
user=with_super_admin_user,
@ -1156,7 +1136,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_process_model_when_found."""
process_model_identifier = self.create_group_and_model_with_bpmn(
client, with_super_admin_user, bpmn_file_name="random_fact.bpmn"
)
@ -1181,7 +1160,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_process_model_when_not_found."""
process_model_dir_name = "THIS_NO_EXISTS"
group_id = self.create_process_group_with_api(client, with_super_admin_user, "my_group")
bad_process_model_id = f"{group_id}/{process_model_dir_name}"
@ -1201,7 +1179,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""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_from_process_model_id_with_api(client, test_process_model_id, headers)
@ -1220,7 +1197,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_run."""
# process_model_id = "runs_without_input/sample"
process_model_identifier = self.create_group_and_model_with_bpmn(
client=client,
@ -1257,7 +1233,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_show."""
process_group_id = "simple_script"
process_model_id = "simple_script"
process_model_identifier = self.create_group_and_model_with_bpmn(
@ -1296,7 +1271,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_show_with_specified_process_identifier."""
process_model_id = "call_activity_nested"
process_model_identifier = self.create_group_and_model_with_bpmn(
client=client,
@ -1343,7 +1317,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_message_send_when_starting_process_instance."""
# ensure process model is loaded
process_group_id = "test_message_send"
process_model_id = "message_receiver"
@ -1391,7 +1364,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_message_send_when_providing_message_to_running_process_instance."""
process_group_id = "test_message_send"
process_model_id = "message_sender"
bpmn_file_name = "message_sender.bpmn"
@ -1467,7 +1439,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_message_send_when_providing_message_to_running_process_instance."""
process_group_id = "test_message_send"
process_model_id = "message_sender"
bpmn_file_name = "message_sender.bpmn"
@ -1562,7 +1533,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_message_send_when_providing_message_to_running_process_instance."""
# this task will wait on a catch event
process_group_id = "test_message_send"
process_model_id = "message_sender"
@ -1625,7 +1595,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_delete."""
process_group_id = "my_process_group"
process_model_id = "sample"
bpmn_file_location = "sample"
@ -1665,7 +1634,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_run_user_task."""
process_group_id = "my_process_group"
process_model_id = "dynamic_enum_select_fields"
bpmn_file_location = "dynamic_enum_select_fields"
@ -1807,7 +1775,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_list_with_default_list."""
process_group_id = "runs_without_input"
process_model_id = "sample"
bpmn_file_location = "sample"
@ -1843,7 +1810,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_list_with_paginated_items."""
process_group_id = "runs_without_input"
process_model_id = "sample"
bpmn_file_name = "sample.bpmn"
@ -1882,7 +1848,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_list_filter."""
process_group_id = "runs_without_input"
process_model_id = "sample"
bpmn_file_name = "sample.bpmn"
@ -2058,7 +2023,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_report_list."""
process_group_id = "runs_without_input"
process_model_id = "sample"
bpmn_file_name = "sample.bpmn"
@ -2097,7 +2061,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_error_handler."""
process_group_id = "data"
process_model_id = "error"
bpmn_file_name = "error.bpmn"
@ -2138,7 +2101,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_error_handler_suspend."""
process_group_id = "data"
process_model_id = "error"
bpmn_file_name = "error.bpmn"
@ -2174,7 +2136,6 @@ class TestProcessApi(BaseTest):
assert process.status == "suspended"
def test_error_handler_system_notification(self) -> None:
"""Test_error_handler_system_notification."""
# TODO: make sure the system notification process is run on exceptions
...
@ -2185,7 +2146,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_task_data_is_set_even_if_process_instance_errors."""
process_model = load_test_spec(
process_model_id="group/error_with_task_data",
bpmn_file_name="script_error_with_task_data.bpmn",
@ -2214,7 +2174,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_file_create."""
process_group_id = "hello_world"
process_model_id = "hello_world"
file_name = "hello_world.svg"
@ -2249,7 +2208,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_can_get_message_instances_by_process_instance_id."""
process_group_id = "test_message_send"
process_model_id = "message_receiver"
bpmn_file_name = "message_receiver.bpmn"
@ -2540,7 +2498,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_suspend."""
bpmn_file_name = "manual_task.bpmn"
bpmn_file_location = "manual_task"
process_model_identifier = self.create_group_and_model_with_bpmn(
@ -2606,7 +2563,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_script_unit_test_run."""
process_group_id = "test_group"
process_model_id = "simple_script"
bpmn_file_name = "simple_script.bpmn"
@ -2663,7 +2619,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_script_unit_test_run."""
process_group_id = "test_group"
process_model_id = "process_navigation"
bpmn_file_name = "process_navigation.bpmn"
@ -2740,7 +2695,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_script_unit_test_run."""
process_group_id = "test_group"
process_model_id = "manual_task"
bpmn_file_name = "manual_task.bpmn"
@ -2801,7 +2755,6 @@ class TestProcessApi(BaseTest):
assert len(response.json) == 7
def setup_initial_groups_for_move_tests(self, client: FlaskClient, with_super_admin_user: UserModel) -> None:
"""Setup_initial_groups_for_move_tests."""
groups = ["group_a", "group_b", "group_b/group_bb"]
# setup initial groups
for group in groups:
@ -2819,7 +2772,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_move_model."""
self.setup_initial_groups_for_move_tests(client, with_super_admin_user)
process_model_id = "test_model"
@ -2867,7 +2819,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_move_group."""
self.setup_initial_groups_for_move_tests(client, with_super_admin_user)
# add sub group to `group_a`
@ -3094,7 +3045,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_can_get_process_instance_list_with_report_metadata_and_process_initator."""
user_one = self.create_user_with_permission(username="user_one")
process_model = load_test_spec(
@ -3267,7 +3217,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_instance_list_can_order_by_metadata."""
process_model = load_test_spec(
"test_group/hello_world",
process_model_source_directory="nested-task-data-structure",
@ -3339,7 +3288,6 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_data_show."""
process_model = load_test_spec(
"test_group/data_object_test",
process_model_source_directory="data_object_test",

View File

@ -1,4 +1,3 @@
"""Test_users_controller."""
from flask.app import Flask
from flask.testing import FlaskClient
from spiffworkflow_backend.models.user import UserModel
@ -8,8 +7,6 @@ from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
class TestProcessInstancesController(BaseTest):
"""TestProcessInstancesController."""
def test_find_by_id(
self,
app: Flask,
@ -17,7 +14,6 @@ class TestProcessInstancesController(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_user_search_returns_a_user."""
user_one = self.create_user_with_permission(username="user_one", target_uri="/process-instances/find-by-id/*")
user_two = self.create_user_with_permission(username="user_two", target_uri="/process-instances/find-by-id/*")

View File

@ -12,8 +12,6 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
class SecretServiceTestHelpers(BaseTest):
"""SecretServiceTestHelpers."""
test_key = "test_key"
test_value = "test_value"
test_process_group_id = "test"
@ -23,11 +21,9 @@ class SecretServiceTestHelpers(BaseTest):
test_process_model_description = "Om nom nom delicious cookies"
def add_test_secret(self, user: UserModel) -> SecretModel:
"""Add_test_secret."""
return SecretService().add_secret(self.test_key, self.test_value, user.id)
def add_test_process(self, client: FlaskClient, user: UserModel) -> ProcessModelInfo:
"""Add_test_process."""
self.create_process_group_with_api(
client,
user,
@ -47,15 +43,12 @@ class SecretServiceTestHelpers(BaseTest):
class TestSecretService(SecretServiceTestHelpers):
"""TestSecretService."""
def test_add_secret(
self,
app: Flask,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_add_secret."""
test_secret = self.add_test_secret(with_super_admin_user)
assert test_secret is not None
@ -69,7 +62,6 @@ class TestSecretService(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_add_secret_duplicate_key_fails."""
self.add_test_secret(with_super_admin_user)
with pytest.raises(ApiError) as ae:
self.add_test_secret(with_super_admin_user)
@ -81,7 +73,6 @@ class TestSecretService(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_secret."""
self.add_test_secret(with_super_admin_user)
secret = SecretService().get_secret(self.test_key)
@ -94,7 +85,6 @@ class TestSecretService(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_get_secret_bad_service."""
self.add_test_secret(with_super_admin_user)
with pytest.raises(ApiError):
@ -124,7 +114,6 @@ class TestSecretService(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_update_secret_bad_secret_fails."""
secret = self.add_test_secret(with_super_admin_user)
with pytest.raises(ApiError) as ae:
SecretService.update_secret(secret.key + "x", "some_new_value", with_super_admin_user.id)
@ -154,7 +143,6 @@ class TestSecretService(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_delete_secret_bad_secret_fails."""
self.add_test_secret(with_super_admin_user)
with pytest.raises(ApiError) as ae:
SecretService.delete_secret(self.test_key + "x", with_super_admin_user.id)

View File

@ -20,7 +20,6 @@ class TestSecretsController(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_add_secret."""
secret_model = SecretModel(
key=self.test_key,
value=self.test_value,
@ -66,7 +65,6 @@ class TestSecretsController(SecretServiceTestHelpers):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_update_secret."""
self.add_test_secret(with_super_admin_user)
secret: SecretModel | None = SecretService.get_secret(self.test_key)
assert secret

View File

@ -6,8 +6,6 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
class TestUsersController(BaseTest):
"""TestUsersController."""
def test_user_search_returns_a_user(
self,
app: Flask,
@ -15,7 +13,6 @@ class TestUsersController(BaseTest):
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_user_search_returns_a_user."""
self.find_or_create_user(username="aa")
self.find_or_create_user(username="ab")
self.find_or_create_user(username="abc")

View File

@ -1,4 +1,3 @@
"""Test_get_localtime."""
import json
from flask import g

View File

@ -1,4 +1,3 @@
"""Test_environment_var_script."""
from flask import Flask
from spiffworkflow_backend.models.script_attributes_context import ScriptAttributesContext
from spiffworkflow_backend.scripts.get_env import GetEnv

View File

@ -1,4 +1,3 @@
"""Test_get_localtime."""
from flask.app import Flask
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
@ -14,7 +13,6 @@ class TestGetProcessInitiatorUser(BaseTest):
app: Flask,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_sets_permission_correctly_on_human_task."""
initiator_user = self.find_or_create_user("initiator_user")
assert initiator_user.principal is not None
AuthorizationService.import_permissions_from_yaml_file()

View File

@ -1,4 +1,3 @@
"""Test_get_localtime."""
import pytest
from flask.app import Flask
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor

Some files were not shown because too many files have changed in this diff Show More