Skip to content

Commit

Permalink
Merge pull request #2435 from auslin-aot/feature/fwf-4093-webapi-perm…
Browse files Browse the repository at this point in the history
…ission-matrix-changes

FWF-4093: [Feature] Webapi permission matrix changes
  • Loading branch information
arun-s-aot authored Dec 17, 2024
2 parents bcff5c3 + 8145848 commit df31658
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
MANAGE_USERS,
MANAGE_ROLES,
ADMIN,
CREATE_BPMN_FLOWS,
MANAGE_DECISION_TABLES,
MANAGE_SUBFLOWS,
)
from .file_log_handler import CustomTimedRotatingFileHandler, register_log_handlers
from .format import CustomFormatter
Expand Down
2 changes: 1 addition & 1 deletion forms-flow-api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ecdsa==0.19.0
flask-jwt-oidc==0.7.0
flask-marshmallow==1.2.1
flask-restx==1.3.0
formsflow_api_utils @ git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#subdirectory=forms-flow-api-utils
formsflow_api_utils @ git+https://github.com/auslin-aot/forms-flow-ai.git@feature/fwf-4093-webapi-permission-matrix-changes#subdirectory=forms-flow-api-utils
gunicorn==23.0.0
h11==0.14.0
h2==4.1.0
Expand Down
2 changes: 1 addition & 1 deletion forms-flow-api/requirements/prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ markupsafe
PyJWT
redis
lxml
git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#subdirectory=forms-flow-api-utils
git+https://github.com/auslin-aot/forms-flow-ai.git@feature/fwf-4093-webapi-permission-matrix-changes#subdirectory=forms-flow-api-utils
35 changes: 25 additions & 10 deletions forms-flow-api/src/formsflow_api/resources/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from flask_restx import Namespace, Resource, fields
from formsflow_api_utils.utils import (
CREATE_DESIGNS,
MANAGE_DECISION_TABLES,
MANAGE_SUBFLOWS,
VIEW_DESIGNS,
VIEW_SUBMISSIONS,
VIEW_TASKS,
Expand Down Expand Up @@ -101,7 +103,7 @@ class ProcessDataResource(Resource):
"""Resource to create and list process data."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.doc(
params={
Expand Down Expand Up @@ -179,15 +181,19 @@ class ProcessDataResource(Resource):
)
def get():
"""List all process data."""
process_list, count = ProcessService.get_all_process(request.args)
process_list, count = ProcessService.get_all_process(
request.args,
auth.has_role([MANAGE_SUBFLOWS]),
auth.has_role([MANAGE_DECISION_TABLES]),
)
response = {
"process": process_list,
"totalCount": count,
}
return response, HTTPStatus.OK

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.doc(
responses={
Expand Down Expand Up @@ -216,7 +222,7 @@ class ProcessResourceById(Resource):
"""Resource for managing process by id."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.doc(
responses={
Expand All @@ -233,7 +239,7 @@ def get(process_id: int):
return response, status

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.doc(
responses={
Expand Down Expand Up @@ -281,7 +287,7 @@ class ProcessHistoryResource(Resource):
"""Resource for retrieving process history."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.doc(
params={
Expand Down Expand Up @@ -327,7 +333,7 @@ class ValidateProcess(Resource):
"""Resource for validating a process name or key."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.response(200, "OK:- Successful request.")
@API.response(400, "BAD_REQUEST:- Invalid request.")
Expand All @@ -352,7 +358,7 @@ class PublishResource(Resource):
"""Resource to support publish sub-process/worklfow."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.response(200, "OK:- Successful request.")
@API.response(
Expand Down Expand Up @@ -381,7 +387,7 @@ class UnpublishResource(Resource):
"""Resource to support unpublish sub-process/workflow."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS])
@auth.has_one_of_roles([CREATE_DESIGNS, MANAGE_SUBFLOWS, MANAGE_DECISION_TABLES])
@profiletime
@API.response(200, "OK:- Successful request.")
@API.response(
Expand Down Expand Up @@ -411,7 +417,16 @@ class ProcessResourceByProcessKey(Resource):
"""Resource for managing process by process key."""

@staticmethod
@auth.has_one_of_roles([CREATE_DESIGNS, VIEW_DESIGNS, VIEW_SUBMISSIONS, VIEW_TASKS])
@auth.has_one_of_roles(
[
CREATE_DESIGNS,
VIEW_DESIGNS,
VIEW_SUBMISSIONS,
VIEW_TASKS,
MANAGE_SUBFLOWS,
MANAGE_DECISION_TABLES,
]
)
@profiletime
@API.doc(
responses={
Expand Down
4 changes: 3 additions & 1 deletion forms-flow-api/src/formsflow_api/services/import_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from flask import current_app
from formsflow_api_utils.exceptions import BusinessException
from formsflow_api_utils.services.external import FormioService
from formsflow_api_utils.utils import Cache
from formsflow_api_utils.utils import CREATE_BPMN_FLOWS, Cache
from formsflow_api_utils.utils.enums import FormProcessMapperStatus
from formsflow_api_utils.utils.startup import collect_role_ids
from formsflow_api_utils.utils.user_context import UserContext, user_context
Expand Down Expand Up @@ -725,6 +725,8 @@ def import_form_workflow(
else:
raise BusinessException(BusinessErrorCode.INVALID_FILE_TYPE)
elif valid_file == ".bpmn":
if CREATE_BPMN_FLOWS not in user.roles:
raise BusinessException(BusinessErrorCode.PERMISSION_DENIED)
current_app.logger.info("Workflow validated successfully.")
if action == "validate":
major, minor = self.determine_process_version_by_key(
Expand Down
20 changes: 14 additions & 6 deletions forms-flow-api/src/formsflow_api/services/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,28 @@ def get_subflows_dmns(cls, process_type, **kwargs):
)

@classmethod
def get_all_process(cls, request_args): # pylint:disable=too-many-locals
def get_all_process(
cls, request_args, subflows_auth, decision_auth
): # pylint:disable=too-many-locals
"""Get all process list."""
dict_data = ProcessListRequestSchema().load(request_args) or {}
process_type = (
dict_data.get("process_data_type").upper()
if dict_data.get("process_data_type")
else None
)
if (
process_type
and (process_type == ProcessType.BPMN.value and not subflows_auth)
or (process_type == ProcessType.DMN.value and not decision_auth)
):
raise BusinessException(BusinessErrorCode.PERMISSION_DENIED)
page_no = dict_data.get("page_no")
limit = dict_data.get("limit")
sort_by = dict_data.get("sort_by", "")
process_id = dict_data.get("process_id")
process_name = dict_data.get("name")
status = dict_data.get("status").upper() if dict_data.get("status") else None
process_type = (
dict_data.get("process_data_type").upper()
if dict_data.get("process_data_type")
else None
)
created_by = dict_data.get("created_by")
created_from_date = dict_data.get("created_from_date")
created_to_date = dict_data.get("created_to_date")
Expand Down
14 changes: 9 additions & 5 deletions forms-flow-api/tests/unit/api/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
from unittest.mock import MagicMock, patch

import pytest
from formsflow_api_utils.utils import CREATE_DESIGNS, MANAGE_TASKS
from formsflow_api_utils.utils import (
CREATE_DESIGNS,
MANAGE_SUBFLOWS,
MANAGE_TASKS,
)

from formsflow_api.models import Process
from formsflow_api.services import ProcessService
from tests.utilities.base_test import (
get_process_request_payload,
get_process_request_payload_low_code,
get_process_request_payload_for_dmn,
get_process_request_payload_low_code,
get_token,
)

Expand Down Expand Up @@ -150,7 +154,7 @@ def test_process_list(
self, app, client, session, jwt, create_process_with_api_call
):
"""Testing process listing API."""
token = get_token(jwt, role=CREATE_DESIGNS, username="designer")
token = get_token(jwt, role=MANAGE_SUBFLOWS, username="designer")
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
Expand Down Expand Up @@ -180,7 +184,7 @@ def test_process_list_with_pagination_sorted_list(
create_process_with_api_call,
):
"""Testing process listing API with pagination and sorted list."""
token = get_token(jwt, role=CREATE_DESIGNS, username="designer")
token = get_token(jwt, role=MANAGE_SUBFLOWS, username="designer")
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
Expand All @@ -199,7 +203,7 @@ def test_process_list_with_filters(
self, app, client, session, jwt, create_process_with_api_call
):
"""Testing process listing API with filters."""
token = get_token(jwt, role=CREATE_DESIGNS, username="designer")
token = get_token(jwt, role=MANAGE_SUBFLOWS, username="designer")
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
Expand Down

0 comments on commit df31658

Please sign in to comment.