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
|
||||
|
||||
Revision ID: b41f0d35641a
|
||||
Revision ID: 3a95e16cf17c
|
||||
Revises:
|
||||
Create Date: 2022-10-18 16:16:23.575571
|
||||
Create Date: 2022-10-19 12:42:38.086243
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
|
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
|||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'b41f0d35641a'
|
||||
revision = '3a95e16cf17c'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
@ -137,7 +137,7 @@ def upgrade():
|
|||
op.create_table('secret',
|
||||
sa.Column('id', sa.Integer(), 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.ForeignKeyConstraint(['creator_user_id'], ['user.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
|
@ -639,7 +639,7 @@ werkzeug = "*"
|
|||
type = "git"
|
||||
url = "https://github.com/sartography/flask-bpmn"
|
||||
reference = "main"
|
||||
resolved_reference = "42cebab51fe469ab9dcb45672917d34c1f30987a"
|
||||
resolved_reference = "6e1411dd134955a829bb9f3d59b4af121907cd35"
|
||||
|
||||
[[package]]
|
||||
name = "Flask-Cors"
|
||||
|
@ -1847,8 +1847,8 @@ test = ["pytest"]
|
|||
|
||||
[[package]]
|
||||
name = "SpiffWorkflow"
|
||||
version = "1.2.0"
|
||||
description = "A workflow framework and BPMN/DMN Processor"
|
||||
version = "1.2.1"
|
||||
description = ""
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
@ -1858,7 +1858,6 @@ develop = false
|
|||
celery = "*"
|
||||
configparser = "*"
|
||||
dateparser = "*"
|
||||
importlib-metadata = "<5.0"
|
||||
lxml = "*"
|
||||
pytz = "*"
|
||||
|
||||
|
@ -1866,7 +1865,7 @@ pytz = "*"
|
|||
type = "git"
|
||||
url = "https://github.com/sartography/SpiffWorkflow"
|
||||
reference = "main"
|
||||
resolved_reference = "d9fcd45a384f8376a669cf58677564289d2c661c"
|
||||
resolved_reference = "a094adad8767f82e9c5fa806a46597e066252a72"
|
||||
|
||||
[[package]]
|
||||
name = "SQLAlchemy"
|
||||
|
|
|
@ -951,6 +951,47 @@ paths:
|
|||
schema:
|
||||
$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}:
|
||||
parameters:
|
||||
- name: task_id
|
||||
|
|
|
@ -16,7 +16,7 @@ class SecretModel(SpiffworkflowBaseDBModel):
|
|||
__tablename__ = "secret"
|
||||
id: int = db.Column(db.Integer, primary_key=True)
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -13,11 +13,13 @@ from typing import Union
|
|||
import connexion # type: ignore
|
||||
import flask.wrappers
|
||||
import jinja2
|
||||
import werkzeug
|
||||
from flask import Blueprint
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import jsonify
|
||||
from flask import make_response
|
||||
from flask import redirect
|
||||
from flask import request
|
||||
from flask.wrappers import Response
|
||||
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.spiff_logging import SpiffLoggingModel
|
||||
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.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.git_service import GitService
|
||||
|
@ -780,11 +783,28 @@ def authentication_list() -> flask.wrappers.Response:
|
|||
response_json = {
|
||||
"results": available_authentications,
|
||||
"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")
|
||||
|
||||
|
||||
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(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
|
|
|
@ -69,7 +69,8 @@ class SecretService:
|
|||
def update_secret(
|
||||
key: str,
|
||||
value: str,
|
||||
creator_user_id: Optional[int] = None,
|
||||
creator_user_id: int,
|
||||
create_if_not_exists: Optional[bool] = False,
|
||||
) -> None:
|
||||
"""Does this pass pre commit?"""
|
||||
secret_model = SecretModel.query.filter(SecretModel.key == key).first()
|
||||
|
@ -80,16 +81,18 @@ class SecretService:
|
|||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
raise ApiError(
|
||||
error_code="update_secret_error",
|
||||
message=f"There was an error updating the secret with key: {key}, and value: {value}",
|
||||
) from e
|
||||
db.session.rollback()
|
||||
raise e
|
||||
else:
|
||||
raise ApiError(
|
||||
error_code="update_secret_error",
|
||||
message=f"User: {creator_user_id} cannot update the secret with key : {key}",
|
||||
status_code=401,
|
||||
)
|
||||
elif create_if_not_exists:
|
||||
SecretService.add_secret(
|
||||
key=key, value=value, creator_user_id=creator_user_id
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
error_code="update_secret_error",
|
||||
|
|
|
@ -90,5 +90,4 @@ class ServiceTaskService:
|
|||
parsed_response = json.loads(response.text)
|
||||
return parsed_response
|
||||
except Exception as exception:
|
||||
current_app.logger.error(exception)
|
||||
raise ConnectorProxyError(exception.__class__.__name__) from exception
|
||||
|
|
|
@ -1560,6 +1560,16 @@ class TestProcessApi(BaseTest):
|
|||
assert response.json is not None
|
||||
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):
|
||||
#
|
||||
# load_test_spec('random_fact')
|
||||
|
|
Loading…
Reference in New Issue