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

FWF-3584: [Feature] Added Publish endpoint #375

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Added prompt_new_version column in form_process_mapper

Revision ID: d4618d0e45ca
Revises: 9929f234cef0
Create Date: 2024-09-12 15:57:52.395411

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'd4618d0e45ca'
down_revision = '9929f234cef0'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('form_process_mapper', sa.Column('prompt_new_version', sa.Boolean(), nullable=True, server_default='false'))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('form_process_mapper', 'prompt_new_version')
# ### end Alembic commands ###
76 changes: 76 additions & 0 deletions forms-flow-api/src/formsflow_api/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,79 @@ def message(self):
def status_code(self):
"""Return status code."""
return self._value


def default_flow_xml_data(name="Defaultflow"):
"""Xml data for default flow."""
return f"""<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:modeler="http://camunda.org/schema/modeler/1.0"
id="Definitions_1gblxi8" targetNamespace="http://bpmn.io/schema/bpmn"
exporter="Camunda Modeler" exporterVersion="4.12.0"
modeler:executionPlatform="Camunda Platform"
modeler:executionPlatformVersion="7.15.0">
<bpmn:process id="{name}" name="{name}" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Default Flow Started">
<bpmn:outgoing>Flow_09rbji4</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Audit_Task_Executed" name="Execute Audit Task">
<bpmn:extensionElements>
<camunda:executionListener event="start">
<camunda:script scriptFormat="javascript">execution.setVariable('applicationStatus', 'Completed');</camunda:script>
</camunda:executionListener>
<camunda:executionListener class="org.camunda.bpm.extension.hooks.listeners.BPMFormDataPipelineListener" event="start">
<camunda:field name="fields">
<camunda:expression>["applicationId","applicationStatus"]</camunda:expression>
</camunda:field>
</camunda:executionListener>
<camunda:executionListener class="org.camunda.bpm.extension.hooks.listeners.ApplicationStateListener" event="end" />
</bpmn:extensionElements>
<bpmn:incoming>Flow_09rbji4</bpmn:incoming>
<bpmn:outgoing>Flow_0klorcg</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_09rbji4" sourceRef="StartEvent_1" targetRef="Audit_Task_Executed">
<bpmn:extensionElements>
<camunda:executionListener event="take">
<camunda:script scriptFormat="javascript">execution.setVariable('applicationStatus', 'New');</camunda:script>
</camunda:executionListener>
<camunda:executionListener class="org.camunda.bpm.extension.hooks.listeners.ApplicationStateListener" event="take" />
</bpmn:extensionElements>
</bpmn:sequenceFlow>
<bpmn:endEvent id="Event_1ws2h5w" name="Default Flow Ended">
<bpmn:incoming>Flow_0klorcg</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0klorcg" sourceRef="Audit_Task_Executed" targetRef="Event_1ws2h5w" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Defaultflow">
<bpmndi:BPMNEdge id="Flow_0klorcg_di" bpmnElement="Flow_0klorcg">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_09rbji4_di" bpmnElement="Flow_09rbji4">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="166" y="142" width="62" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1qmqqen_di" bpmnElement="Audit_Task_Executed">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1ws2h5w_di" bpmnElement="Event_1ws2h5w">
<dc:Bounds x="432" y="99" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="419" y="142" width="62" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>"""
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class FormProcessMapper(AuditDateTimeMixin, AuditUserMixin, BaseModel, db.Model)
task_variable = db.Column(JSON, nullable=True)
version = db.Column(db.Integer, nullable=False, default=1)
description = db.Column(db.String, nullable=True)
prompt_new_version = db.Column(db.Boolean, nullable=True, default=False)

__table_args__ = (
UniqueConstraint("form_id", "version", "tenant", name="_form_version_uc"),
Expand Down Expand Up @@ -105,6 +106,7 @@ def update(self, mapper_info: dict):
"task_variable",
"process_tenant",
"description",
"prompt_new_version",
],
mapper_info,
)
Expand Down
9 changes: 3 additions & 6 deletions forms-flow-api/src/formsflow_api/models/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def find_all_process(
def get_latest_version(cls, process_name):
"""Get latest version of process."""
query = (
cls.query.filter(cls.name == process_name)
cls.auth_query(cls.query.filter(cls.name == process_name))
.order_by(cls.major_version.desc(), cls.minor_version.desc())
.first()
)
Expand All @@ -143,11 +143,8 @@ def fetch_histories_by_process_name(cls, process_name: str) -> List[Process]:
"""Fetch all versions (histories) of a process by process_name."""
assert process_name is not None

query = (
cls.auth_query(
cls.query.filter(cls.name == process_name)
)
.order_by(desc(cls.major_version), desc(cls.minor_version))
query = cls.auth_query(cls.query.filter(cls.name == process_name)).order_by(
desc(cls.major_version), desc(cls.minor_version)
)

return query.all()
60 changes: 60 additions & 0 deletions forms-flow-api/src/formsflow_api/resources/form_process_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,3 +702,63 @@ def get():
"""
response = FormProcessMapperService.validate_form_name_path_title(request)
return response, HTTPStatus.OK


@cors_preflight("POST,OPTIONS")
@API.route("/<int:mapper_id>/publish", methods=["POST", "OPTIONS"])
class PublishResource(Resource):
"""Resource to support publish."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@profiletime
@API.response(200, "OK:- Successful request.")
@API.response(
400,
"BAD_REQUEST:- Invalid request.",
)
@API.response(
401,
"UNAUTHORIZED:- Authorization header not provided or an invalid token passed.",
)
@API.response(
403,
"FORBIDDEN:- Authorization will not help.",
)
def post(mapper_id: int):
"""Publish by mapper_id."""
form_service = FormProcessMapperService()
return (
form_service.publish(mapper_id),
HTTPStatus.OK,
)


@cors_preflight("POST,OPTIONS")
@API.route("/<int:mapper_id>/unpublish", methods=["POST", "OPTIONS"])
class UnpublishResource(Resource):
"""Resource to support unpublish."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@profiletime
@API.response(200, "OK:- Successful request.")
@API.response(
400,
"BAD_REQUEST:- Invalid request.",
)
@API.response(
401,
"UNAUTHORIZED:- Authorization header not provided or an invalid token passed.",
)
@API.response(
403,
"FORBIDDEN:- Authorization will not help.",
)
def post(mapper_id: int):
"""Unpublish by mapper_id."""
form_service = FormProcessMapperService()
return (
form_service.unpublish(mapper_id),
HTTPStatus.OK,
)
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Meta: # pylint: disable=too-few-public-methods
process_tenant = fields.Str(data_key="processTenant")
deleted = fields.Boolean(data_key="deleted")
description = fields.Str(data_key="description")
prompt_new_version = fields.Bool(data_key="promptNewVersion", dump_only=True)


class FormProcessMapperListReqSchema(Schema):
Expand Down
14 changes: 9 additions & 5 deletions forms-flow-api/src/formsflow_api/services/external/base_bpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ def get_request(cls, url, token):
return data

@classmethod
def post_request(cls, url, token, payload=None, tenant_key=None):
def post_request(cls, url, token, payload=None, tenant_key=None, files=None): # pylint: disable=too-many-arguments
"""Post HTTP request to BPM API with auth header."""
headers = cls._get_headers_(token, tenant_key)
payload = json.dumps(payload)
response = requests.post(url, data=payload, headers=headers, timeout=120)
headers = cls._get_headers_(token, tenant_key, files)
payload = payload if files else json.dumps(payload)
response = requests.post(
url, data=payload, headers=headers, timeout=120, files=files
)
current_app.logger.debug(
"POST URL : %s, Response Code : %s", url, response.status_code
)
Expand All @@ -61,7 +63,7 @@ def post_request(cls, url, token, payload=None, tenant_key=None):
return data

@classmethod
def _get_headers_(cls, token, tenant_key=None):
def _get_headers_(cls, token, tenant_key=None, files=None):
"""Generate headers."""
bpm_token_api = current_app.config.get("BPM_TOKEN_API")
bpm_client_id = current_app.config.get("BPM_CLIENT_ID")
Expand All @@ -77,6 +79,8 @@ def _get_headers_(cls, token, tenant_key=None):
"grant_type": bpm_grant_type,
}
if token:
if files:
return {"Authorization": token}
return {"Authorization": token, "content-type": "application/json"}

response = requests.post(
Expand Down
9 changes: 9 additions & 0 deletions forms-flow-api/src/formsflow_api/services/external/bpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class BPMEndpointType(IntEnum):
FORM_AUTH_DETAILS = 2
MESSAGE_EVENT = 3
DECISION_DEFINITION = 4
DEPLOYMENT = 5


class BPMService(BaseBPMService):
Expand Down Expand Up @@ -109,6 +110,12 @@ def decision_definition_xml(cls, decision_key, token, tenant_key):
url += f"?tenantId={tenant_key}"
return cls.get_request(url, token)

@classmethod
def post_deployment(cls, token, payload, tenant_key, files):
"""Create new deployment."""
url = f"{cls._get_url_(BPMEndpointType.DEPLOYMENT)}"
return cls.post_request(url, token, payload, tenant_key, files)

@classmethod
def _get_url_(cls, endpoint_type: BPMEndpointType):
"""Get Url."""
Expand All @@ -123,6 +130,8 @@ def _get_url_(cls, endpoint_type: BPMEndpointType):
url = f"{bpm_api_base}/engine-rest-ext/v1/message"
elif endpoint_type == BPMEndpointType.DECISION_DEFINITION:
url = f"{bpm_api_base}/engine-rest-ext/v1/decision-definition"
elif endpoint_type == BPMEndpointType.DEPLOYMENT:
url = f"{bpm_api_base}/engine-rest-ext/v1/deployment/create"
return url

except BaseException as e: # pylint: disable=broad-except
Expand Down
Loading
Loading