some precommit stuff w/ burnettk

This commit is contained in:
jasquat 2022-10-21 11:00:31 -04:00
parent 579f0902ed
commit 49eefc561e
12 changed files with 77 additions and 50 deletions

View File

@ -6,10 +6,10 @@ import pytest
from flask.app import Flask from flask.app import Flask
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (

View File

@ -1,5 +1,3 @@
from __future__ import with_statement
import logging import logging
from logging.config import fileConfig from logging.config import fileConfig

View File

@ -16,7 +16,6 @@ from spiffworkflow_backend.models.user_group_assignment import (
) # noqa: F401 ) # noqa: F401
from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401 from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401
from spiffworkflow_backend.models.active_task_user import (ActiveTaskUserModel)
from spiffworkflow_backend.models.bpmn_process_id_lookup import ( from spiffworkflow_backend.models.bpmn_process_id_lookup import (
BpmnProcessIdLookup, BpmnProcessIdLookup,
) # noqa: F401 ) # noqa: F401

View File

@ -9,18 +9,17 @@ from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.orm import RelationshipProperty from sqlalchemy.orm import RelationshipProperty
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import Task
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
if TYPE_CHECKING: if TYPE_CHECKING:
from spiffworkflow_backend.models.active_task_user import ( from spiffworkflow_backend.models.active_task_user import ( # noqa: F401
ActiveTaskUserModel, ActiveTaskUserModel,
) # noqa: F401 )
@dataclass @dataclass
@ -34,9 +33,7 @@ class ActiveTaskModel(SpiffworkflowBaseDBModel):
), ),
) )
actual_owner: RelationshipProperty[UserModel] = relationship( actual_owner: RelationshipProperty[UserModel] = relationship(UserModel)
UserModel
)
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
process_instance_id: int = db.Column( process_instance_id: int = db.Column(
ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore

View File

@ -1,4 +1,6 @@
"""Active_task_user."""
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
@ -11,6 +13,7 @@ from spiffworkflow_backend.models.user import UserModel
@dataclass @dataclass
class ActiveTaskUserModel(SpiffworkflowBaseDBModel): class ActiveTaskUserModel(SpiffworkflowBaseDBModel):
"""ActiveTaskUserModel."""
__tablename__ = "active_task_user" __tablename__ = "active_task_user"
@ -26,6 +29,4 @@ class ActiveTaskUserModel(SpiffworkflowBaseDBModel):
active_task_id = db.Column( active_task_id = db.Column(
ForeignKey(ActiveTaskModel.id), nullable=False, index=True # type: ignore ForeignKey(ActiveTaskModel.id), nullable=False, index=True # type: ignore
) )
user_id = db.Column( user_id = db.Column(ForeignKey(UserModel.id), nullable=False, index=True)
ForeignKey(UserModel.id), nullable=False, index=True
)

View File

@ -1,5 +1,6 @@
"""User.""" """User."""
from __future__ import annotations from __future__ import annotations
from typing import Any from typing import Any
import jwt import jwt

View File

@ -1298,7 +1298,6 @@ def find_active_task_by_id_or_raise(
process_instance_id: int, task_id: str, principal_id: PrincipalModel process_instance_id: int, task_id: str, principal_id: PrincipalModel
) -> ActiveTaskModel: ) -> ActiveTaskModel:
"""Find_active_task_by_id_or_raise.""" """Find_active_task_by_id_or_raise."""
# TODO: update # TODO: update
active_task_assigned_to_me = ActiveTaskModel.query.filter_by( active_task_assigned_to_me = ActiveTaskModel.query.filter_by(
process_instance_id=process_instance_id, process_instance_id=process_instance_id,

View File

@ -70,7 +70,6 @@ from spiffworkflow_backend.models.message_correlation_property import (
) )
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.message_instance import MessageModel from spiffworkflow_backend.models.message_instance import MessageModel
from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfo
@ -112,7 +111,7 @@ class ProcessInstanceProcessorError(Exception):
class NoPotentialOwnersForTaskError(Exception): class NoPotentialOwnersForTaskError(Exception):
pass """NoPotentialOwnersForTaskError."""
class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
@ -518,7 +517,6 @@ class ProcessInstanceProcessor:
if self.bpmn_process_instance.is_completed(): if self.bpmn_process_instance.is_completed():
self.process_instance_model.end_in_seconds = round(time.time()) self.process_instance_model.end_in_seconds = round(time.time())
active_tasks = ActiveTaskModel.query.filter_by( active_tasks = ActiveTaskModel.query.filter_by(
process_instance_id=self.process_instance_model.id process_instance_id=self.process_instance_model.id
).all() ).all()
@ -534,7 +532,7 @@ class ProcessInstanceProcessor:
# filter out non-usertasks # filter out non-usertasks
task_spec = ready_or_waiting_task.task_spec task_spec = ready_or_waiting_task.task_spec
if not self.bpmn_process_instance._is_engine_task(task_spec): if not self.bpmn_process_instance._is_engine_task(task_spec):
user_id = ready_or_waiting_task.data["current_user"]["id"] ready_or_waiting_task.data["current_user"]["id"]
# principal = PrincipalModel.query.filter_by(user_id=user_id).first() # principal = PrincipalModel.query.filter_by(user_id=user_id).first()
# if principal is None: # if principal is None:
# raise ( # raise (
@ -545,19 +543,29 @@ class ProcessInstanceProcessor:
# ) # )
# ) # )
# import pdb; pdb.set_trace() # import pdb; pdb.set_trace()
task_lane = 'process_initiator' task_lane = "process_initiator"
if task_spec.lane is not None: if task_spec.lane is not None:
task_lane = task_spec.lane task_lane = task_spec.lane
potential_owner_ids = [] potential_owner_ids = []
lane_assignment_id = None lane_assignment_id = None
if re.match(r"(process.?)initiator", task_lane, re.IGNORECASE): if re.match(r"(process.?)initiator", task_lane, re.IGNORECASE):
potential_owner_ids = [self.process_instance_model.process_initiator_id] potential_owner_ids = [
self.process_instance_model.process_initiator_id
]
else: else:
group_model = GroupModel.query.filter_by(identifier=task_lane).first() group_model = GroupModel.query.filter_by(
identifier=task_lane
).first()
if group_model is None: if group_model is None:
raise (NoPotentialOwnersForTaskError(f"Could not find a group with name matching lane: {task_lane}")) raise (
potential_owner_ids = [i.user_id for i in group_model.user_group_assignments] NoPotentialOwnersForTaskError(
f"Could not find a group with name matching lane: {task_lane}"
)
)
potential_owner_ids = [
i.user_id for i in group_model.user_group_assignments
]
lane_assignment_id = group_model.id lane_assignment_id = group_model.id
extensions = ready_or_waiting_task.task_spec.extensions extensions = ready_or_waiting_task.task_spec.extensions
@ -588,14 +596,15 @@ class ProcessInstanceProcessor:
task_title=ready_or_waiting_task.task_spec.description, task_title=ready_or_waiting_task.task_spec.description,
task_type=ready_or_waiting_task.task_spec.__class__.__name__, task_type=ready_or_waiting_task.task_spec.__class__.__name__,
task_status=ready_or_waiting_task.get_state_name(), task_status=ready_or_waiting_task.get_state_name(),
task_data=json.dumps(ready_or_waiting_task.data),
lane_assignment_id=lane_assignment_id, lane_assignment_id=lane_assignment_id,
) )
db.session.add(active_task) db.session.add(active_task)
db.session.commit() db.session.commit()
for potential_owner_id in potential_owner_ids: for potential_owner_id in potential_owner_ids:
active_task_user = ActiveTaskUserModel(user_id=potential_owner_id,active_task_id=active_task.id) active_task_user = ActiveTaskUserModel(
user_id=potential_owner_id, active_task_id=active_task.id
)
db.session.add(active_task_user) db.session.add(active_task_user)
db.session.commit() db.session.commit()

View File

@ -10,8 +10,8 @@ from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from SpiffWorkflow.util.deep_merge import DeepMerge from SpiffWorkflow.util.deep_merge import DeepMerge
from spiffworkflow_backend.models.active_task import ActiveTaskModel # type: ignore
from spiffworkflow_backend.models.active_task import ActiveTaskModel # type: ignore
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceApi
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
@ -28,11 +28,11 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelSer
class ActiveTaskNotFoundError(Exception): class ActiveTaskNotFoundError(Exception):
pass """ActiveTaskNotFoundError."""
class UserDoesNotHaveAccessToTaskError(Exception): class UserDoesNotHaveAccessToTaskError(Exception):
pass """UserDoesNotHaveAccessToTaskError."""
class ProcessInstanceService: class ProcessInstanceService:
@ -279,12 +279,21 @@ class ProcessInstanceService:
Abstracted here because we need to do it multiple times when completing all tasks in Abstracted here because we need to do it multiple times when completing all tasks in
a multi-instance task. a multi-instance task.
""" """
active_task = ActiveTaskModel.query.filter_by(task_name=spiff_task.task_spec.name, process_instance_id=processor.process_instance_model.id).first() active_task = ActiveTaskModel.query.filter_by(
task_name=spiff_task.task_spec.name,
process_instance_id=processor.process_instance_model.id,
).first()
if active_task is None: if active_task is None:
raise ActiveTaskNotFoundError("Could find an active task with task name '{spiff_task.task_spec.name}' for process instance '{processor.process_instance_model.id}'") raise ActiveTaskNotFoundError(
f"Could find an active task with task name '{spiff_task.task_spec.name}'"
f" for process instance '{processor.process_instance_model.id}'"
)
if user not in active_task.potential_owners: if user not in active_task.potential_owners:
raise UserDoesNotHaveAccessToTaskError("User {user.username} does not have access to update task'{spiff_task.task_spec.name}' for process instance '{processor.process_instance_model.id}'") raise UserDoesNotHaveAccessToTaskError(
f"User {user.username} does not have access to update task'{spiff_task.task_spec.name}'"
f" for process instance '{processor.process_instance_model.id}'"
)
dot_dct = ProcessInstanceService.create_dot_dict(data) dot_dct = ProcessInstanceService.create_dot_dict(data)
spiff_task.update_data(dot_dct) spiff_task.update_data(dot_dct)

View File

@ -207,7 +207,10 @@ class BaseTest:
# return public_access_token # return public_access_token
def create_process_instance_from_process_model( def create_process_instance_from_process_model(
self, process_model: ProcessModelInfo, status: Optional[str] = "not_started", user: Optional[UserModel] = None self,
process_model: ProcessModelInfo,
status: Optional[str] = "not_started",
user: Optional[UserModel] = None,
) -> ProcessInstanceModel: ) -> ProcessInstanceModel:
"""Create_process_instance_from_process_model.""" """Create_process_instance_from_process_model."""
if user is None: if user is None:

View File

@ -22,6 +22,7 @@ class TestAuthorizationService(BaseTest):
def test_does_not_fail_if_user_not_created( def test_does_not_fail_if_user_not_created(
self, app: Flask, with_db_and_bpmn_file_cleanup: None self, app: Flask, with_db_and_bpmn_file_cleanup: None
) -> None: ) -> None:
"""Test_does_not_fail_if_user_not_created."""
AuthorizationService.import_permissions_from_yaml_file() AuthorizationService.import_permissions_from_yaml_file()
def test_can_import_permissions_from_yaml( def test_can_import_permissions_from_yaml(

View File

@ -1,16 +1,21 @@
"""Test_process_instance_processor.""" """Test_process_instance_processor."""
import pytest import pytest
from flask.app import Flask from flask.app import Flask
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel, ProcessInstanceStatus
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService, UserDoesNotHaveAccessToTaskError
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,
) )
from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
from spiffworkflow_backend.services.process_instance_service import (
UserDoesNotHaveAccessToTaskError,
)
class TestProcessInstanceProcessor(BaseTest): class TestProcessInstanceProcessor(BaseTest):
@ -46,6 +51,7 @@ class TestProcessInstanceProcessor(BaseTest):
app: Flask, app: Flask,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
) -> None: ) -> None:
"""Test_sets_permission_correctly_on_active_task."""
testuser1 = self.find_or_create_user("testuser1") testuser1 = self.find_or_create_user("testuser1")
testuser2 = self.find_or_create_user("testuser2") testuser2 = self.find_or_create_user("testuser2")
assert testuser1.principal is not None assert testuser1.principal is not None
@ -55,8 +61,12 @@ class TestProcessInstanceProcessor(BaseTest):
finance_group = GroupModel.query.filter_by(identifier="Finance Team").first() finance_group = GroupModel.query.filter_by(identifier="Finance Team").first()
assert finance_group is not None assert finance_group is not None
process_model = load_test_spec(process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn") process_model = load_test_spec(
process_instance = self.create_process_instance_from_process_model(process_model=process_model, user=testuser1) process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn"
)
process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=testuser1
)
processor = ProcessInstanceProcessor(process_instance) processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps(save=True) processor.do_engine_steps(save=True)
@ -66,14 +76,14 @@ class TestProcessInstanceProcessor(BaseTest):
assert len(active_task.potential_owners) == 1 assert len(active_task.potential_owners) == 1
assert active_task.potential_owners[0] == testuser1 assert active_task.potential_owners[0] == testuser1
spiff_task = processor.__class__.get_task_by_bpmn_identifier(active_task.task_name, processor.bpmn_process_instance) spiff_task = processor.__class__.get_task_by_bpmn_identifier(
active_task.task_name, processor.bpmn_process_instance
)
with pytest.raises(UserDoesNotHaveAccessToTaskError): with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task( ProcessInstanceService.complete_form_task(
processor, spiff_task, {}, testuser2 processor, spiff_task, {}, testuser2
) )
ProcessInstanceService.complete_form_task( ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testuser1)
processor, spiff_task, {}, testuser1
)
assert len(process_instance.active_tasks) == 1 assert len(process_instance.active_tasks) == 1
active_task = process_instance.active_tasks[0] active_task = process_instance.active_tasks[0]
@ -81,24 +91,24 @@ class TestProcessInstanceProcessor(BaseTest):
assert len(active_task.potential_owners) == 1 assert len(active_task.potential_owners) == 1
assert active_task.potential_owners[0] == testuser2 assert active_task.potential_owners[0] == testuser2
spiff_task = processor.__class__.get_task_by_bpmn_identifier(active_task.task_name, processor.bpmn_process_instance) spiff_task = processor.__class__.get_task_by_bpmn_identifier(
active_task.task_name, processor.bpmn_process_instance
)
with pytest.raises(UserDoesNotHaveAccessToTaskError): with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task( ProcessInstanceService.complete_form_task(
processor, spiff_task, {}, testuser1 processor, spiff_task, {}, testuser1
) )
ProcessInstanceService.complete_form_task( ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testuser2)
processor, spiff_task, {}, testuser2
)
assert len(process_instance.active_tasks) == 1 assert len(process_instance.active_tasks) == 1
active_task = process_instance.active_tasks[0] active_task = process_instance.active_tasks[0]
assert active_task.lane_assignment_id is None assert active_task.lane_assignment_id is None
assert len(active_task.potential_owners) == 1 assert len(active_task.potential_owners) == 1
assert active_task.potential_owners[0] == testuser1 assert active_task.potential_owners[0] == testuser1
spiff_task = processor.__class__.get_task_by_bpmn_identifier(active_task.task_name, processor.bpmn_process_instance) spiff_task = processor.__class__.get_task_by_bpmn_identifier(
ProcessInstanceService.complete_form_task( active_task.task_name, processor.bpmn_process_instance
processor, spiff_task, {}, testuser1
) )
ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testuser1)
assert process_instance.status == ProcessInstanceStatus.complete.value assert process_instance.status == ProcessInstanceStatus.complete.value