attempting to respect permissions w/ burnettk
This commit is contained in:
parent
10c443a2d8
commit
d07fbbeff9
|
@ -17,7 +17,9 @@ from flask_mail import Mail # type: ignore
|
|||
import spiffworkflow_backend.load_database_models # noqa: F401
|
||||
from spiffworkflow_backend.config import setup_config
|
||||
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
|
||||
from spiffworkflow_backend.routes.process_api_blueprint import check_for_permission
|
||||
from spiffworkflow_backend.routes.process_api_blueprint import process_api_blueprint
|
||||
from spiffworkflow_backend.routes.user import verify_token
|
||||
from spiffworkflow_backend.routes.user_blueprint import user_blueprint
|
||||
from spiffworkflow_backend.services.background_processing_service import (
|
||||
BackgroundProcessingService,
|
||||
|
@ -113,6 +115,9 @@ def create_app() -> flask.app.Flask:
|
|||
|
||||
configure_sentry(app)
|
||||
|
||||
app.before_request(verify_token)
|
||||
app.before_request(check_for_permission)
|
||||
|
||||
return app # type: ignore
|
||||
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ info:
|
|||
name: MIT
|
||||
servers:
|
||||
- url: http://localhost:5000/v1.0
|
||||
security:
|
||||
- jwt: ["secret"]
|
||||
security: []
|
||||
# - jwt: ["secret"]
|
||||
# - oAuth2AuthCode:
|
||||
# - read_email
|
||||
# - uid
|
||||
|
@ -378,7 +378,6 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
# process model update
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_update
|
||||
summary: Modifies an existing process mosel with the given parameters.
|
||||
|
@ -827,7 +826,6 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/File"
|
||||
# process_model_file_update
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_file_update
|
||||
summary: save the contents to the given file
|
||||
|
|
|
@ -31,7 +31,13 @@ class Permission(enum.Enum):
|
|||
read = "read"
|
||||
update = "update"
|
||||
delete = "delete"
|
||||
|
||||
# maybe read to GET process_model/process-instances instead?
|
||||
list = "list"
|
||||
|
||||
# maybe use create instead on
|
||||
# POST http://localhost:7000/v1.0/process-models/category_number_one/call-activity/process-instances/*
|
||||
# POST http://localhost:7000/v1.0/process-models/category_number_one/call-activity/process-instances/332/run
|
||||
instantiate = "instantiate" # this is something you do to a process model
|
||||
|
||||
|
||||
|
|
|
@ -4,10 +4,14 @@ import os
|
|||
import random
|
||||
import string
|
||||
import uuid
|
||||
from functools import wraps
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import Dict
|
||||
from typing import Optional
|
||||
from typing import TypedDict
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
import connexion # type: ignore
|
||||
|
@ -53,6 +57,7 @@ from spiffworkflow_backend.models.secret_model import SecretModel
|
|||
from spiffworkflow_backend.models.secret_model import SecretModelSchema
|
||||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||
from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService
|
||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.git_service import GitService
|
||||
|
@ -87,6 +92,51 @@ class ReactJsonSchemaSelectOption(TypedDict):
|
|||
|
||||
|
||||
process_api_blueprint = Blueprint("process_api", __name__)
|
||||
authorization_exclusion_list = ['status']
|
||||
|
||||
|
||||
def check_for_permission() -> None:
|
||||
"""Check_for_permission."""
|
||||
if request.method == 'OPTIONS':
|
||||
return None
|
||||
|
||||
if not request.endpoint:
|
||||
raise ApiError(
|
||||
error_code="request_endpoint_not_found",
|
||||
message="Could not find the endpong from the rquest.",
|
||||
status_code=500,
|
||||
)
|
||||
|
||||
api_view_function = current_app.view_functions[request.endpoint]
|
||||
if api_view_function and api_view_function.__name__ not in authorization_exclusion_list:
|
||||
permission_string = get_permission_from_request_method()
|
||||
if permission_string:
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=g.user,
|
||||
permission=permission_string,
|
||||
target_uri=request.path,
|
||||
)
|
||||
if has_permission:
|
||||
return None
|
||||
|
||||
raise ApiError(
|
||||
error_code="unauthorized",
|
||||
message="User is not authorized to perform requested action.",
|
||||
status_code=403,
|
||||
)
|
||||
|
||||
|
||||
def get_permission_from_request_method() -> Optional[str]:
|
||||
request_method_mapper = {
|
||||
"POST": "create",
|
||||
"GET": "read",
|
||||
"PUT": "update",
|
||||
"DELETE": "delete"
|
||||
}
|
||||
if request.method in request_method_mapper:
|
||||
return request_method_mapper[request.method]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def status() -> flask.wrappers.Response:
|
||||
|
|
|
@ -10,6 +10,7 @@ import jwt
|
|||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import redirect
|
||||
from flask import request
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from werkzeug.wrappers.response import Response
|
||||
|
||||
|
@ -26,6 +27,7 @@ from spiffworkflow_backend.services.user_service import UserService
|
|||
"""
|
||||
|
||||
|
||||
# authorization_exclusion_list = ['status']
|
||||
def verify_token(token: Optional[str] = None) -> Dict[str, Optional[Union[str, int]]]:
|
||||
"""Verify the token for the user (if provided).
|
||||
|
||||
|
@ -41,6 +43,17 @@ def verify_token(token: Optional[str] = None) -> Dict[str, Optional[Union[str, i
|
|||
ApiError: If not on production and token is not valid, returns an 'invalid_token' 403 error.
|
||||
If on production and user is not authenticated, returns a 'no_user' 403 error.
|
||||
"""
|
||||
|
||||
if request.method == 'OPTIONS':
|
||||
return None
|
||||
|
||||
api_view_function = current_app.view_functions[request.endpoint]
|
||||
if api_view_function and api_view_function.__name__.startswith('login'):
|
||||
return None
|
||||
|
||||
if not token and 'Authorization' in request.headers:
|
||||
token = request.headers['Authorization'].removeprefix('Bearer ')
|
||||
|
||||
if token:
|
||||
user_model = None
|
||||
decoded_token = get_decoded_token(token)
|
||||
|
|
|
@ -21,6 +21,9 @@ from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignme
|
|||
from spiffworkflow_backend.services.user_service import UserService
|
||||
|
||||
|
||||
class PermissionsFileNotSetError(Exception):
|
||||
pass
|
||||
|
||||
class AuthorizationService:
|
||||
"""Determine whether a user has permission to perform their request."""
|
||||
|
||||
|
@ -77,6 +80,9 @@ class AuthorizationService:
|
|||
cls, raise_if_missing_user: bool = False
|
||||
) -> None:
|
||||
"""Import_permissions_from_yaml_file."""
|
||||
if current_app.config["SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME"] is None:
|
||||
raise(PermissionsFileNotSetError("SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME needs to be set in order to import permissions"))
|
||||
|
||||
permission_configs = None
|
||||
with open(current_app.config["PERMISSIONS_FILE_FULLPATH"]) as file:
|
||||
permission_configs = yaml.safe_load(file)
|
||||
|
|
Loading…
Reference in New Issue