added authentication callback endpoint. w/ burnettk, cullerton, jbirddog

This commit is contained in:
jasquat 2022-10-19 14:19:12 -04:00
parent 1902b785d9
commit 72049c0041
8 changed files with 85 additions and 12 deletions

View File

@ -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'),

2
poetry.lock generated
View File

@ -639,7 +639,7 @@ werkzeug = "*"
type = "git"
url = "https://github.com/sartography/flask-bpmn"
reference = "main"
resolved_reference = "5edb83f662a6da2c8ce0dea8992ef8602218828f"
resolved_reference = "6e1411dd134955a829bb9f3d59b4af121907cd35"
[[package]]
name = "Flask-Cors"

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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",

View File

@ -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

View File

@ -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')