mirror of
https://github.com/sartography/spiffworkflow-backend.git
synced 2025-02-23 21:08:18 +00:00
Merge remote-tracking branch 'origin/main' into feature/process_instance_search
This commit is contained in:
commit
4736e2878e
@ -1,8 +1,8 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: e9763012b98b
|
||||
Revision ID: 86bdc3330645
|
||||
Revises:
|
||||
Create Date: 2022-09-22 16:15:16.490215
|
||||
Create Date: 2022-09-22 18:01:10.013335
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e9763012b98b'
|
||||
revision = '86bdc3330645'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@ -126,6 +126,15 @@ def upgrade():
|
||||
op.create_index(op.f('ix_process_instance_report_identifier'), 'process_instance_report', ['identifier'], unique=False)
|
||||
op.create_index(op.f('ix_process_instance_report_process_group_identifier'), 'process_instance_report', ['process_group_identifier'], unique=False)
|
||||
op.create_index(op.f('ix_process_instance_report_process_model_identifier'), 'process_instance_report', ['process_model_identifier'], unique=False)
|
||||
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('creator_user_id', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['creator_user_id'], ['user.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('key')
|
||||
)
|
||||
op.create_table('user_group_assignment',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||
@ -205,6 +214,14 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('secret_allowed_process',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('secret_id', sa.Integer(), nullable=False),
|
||||
sa.Column('allowed_relative_path', sa.String(length=500), nullable=False),
|
||||
sa.ForeignKeyConstraint(['secret_id'], ['secret.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('secret_id', 'allowed_relative_path', name='unique_secret_path')
|
||||
)
|
||||
op.create_table('spiff_logging',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('process_instance_id', sa.Integer(), nullable=False),
|
||||
@ -277,6 +294,7 @@ def downgrade():
|
||||
op.drop_table('data_store')
|
||||
op.drop_table('task_event')
|
||||
op.drop_table('spiff_logging')
|
||||
op.drop_table('secret_allowed_process')
|
||||
op.drop_table('message_instance')
|
||||
op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation')
|
||||
op.drop_index(op.f('ix_message_correlation_process_instance_id'), table_name='message_correlation')
|
||||
@ -286,6 +304,7 @@ def downgrade():
|
||||
op.drop_table('file')
|
||||
op.drop_table('active_task')
|
||||
op.drop_table('user_group_assignment')
|
||||
op.drop_table('secret')
|
||||
op.drop_index(op.f('ix_process_instance_report_process_model_identifier'), table_name='process_instance_report')
|
||||
op.drop_index(op.f('ix_process_instance_report_process_group_identifier'), table_name='process_instance_report')
|
||||
op.drop_index(op.f('ix_process_instance_report_identifier'), table_name='process_instance_report')
|
@ -8,6 +8,8 @@ servers:
|
||||
- url: http://localhost:5000/v1.0
|
||||
security:
|
||||
- jwt: ["secret"]
|
||||
# - oAuth2AuthCode:
|
||||
# - read_email
|
||||
|
||||
paths:
|
||||
/login:
|
||||
@ -83,35 +85,47 @@ paths:
|
||||
"200":
|
||||
description: Logout Authenticated User
|
||||
|
||||
/login_swagger:
|
||||
parameters:
|
||||
- name: uid
|
||||
in: query
|
||||
required: true
|
||||
description: The user we are authenticating
|
||||
schema:
|
||||
type: string
|
||||
- name: password
|
||||
in: query
|
||||
required: true
|
||||
description: The password for the user
|
||||
schema:
|
||||
type: string
|
||||
format: password
|
||||
- name: redirect_url
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
get:
|
||||
security: []
|
||||
operationId: spiffworkflow_backend.routes.user.api_login
|
||||
summary: Authenticate user for API access
|
||||
tags:
|
||||
- Authentication
|
||||
responses:
|
||||
"304":
|
||||
description: Redirection to the hosted frontend with an auth_token header.
|
||||
# /login_api:
|
||||
# parameters:
|
||||
# - name: redirect_url
|
||||
# in: query
|
||||
# required: false
|
||||
# schema:
|
||||
# type: string
|
||||
# get:
|
||||
# security: []
|
||||
# operationId: spiffworkflow_backend.routes.user.login_api
|
||||
# summary: Authenticate user for API access
|
||||
# tags:
|
||||
# - Authentication
|
||||
# responses:
|
||||
# "304":
|
||||
# description: Redirection to the hosted frontend with an auth_token header.
|
||||
# /login_api_return:
|
||||
# parameters:
|
||||
# - name: code
|
||||
# in: query
|
||||
# required: true
|
||||
# schema:
|
||||
# type: string
|
||||
# - name: state
|
||||
# in: query
|
||||
# required: true
|
||||
# schema:
|
||||
# type: string
|
||||
# - name: session_state
|
||||
# in: query
|
||||
# required: false
|
||||
# schema:
|
||||
# type: string
|
||||
# get:
|
||||
# security: []
|
||||
# operationId: spiffworkflow_backend.routes.user.login_api_return
|
||||
# tags:
|
||||
# - Authentication
|
||||
# responses:
|
||||
# "200":
|
||||
# description: Test Return Response
|
||||
|
||||
/status:
|
||||
get:
|
||||
@ -127,7 +141,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-groups:
|
||||
parameters:
|
||||
@ -208,7 +222,7 @@ paths:
|
||||
description: The process group was deleted.
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_group_update
|
||||
summary: Upates a single process group
|
||||
summary: Updates a single process group
|
||||
tags:
|
||||
- Process Groups
|
||||
requestBody:
|
||||
@ -313,7 +327,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/File"
|
||||
$ref: "#/components/schemas/File"
|
||||
# get:
|
||||
# operationId: spiffworkflow_backend.api.process_api_blueprint.get_files
|
||||
# summary: Provide a list of workflow spec files for the given workflow_spec_id. IMPORTANT, only includes metadata, not the file content.
|
||||
@ -368,7 +382,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
# process model update
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_update
|
||||
@ -531,7 +545,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run:
|
||||
parameters:
|
||||
@ -604,7 +618,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/reports:
|
||||
parameters:
|
||||
@ -657,7 +671,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/reports/{report_identifier}:
|
||||
parameters:
|
||||
@ -716,7 +730,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_delete
|
||||
summary: Delete a process instance report
|
||||
@ -728,7 +742,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/files/{file_name}:
|
||||
parameters:
|
||||
@ -762,7 +776,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/File"
|
||||
$ref: "#/components/schemas/File"
|
||||
# process_model_file_update
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_file_update
|
||||
@ -786,7 +800,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_file_delete
|
||||
summary: Removes an existing process model file
|
||||
@ -798,7 +812,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#components/schemas/OkTrue"
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/tasks:
|
||||
parameters:
|
||||
@ -954,11 +968,6 @@ paths:
|
||||
- Messages
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.message_instance_list
|
||||
summary: Get a list of message instances
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
responses:
|
||||
"200":
|
||||
description: One task
|
||||
@ -1036,7 +1045,115 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
$ref: "#/components/schemas/ProcessInstanceLog"
|
||||
|
||||
/secrets:
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.add_secret
|
||||
summary: Create a secret for a key and value
|
||||
tags:
|
||||
- Secrets
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Secret"
|
||||
responses:
|
||||
"201":
|
||||
description: Secret created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: number
|
||||
|
||||
/secrets/{key}:
|
||||
parameters:
|
||||
- name: key
|
||||
in: path
|
||||
required: true
|
||||
description: The key we are using
|
||||
schema:
|
||||
type: string
|
||||
get:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.get_secret
|
||||
summary: Return a secret value for a key
|
||||
tags:
|
||||
- Secrets
|
||||
responses:
|
||||
"200":
|
||||
description: We return a secret
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.delete_secret
|
||||
summary: Delete an existing secret
|
||||
tags:
|
||||
- Secrets
|
||||
responses:
|
||||
"204":
|
||||
description: The secret is deleted
|
||||
"401":
|
||||
description: Unauthorized to delete secret
|
||||
"404":
|
||||
description: Secret does not exist
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.update_secret
|
||||
summary: Modify an existing secret
|
||||
tags:
|
||||
- Secrets
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Secret"
|
||||
responses:
|
||||
"200":
|
||||
description: Secret updated successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Secret"
|
||||
"401":
|
||||
description: Unauthorized to update secret
|
||||
"404":
|
||||
description: Secret does not exist
|
||||
|
||||
/secrets/allowed_process_paths:
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.add_allowed_process_path
|
||||
summary: Create an allowed process to a secret
|
||||
tags:
|
||||
- Secrets
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SecretAllowedProcessPath"
|
||||
responses:
|
||||
"201":
|
||||
description: Allowed process created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SecretAllowedProcessPath"
|
||||
/secrets/allowed_process_paths/{allowed_process_path_id}:
|
||||
parameters:
|
||||
- name: allowed_process_path_id
|
||||
in: path
|
||||
required: true
|
||||
description: The id of the allowed process path to delete
|
||||
schema:
|
||||
type: integer
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.delete_allowed_process_path
|
||||
summary: Delete an existing allowed process for a secret
|
||||
tags:
|
||||
- Secrets
|
||||
responses:
|
||||
"204":
|
||||
description: The allowed process is deleted.
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
@ -1046,6 +1163,18 @@ components:
|
||||
bearerFormat: JWT
|
||||
x-bearerInfoFunc: spiffworkflow_backend.routes.user.verify_token
|
||||
x-scopeValidateFunc: spiffworkflow_backend.routes.user.validate_scope
|
||||
|
||||
oAuth2AuthCode:
|
||||
type: oauth2
|
||||
description: authenticate with openid server
|
||||
flows:
|
||||
authorizationCode:
|
||||
authorizationUrl: /v1.0/login_api
|
||||
tokenUrl: /v1.0/login_return
|
||||
scopes:
|
||||
read_email: read email
|
||||
x-tokenInfoFunc: spiffworkflow_backend.routes.user.get_scope
|
||||
|
||||
schemas:
|
||||
OkTrue:
|
||||
properties:
|
||||
@ -1764,3 +1893,72 @@ components:
|
||||
untracked:
|
||||
type: array
|
||||
example: ["a_file.txt", "b_file.txt"]
|
||||
Secret:
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret we want to use
|
||||
type: string
|
||||
example: my_secret_key
|
||||
nullable: false
|
||||
value:
|
||||
description: The value associated with the key
|
||||
type: string
|
||||
example: my_super_secret_value
|
||||
nullable: false
|
||||
creator_user_id:
|
||||
description: The id of the logged in user that created this secret
|
||||
type: number
|
||||
example: 1
|
||||
nullable: false
|
||||
allowed_processes:
|
||||
description: The processes allowed to access this secret
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/SecretAllowedProcessPath"
|
||||
nullable: true
|
||||
ProcessInstanceLog:
|
||||
properties:
|
||||
id:
|
||||
description: The id of the log
|
||||
type: number
|
||||
example: 1
|
||||
nullable: false
|
||||
process_instance_id:
|
||||
description: The id of the associated process instance
|
||||
type: number
|
||||
example: 2
|
||||
nullable: false
|
||||
bpmn_process_identifier:
|
||||
description: The id of the bpmn process element
|
||||
type: string
|
||||
example: Process_SimpleProcess
|
||||
nullable: false
|
||||
task:
|
||||
description: The task identifier
|
||||
type: number
|
||||
example: 1234567890
|
||||
nullable: false
|
||||
message:
|
||||
description: The msg returned in the log
|
||||
type: string
|
||||
example: Some message returned in the log
|
||||
nullable: true
|
||||
timestamp:
|
||||
description: The timestamp returned in the log
|
||||
type: number
|
||||
example: 123456789.12345
|
||||
SecretAllowedProcessPath:
|
||||
properties:
|
||||
id:
|
||||
description: The id of the allowed process path
|
||||
type: number
|
||||
example: 1
|
||||
nullable: true
|
||||
secret_id:
|
||||
description: The id of the secret associated with this allowed process path
|
||||
type: number
|
||||
example: 2
|
||||
allowed_relative_path:
|
||||
description: The allowed process path
|
||||
type: string
|
||||
example: /group_one/group_two/model_a
|
||||
|
@ -27,9 +27,11 @@ from spiffworkflow_backend.models.process_instance import (
|
||||
from spiffworkflow_backend.models.process_instance_report import (
|
||||
ProcessInstanceReportModel,
|
||||
) # noqa: F401
|
||||
from spiffworkflow_backend.models.spiff_logging import (
|
||||
SpiffLoggingModel,
|
||||
from spiffworkflow_backend.models.secret_model import (
|
||||
SecretAllowedProcessPathModel,
|
||||
) # noqa: F401
|
||||
from spiffworkflow_backend.models.secret_model import SecretModel # noqa: F401
|
||||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel # noqa: F401
|
||||
from spiffworkflow_backend.models.task_event import TaskEventModel # noqa: F401
|
||||
from spiffworkflow_backend.models.user import UserModel # noqa: F401
|
||||
from spiffworkflow_backend.models.user_group_assignment import (
|
||||
|
58
src/spiffworkflow_backend/models/secret_model.py
Normal file
58
src/spiffworkflow_backend/models/secret_model.py
Normal file
@ -0,0 +1,58 @@
|
||||
"""Secret_model."""
|
||||
from flask_bpmn.models.db import db
|
||||
from flask_bpmn.models.db import SpiffworkflowBaseDBModel
|
||||
from marshmallow import Schema
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
|
||||
|
||||
class SecretModel(SpiffworkflowBaseDBModel):
|
||||
"""SecretModel."""
|
||||
|
||||
__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)
|
||||
creator_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
||||
|
||||
allowed_processes = relationship("SecretAllowedProcessPathModel", cascade="delete")
|
||||
|
||||
|
||||
class SecretModelSchema(Schema):
|
||||
"""SecretModelSchema."""
|
||||
|
||||
class Meta:
|
||||
"""Meta."""
|
||||
|
||||
model = SecretModel
|
||||
fields = ["key", "value", "creator_user_id"]
|
||||
|
||||
|
||||
class SecretAllowedProcessPathModel(SpiffworkflowBaseDBModel):
|
||||
"""Allowed processes can be Process Groups or Process Models.
|
||||
|
||||
We store the path in either case.
|
||||
"""
|
||||
|
||||
__tablename__ = "secret_allowed_process"
|
||||
__table_args__ = (
|
||||
db.UniqueConstraint(
|
||||
"secret_id", "allowed_relative_path", name="unique_secret_path"
|
||||
),
|
||||
)
|
||||
|
||||
id: int = db.Column(db.Integer, primary_key=True)
|
||||
secret_id: int = db.Column(ForeignKey(SecretModel.id), nullable=False) # type: ignore
|
||||
allowed_relative_path: str = db.Column(db.String(500), nullable=False)
|
||||
|
||||
|
||||
class SecretAllowedProcessSchema(Schema):
|
||||
"""SecretAllowedProcessSchema."""
|
||||
|
||||
class Meta:
|
||||
"""Meta."""
|
||||
|
||||
model = SecretAllowedProcessPathModel
|
||||
fields = ["secret_id", "allowed_relative_path"]
|
@ -43,6 +43,8 @@ from spiffworkflow_backend.models.process_instance_report import (
|
||||
)
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
|
||||
from spiffworkflow_backend.models.secret_model import SecretAllowedProcessSchema
|
||||
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.services.error_handling_service import ErrorHandlingService
|
||||
@ -55,8 +57,10 @@ from spiffworkflow_backend.services.process_instance_service import (
|
||||
ProcessInstanceService,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.secret_service import SecretService
|
||||
from spiffworkflow_backend.services.service_task_service import ServiceTaskService
|
||||
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||
from spiffworkflow_backend.services.user_service import UserService
|
||||
|
||||
process_api_blueprint = Blueprint("process_api", __name__)
|
||||
|
||||
@ -283,7 +287,6 @@ def process_model_file_delete(
|
||||
|
||||
def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Response:
|
||||
"""Add_file."""
|
||||
ProcessModelService()
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
request_file = get_file_from_request()
|
||||
if not request_file.filename:
|
||||
@ -1096,3 +1099,52 @@ def get_spiff_task_from_process_instance(
|
||||
)
|
||||
)
|
||||
return spiff_task
|
||||
|
||||
|
||||
#
|
||||
# Methods for secrets CRUD - maybe move somewhere else:
|
||||
#
|
||||
def get_secret(key: str) -> str | None:
|
||||
"""Get_secret."""
|
||||
return SecretService.get_secret(key)
|
||||
|
||||
|
||||
def add_secret(body: Dict) -> Response:
|
||||
"""Add secret."""
|
||||
secret_model = SecretService().add_secret(
|
||||
body["key"], body["value"], body["creator_user_id"]
|
||||
)
|
||||
assert secret_model # noqa: S101
|
||||
return Response(
|
||||
json.dumps(SecretModelSchema().dump(secret_model)),
|
||||
status=201,
|
||||
mimetype="application/json",
|
||||
)
|
||||
|
||||
|
||||
def update_secret(key: str, body: dict) -> None:
|
||||
"""Update secret."""
|
||||
SecretService().update_secret(key, body["value"], body["creator_user_id"])
|
||||
|
||||
|
||||
def delete_secret(key: str) -> None:
|
||||
"""Delete secret."""
|
||||
current_user = UserService.current_user()
|
||||
SecretService.delete_secret(key, current_user.id)
|
||||
|
||||
|
||||
def add_allowed_process_path(body: dict) -> Any:
|
||||
"""Get allowed process paths."""
|
||||
allowed_process_path = SecretService.add_allowed_process(
|
||||
body["secret_id"], g.user.id, body["allowed_relative_path"]
|
||||
)
|
||||
return Response(
|
||||
json.dumps(SecretAllowedProcessSchema().dump(allowed_process_path)),
|
||||
status=201,
|
||||
mimetype="application/json",
|
||||
)
|
||||
|
||||
|
||||
def delete_allowed_process_path(allowed_process_path_id: int) -> Any:
|
||||
"""Get allowed process paths."""
|
||||
SecretService().delete_allowed_process(allowed_process_path_id, g.user.id)
|
||||
|
@ -151,22 +151,41 @@ def validate_scope(token: Any) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def api_login(uid: str, password: str, redirect_url: Optional[str] = None) -> dict:
|
||||
"""Api_login."""
|
||||
# TODO: Fix this! mac 20220801
|
||||
# token:dict = PublicAuthenticationService().get_public_access_token(uid, password)
|
||||
# g.token = token
|
||||
#
|
||||
# return token
|
||||
return {}
|
||||
# def login_api(redirect_url: str = "/v1.0/ui") -> Response:
|
||||
# """Api_login."""
|
||||
# # TODO: Fix this! mac 20220801
|
||||
# # token:dict = PublicAuthenticationService().get_public_access_token(uid, password)
|
||||
# #
|
||||
# # return token
|
||||
# # if uid:
|
||||
# # sub = f"service:internal::service_id:{uid}"
|
||||
# # token = encode_auth_token(sub)
|
||||
# # user_model = UserModel(username=uid,
|
||||
# # uid=uid,
|
||||
# # service='internal',
|
||||
# # name="API User")
|
||||
# # g.user = user_model
|
||||
# #
|
||||
# # g.token = token
|
||||
# # scope = get_scope(token)
|
||||
# # return token
|
||||
# # return {"uid": uid, "sub": uid, "scope": scope}
|
||||
# return login(redirect_url)
|
||||
|
||||
|
||||
def encode_auth_token(uid: str) -> str:
|
||||
# def login_api_return(code: str, state: str, session_state: str) -> Optional[Response]:
|
||||
# print("login_api_return")
|
||||
|
||||
|
||||
def encode_auth_token(sub: str, token_type: Optional[str] = None) -> str:
|
||||
"""Generates the Auth Token.
|
||||
|
||||
:return: string
|
||||
"""
|
||||
payload = {"sub": uid}
|
||||
payload = {"sub": sub}
|
||||
if token_type is None:
|
||||
token_type = "internal" # noqa: S105
|
||||
payload["token_type"] = token_type
|
||||
if "SECRET_KEY" in current_app.config:
|
||||
secret_key = current_app.config.get("SECRET_KEY")
|
||||
else:
|
||||
@ -304,4 +323,15 @@ def get_user_from_decoded_internal_token(decoded_token: dict) -> Optional[UserMo
|
||||
.filter(UserModel.service_id == service_id)
|
||||
.first()
|
||||
)
|
||||
# user: UserModel = UserModel.query.filter()
|
||||
if user:
|
||||
return user
|
||||
user = UserModel(
|
||||
username=service_id,
|
||||
uid=service_id,
|
||||
service=service,
|
||||
service_id=service_id,
|
||||
name="API User",
|
||||
)
|
||||
|
||||
return user
|
||||
|
@ -132,7 +132,9 @@ def setup_logger(app: Flask) -> None:
|
||||
|
||||
spiff_logger_filehandler = None
|
||||
if app.config["SPIFFWORKFLOW_BACKEND_LOG_TO_FILE"]:
|
||||
spiff_logger_filehandler = logging.FileHandler(f"log/{app.env}.log")
|
||||
spiff_logger_filehandler = logging.FileHandler(
|
||||
f"{app.root_path}/../../log/{app.env}.log"
|
||||
)
|
||||
spiff_logger_filehandler.setLevel(spiff_log_level)
|
||||
spiff_logger_filehandler.setFormatter(log_formatter)
|
||||
|
||||
|
204
src/spiffworkflow_backend/services/secret_service.py
Normal file
204
src/spiffworkflow_backend/services/secret_service.py
Normal file
@ -0,0 +1,204 @@
|
||||
"""Secret_service."""
|
||||
from typing import Optional
|
||||
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from flask_bpmn.models.db import db
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from spiffworkflow_backend.models.secret_model import SecretAllowedProcessPathModel
|
||||
from spiffworkflow_backend.models.secret_model import SecretModel
|
||||
|
||||
# from cryptography.fernet import Fernet
|
||||
#
|
||||
#
|
||||
# class EncryptionService:
|
||||
# key = Fernet.generate_key() # this is your "password"
|
||||
# cipher_suite = Fernet(key)
|
||||
# encoded_text = cipher_suite.encrypt(b"Hello stackoverflow!")
|
||||
# decoded_text = cipher_suite.decrypt(encoded_text)
|
||||
|
||||
|
||||
class SecretService:
|
||||
"""SecretService."""
|
||||
|
||||
def encrypt_key(self, plain_key: str) -> str:
|
||||
"""Encrypt_key."""
|
||||
# flask_secret = current_app.secret_key
|
||||
# print("encrypt_key")
|
||||
...
|
||||
|
||||
def decrypt_key(self, encrypted_key: str) -> str:
|
||||
"""Decrypt key."""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
def add_secret(
|
||||
key: str,
|
||||
value: str,
|
||||
creator_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
|
||||
)
|
||||
db.session.add(secret_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
raise ApiError(
|
||||
code="create_secret_error",
|
||||
message=f"There was an error creating a secret with key: {key} and value ending with: {value[:-4]}. "
|
||||
f"Original error is {e}",
|
||||
) from e
|
||||
return secret_model
|
||||
|
||||
@staticmethod
|
||||
def get_secret(key: str) -> str | None:
|
||||
"""Get_secret."""
|
||||
secret: SecretModel = (
|
||||
db.session.query(SecretModel).filter(SecretModel.key == key).first()
|
||||
)
|
||||
if secret is not None:
|
||||
return secret.value
|
||||
|
||||
@staticmethod
|
||||
def update_secret(
|
||||
key: str,
|
||||
value: str,
|
||||
creator_user_id: Optional[int] = None,
|
||||
) -> 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:
|
||||
raise ApiError(
|
||||
code="update_secret_error",
|
||||
message=f"There was an error updating the secret with key: {key}, and value: {value}",
|
||||
) from e
|
||||
else:
|
||||
raise ApiError(
|
||||
code="update_secret_error",
|
||||
message=f"User: {creator_user_id} cannot update the secret with key : {key}",
|
||||
status_code=401,
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
code="update_secret_error",
|
||||
message=f"Cannot update secret with key: {key}. Resource does not exist.",
|
||||
status_code=404,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_secret(key: str, user_id: int) -> None:
|
||||
"""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(
|
||||
code="delete_secret_error",
|
||||
message=f"Could not delete secret with key: {key}. Original error is: {e}",
|
||||
) from e
|
||||
else:
|
||||
raise ApiError(
|
||||
code="delete_secret_error",
|
||||
message=f"User: {user_id} cannot delete the secret with key : {key}",
|
||||
status_code=401,
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
code="delete_secret_error",
|
||||
message=f"Cannot delete secret with key: {key}. Resource does not exist.",
|
||||
status_code=404,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def add_allowed_process(
|
||||
secret_id: int, user_id: str, allowed_relative_path: str
|
||||
) -> SecretAllowedProcessPathModel:
|
||||
"""Add_allowed_process."""
|
||||
secret_model = SecretModel.query.filter(SecretModel.id == secret_id).first()
|
||||
if secret_model:
|
||||
if secret_model.creator_user_id == user_id:
|
||||
secret_process_model = SecretAllowedProcessPathModel(
|
||||
secret_id=secret_model.id,
|
||||
allowed_relative_path=allowed_relative_path,
|
||||
)
|
||||
assert secret_process_model # noqa: S101
|
||||
db.session.add(secret_process_model)
|
||||
try:
|
||||
db.session.commit()
|
||||
except IntegrityError as ie:
|
||||
db.session.rollback()
|
||||
raise ApiError(
|
||||
code="add_allowed_process_error",
|
||||
message=f"Error adding allowed_process with secret {secret_model.id}, "
|
||||
f"and path: {allowed_relative_path}. Resource already exists. "
|
||||
f"Original error is {ie}",
|
||||
status_code=409,
|
||||
) from ie
|
||||
except Exception as e:
|
||||
# TODO: should we call db.session.rollback() here?
|
||||
# db.session.rollback()
|
||||
raise ApiError(
|
||||
code="add_allowed_process_error",
|
||||
message=f"Could not create an allowed process for secret with key: {secret_model.key} "
|
||||
f"with path: {allowed_relative_path}. "
|
||||
f"Original error is {e}",
|
||||
) from e
|
||||
return secret_process_model
|
||||
else:
|
||||
raise ApiError(
|
||||
code="add_allowed_process_error",
|
||||
message=f"User: {user_id} cannot modify the secret with key : {secret_model.key}",
|
||||
status_code=401,
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
code="add_allowed_process_error",
|
||||
message=f"Cannot add allowed process to secret with key: {secret_id}. Resource does not exist.",
|
||||
status_code=404,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_allowed_process(allowed_process_id: int, user_id: int) -> None:
|
||||
"""Delete_allowed_process."""
|
||||
allowed_process = SecretAllowedProcessPathModel.query.filter(
|
||||
SecretAllowedProcessPathModel.id == allowed_process_id
|
||||
).first()
|
||||
if allowed_process:
|
||||
secret = SecretModel.query.filter(
|
||||
SecretModel.id == allowed_process.secret_id
|
||||
).first()
|
||||
assert secret # noqa: S101
|
||||
if secret.creator_user_id == user_id:
|
||||
db.session.delete(allowed_process)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
raise ApiError(
|
||||
code="delete_allowed_process_error",
|
||||
message=f"There was an exception deleting allowed_process: {allowed_process_id}. "
|
||||
f"Original error is: {e}",
|
||||
) from e
|
||||
else:
|
||||
raise ApiError(
|
||||
code="delete_allowed_process_error",
|
||||
message=f"User: {user_id} cannot delete the allowed_process with id : {allowed_process_id}",
|
||||
status_code=401,
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
code="delete_allowed_process_error",
|
||||
message=f"Cannot delete allowed_process: {allowed_process_id}. Resource does not exist.",
|
||||
status_code=404,
|
||||
)
|
@ -13,7 +13,6 @@ from flask.testing import FlaskClient
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers
|
||||
from werkzeug.test import TestResponse
|
||||
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroup
|
||||
@ -26,12 +25,14 @@ from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.user_service import UserService
|
||||
|
||||
# from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers
|
||||
|
||||
|
||||
class BaseTest:
|
||||
"""BaseTest."""
|
||||
|
||||
@staticmethod
|
||||
def find_or_create_user(username: str = "test_user1") -> UserModel:
|
||||
def find_or_create_user(username: str = "test_user_1") -> UserModel:
|
||||
"""Find_or_create_user."""
|
||||
user = UserModel.query.filter_by(username=username).first()
|
||||
if isinstance(user, UserModel):
|
||||
@ -39,7 +40,6 @@ class BaseTest:
|
||||
|
||||
user = UserService().create_user("internal", username, username=username)
|
||||
if isinstance(user, UserModel):
|
||||
UserService().create_principal(user_id=user.id)
|
||||
return user
|
||||
|
||||
raise ApiError(
|
||||
@ -128,7 +128,7 @@ class BaseTest:
|
||||
"/v1.0/process-models",
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessModelInfoSchema().dump(model)),
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
return response
|
||||
@ -154,7 +154,7 @@ class BaseTest:
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert response.get_data() is not None
|
||||
@ -164,7 +164,7 @@ class BaseTest:
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/{file_name}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
file2 = json.loads(response.get_data(as_text=True))
|
||||
@ -184,7 +184,7 @@ class BaseTest:
|
||||
)
|
||||
response = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group)),
|
||||
)
|
||||
@ -220,6 +220,32 @@ class BaseTest:
|
||||
db.session.commit()
|
||||
return process_instance
|
||||
|
||||
@staticmethod
|
||||
def logged_in_headers(
|
||||
user: UserModel, _redirect_url: str = "http://some/frontend/url"
|
||||
) -> Dict[str, str]:
|
||||
"""Logged_in_headers."""
|
||||
# if user is None:
|
||||
# uid = 'test_user'
|
||||
# user_info = {'uid': 'test_user'}
|
||||
# else:
|
||||
# uid = user.uid
|
||||
# user_info = {'uid': user.uid}
|
||||
|
||||
# query_string = user_info_to_query_string(user_info, redirect_url)
|
||||
# rv = self.app.get("/v1.0/login%s" % query_string, follow_redirects=False)
|
||||
# self.assertTrue(rv.status_code == 302)
|
||||
# self.assertTrue(str.startswith(rv.location, redirect_url))
|
||||
#
|
||||
# user_model = session.query(UserModel).filter_by(uid=uid).first()
|
||||
# self.assertIsNotNone(user_model.ldap_info.display_name)
|
||||
# self.assertEqual(user_model.uid, uid)
|
||||
# self.assertTrue('user' in g, 'User should be in Flask globals')
|
||||
# user = UserService.current_user(allow_admin_impersonate=True)
|
||||
# self.assertEqual(uid, user.uid, 'Logged in user should match given user uid')
|
||||
|
||||
return dict(Authorization="Bearer " + user.encode_auth_token())
|
||||
|
||||
def get_test_data_file_contents(
|
||||
self, file_name: str, process_model_test_data_dir: str
|
||||
) -> bytes:
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""User."""
|
||||
from typing import Dict
|
||||
from typing import Optional
|
||||
|
||||
from tests.spiffworkflow_backend.helpers.example_data import ExampleDataLoader
|
||||
@ -9,7 +8,6 @@ from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
||||
)
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroup
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
|
||||
|
||||
@ -81,29 +79,3 @@ def load_test_spec(
|
||||
# query_string_list.append('redirect_url=%s' % redirect_url)
|
||||
#
|
||||
# return '?%s' % '&'.join(query_string_list)
|
||||
|
||||
|
||||
def logged_in_headers(
|
||||
user: UserModel, _redirect_url: str = "http://some/frontend/url"
|
||||
) -> Dict[str, str]:
|
||||
"""Logged_in_headers."""
|
||||
# if user is None:
|
||||
# uid = 'test_user'
|
||||
# user_info = {'uid': 'test_user'}
|
||||
# else:
|
||||
# uid = user.uid
|
||||
# user_info = {'uid': user.uid}
|
||||
|
||||
# query_string = user_info_to_query_string(user_info, redirect_url)
|
||||
# rv = self.app.get("/v1.0/login%s" % query_string, follow_redirects=False)
|
||||
# self.assertTrue(rv.status_code == 302)
|
||||
# self.assertTrue(str.startswith(rv.location, redirect_url))
|
||||
#
|
||||
# user_model = session.query(UserModel).filter_by(uid=uid).first()
|
||||
# self.assertIsNotNone(user_model.ldap_info.display_name)
|
||||
# self.assertEqual(user_model.uid, uid)
|
||||
# self.assertTrue('user' in g, 'User should be in Flask globals')
|
||||
# user = UserService.current_user(allow_admin_impersonate=True)
|
||||
# self.assertEqual(uid, user.uid, 'Logged in user should match given user uid')
|
||||
|
||||
return dict(Authorization="Bearer " + user.encode_auth_token())
|
||||
|
@ -2,7 +2,6 @@
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers
|
||||
|
||||
|
||||
class TestLoggingService(BaseTest):
|
||||
@ -15,7 +14,7 @@ class TestLoggingService(BaseTest):
|
||||
process_group_id = "test_logging_spiff_logger"
|
||||
process_model_id = "simple_script"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
)
|
||||
@ -23,13 +22,13 @@ class TestLoggingService(BaseTest):
|
||||
process_instance_id = response.json["id"]
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
log_response = client.get(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/logs",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert log_response.status_code == 200
|
||||
assert log_response.json
|
||||
|
@ -10,7 +10,6 @@ from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers
|
||||
|
||||
from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
||||
ProcessEntityNotFoundError,
|
||||
@ -101,7 +100,7 @@ class TestProcessApi(BaseTest):
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
@ -125,7 +124,7 @@ class TestProcessApi(BaseTest):
|
||||
user = self.find_or_create_user()
|
||||
response = client.delete(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -142,7 +141,7 @@ class TestProcessApi(BaseTest):
|
||||
test_process_group_id = "runs_without_input"
|
||||
test_process_model_id = "sample"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
# create an instance from a model
|
||||
response = self.create_process_instance(
|
||||
client, test_process_group_id, test_process_model_id, headers
|
||||
@ -155,7 +154,7 @@ class TestProcessApi(BaseTest):
|
||||
# try to delete the model
|
||||
response = client.delete(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{test_process_model_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
# make sure we get an error in the response
|
||||
@ -183,7 +182,7 @@ class TestProcessApi(BaseTest):
|
||||
user = self.find_or_create_user()
|
||||
response = client.put(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessModelInfoSchema().dump(process_model)),
|
||||
)
|
||||
@ -217,7 +216,7 @@ class TestProcessApi(BaseTest):
|
||||
# get all models
|
||||
response = client.get(
|
||||
f"/v1.0/process-models?process_group_identifier={group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 5
|
||||
@ -228,7 +227,7 @@ class TestProcessApi(BaseTest):
|
||||
# get first page, 1 per page
|
||||
response = client.get(
|
||||
f"/v1.0/process-models?page=1&per_page=1&process_group_identifier={group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
@ -240,7 +239,7 @@ class TestProcessApi(BaseTest):
|
||||
# get second page, 1 per page
|
||||
response = client.get(
|
||||
f"/v1.0/process-models?page=2&per_page=1&process_group_identifier={group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
@ -252,7 +251,7 @@ class TestProcessApi(BaseTest):
|
||||
# get first page, 3 per page
|
||||
response = client.get(
|
||||
f"/v1.0/process-models?page=1&per_page=3&process_group_identifier={group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 3
|
||||
@ -264,7 +263,7 @@ class TestProcessApi(BaseTest):
|
||||
# get second page, 3 per page
|
||||
response = client.get(
|
||||
f"/v1.0/process-models?page=2&per_page=3&process_group_identifier={group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
# there should only be 2 left
|
||||
assert response.json is not None
|
||||
@ -287,7 +286,7 @@ class TestProcessApi(BaseTest):
|
||||
user = self.find_or_create_user()
|
||||
response = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group)),
|
||||
)
|
||||
@ -320,7 +319,8 @@ class TestProcessApi(BaseTest):
|
||||
assert persisted.id == process_group_id
|
||||
|
||||
client.delete(
|
||||
f"/v1.0/process-groups/{process_group_id}", headers=logged_in_headers(user)
|
||||
f"/v1.0/process-groups/{process_group_id}",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
with pytest.raises(ProcessEntityNotFoundError):
|
||||
@ -345,7 +345,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.put(
|
||||
f"/v1.0/process-groups/{group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group)),
|
||||
)
|
||||
@ -370,7 +370,7 @@ class TestProcessApi(BaseTest):
|
||||
# get all groups
|
||||
response = client.get(
|
||||
"/v1.0/process-groups",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 5
|
||||
@ -381,7 +381,7 @@ class TestProcessApi(BaseTest):
|
||||
# get first page, one per page
|
||||
response = client.get(
|
||||
"/v1.0/process-groups?page=1&per_page=1",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
@ -393,7 +393,7 @@ class TestProcessApi(BaseTest):
|
||||
# get second page, one per page
|
||||
response = client.get(
|
||||
"/v1.0/process-groups?page=2&per_page=1",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
@ -405,7 +405,7 @@ class TestProcessApi(BaseTest):
|
||||
# get first page, 3 per page
|
||||
response = client.get(
|
||||
"/v1.0/process-groups?page=1&per_page=3",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 3
|
||||
@ -419,7 +419,7 @@ class TestProcessApi(BaseTest):
|
||||
# get second page, 3 per page
|
||||
response = client.get(
|
||||
"/v1.0/process-groups?page=2&per_page=3",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
# there should only be 2 left
|
||||
assert response.json is not None
|
||||
@ -444,7 +444,7 @@ class TestProcessApi(BaseTest):
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
@ -465,7 +465,7 @@ class TestProcessApi(BaseTest):
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
@ -487,7 +487,7 @@ class TestProcessApi(BaseTest):
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@ -496,7 +496,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
updated_file = json.loads(response.get_data(as_text=True))
|
||||
@ -514,7 +514,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.delete(
|
||||
f"/v1.0/process-models/INCORRECT-NON-EXISTENT-GROUP/{process_model.id}/files/random_fact.svg",
|
||||
follow_redirects=True,
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
@ -532,7 +532,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.delete(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact_DOES_NOT_EXIST.svg",
|
||||
follow_redirects=True,
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
@ -550,7 +550,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.delete(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg",
|
||||
follow_redirects=True,
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@ -559,7 +559,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
@ -573,7 +573,7 @@ class TestProcessApi(BaseTest):
|
||||
load_test_spec(process_model_dir_name, process_group_id=test_process_group_id)
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/files/hello_world.bpmn",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -589,7 +589,7 @@ class TestProcessApi(BaseTest):
|
||||
process_model = load_test_spec("hello_world")
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/process-instances",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert response.json is not None
|
||||
@ -601,7 +601,9 @@ class TestProcessApi(BaseTest):
|
||||
) -> None:
|
||||
"""Test_get_process_groups_when_none."""
|
||||
user = self.find_or_create_user()
|
||||
response = client.get("/v1.0/process-groups", headers=logged_in_headers(user))
|
||||
response = client.get(
|
||||
"/v1.0/process-groups", headers=self.logged_in_headers(user)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert response.json["results"] == []
|
||||
@ -612,7 +614,9 @@ class TestProcessApi(BaseTest):
|
||||
"""Test_get_process_groups_when_there_are_some."""
|
||||
user = self.find_or_create_user()
|
||||
load_test_spec("hello_world")
|
||||
response = client.get("/v1.0/process-groups", headers=logged_in_headers(user))
|
||||
response = client.get(
|
||||
"/v1.0/process-groups", headers=self.logged_in_headers(user)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
@ -630,7 +634,7 @@ class TestProcessApi(BaseTest):
|
||||
load_test_spec(process_model_dir_name, process_group_id=test_process_group_id)
|
||||
response = client.get(
|
||||
f"/v1.0/process-groups/{test_process_group_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -647,7 +651,7 @@ class TestProcessApi(BaseTest):
|
||||
load_test_spec(process_model_dir_name, process_group_id=test_process_group_id)
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -664,7 +668,7 @@ class TestProcessApi(BaseTest):
|
||||
group_id = self.create_process_group(client, user, "my_group")
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{group_id}/{process_model_dir_name}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.json is not None
|
||||
@ -677,7 +681,7 @@ class TestProcessApi(BaseTest):
|
||||
test_process_group_id = "runs_without_input"
|
||||
test_process_model_id = "sample"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, test_process_group_id, test_process_model_id, headers
|
||||
)
|
||||
@ -693,7 +697,7 @@ class TestProcessApi(BaseTest):
|
||||
process_group_id = "runs_without_input"
|
||||
process_model_id = "sample"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
)
|
||||
@ -701,7 +705,7 @@ class TestProcessApi(BaseTest):
|
||||
process_instance_id = response.json["id"]
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.json is not None
|
||||
@ -709,7 +713,7 @@ class TestProcessApi(BaseTest):
|
||||
assert response.json["updated_at_in_seconds"] > 0
|
||||
assert response.json["status"] == "complete"
|
||||
assert response.json["process_model_identifier"] == process_model_id
|
||||
assert response.json["data"]["current_user"]["username"] == "test_user1"
|
||||
assert response.json["data"]["current_user"]["username"] == user.username
|
||||
assert response.json["data"]["Mike"] == "Awesome"
|
||||
assert response.json["data"]["person"] == "Kevin"
|
||||
|
||||
@ -733,7 +737,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/messages/{message_model_identifier}",
|
||||
content_type="application/json",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
data=json.dumps({"payload": payload}),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@ -773,7 +777,7 @@ class TestProcessApi(BaseTest):
|
||||
client,
|
||||
process_model.process_group_id,
|
||||
process_model.id,
|
||||
logged_in_headers(user),
|
||||
self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
process_instance_id = response.json["id"]
|
||||
@ -781,7 +785,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/"
|
||||
f"{process_model.id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.json is not None
|
||||
@ -789,7 +793,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/messages/{message_model_identifier}",
|
||||
content_type="application/json",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
data=json.dumps(
|
||||
{"payload": payload, "process_instance_id": process_instance_id}
|
||||
),
|
||||
@ -824,7 +828,7 @@ class TestProcessApi(BaseTest):
|
||||
client,
|
||||
process_model.process_group_id,
|
||||
process_model.id,
|
||||
logged_in_headers(user),
|
||||
self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
process_instance_id = response.json["id"]
|
||||
@ -832,7 +836,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/"
|
||||
f"{process_model.id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -840,7 +844,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/"
|
||||
f"{process_model.id}/process-instances/{process_instance_id}/terminate",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -859,7 +863,7 @@ class TestProcessApi(BaseTest):
|
||||
process_model_id = "user_task"
|
||||
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
)
|
||||
@ -868,7 +872,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.json is not None
|
||||
@ -883,7 +887,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
delete_response = client.delete(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert delete_response.status_code == 200
|
||||
|
||||
@ -895,7 +899,7 @@ class TestProcessApi(BaseTest):
|
||||
process_model_id = "user_task"
|
||||
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
)
|
||||
@ -904,7 +908,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
|
||||
assert response.json is not None
|
||||
@ -925,14 +929,14 @@ class TestProcessApi(BaseTest):
|
||||
test_process_group_id = "runs_without_input"
|
||||
process_model_dir_name = "sample"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
self.create_process_instance(
|
||||
client, test_process_group_id, process_model_dir_name, headers
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-instances",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -961,7 +965,7 @@ class TestProcessApi(BaseTest):
|
||||
test_process_group_id = "runs_without_input"
|
||||
process_model_dir_name = "sample"
|
||||
user = self.find_or_create_user()
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
self.create_process_instance(
|
||||
client, test_process_group_id, process_model_dir_name, headers
|
||||
)
|
||||
@ -980,7 +984,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?per_page=2&page=3",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -991,7 +995,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?per_page=2&page=1",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1028,7 +1032,7 @@ class TestProcessApi(BaseTest):
|
||||
# Without filtering we should get all 5 instances
|
||||
response = client.get(
|
||||
f"/v1.0/process-instances?process_group_identifier={test_process_group_id}&process_model_identifier={test_process_model_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1039,7 +1043,7 @@ class TestProcessApi(BaseTest):
|
||||
for i in range(5):
|
||||
response = client.get(
|
||||
f"/v1.0/process-instances?process_status={ProcessInstanceStatus[statuses[i]].value}&process_group_identifier={test_process_group_id}&process_model_identifier={test_process_model_id}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1050,7 +1054,7 @@ class TestProcessApi(BaseTest):
|
||||
# start > 1000 - this should eliminate the first
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?start_from=1001",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1061,7 +1065,7 @@ class TestProcessApi(BaseTest):
|
||||
# start > 2000, end < 5000 - this should eliminate the first 2 and the last
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?start_from=2001&end_till=5999",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1072,7 +1076,7 @@ class TestProcessApi(BaseTest):
|
||||
# start > 1000, start < 4000 - this should eliminate the first and the last 2
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?start_from=1001&start_till=3999",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1083,7 +1087,7 @@ class TestProcessApi(BaseTest):
|
||||
# end > 2000, end < 6000 - this should eliminate the first and the last
|
||||
response = client.get(
|
||||
"/v1.0/process-instances?end_from=2001&end_till=5999",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.json is not None
|
||||
results = response.json["results"]
|
||||
@ -1098,7 +1102,7 @@ class TestProcessApi(BaseTest):
|
||||
process_group_identifier = "runs_without_input"
|
||||
process_model_identifier = "sample"
|
||||
user = self.find_or_create_user()
|
||||
logged_in_headers(user)
|
||||
self.logged_in_headers(user)
|
||||
load_test_spec(
|
||||
process_model_identifier, process_group_id=process_group_identifier
|
||||
)
|
||||
@ -1113,7 +1117,7 @@ class TestProcessApi(BaseTest):
|
||||
)
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{process_group_identifier}/{process_model_identifier}/process-instances/reports",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1162,7 +1166,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/process-instances/reports/sure",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1215,7 +1219,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/process-instances/reports/sure?grade_level=1",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1235,7 +1239,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/process-instances/reports/sure?grade_level=1",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 404
|
||||
data = json.loads(response.get_data(as_text=True))
|
||||
@ -1249,7 +1253,7 @@ class TestProcessApi(BaseTest):
|
||||
user: UserModel,
|
||||
) -> Any:
|
||||
"""Setup_testing_instance."""
|
||||
headers = logged_in_headers(user)
|
||||
headers = self.logged_in_headers(user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
)
|
||||
@ -1279,7 +1283,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
@ -1325,7 +1329,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
@ -1360,7 +1364,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert len(outbox) == 1
|
||||
@ -1419,7 +1423,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/messages/{message_model_identifier}",
|
||||
content_type="application/json",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
data=json.dumps({"payload": payload}),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@ -1429,7 +1433,7 @@ class TestProcessApi(BaseTest):
|
||||
response = client.post(
|
||||
f"/v1.0/messages/{message_model_identifier}",
|
||||
content_type="application/json",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
data=json.dumps({"payload": payload}),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@ -1438,7 +1442,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/messages?process_instance_id={process_instance_id_one}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1450,7 +1454,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/messages?process_instance_id={process_instance_id_two}",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1462,7 +1466,7 @@ class TestProcessApi(BaseTest):
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/messages",
|
||||
headers=logged_in_headers(user),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
@ -1471,7 +1475,7 @@ class TestProcessApi(BaseTest):
|
||||
# def test_get_process_model(self):
|
||||
#
|
||||
# load_test_spec('random_fact')
|
||||
# response = client.get('/v1.0/workflow-specification/random_fact', headers=logged_in_headers())
|
||||
# response = client.get('/v1.0/workflow-specification/random_fact', headers=self.logged_in_headers())
|
||||
# assert_success(response)
|
||||
# json_data = json.loads(response.get_data(as_text=True))
|
||||
# api_spec = WorkflowSpecInfoSchema().load(json_data)
|
||||
|
492
tests/spiffworkflow_backend/integration/test_secret_service.py
Normal file
492
tests/spiffworkflow_backend/integration/test_secret_service.py
Normal file
@ -0,0 +1,492 @@
|
||||
"""Test_secret_service."""
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from werkzeug.test import TestResponse
|
||||
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.secret_model import SecretAllowedProcessPathModel
|
||||
from spiffworkflow_backend.models.secret_model import SecretModel
|
||||
from spiffworkflow_backend.models.secret_model import SecretModelSchema
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.secret_service import SecretService
|
||||
|
||||
|
||||
class SecretServiceTestHelpers(BaseTest):
|
||||
"""SecretServiceTestHelpers."""
|
||||
|
||||
test_key = "test_key"
|
||||
test_value = "test_value"
|
||||
test_process_group_id = "test"
|
||||
test_process_group_display_name = "My Test Process Group"
|
||||
test_process_model_id = "make_cookies"
|
||||
test_process_model_display_name = "Cooooookies"
|
||||
test_process_model_description = "Om nom nom delicious cookies"
|
||||
|
||||
def add_test_secret(self, user: UserModel) -> SecretModel:
|
||||
"""Add_test_secret."""
|
||||
return SecretService().add_secret(self.test_key, self.test_value, user.id)
|
||||
|
||||
def add_test_process(
|
||||
self, client: FlaskClient, user: UserModel
|
||||
) -> ProcessModelInfo:
|
||||
"""Add_test_process."""
|
||||
self.create_process_group(
|
||||
client,
|
||||
user,
|
||||
self.test_process_group_id,
|
||||
display_name=self.test_process_group_display_name,
|
||||
)
|
||||
self.create_process_model_with_api(
|
||||
client,
|
||||
process_group_id=self.test_process_group_id,
|
||||
process_model_id=self.test_process_model_id,
|
||||
process_model_display_name=self.test_process_model_display_name,
|
||||
process_model_description=self.test_process_model_description,
|
||||
)
|
||||
process_model_info = ProcessModelService().get_process_model(
|
||||
self.test_process_model_id, self.test_process_group_id
|
||||
)
|
||||
return process_model_info
|
||||
|
||||
def add_test_secret_allowed_process(
|
||||
self, client: FlaskClient, user: UserModel
|
||||
) -> SecretAllowedProcessPathModel:
|
||||
"""Add_test_secret_allowed_process."""
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
|
||||
test_secret = self.add_test_secret(user)
|
||||
allowed_process_model = SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id,
|
||||
user_id=user.id,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
return allowed_process_model
|
||||
|
||||
|
||||
class TestSecretService(SecretServiceTestHelpers):
|
||||
"""TestSecretService."""
|
||||
|
||||
def test_add_secret(self, app: Flask, with_db_and_bpmn_file_cleanup: None) -> None:
|
||||
"""Test_add_secret."""
|
||||
user = self.find_or_create_user()
|
||||
test_secret = self.add_test_secret(user)
|
||||
|
||||
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 == user.id
|
||||
|
||||
def test_add_secret_duplicate_key_fails(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_add_secret_duplicate_key_fails."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
self.add_test_secret(user)
|
||||
assert "Duplicate entry" in ae.value.message
|
||||
|
||||
def test_get_secret(self, app: Flask, with_db_and_bpmn_file_cleanup: None) -> None:
|
||||
"""Test_get_secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
|
||||
secret = SecretService().get_secret(self.test_key)
|
||||
assert secret is not None
|
||||
assert secret == self.test_value
|
||||
|
||||
def test_get_secret_bad_key_fails(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_get_secret_bad_service."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
|
||||
bad_secret = SecretService().get_secret("bad_key")
|
||||
assert bad_secret is None
|
||||
|
||||
def test_update_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test update secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
secret = SecretService.get_secret(self.test_key)
|
||||
assert secret == self.test_value
|
||||
SecretService.update_secret(self.test_key, "new_secret_value", user.id)
|
||||
new_secret = SecretService.get_secret(self.test_key)
|
||||
assert new_secret == "new_secret_value" # noqa: S105
|
||||
|
||||
def test_update_secret_bad_user_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_update_secret_bad_user."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.update_secret(
|
||||
self.test_key, "new_secret_value", user.id + 1
|
||||
) # noqa: S105
|
||||
assert (
|
||||
ae.value.message
|
||||
== f"User: {user.id+1} cannot update the secret with key : test_key"
|
||||
)
|
||||
|
||||
def test_update_secret_bad_secret_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_update_secret_bad_secret_fails."""
|
||||
user = self.find_or_create_user()
|
||||
secret = self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.update_secret(secret.key + "x", "some_new_value", user.id)
|
||||
assert "Resource does not exist" in ae.value.message
|
||||
|
||||
def test_delete_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test delete secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
secrets = SecretModel.query.all()
|
||||
assert len(secrets) == 1
|
||||
assert secrets[0].creator_user_id == user.id
|
||||
SecretService.delete_secret(self.test_key, 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
|
||||
) -> None:
|
||||
"""Test_delete_secret_bad_user."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.delete_secret(self.test_key, user.id + 1)
|
||||
assert (
|
||||
f"User: {user.id+1} cannot delete the secret with key" in ae.value.message
|
||||
)
|
||||
|
||||
def test_delete_secret_bad_secret_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_delete_secret_bad_secret_fails."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService.delete_secret(self.test_key + "x", user.id)
|
||||
assert "Resource does not exist" in ae.value.message
|
||||
|
||||
def test_secret_add_allowed_process(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_add_allowed_process."""
|
||||
user = self.find_or_create_user()
|
||||
test_secret = self.add_test_secret(user)
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
allowed_process_model = SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id,
|
||||
user_id=user.id,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
|
||||
assert allowed_process_model is not None
|
||||
assert isinstance(allowed_process_model, SecretAllowedProcessPathModel)
|
||||
assert allowed_process_model.secret_id == test_secret.id
|
||||
assert (
|
||||
allowed_process_model.allowed_relative_path == process_model_relative_path
|
||||
)
|
||||
|
||||
assert len(test_secret.allowed_processes) == 1
|
||||
assert test_secret.allowed_processes[0] == allowed_process_model
|
||||
|
||||
def test_secret_add_allowed_process_same_process_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Do not allow duplicate entries for secret_id/allowed_relative_path pairs.
|
||||
|
||||
We actually take care of this in the db model with a unique constraint
|
||||
on the 2 columns.
|
||||
"""
|
||||
user = self.find_or_create_user()
|
||||
test_secret = self.add_test_secret(user)
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id,
|
||||
user_id=user.id,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 1
|
||||
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id,
|
||||
user_id=user.id,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
assert "Resource already exists" in ae.value.message
|
||||
assert "IntegrityError" in ae.value.message
|
||||
assert "Duplicate entry" in ae.value.message
|
||||
|
||||
def test_secret_add_allowed_process_bad_user_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_add_allowed_process_bad_user."""
|
||||
user = self.find_or_create_user()
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
test_secret = self.add_test_secret(user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id,
|
||||
user_id=user.id + 1,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
assert (
|
||||
ae.value.message
|
||||
== f"User: {user.id+1} cannot modify the secret with key : {self.test_key}"
|
||||
)
|
||||
|
||||
def test_secret_add_allowed_process_bad_secret_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_add_allowed_process_bad_secret_fails."""
|
||||
user = self.find_or_create_user()
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
test_secret = self.add_test_secret(user)
|
||||
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService().add_allowed_process(
|
||||
secret_id=test_secret.id + 1,
|
||||
user_id=user.id,
|
||||
allowed_relative_path=process_model_relative_path,
|
||||
)
|
||||
assert "Resource does not exist" in ae.value.message
|
||||
print("test_secret_add_allowed_process_bad_secret")
|
||||
|
||||
def test_secret_delete_allowed_process(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_delete_allowed_process."""
|
||||
user = self.find_or_create_user()
|
||||
allowed_process_model = self.add_test_secret_allowed_process(client, user)
|
||||
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 1
|
||||
|
||||
SecretService().delete_allowed_process(allowed_process_model.id, user.id)
|
||||
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 0
|
||||
|
||||
def test_secret_delete_allowed_process_bad_user_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_delete_allowed_process_bad_user_fails."""
|
||||
user = self.find_or_create_user()
|
||||
allowed_process_model = self.add_test_secret_allowed_process(client, user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService().delete_allowed_process(
|
||||
allowed_process_model.id, user.id + 1
|
||||
)
|
||||
message = ae.value.message
|
||||
assert (
|
||||
f"User: {user.id+1} cannot delete the allowed_process with id : {allowed_process_model.id}"
|
||||
in message
|
||||
)
|
||||
|
||||
def test_secret_delete_allowed_process_bad_allowed_process_fails(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_secret_delete_allowed_process_bad_allowed_process_fails."""
|
||||
user = self.find_or_create_user()
|
||||
allowed_process_model = self.add_test_secret_allowed_process(client, user)
|
||||
with pytest.raises(ApiError) as ae:
|
||||
SecretService().delete_allowed_process(
|
||||
allowed_process_model.id + 1, user.id
|
||||
)
|
||||
assert "Resource does not exist" in ae.value.message
|
||||
|
||||
|
||||
class TestSecretServiceApi(SecretServiceTestHelpers):
|
||||
"""TestSecretServiceApi."""
|
||||
|
||||
def test_add_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_add_secret."""
|
||||
user = self.find_or_create_user()
|
||||
secret_model = SecretModel(
|
||||
key=self.test_key,
|
||||
value=self.test_value,
|
||||
creator_user_id=user.id,
|
||||
)
|
||||
data = json.dumps(SecretModelSchema().dump(secret_model))
|
||||
response: TestResponse = client.post(
|
||||
"/v1.0/secrets",
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=data,
|
||||
)
|
||||
assert response.json
|
||||
secret: dict = response.json
|
||||
for key in ["key", "value", "creator_user_id"]:
|
||||
assert key in secret.keys()
|
||||
assert secret["key"] == self.test_key
|
||||
assert secret["value"] == self.test_value
|
||||
assert secret["creator_user_id"] == user.id
|
||||
|
||||
def test_get_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test get secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
secret_response = client.get(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert secret_response
|
||||
assert secret_response.status_code == 200
|
||||
assert secret_response.json == self.test_value
|
||||
|
||||
def test_update_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_update_secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
secret = SecretService.get_secret(self.test_key)
|
||||
assert secret == self.test_value
|
||||
secret_model = SecretModel(
|
||||
key=self.test_key, value="new_secret_value", creator_user_id=user.id
|
||||
)
|
||||
response = client.put(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(SecretModelSchema().dump(secret_model)),
|
||||
)
|
||||
assert response.status_code == 204
|
||||
|
||||
secret_model = SecretModel.query.filter(
|
||||
SecretModel.key == self.test_key
|
||||
).first()
|
||||
assert secret_model.value == "new_secret_value"
|
||||
|
||||
def test_delete_secret(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test delete secret."""
|
||||
user = self.find_or_create_user()
|
||||
self.add_test_secret(user)
|
||||
secret = SecretService.get_secret(self.test_key)
|
||||
assert secret
|
||||
assert secret == self.test_value
|
||||
secret_response = client.delete(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert secret_response.status_code == 204
|
||||
secret = SecretService.get_secret(self.test_key)
|
||||
assert secret is None
|
||||
|
||||
def test_delete_secret_bad_user(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> 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)
|
||||
secret_response = client.delete(
|
||||
f"/v1.0/secrets/{self.test_key}",
|
||||
headers=self.logged_in_headers(user_2),
|
||||
)
|
||||
assert secret_response.status_code == 401
|
||||
|
||||
def test_delete_secret_bad_key(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test delete secret."""
|
||||
user = self.find_or_create_user()
|
||||
secret_response = client.delete(
|
||||
"/v1.0/secrets/bad_secret_key",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert secret_response.status_code == 404
|
||||
print("test_delete_secret_bad_key")
|
||||
|
||||
def test_add_secret_allowed_process(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test add secret allowed process."""
|
||||
user = self.find_or_create_user()
|
||||
test_secret = self.add_test_secret(user)
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
data = {
|
||||
"secret_id": test_secret.id,
|
||||
"allowed_relative_path": process_model_relative_path,
|
||||
}
|
||||
response: TestResponse = client.post(
|
||||
"/v1.0/secrets/allowed_process_paths",
|
||||
headers=self.logged_in_headers(user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(data),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 1
|
||||
assert allowed_processes[0].allowed_relative_path == process_model_relative_path
|
||||
assert allowed_processes[0].secret_id == test_secret.id
|
||||
|
||||
def test_delete_secret_allowed_process(
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test delete secret allowed process."""
|
||||
user = self.find_or_create_user()
|
||||
test_secret = self.add_test_secret(user)
|
||||
process_model_info = self.add_test_process(client, user)
|
||||
process_model_relative_path = FileSystemService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
allowed_process = SecretService.add_allowed_process(
|
||||
test_secret.id, user.id, process_model_relative_path
|
||||
)
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 1
|
||||
assert allowed_processes[0].secret_id == test_secret.id
|
||||
assert allowed_processes[0].allowed_relative_path == process_model_relative_path
|
||||
response = client.delete(
|
||||
f"/v1.0/secrets/allowed_process_paths/{allowed_process.id}",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 204
|
||||
allowed_processes = SecretAllowedProcessPathModel.query.all()
|
||||
assert len(allowed_processes) == 0
|
Loading…
x
Reference in New Issue
Block a user