Squashed 'spiffworkflow-backend/' changes from 57ba8e0c8..72049c004
72049c004 added authentication callback endpoint. w/ burnettk, cullerton, jbirddog 1902b785d updated flask-bpmn w/ burnettk cullerton git-subtree-dir: spiffworkflow-backend git-subtree-split: 72049c00413ab9aa7d4c65b77247583654c06488
This commit is contained in:
parent
9781908243
commit
a166df8303
|
@ -1,8 +1,8 @@
|
||||||
"""empty message
|
"""empty message
|
||||||
|
|
||||||
Revision ID: b41f0d35641a
|
Revision ID: 3a95e16cf17c
|
||||||
Revises:
|
Revises:
|
||||||
Create Date: 2022-10-18 16:16:23.575571
|
Create Date: 2022-10-19 12:42:38.086243
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from alembic import op
|
from alembic import op
|
||||||
|
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'b41f0d35641a'
|
revision = '3a95e16cf17c'
|
||||||
down_revision = None
|
down_revision = None
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
@ -137,7 +137,7 @@ def upgrade():
|
||||||
op.create_table('secret',
|
op.create_table('secret',
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
sa.Column('key', sa.String(length=50), nullable=False),
|
sa.Column('key', sa.String(length=50), nullable=False),
|
||||||
sa.Column('value', sa.String(length=255), nullable=False),
|
sa.Column('value', sa.Text(), nullable=False),
|
||||||
sa.Column('creator_user_id', sa.Integer(), nullable=False),
|
sa.Column('creator_user_id', sa.Integer(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['creator_user_id'], ['user.id'], ),
|
sa.ForeignKeyConstraint(['creator_user_id'], ['user.id'], ),
|
||||||
sa.PrimaryKeyConstraint('id'),
|
sa.PrimaryKeyConstraint('id'),
|
|
@ -639,7 +639,7 @@ werkzeug = "*"
|
||||||
type = "git"
|
type = "git"
|
||||||
url = "https://github.com/sartography/flask-bpmn"
|
url = "https://github.com/sartography/flask-bpmn"
|
||||||
reference = "main"
|
reference = "main"
|
||||||
resolved_reference = "42cebab51fe469ab9dcb45672917d34c1f30987a"
|
resolved_reference = "6e1411dd134955a829bb9f3d59b4af121907cd35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "Flask-Cors"
|
name = "Flask-Cors"
|
||||||
|
@ -1847,8 +1847,8 @@ test = ["pytest"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "SpiffWorkflow"
|
name = "SpiffWorkflow"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
description = "A workflow framework and BPMN/DMN Processor"
|
description = ""
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
@ -1858,7 +1858,6 @@ develop = false
|
||||||
celery = "*"
|
celery = "*"
|
||||||
configparser = "*"
|
configparser = "*"
|
||||||
dateparser = "*"
|
dateparser = "*"
|
||||||
importlib-metadata = "<5.0"
|
|
||||||
lxml = "*"
|
lxml = "*"
|
||||||
pytz = "*"
|
pytz = "*"
|
||||||
|
|
||||||
|
@ -1866,7 +1865,7 @@ pytz = "*"
|
||||||
type = "git"
|
type = "git"
|
||||||
url = "https://github.com/sartography/SpiffWorkflow"
|
url = "https://github.com/sartography/SpiffWorkflow"
|
||||||
reference = "main"
|
reference = "main"
|
||||||
resolved_reference = "d9fcd45a384f8376a669cf58677564289d2c661c"
|
resolved_reference = "a094adad8767f82e9c5fa806a46597e066252a72"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "SQLAlchemy"
|
name = "SQLAlchemy"
|
||||||
|
|
|
@ -951,6 +951,47 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/ServiceTask"
|
$ref: "#/components/schemas/ServiceTask"
|
||||||
|
|
||||||
|
/authentication_callback/{service}/{auth_method}:
|
||||||
|
parameters:
|
||||||
|
- name: service
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The name of the service
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: auth_method
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The method
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: response
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
description: The response
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: token
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
description: The response
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
get:
|
||||||
|
# disable security so we can get the token from query params instead
|
||||||
|
security: []
|
||||||
|
tags:
|
||||||
|
- Authentications
|
||||||
|
operationId: spiffworkflow_backend.routes.process_api_blueprint.authentication_callback
|
||||||
|
summary: Callback to backend
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: All authentications
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ServiceTask"
|
||||||
|
|
||||||
/tasks/{process_instance_id}/{task_id}:
|
/tasks/{process_instance_id}/{task_id}:
|
||||||
parameters:
|
parameters:
|
||||||
- name: task_id
|
- name: task_id
|
||||||
|
|
|
@ -16,7 +16,7 @@ class SecretModel(SpiffworkflowBaseDBModel):
|
||||||
__tablename__ = "secret"
|
__tablename__ = "secret"
|
||||||
id: int = db.Column(db.Integer, primary_key=True)
|
id: int = db.Column(db.Integer, primary_key=True)
|
||||||
key: str = db.Column(db.String(50), unique=True, nullable=False)
|
key: str = db.Column(db.String(50), unique=True, nullable=False)
|
||||||
value: str = db.Column(db.String(255), nullable=False)
|
value: str = db.Column(db.Text(), nullable=False)
|
||||||
creator_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
creator_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,13 @@ from typing import Union
|
||||||
import connexion # type: ignore
|
import connexion # type: ignore
|
||||||
import flask.wrappers
|
import flask.wrappers
|
||||||
import jinja2
|
import jinja2
|
||||||
|
import werkzeug
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask import g
|
from flask import g
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
from flask import make_response
|
from flask import make_response
|
||||||
|
from flask import redirect
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask.wrappers import Response
|
from flask.wrappers import Response
|
||||||
from flask_bpmn.api.api_error import ApiError
|
from flask_bpmn.api.api_error import ApiError
|
||||||
|
@ -52,6 +54,7 @@ from spiffworkflow_backend.models.secret_model import SecretModel
|
||||||
from spiffworkflow_backend.models.secret_model import SecretModelSchema
|
from spiffworkflow_backend.models.secret_model import SecretModelSchema
|
||||||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
||||||
from spiffworkflow_backend.models.user import UserModel
|
from spiffworkflow_backend.models.user import UserModel
|
||||||
|
from spiffworkflow_backend.routes.user import verify_token
|
||||||
from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService
|
from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService
|
||||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||||
from spiffworkflow_backend.services.git_service import GitService
|
from spiffworkflow_backend.services.git_service import GitService
|
||||||
|
@ -780,11 +783,28 @@ def authentication_list() -> flask.wrappers.Response:
|
||||||
response_json = {
|
response_json = {
|
||||||
"results": available_authentications,
|
"results": available_authentications,
|
||||||
"connector_proxy_base_url": current_app.config["CONNECTOR_PROXY_URL"],
|
"connector_proxy_base_url": current_app.config["CONNECTOR_PROXY_URL"],
|
||||||
|
"redirect_url": f"{current_app.config['SPIFFWORKFLOW_BACKEND_URL']}/v1.0/authentication_callback",
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response(json.dumps(response_json), status=200, mimetype="application/json")
|
return Response(json.dumps(response_json), status=200, mimetype="application/json")
|
||||||
|
|
||||||
|
|
||||||
|
def authentication_callback(
|
||||||
|
service: str,
|
||||||
|
auth_method: str,
|
||||||
|
) -> werkzeug.wrappers.Response:
|
||||||
|
"""Authentication_callback."""
|
||||||
|
verify_token(request.args.get("token"))
|
||||||
|
response = request.args["response"]
|
||||||
|
print(f"response: {response}")
|
||||||
|
SecretService().update_secret(
|
||||||
|
f"{service}/{auth_method}", response, g.user.id, create_if_not_exists=True
|
||||||
|
)
|
||||||
|
return redirect(
|
||||||
|
f"{current_app.config['SPIFFWORKFLOW_FRONTEND_URL']}/admin/authentications"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def process_instance_report_show(
|
def process_instance_report_show(
|
||||||
process_group_id: str,
|
process_group_id: str,
|
||||||
process_model_id: str,
|
process_model_id: str,
|
||||||
|
|
|
@ -69,7 +69,8 @@ class SecretService:
|
||||||
def update_secret(
|
def update_secret(
|
||||||
key: str,
|
key: str,
|
||||||
value: str,
|
value: str,
|
||||||
creator_user_id: Optional[int] = None,
|
creator_user_id: int,
|
||||||
|
create_if_not_exists: Optional[bool] = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Does this pass pre commit?"""
|
"""Does this pass pre commit?"""
|
||||||
secret_model = SecretModel.query.filter(SecretModel.key == key).first()
|
secret_model = SecretModel.query.filter(SecretModel.key == key).first()
|
||||||
|
@ -80,16 +81,18 @@ class SecretService:
|
||||||
try:
|
try:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ApiError(
|
db.session.rollback()
|
||||||
error_code="update_secret_error",
|
raise e
|
||||||
message=f"There was an error updating the secret with key: {key}, and value: {value}",
|
|
||||||
) from e
|
|
||||||
else:
|
else:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
error_code="update_secret_error",
|
error_code="update_secret_error",
|
||||||
message=f"User: {creator_user_id} cannot update the secret with key : {key}",
|
message=f"User: {creator_user_id} cannot update the secret with key : {key}",
|
||||||
status_code=401,
|
status_code=401,
|
||||||
)
|
)
|
||||||
|
elif create_if_not_exists:
|
||||||
|
SecretService.add_secret(
|
||||||
|
key=key, value=value, creator_user_id=creator_user_id
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
error_code="update_secret_error",
|
error_code="update_secret_error",
|
||||||
|
|
|
@ -90,5 +90,4 @@ class ServiceTaskService:
|
||||||
parsed_response = json.loads(response.text)
|
parsed_response = json.loads(response.text)
|
||||||
return parsed_response
|
return parsed_response
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
current_app.logger.error(exception)
|
|
||||||
raise ConnectorProxyError(exception.__class__.__name__) from exception
|
raise ConnectorProxyError(exception.__class__.__name__) from exception
|
||||||
|
|
|
@ -1560,6 +1560,16 @@ class TestProcessApi(BaseTest):
|
||||||
assert response.json is not None
|
assert response.json is not None
|
||||||
assert len(response.json["results"]) == 2
|
assert len(response.json["results"]) == 2
|
||||||
|
|
||||||
|
# TODO: test the auth callback endpoint
|
||||||
|
# def test_can_store_authentication_secret(
|
||||||
|
# self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||||
|
# ) -> None:
|
||||||
|
# """Test_can_store_authentication_secret."""
|
||||||
|
# response = client.get(
|
||||||
|
# "/v1.0/authentication_callback",
|
||||||
|
# headers=self.logged_in_headers(user),
|
||||||
|
# )
|
||||||
|
|
||||||
# def test_get_process_model(self):
|
# def test_get_process_model(self):
|
||||||
#
|
#
|
||||||
# load_test_spec('random_fact')
|
# load_test_spec('random_fact')
|
||||||
|
|
Loading…
Reference in New Issue