diff --git a/bento_lib/auth/middleware/base.py b/bento_lib/auth/middleware/base.py index bf8272b..75322e2 100644 --- a/bento_lib/auth/middleware/base.py +++ b/bento_lib/auth/middleware/base.py @@ -6,6 +6,7 @@ from typing import Any, Callable, Iterable from ..exceptions import BentoAuthException +from ..permissions import Permission from ..types import EvaluationResultMatrix, EvaluationResultDict from .mark_authz_done_mixin import MarkAuthzDoneMixin @@ -94,7 +95,7 @@ def authz_post( return res.json() @staticmethod - def _evaluate_body(resources: Iterable[dict], permissions: Iterable[str]) -> dict: + def _evaluate_body(resources: Iterable[dict], permissions: Iterable[Permission]) -> dict: return {"resources": tuple(resources), "permissions": tuple(permissions)} @staticmethod @@ -102,14 +103,17 @@ def _matrix_tuple_cast(authz_result: list[list[bool]]) -> EvaluationResultMatrix return tuple(tuple(x) for x in authz_result) @staticmethod - def _permissions_matrix_to_dict(m: EvaluationResultMatrix, permissions: Iterable[str]) -> EvaluationResultDict: + def _permissions_matrix_to_dict( + m: EvaluationResultMatrix, + permissions: Iterable[Permission], + ) -> EvaluationResultDict: return tuple({p: pv for p, pv in zip(permissions, r)} for r in m) def evaluate( self, request: Any, resources: Iterable[dict], - permissions: Iterable[str], + permissions: Iterable[Permission], require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -130,7 +134,7 @@ def evaluate_to_dict( self, request: Any, resources: Iterable[dict], - permissions: Iterable[str], + permissions: Iterable[Permission], require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -144,7 +148,7 @@ def evaluate_one( self, request: Any, resource: dict, - permission: str, + permission: Permission, require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -175,7 +179,7 @@ async def async_evaluate( self, request: Any, resources: Iterable[dict], - permissions: Iterable[str], + permissions: Iterable[Permission], require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -198,7 +202,7 @@ async def async_evaluate_to_dict( self, request: Any, resources: Iterable[dict], - permissions: Iterable[str], + permissions: Iterable[Permission], require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -213,7 +217,7 @@ async def async_evaluate_one( self, request: Any, resource: dict, - permission: str, + permission: Permission, require_token: bool = False, headers_getter: Callable[[Any], dict[str, str]] | None = None, mark_authz_done: bool = False, @@ -227,7 +231,7 @@ async def async_evaluate_one( def check_authz_evaluate( self, request: Any, - permissions: frozenset[str], + permissions: frozenset[Permission], resource: dict, require_token: bool = True, set_authz_flag: bool = False, @@ -253,7 +257,7 @@ def check_authz_evaluate( async def async_check_authz_evaluate( self, request: Any, - permissions: frozenset[str], + permissions: frozenset[Permission], resource: dict, require_token: bool = True, set_authz_flag: bool = False, diff --git a/bento_lib/auth/middleware/constants.py b/bento_lib/auth/middleware/constants.py deleted file mode 100644 index aba067c..0000000 --- a/bento_lib/auth/middleware/constants.py +++ /dev/null @@ -1 +0,0 @@ -RESOURCE_EVERYTHING = {"everything": True} diff --git a/bento_lib/auth/middleware/fastapi.py b/bento_lib/auth/middleware/fastapi.py index 64d700d..0fe7f15 100644 --- a/bento_lib/auth/middleware/fastapi.py +++ b/bento_lib/auth/middleware/fastapi.py @@ -7,7 +7,8 @@ from bento_lib.responses.errors import http_error from bento_lib.auth.exceptions import BentoAuthException from bento_lib.auth.middleware.base import BaseAuthMiddleware -from bento_lib.auth.middleware.constants import RESOURCE_EVERYTHING +from bento_lib.auth.permissions import Permission +from bento_lib.auth.resources import RESOURCE_EVERYTHING __all__ = [ "FastApiAuthMiddleware", @@ -74,7 +75,7 @@ def _inner(request: Request): def dep_require_permissions_on_resource( self, - permissions: frozenset[str], + permissions: frozenset[Permission], resource: dict | None = None, require_token: bool = True, set_authz_flag: bool = True, diff --git a/bento_lib/auth/middleware/flask.py b/bento_lib/auth/middleware/flask.py index 4284ae9..792c114 100644 --- a/bento_lib/auth/middleware/flask.py +++ b/bento_lib/auth/middleware/flask.py @@ -5,7 +5,8 @@ from bento_lib.auth.exceptions import BentoAuthException from bento_lib.auth.middleware.base import BaseAuthMiddleware -from bento_lib.auth.middleware.constants import RESOURCE_EVERYTHING +from bento_lib.auth.permissions import Permission +from bento_lib.auth.resources import RESOURCE_EVERYTHING from bento_lib.responses.errors import http_error __all__ = [ @@ -75,7 +76,7 @@ def get_authz_header_value(self, r: Request) -> str | None: def deco_require_permissions_on_resource( self, - permissions: frozenset[str], + permissions: frozenset[Permission], resource: dict | None = None, require_token: bool = True, set_authz_flag: bool = True, diff --git a/tests/common.py b/tests/common.py index 22a3da3..2ea4afc 100644 --- a/tests/common.py +++ b/tests/common.py @@ -3,7 +3,6 @@ from bento_lib import workflows __all__ = [ - "PERMISSION_INGEST_DATA", "authz_test_case_params", "authz_test_cases", "TEST_AUTHZ_VALID_POST_BODY", @@ -12,9 +11,6 @@ "WORKFLOW_DEF", ] - -PERMISSION_INGEST_DATA = "ingest:data" - # cases: (authz response code, authz response result, test client URL, auth header included, assert final response) authz_test_case_params = "authz_code, authz_res, test_url, inc_headers, test_code" authz_test_cases = ( diff --git a/tests/django_test_project/test_app/views.py b/tests/django_test_project/test_app/views.py index 50e7bcf..8467eb9 100644 --- a/tests/django_test_project/test_app/views.py +++ b/tests/django_test_project/test_app/views.py @@ -1,11 +1,10 @@ import json -from bento_lib.auth.middleware.constants import RESOURCE_EVERYTHING +from bento_lib.auth.resources import RESOURCE_EVERYTHING +from bento_lib.auth.permissions import P_INGEST_DATA from django.http import HttpRequest, JsonResponse from ..django_test_project.authz import authz -PERMISSION_INGEST_DATA = "ingest:data" - def auth_post_public(request: HttpRequest): authz.mark_authz_done(request) @@ -15,7 +14,7 @@ def auth_post_public(request: HttpRequest): def auth_post_private(request: HttpRequest): authz.check_authz_evaluate( request, - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), RESOURCE_EVERYTHING, require_token=True, set_authz_flag=True, @@ -26,7 +25,7 @@ def auth_post_private(request: HttpRequest): def auth_post_private_no_flag(request: HttpRequest): authz.check_authz_evaluate( request, - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), RESOURCE_EVERYTHING, require_token=True, set_authz_flag=False, @@ -38,7 +37,7 @@ def auth_post_private_no_flag(request: HttpRequest): def auth_post_private_no_token(request: HttpRequest): authz.check_authz_evaluate( request, - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), RESOURCE_EVERYTHING, require_token=False, set_authz_flag=True, diff --git a/tests/test_platform_fastapi.py b/tests/test_platform_fastapi.py index e1a7d62..d8191c6 100644 --- a/tests/test_platform_fastapi.py +++ b/tests/test_platform_fastapi.py @@ -12,9 +12,9 @@ from pydantic import BaseModel from bento_lib.auth.exceptions import BentoAuthException -from bento_lib.auth.middleware.constants import RESOURCE_EVERYTHING from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware from bento_lib.auth.permissions import P_INGEST_DATA +from bento_lib.auth.resources import RESOURCE_EVERYTHING from bento_lib.responses.fastapi_errors import ( http_exception_handler_factory, bento_auth_exception_handler_factory, @@ -24,7 +24,6 @@ from bento_lib.workflows.fastapi import build_workflow_router from .common import ( - PERMISSION_INGEST_DATA, authz_test_case_params, authz_test_cases, TEST_AUTHZ_VALID_POST_BODY, @@ -157,7 +156,7 @@ async def auth_post_with_token_in_body(request: Request, body: TestTokenPayloadB token = body.token await auth_middleware.async_check_authz_evaluate( request, - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), RESOURCE_EVERYTHING, require_token=True, set_authz_flag=True, @@ -365,7 +364,7 @@ async def test_fastapi_auth_disabled(aioresponse: aioresponses, fastapi_client_a assert await auth_middleware_disabled.async_check_authz_evaluate( Request({"type": "http"}), - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), {"everything": True}, ) is None diff --git a/tests/test_platform_flask.py b/tests/test_platform_flask.py index 2bd304a..7b3bb88 100644 --- a/tests/test_platform_flask.py +++ b/tests/test_platform_flask.py @@ -8,11 +8,11 @@ from flask.testing import FlaskClient from werkzeug.exceptions import BadRequest, NotFound, InternalServerError -from bento_lib.auth.middleware.constants import RESOURCE_EVERYTHING from bento_lib.auth.middleware.flask import FlaskAuthMiddleware +from bento_lib.auth.permissions import P_INGEST_DATA +from bento_lib.auth.resources import RESOURCE_EVERYTHING from .common import ( - PERMISSION_INGEST_DATA, authz_test_case_params, authz_test_cases, TEST_AUTHZ_VALID_POST_BODY, @@ -73,18 +73,18 @@ def auth_post_public(): return jsonify(request.json) @test_app_auth.route("/post-private", methods=["POST"]) - @auth_middleware.deco_require_permissions_on_resource(frozenset({PERMISSION_INGEST_DATA})) + @auth_middleware.deco_require_permissions_on_resource(frozenset({P_INGEST_DATA})) def auth_post_private(): return jsonify(request.json) @test_app_auth.route("/post-private-no-flag", methods=["POST"]) - @auth_middleware.deco_require_permissions_on_resource(frozenset({PERMISSION_INGEST_DATA}), set_authz_flag=False) + @auth_middleware.deco_require_permissions_on_resource(frozenset({P_INGEST_DATA}), set_authz_flag=False) def auth_post_private_no_flag(): auth_middleware.mark_authz_done(request) return jsonify(request.json) @test_app_auth.route("/post-private-no-token", methods=["POST"]) - @auth_middleware.deco_require_permissions_on_resource(frozenset({PERMISSION_INGEST_DATA}), require_token=False) + @auth_middleware.deco_require_permissions_on_resource(frozenset({P_INGEST_DATA}), require_token=False) def auth_post_private_no_token(): return jsonify(request.json) @@ -106,7 +106,7 @@ def auth_post_with_token_in_body(): payload = request.json["payload"] auth_middleware.check_authz_evaluate( request, - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), RESOURCE_EVERYTHING, require_token=True, set_authz_flag=True, @@ -122,7 +122,7 @@ def auth_post_with_token_evaluate_one(): return jsonify({"payload": auth_middleware.evaluate_one( request, RESOURCE_EVERYTHING, - PERMISSION_INGEST_DATA, + P_INGEST_DATA, require_token=True, headers_getter=(lambda _r: {"Authorization": f"Bearer {token}"}), )}) @@ -135,7 +135,7 @@ def auth_post_with_token_evaluate__to_dict(): return jsonify({"payload": auth_middleware.evaluate_to_dict( request, (RESOURCE_EVERYTHING,), - (PERMISSION_INGEST_DATA,), + (P_INGEST_DATA,), require_token=True, headers_getter=(lambda _r: {"Authorization": f"Bearer {token}"}), )}) @@ -163,7 +163,7 @@ def auth_disabled_post_public(): return jsonify(request.json) @test_app_auth_disabled.route("/post-private", methods=["POST"]) - @auth_middleware_disabled.deco_require_permissions_on_resource(frozenset({PERMISSION_INGEST_DATA})) + @auth_middleware_disabled.deco_require_permissions_on_resource(frozenset({P_INGEST_DATA})) def auth_disabled_post_private(): return jsonify(request.json) @@ -293,6 +293,6 @@ def test_flask_auth_disabled(flask_client_auth_disabled_with_middleware: tuple[F assert auth_middleware_disabled.check_authz_evaluate( Request({}), - frozenset({PERMISSION_INGEST_DATA}), + frozenset({P_INGEST_DATA}), {"everything": True}, ) is None