mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-01-11 18:54:25 +00:00
Squashed 'spiffworkflow-backend/' changes from 153061d4..1092ed11
1092ed11 Merge branch 'main' of github.com:sartography/spiffworkflow-backend into main 97b96fa9 Merge commit '999e0f4d2b7a3c3665feb806fd4f00dc50f2de8e' 4d2ebbe2 Refresh token (#6) 2c47d862 Revert "Assure that the Active Task Users table is cleared out before deleting the Active Task Record." 6c1660a3 Merge commit 'eff49e1ddb2e70d62e45866b429a1350443107d0' into main f7949ada Merge commit 'ac929cbae7717affed5fa357a56cf1a0256289d5' into main b70804ea Merge commit '65283df3cbfe95c6cd0d69e1cc0204d91c5d535b' 5b9ad7a7 Merge commit 'a59108db95274bef304cbd9246537206d0b449cf' 038c8e68 Merge commit '835160e5a82c7e0518fa25ed7fa1168c9c435739' aae7966b Merge commit 'a1cce807be1c4ac5f04c42d780df06c216a0de9c' 8527c6be Merge commit '7026fe1f779051f6eb99b872bcd45b14c0cbe88f' 1aa9a8da Merge commit '70480e9f91a1053531ea5db32a13a791c39fd89f' 40383711 Merge commit '9a1e33696a744527a18dbec667140edb4038ac94' 2c7b2e28 Merge commit 'd643de93e5ceaae28a6e65044cc85dd039530d2c' e5e70161 Merge commit '2b702661f3bd9b79de887e82e5a5925d07341eb6' b0b92474 updateing poetry lock file. e5fd3df1 Merge commit 'f0b608789b6cdc3ef4303efac053746c98571a48' dfe4e3e1 Merge commit 'c5a2f8b16c9a614b944a6e4610594eba1dac7b9f' into main 78dcaec3 pointless change git-subtree-dir: spiffworkflow-backend git-subtree-split: 1092ed11187d1b825fa1c5e18f0d96592f0b98e7
This commit is contained in:
parent
999e0f4d2b
commit
1f25521506
@ -90,3 +90,5 @@ This project was generated from `@cjolowicz`_'s `Hypermodern Python Cookiecutter
|
||||
.. github-only
|
||||
.. _Contributor Guide: CONTRIBUTING.rst
|
||||
.. _Usage: https://spiffworkflow-backend.readthedocs.io/en/latest/usage.html
|
||||
|
||||
(test)
|
||||
|
@ -1,8 +1,8 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 4ba2ed52a63a
|
||||
Revision ID: 3bd6b0b1b8ae
|
||||
Revises:
|
||||
Create Date: 2022-10-21 09:31:30.520942
|
||||
Create Date: 2022-10-25 12:31:50.177599
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '4ba2ed52a63a'
|
||||
revision = '3bd6b0b1b8ae'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@ -146,10 +146,10 @@ def upgrade():
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('key', sa.String(length=50), nullable=False),
|
||||
sa.Column('value', sa.Text(), nullable=False),
|
||||
sa.Column('creator_user_id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||
sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True),
|
||||
sa.Column('created_at_in_seconds', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['creator_user_id'], ['user.id'], ),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('key')
|
||||
)
|
@ -2117,8 +2117,8 @@ components:
|
||||
type: string
|
||||
example: my_super_secret_value
|
||||
nullable: false
|
||||
creator_user_id:
|
||||
description: The id of the logged in user that created this secret
|
||||
user_id:
|
||||
description: The id of the logged in user that updated this secret
|
||||
type: number
|
||||
example: 1
|
||||
nullable: false
|
||||
|
@ -17,7 +17,7 @@ class SecretModel(SpiffworkflowBaseDBModel):
|
||||
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.Text(), nullable=False)
|
||||
creator_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
||||
user_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
||||
updated_at_in_seconds: int = db.Column(db.Integer)
|
||||
created_at_in_seconds: int = db.Column(db.Integer)
|
||||
|
||||
@ -29,4 +29,4 @@ class SecretModelSchema(Schema):
|
||||
"""Meta."""
|
||||
|
||||
model = SecretModel
|
||||
fields = ["key", "value", "creator_user_id"]
|
||||
fields = ["key", "value", "user_id"]
|
||||
|
@ -1408,7 +1408,7 @@ def add_secret(body: Dict) -> Response:
|
||||
|
||||
def update_secret(key: str, body: dict) -> Response:
|
||||
"""Update secret."""
|
||||
SecretService().update_secret(key, body["value"], body["creator_user_id"])
|
||||
SecretService().update_secret(key, body["value"], body["user_id"])
|
||||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
||||
|
||||
|
||||
|
@ -522,10 +522,6 @@ class ProcessInstanceProcessor:
|
||||
).all()
|
||||
if len(active_tasks) > 0:
|
||||
for at in active_tasks:
|
||||
active_task_users = at.active_task_users
|
||||
for atu in active_task_users:
|
||||
# don't trust sqlalchemy to cascade - ran into race condition here.
|
||||
db.session.delete(atu)
|
||||
db.session.delete(at)
|
||||
|
||||
db.session.add(self.process_instance_model)
|
||||
|
@ -33,12 +33,12 @@ class SecretService:
|
||||
def add_secret(
|
||||
key: str,
|
||||
value: str,
|
||||
creator_user_id: int,
|
||||
user_id: int,
|
||||
) -> SecretModel:
|
||||
"""Add_secret."""
|
||||
# encrypted_key = self.encrypt_key(key)
|
||||
secret_model = SecretModel(
|
||||
key=key, value=value, creator_user_id=creator_user_id
|
||||
key=key, value=value, user_id=user_id
|
||||
)
|
||||
db.session.add(secret_model)
|
||||
try:
|
||||
@ -67,29 +67,22 @@ class SecretService:
|
||||
def update_secret(
|
||||
key: str,
|
||||
value: str,
|
||||
creator_user_id: int,
|
||||
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()
|
||||
if secret_model:
|
||||
if secret_model.creator_user_id == creator_user_id:
|
||||
secret_model.value = value
|
||||
db.session.add(secret_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as 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,
|
||||
)
|
||||
secret_model.value = value
|
||||
db.session.add(secret_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
raise e
|
||||
elif create_if_not_exists:
|
||||
SecretService.add_secret(
|
||||
key=key, value=value, creator_user_id=creator_user_id
|
||||
key=key, value=value, user_id=user_id
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
@ -103,21 +96,14 @@ class SecretService:
|
||||
"""Delete secret."""
|
||||
secret_model = SecretModel.query.filter(SecretModel.key == key).first()
|
||||
if secret_model:
|
||||
if secret_model.creator_user_id == user_id:
|
||||
db.session.delete(secret_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
raise ApiError(
|
||||
error_code="delete_secret_error",
|
||||
message=f"Could not delete secret with key: {key}. Original error is: {e}",
|
||||
) from e
|
||||
else:
|
||||
db.session.delete(secret_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
raise ApiError(
|
||||
error_code="delete_secret_error",
|
||||
message=f"User: {user_id} cannot delete the secret with key : {key}",
|
||||
status_code=401,
|
||||
)
|
||||
message=f"Could not delete secret with key: {key}. Original error is: {e}",
|
||||
) from e
|
||||
else:
|
||||
raise ApiError(
|
||||
error_code="delete_secret_error",
|
||||
|
@ -4,6 +4,7 @@ from typing import Any
|
||||
|
||||
import requests
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
|
||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.secret_service import SecretService
|
||||
@ -57,7 +58,20 @@ class ServiceTaskDelegate:
|
||||
if proxied_response.status_code != 200:
|
||||
print("got error from connector proxy")
|
||||
|
||||
return proxied_response.text
|
||||
parsed_response = json.loads(proxied_response.text)
|
||||
|
||||
if "refreshed_token_set" not in parsed_response:
|
||||
return proxied_response.text
|
||||
|
||||
secret_key = parsed_response["auth"]
|
||||
refreshed_token_set = json.dumps(
|
||||
parsed_response["refreshed_token_set"]
|
||||
)
|
||||
SecretService().update_secret(
|
||||
secret_key, refreshed_token_set, g.user.id
|
||||
)
|
||||
|
||||
return json.dumps(parsed_response["api_response"])
|
||||
|
||||
|
||||
class ServiceTaskService:
|
||||
|
@ -71,7 +71,7 @@ class TestSecretService(SecretServiceTestHelpers):
|
||||
assert test_secret is not None
|
||||
assert test_secret.key == self.test_key
|
||||
assert test_secret.value == self.test_value
|
||||
assert test_secret.creator_user_id == with_super_admin_user.id
|
||||
assert test_secret.user_id == with_super_admin_user.id
|
||||
|
||||
def test_add_secret_duplicate_key_fails(
|
||||
self,
|
||||
@ -129,24 +129,6 @@ class TestSecretService(SecretServiceTestHelpers):
|
||||
assert new_secret
|
||||
assert new_secret.value == "new_secret_value" # noqa: S105
|
||||
|
||||
def test_update_secret_bad_user_fails(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_update_secret_bad_user."""
|
||||
self.add_test_secret(with_super_admin_user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.update_secret(
|
||||
self.test_key, "new_secret_value", with_super_admin_user.id + 1
|
||||
) # noqa: S105
|
||||
assert (
|
||||
ae.value.message
|
||||
== f"User: {with_super_admin_user.id+1} cannot update the secret with key : test_key"
|
||||
)
|
||||
|
||||
def test_update_secret_bad_secret_fails(
|
||||
self,
|
||||
app: Flask,
|
||||
@ -174,27 +156,11 @@ class TestSecretService(SecretServiceTestHelpers):
|
||||
self.add_test_secret(with_super_admin_user)
|
||||
secrets = SecretModel.query.all()
|
||||
assert len(secrets) == 1
|
||||
assert secrets[0].creator_user_id == with_super_admin_user.id
|
||||
assert secrets[0].user_id == with_super_admin_user.id
|
||||
SecretService.delete_secret(self.test_key, with_super_admin_user.id)
|
||||
secrets = SecretModel.query.all()
|
||||
assert len(secrets) == 0
|
||||
|
||||
def test_delete_secret_bad_user_fails(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_delete_secret_bad_user."""
|
||||
self.add_test_secret(with_super_admin_user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.delete_secret(self.test_key, with_super_admin_user.id + 1)
|
||||
assert (
|
||||
f"User: {with_super_admin_user.id+1} cannot delete the secret with key"
|
||||
in ae.value.message
|
||||
)
|
||||
|
||||
def test_delete_secret_bad_secret_fails(
|
||||
self,
|
||||
app: Flask,
|
||||
@ -223,7 +189,7 @@ class TestSecretServiceApi(SecretServiceTestHelpers):
|
||||
secret_model = SecretModel(
|
||||
key=self.test_key,
|
||||
value=self.test_value,
|
||||
creator_user_id=with_super_admin_user.id,
|
||||
user_id=with_super_admin_user.id,
|
||||
)
|
||||
data = json.dumps(SecretModelSchema().dump(secret_model))
|
||||
response: TestResponse = client.post(
|
||||
@ -234,11 +200,11 @@ class TestSecretServiceApi(SecretServiceTestHelpers):
|
||||
)
|
||||
assert response.json
|
||||
secret: dict = response.json
|
||||
for key in ["key", "value", "creator_user_id"]:
|
||||
for key in ["key", "value", "user_id"]:
|
||||
assert key in secret.keys()
|
||||
assert secret["key"] == self.test_key
|
||||
assert secret["value"] == self.test_value
|
||||
assert secret["creator_user_id"] == with_super_admin_user.id
|
||||
assert secret["user_id"] == with_super_admin_user.id
|
||||
|
||||
def test_get_secret(
|
||||
self,
|
||||
@ -273,7 +239,7 @@ class TestSecretServiceApi(SecretServiceTestHelpers):
|
||||
secret_model = SecretModel(
|
||||
key=self.test_key,
|
||||
value="new_secret_value",
|
||||
creator_user_id=with_super_admin_user.id,
|
||||
user_id=with_super_admin_user.id,
|
||||
)
|
||||
response = client.put(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
@ -308,32 +274,6 @@ class TestSecretServiceApi(SecretServiceTestHelpers):
|
||||
with pytest.raises(ApiError):
|
||||
secret = SecretService.get_secret(self.test_key)
|
||||
|
||||
def test_delete_secret_bad_user(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_delete_secret_bad_user."""
|
||||
user_1 = self.find_or_create_user()
|
||||
user_2 = self.find_or_create_user("test_user_2")
|
||||
self.add_test_secret(user_1)
|
||||
|
||||
# ensure user has permissions to delete the given secret
|
||||
self.add_permissions_to_user(
|
||||
user_2,
|
||||
target_uri=f"/v1.0/secrets/{self.test_key}",
|
||||
permission_names=["delete"],
|
||||
)
|
||||
secret_response = client.delete(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
headers=self.logged_in_headers(user_2),
|
||||
)
|
||||
assert secret_response.status_code == 401
|
||||
assert secret_response.json
|
||||
assert secret_response.json["error_code"] == "delete_secret_error"
|
||||
|
||||
def test_delete_secret_bad_key(
|
||||
self,
|
||||
app: Flask,
|
||||
|
@ -1,49 +0,0 @@
|
||||
"""Process Model."""
|
||||
from decimal import Decimal
|
||||
|
||||
from flask.app import Flask
|
||||
from flask_bpmn.models.db import db
|
||||
|
||||
from spiffworkflow_backend.models.active_task import ActiveTaskModel
|
||||
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
||||
|
||||
|
||||
class TestActiveTask(BaseTest):
|
||||
|
||||
def test_can_create_and_delete_an_active_task (
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
process_model = load_test_spec(
|
||||
"call_activity_test",
|
||||
process_model_source_directory="call_activity_same_directory",
|
||||
)
|
||||
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model
|
||||
)
|
||||
active_task = ActiveTaskModel(
|
||||
process_instance_id=process_instance.id,
|
||||
process_model_display_name="my shorts",
|
||||
form_file_name="my_file_name",
|
||||
ui_form_file_name="",
|
||||
task_id="1234",
|
||||
task_name="any old thing",
|
||||
task_title="",
|
||||
task_type="test type",
|
||||
task_status="WAITING",
|
||||
lane_assignment_id=None,
|
||||
)
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
db.session.add(active_task)
|
||||
db.session.commit()
|
||||
active_task_user = ActiveTaskUserModel(active_task_id=active_task.id, user_id=initiator_user.id)
|
||||
db.session.add(active_task_user)
|
||||
db.session.commit()
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.save() # This should clear out all active tasks and active task users.
|
||||
assert(len(db.session.query(ActiveTaskModel).all()) == 0)
|
Loading…
x
Reference in New Issue
Block a user