Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New endpoints #4

Draft
wants to merge 16 commits into
base: formsflow
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Changes for saving process models to database and to start instance
sumesh-aot committed Jul 3, 2024
commit 5325c635a347dd168a70c185ffaa71f99bbed251
46 changes: 46 additions & 0 deletions spiffworkflow-backend/migrations/versions/1801292017d5_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""empty message

Revision ID: 1801292017d5
Revises: c8f64c8333d2
Create Date: 2024-06-18 14:19:22.985449

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '1801292017d5'
down_revision = 'c8f64c8333d2'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('process_model_info',
sa.Column('process_id', sa.Integer(), nullable=False),
sa.Column('id', sa.String(), nullable=True),
sa.Column('display_name', sa.String(), nullable=True),
sa.Column('description', sa.String(), nullable=True),
sa.Column('is_executable', sa.Boolean(), nullable=True),
sa.Column('fault_or_suspend_on_exception', sa.String(), nullable=True),
sa.Column('process_group', sa.String(), nullable=True),
sa.Column('content', sa.Text(), nullable=True),
sa.Column('type', sa.String(), nullable=True),
sa.Column('bpmn_version_control_identifier', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('process_id')
)
# with op.batch_alter_table('task', schema=None) as batch_op:
# batch_op.drop_constraint('guid', type_='unique')

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
# with op.batch_alter_table('task', schema=None) as batch_op:
# batch_op.create_unique_constraint('guid', ['guid'])

op.drop_table('process_model_info')
# ### end Alembic commands ###
40 changes: 40 additions & 0 deletions spiffworkflow-backend/migrations/versions/384e2bbda36b_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""empty message

Revision ID: 384e2bbda36b
Revises: 1801292017d5
Create Date: 2024-06-20 13:46:51.568998

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '384e2bbda36b'
down_revision = '1801292017d5'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('process_model_info', schema=None) as batch_op:
batch_op.alter_column('content',
existing_type=sa.TEXT(),
type_=sa.LargeBinary(),
existing_nullable=True,
postgresql_using="content::bytea")

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###

with op.batch_alter_table('process_model_info', schema=None) as batch_op:
batch_op.alter_column('content',
existing_type=sa.LargeBinary(),
type_=sa.TEXT(),
existing_nullable=True)

# ### end Alembic commands ###
34 changes: 34 additions & 0 deletions spiffworkflow-backend/migrations/versions/c8f64c8333d2_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""empty message

Revision ID: c8f64c8333d2
Revises: d4b900e71852
Create Date: 2024-06-14 16:41:02.361125

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'c8f64c8333d2'
down_revision = 'd4b900e71852'
branch_labels = None
depends_on = None


def upgrade():
# Add default permissions mappings for formsflow
op.execute("""
WITH upsert AS (
SELECT 1 FROM permission_target WHERE uri = '/*'
)
INSERT INTO permission_target (uri)
SELECT '/*'
WHERE NOT EXISTS (SELECT 1 FROM upsert);
""")
# Change Process group and process models to work with database rather than disk



def downgrade():
pass
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ def create_app() -> flask.app.Flask:
]
CORS(app, origins=origins_re, max_age=3600, supports_credentials=True)

connexion_app.add_api("api.yml", base_path=V1_API_PATH_PREFIX)
connexion_app.add_api("api.yml", base_path=V1_API_PATH_PREFIX, pythonic_params=True)

app.json = MyJSONEncoder(app)

51 changes: 33 additions & 18 deletions spiffworkflow-backend/src/spiffworkflow_backend/api.yml
Original file line number Diff line number Diff line change
@@ -582,24 +582,6 @@ paths:
schema:
$ref: "#/components/schemas/ProcessModel"

/deployment/create:
post:
operationId: spiffworkflow_backend.routes.process_models_controller.process_model_create
summary: Creates a new process model with the given parameters.
tags:
- Process Models
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/ProcessModel"
responses:
"201":
description: Process model created successfully.
content:
application/json:
schema:
$ref: "#/components/schemas/ProcessModel"

/process-model-natural-language/{modified_process_group_id}:
parameters:
@@ -3226,6 +3208,39 @@ paths:
"200":
description: The requested data store.

/deployment/create:
post:
operationId: spiffworkflow_backend.routes.process_models_controller.process_model_create_formsflow
summary: Creates a new process model with the given parameters.
tags:
- Process Models
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
deployment_name:
type: string
description: The name of the deployment
deployment_source:
type: string
description: The source of the deployment
enable_duplicate_filtering:
type: boolean
description: Whether to enable duplicate filtering
upload:
type: string
format: binary
description: The BPMN file to upload
responses:
"201":
description: Process model created successfully.
content:
application/json:
schema:
$ref: "#/components/schemas/ProcessModel"

components:
securitySchemes:
oAuth2AuthCode:
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
from __future__ import annotations
from dataclasses import dataclass

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.schema import CheckConstraint

from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.user import UserModel

import enum
import os
@@ -30,31 +40,58 @@ class NotificationType(enum.Enum):
suspend = "suspend"


@dataclass(order=True)
class ProcessModelInfo:
@dataclass
class ProcessModelInfo(SpiffworkflowBaseDBModel):
sort_index: str = field(init=False)

id: str
display_name: str
description: str
primary_file_name: str | None = None
primary_process_id: str | None = None
is_executable: bool = True
fault_or_suspend_on_exception: str = NotificationType.fault.value
exception_notification_addresses: list[str] = field(default_factory=list)
metadata_extraction_paths: list[dict[str, str]] | None = None
process_id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.String)
display_name = db.Column(db.String)
description= db.Column(db.String)
is_executable = db.Column(db.Boolean)
fault_or_suspend_on_exception = db.Column(db.String, default=NotificationType.fault.value)

process_group: Any | None = None
files: list[File] | None = field(default_factory=list[File])
process_group=db.Column(db.String, default="formsflow")

# files: list[File] | None = field(default_factory=list[File])
content = db.Column(db.Text)
type = db.Column(db.String, default="bpmn") # BPMN or DMN

# just for the API
parent_groups: list[ProcessGroupLite] | None = None
bpmn_version_control_identifier: str | None = None
# parent_groups: list[ProcessGroupLite] | None = None
bpmn_version_control_identifier= db.Column(db.String)

@property
def primary_file_name(self):
return None

@property
def primary_process_id(self):
return self.id

@property
def exception_notification_addresses(self):
return []

@property
def metadata_extraction_paths(self):
return []

@property
def actions(self):
return {}

@property
def display_order(self):
return 0

# TODO: delete these once they no no longer mentioned in current process_model.json files
display_order: int | None = 0
@property
def files(self):
return [self.content]

actions: dict | None = None
@property
def parent_groups(self):
return []

def __post_init__(self) -> None:
self.sort_index = self.id
@@ -103,7 +140,8 @@ class Meta:
description = marshmallow.fields.String()
primary_file_name = marshmallow.fields.String(allow_none=True)
primary_process_id = marshmallow.fields.String(allow_none=True)
files = marshmallow.fields.List(marshmallow.fields.Nested("File"))
content = marshmallow.fields.String(allow_none=True)
type = marshmallow.fields.String(allow_none=True)
fault_or_suspend_on_exception = marshmallow.fields.String()
exception_notification_addresses = marshmallow.fields.List(marshmallow.fields.String)
metadata_extraction_paths = marshmallow.fields.List(
Original file line number Diff line number Diff line change
@@ -434,15 +434,15 @@ def _get_process_model_for_instantiation(
process_model_identifier: str,
) -> ProcessModelInfo:
process_model = _get_process_model(process_model_identifier)
if process_model.primary_file_name is None:
raise ApiError(
error_code="process_model_missing_primary_bpmn_file",
message=(
f"Process Model '{process_model_identifier}' does not have a primary"
" bpmn file. One must be set in order to instantiate this model."
),
status_code=400,
)
# if process_model.primary_file_name is None:
# raise ApiError(
# error_code="process_model_missing_primary_bpmn_file",
# message=(
# f"Process Model '{process_model_identifier}' does not have a primary"
# " bpmn file. One must be set in order to instantiate this model."
# ),
# status_code=400,
# )
return process_model


Original file line number Diff line number Diff line change
@@ -62,10 +62,12 @@

def process_instance_create(
modified_process_model_identifier: str,
#TODO data payload
) -> flask.wrappers.Response:
process_model_identifier = _un_modify_modified_process_model_id(modified_process_model_identifier)

process_instance = _process_instance_create(process_model_identifier)

return Response(
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
status=201,
@@ -79,6 +81,7 @@ def process_instance_run(
force_run: bool = False,
execution_mode: str | None = None,
) -> flask.wrappers.Response:

process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
_process_instance_run(process_instance, force_run=force_run, execution_mode=execution_mode)

@@ -708,16 +711,16 @@ def _process_instance_run(
def _process_instance_create(
process_model_identifier: str,
) -> ProcessInstanceModel:
process_model = _get_process_model_for_instantiation(process_model_identifier)
if process_model.primary_file_name is None:
raise ApiError(
error_code="process_model_missing_primary_bpmn_file",
message=(
f"Process Model '{process_model_identifier}' does not have a primary"
" bpmn file. One must be set in order to instantiate this model."
),
status_code=400,
)
# process_model = _get_process_model_for_instantiation(process_model_identifier) # Return process model from database
# if process_model.primary_file_name is None:
# raise ApiError(
# error_code="process_model_missing_primary_bpmn_file",
# message=(
# f"Process Model '{process_model_identifier}' does not have a primary"
# " bpmn file. One must be set in order to instantiate this model."
# ),
# status_code=400,
# )

process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier(
process_model_identifier, g.user
Loading