Skip to content

Commit

Permalink
This fixes guest login with using multiple auths, removes empty items…
Browse files Browse the repository at this point in the history
… from ApiError, and raises if redirect_url given to login does not match expected frontend host w/ burnettk
  • Loading branch information
jasquat committed Nov 30, 2023
1 parent a7ab3e2 commit 9c482cd
Show file tree
Hide file tree
Showing 40 changed files with 212 additions and 82 deletions.
3 changes: 2 additions & 1 deletion spiffworkflow-backend/bin/get_bpmn_json_for_process_instance
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ def main(process_instance_id: str) -> None:
if not process_instance:
raise Exception(f"Could not find a process instance with id: {process_instance_id}")

bpmn_process_dict = ProcessInstanceProcessor._get_full_bpmn_process_dict(process_instance, {})
with open(file_path, "w", encoding="utf-8") as f:
f.write(json.dumps(ProcessInstanceProcessor._get_full_bpmn_json(process_instance)))
f.write(json.dumps(bpmn_process_dict, indent=2))
print(f"Saved to {file_path}")


Expand Down
31 changes: 31 additions & 0 deletions spiffworkflow-backend/src/spiffworkflow_backend/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,33 @@ paths:
schema:
$ref: "#/components/schemas/OkTrue"

/tasks/{process_instance_id}/{task_guid}/allows-guest:
parameters:
- name: task_guid
in: path
required: true
description: The unique id of an existing process group.
schema:
type: string
- name: process_instance_id
in: path
required: true
description: The unique id of an existing process instance.
schema:
type: integer
get:
tags:
- Tasks
operationId: spiffworkflow_backend.routes.tasks_controller.task_allows_guest
summary: Gets checks if the given task allows guest login
responses:
"200":
description: Whether the task can be completed by a guest
content:
application/json:
schema:
$ref: "#/components/schemas/TaskAllowsGuest"

# NOTE: this should probably be /process-instances instead
/tasks/{process_instance_id}/send-user-signal-event:
parameters:
Expand Down Expand Up @@ -3013,6 +3040,10 @@ components:
documentation: "# Heading 1\n\nMarkdown documentation text goes here"
type: form
state: ready
TaskAllowsGuest:
properties:
allows_guest:
type: boolean
Task:
properties:
id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import json
from dataclasses import dataclass
from dataclasses import field
from typing import Any

import flask.wrappers
Expand Down Expand Up @@ -38,18 +37,18 @@ class ApiError(Exception):

error_code: str
message: str
error_line: str | None = ""
error_type: str | None = ""
file_name: str | None = ""
line_number: int | None = 0
offset: int | None = 0
error_line: str | None = None
error_type: str | None = None
file_name: str | None = None
line_number: int | None = None
offset: int | None = None
sentry_link: str | None = None
status_code: int | None = 400
tag: str | None = ""
task_data: dict | str | None = field(default_factory=dict)
task_id: str | None = ""
task_name: str | None = ""
task_trace: list | None = field(default_factory=list)
tag: str | None = None
task_data: dict | str | None = None
task_id: str | None = None
task_name: str | None = None
task_trace: list | None = None

# these are useful if the error response cannot be json but has to be something else
# such as returning content type 'text/event-stream' for the interstitial page
Expand All @@ -67,24 +66,32 @@ def __str__(self) -> str:
msg += f"In file {self.file_name}. "
return msg

def serialized(self) -> dict[str, Any]:
initial_dict = self.__dict__
return_dict = {}
for key, value in initial_dict.items():
if value is not None and value != "":
return_dict[key] = value
return return_dict

@classmethod
def from_task(
cls,
error_code: str,
message: str,
task: Task,
status_code: int = 400,
line_number: int = 0,
offset: int = 0,
error_type: str = "",
error_line: str = "",
line_number: int | None = None,
offset: int | None = None,
error_type: str | None = None,
error_line: str | None = None,
task_trace: list | None = None,
) -> ApiError:
"""Constructs an API Error with details pulled from the current task."""
instance = cls(error_code, message, status_code=status_code)
instance.task_id = task.task_spec.name or ""
instance.task_name = task.task_spec.description or ""
instance.file_name = task.workflow.spec.file or ""
instance.task_id = task.task_spec.name
instance.task_name = task.task_spec.description
instance.file_name = task.workflow.spec.file
instance.line_number = line_number
instance.offset = offset
instance.error_type = error_type
Expand All @@ -110,17 +117,17 @@ def from_task_model(
message: str,
task_model: TaskModel,
status_code: int | None = 400,
line_number: int | None = 0,
offset: int | None = 0,
error_type: str | None = "",
error_line: str | None = "",
line_number: int | None = None,
offset: int | None = None,
error_type: str | None = None,
error_line: str | None = None,
task_trace: list | None = None,
) -> ApiError:
"""Constructs an API Error with details pulled from the current task model."""
instance = cls(error_code, message, status_code=status_code)
task_definition = task_model.task_definition
instance.task_id = task_definition.bpmn_identifier
instance.task_name = task_definition.bpmn_name or ""
instance.task_name = task_definition.bpmn_name
instance.line_number = line_number
instance.offset = offset
instance.error_type = error_type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ class UserDoesNotHaveAccessToTaskError(Exception):

class InvalidPermissionError(Exception):
pass


class InvalidRedirectUrlError(Exception):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from werkzeug.wrappers import Response

from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.exceptions.error import InvalidRedirectUrlError
from spiffworkflow_backend.exceptions.error import MissingAccessTokenError
from spiffworkflow_backend.exceptions.error import TokenExpiredError
from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX
Expand Down Expand Up @@ -99,6 +100,12 @@ def login(
process_instance_id: int | None = None,
task_guid: str | None = None,
) -> Response:
frontend_url = str(current_app.config.get("SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND"))
if not redirect_url.startswith(frontend_url):
raise InvalidRedirectUrlError(
f"Invalid redirect url was given: '{redirect_url}'. It must match the domain the frontend is running on."
)

if current_app.config.get("SPIFFWORKFLOW_BACKEND_AUTHENTICATION_DISABLED"):
AuthenticationService.create_guest_token(
username=SPIFF_NO_AUTH_USER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ class ReactJsonSchemaSelectOption(TypedDict):
enum: list[str]


def task_allows_guest(
process_instance_id: int,
task_guid: str,
) -> flask.wrappers.Response:
allows_guest = False
if process_instance_id and task_guid and TaskModel.task_guid_allows_guest(task_guid, process_instance_id):
allows_guest = True
return make_response(jsonify({"allows_guest": allows_guest}), 200)


# this is currently not used by the Frontend
def task_list_my_tasks(
process_instance_id: int | None = None, page: int = 1, per_page: int = 100
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import time

from flask import current_app

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService

from tests.spiffworkflow_backend.helpers.base_test import BaseTest


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from flask import g
from flask import redirect
from flask import request
from werkzeug.wrappers import Response

from spiffworkflow_backend.config import HTTP_REQUEST_TIMEOUT_SECONDS
from spiffworkflow_backend.exceptions.error import OpenIdConnectionError
from spiffworkflow_backend.exceptions.error import RefreshTokenStorageError
Expand All @@ -23,7 +25,6 @@
from spiffworkflow_backend.models.refresh_token import RefreshTokenModel
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.user_service import UserService
from werkzeug.wrappers import Response


class AuthenticationProviderTypes(enum.Enum):
Expand Down Expand Up @@ -146,7 +147,6 @@ def get_login_redirect_url(
+ "scope=openid profile email&"
+ f"redirect_uri={return_redirect_url}"
)
print(f"login_redirect_url: {login_redirect_url}")
return login_redirect_url

def get_auth_token_object(
Expand All @@ -173,7 +173,6 @@ def get_auth_token_object(

response = requests.post(request_url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT_SECONDS)
auth_token_object: dict = json.loads(response.text)
print(f"auth_token_object: {auth_token_object}")
return auth_token_object

@classmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
from flask import g
from flask import request
from flask import scaffold
from sqlalchemy import and_
from sqlalchemy import func
from sqlalchemy import literal
from sqlalchemy import or_

from spiffworkflow_backend.exceptions.error import HumanTaskAlreadyCompletedError
from spiffworkflow_backend.exceptions.error import HumanTaskNotFoundError
from spiffworkflow_backend.exceptions.error import InvalidPermissionError
Expand Down Expand Up @@ -34,10 +39,6 @@
from spiffworkflow_backend.models.user_group_assignment_waiting import UserGroupAssignmentWaitingModel
from spiffworkflow_backend.routes.openid_blueprint import openid_blueprint
from spiffworkflow_backend.services.user_service import UserService
from sqlalchemy import and_
from sqlalchemy import func
from sqlalchemy import literal
from sqlalchemy import or_


@dataclass
Expand Down Expand Up @@ -228,11 +229,15 @@ def create_permission_for_principal(
def should_disable_auth_for_request(cls) -> bool:
swagger_functions = ["get_json_spec"]
authentication_exclusion_list = [
"status",
"test_raise_error",
"authentication_begin",
"authentication_callback",
"authentication_options",
"github_webhook_receive",
"prometheus_metrics",
"status",
"task_allows_guest",
"test_raise_error",
"url_info",
]
if request.method == "OPTIONS":
return True
Expand All @@ -250,10 +255,6 @@ def should_disable_auth_for_request(cls) -> bool:
api_view_function
and api_view_function.__name__.startswith("login")
or api_view_function.__name__.startswith("logout")
or api_view_function.__name__.startswith("authentication_options")
or api_view_function.__name__.startswith("prom")
or api_view_function.__name__ == "url_info"
or api_view_function.__name__.startswith("metric")
or api_view_function.__name__.startswith("console_ui_")
or api_view_function.__name__ in authentication_exclusion_list
or api_view_function.__name__ in swagger_functions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import flask

from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.services.message_service import MessageService
from spiffworkflow_backend.services.process_instance_lock_service import ProcessInstanceLockService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore
from SpiffWorkflow.spiff.parser.process import SpiffBpmnParser # type: ignore
from SpiffWorkflow.spiff.parser.task_spec import ServiceTaskParser # type: ignore

from spiffworkflow_backend.data_stores import register_data_store_classes
from spiffworkflow_backend.services.service_task_service import CustomServiceTask
from spiffworkflow_backend.specs.start_event import StartEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os

from flask import current_app

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.reference_cache import ReferenceCacheModel
from spiffworkflow_backend.services.file_system_service import FileSystemService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from flask import current_app
from flask import g

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pytz
from flask import current_app

from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.file import CONTENT_TYPES
from spiffworkflow_backend.models.file import File
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from flask import current_app
from flask import g

from spiffworkflow_backend.config import ConfigurationError
from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.services.data_setup_service import DataSetupService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from jinja2 import TemplateSyntaxError
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskException # type: ignore
from SpiffWorkflow.task import Task as SpiffTask # type: ignore

from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
from spiffworkflow_backend.services.task_service import TaskModelError
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from SpiffWorkflow.bpmn.event import BpmnEvent # type: ignore
from SpiffWorkflow.bpmn.specs.event_definitions.message import CorrelationProperty # type: ignore
from SpiffWorkflow.spiff.specs.event_definitions import MessageEventDefinition # type: ignore

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.message_instance import MessageStatuses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from flask import Flask
from flask import session
from flask_oauthlib.client import OAuth # type: ignore

from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.services.configuration_service import ConfigurationService
from spiffworkflow_backend.services.secret_service import SecretService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sqlalchemy import or_

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_caller import ProcessCallerCacheModel
from sqlalchemy import or_


class ProcessCallerService:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from typing import Any

from flask import current_app
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance_queue import ProcessInstanceQueueModel
from sqlalchemy import and_
from sqlalchemy import or_

from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance_queue import ProcessInstanceQueueModel


class ExpectedLockNotFoundError(Exception):
pass
Expand Down
Loading

0 comments on commit 9c482cd

Please sign in to comment.