diff --git a/dev_requirements.txt b/dev_requirements.txt index 695ce38..8588009 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -5,7 +5,7 @@ sphinx sphinx_rtd_theme pytest pytest-cov -casbin_sqlalchemy_adapter +casbin_sqlalchemy_adapter==0.3.2 coverage pypi-publisher bumpversion \ No newline at end of file diff --git a/flask_authz/casbin_enforcer.py b/flask_authz/casbin_enforcer.py index 59841fa..19fc5ac 100644 --- a/flask_authz/casbin_enforcer.py +++ b/flask_authz/casbin_enforcer.py @@ -5,6 +5,7 @@ from functools import wraps from abc import ABC from abc import abstractmethod +import shlex from flask_authz.utils import authorization_decoder, UnSupportedAuthType @@ -161,7 +162,9 @@ def sanitize_group_headers(headers_str, delimiter=',') -> list: Returns: list """ - + if delimiter == ' ' and ((headers_str.startswith("'") and headers_str.endswith("'")) or ( + headers_str.startswith('"') and headers_str.endswith('"'))): + return [string.strip() for string in shlex.split(headers_str) if string != ""] return [string.strip() for string in headers_str.split(delimiter) if string != ""] def manager(self, func): diff --git a/tests/test_casbin_enforcer.py b/tests/test_casbin_enforcer.py index 12aa420..f4d2c9a 100644 --- a/tests/test_casbin_enforcer.py +++ b/tests/test_casbin_enforcer.py @@ -25,6 +25,7 @@ def enforcer(app_fixture): s.add(CasbinRule(ptype="p", v0="data2_admin", v1="/item", v2="GET")) s.add(CasbinRule(ptype="g", v0="alice", v1="data2_admin")) s.add(CasbinRule(ptype="g", v0="users", v1="data2_admin")) + s.add(CasbinRule(ptype="g", v0="group with space", v1="data2_admin")) s.commit() s.close() @@ -57,10 +58,12 @@ def update_callback(self): ("X-User", "bob", "POST", 401, None), ("X-User", "bob", "DELETE", 401, None), ("X-Idp-Groups", "admin", "GET", 401, "X-User"), - ("X-Idp-Groups", "users", "GET", 200, None), + ("X-Idp-Groups", "group with space, users", "GET", 200, None), ("X-Idp-Groups", "noexist,testnoexist,users", "GET", 200, None), # ("X-Idp-Groups", "noexist testnoexist users", "GET", 200, None), ("X-Idp-Groups", "noexist, testnoexist, users", "GET", 200, None), + ("X-Idp-Groups", "group with space", "GET", 200, None), + ("X-Idp-Groups", "somegroup, group with space", "GET", 200, None), ("Authorization", "Basic Ym9iOnBhc3N3b3Jk", "GET", 200, "Authorization"), ("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVudGl0eSI6ImJvYiJ9." "LM-CqxAM2MtT2uT3AO69rZ3WJ81nnyMQicizh4oqBwk", "GET", 200, None), @@ -146,6 +149,21 @@ def item(): assert rv.status_code == status +@pytest.mark.parametrize( + "header_string, expected_list", + [ + ("noexist,testnoexist,users ", ["noexist", "testnoexist", "users"]), + ("noexist testnoexist users", ["noexist", "testnoexist", "users"]), + ("noexist, testnoexist, users", ["noexist", "testnoexist", "users"]), + ("somegroup, group with space", ["somegroup", "group with space"]), + ("group with space", ["group with space"]) + ] +) +def test_sanitize_group_headers(header_string, expected_list): + header_list = CasbinEnforcer.sanitize_group_headers(header_string) + assert header_list == expected_list + + def test_manager(app_fixture, enforcer): @app_fixture.route("/manager", methods=["POST"]) @enforcer.manager @@ -214,7 +232,8 @@ def owner_loader(): ("noexist, testnoexist, users", ["noexist", "testnoexist", "users"]), ("noexist, testnoexist, users", ["noexist", "testnoexist", "users"]), ("somegroup, group with space", ["somegroup", "group with space"]), - ("group with space", ["group with space"]) + ("group with space", ["group with space"]), + ("group 'with, space", ["group 'with", "space"]) ] ) def test_sanitize_group_headers(header_string, expected_list): @@ -229,6 +248,13 @@ def test_sanitize_group_headers(header_string, expected_list): ("noexist testnoexist users", ["noexist", "testnoexist", "users"]), ("noexist, testnoexist, users", ["noexist,", "testnoexist,", "users"]), ("somegroup, group with space", ["somegroup,", "group", "with", "space"]), + ('"agroup" "delimited by" "spaces"', ["agroup", "delimited by", "spaces"]), + ("'agroup' 'delimited by' 'spaces'", ["agroup", "delimited by", "spaces"]), + ("group'with space", ["group'with", "space"]), + ("group' with space", ["group'", "with", "space"]), + ("'group with' space", ["'group", "with'", "space"]), # quotes must be used on all groups, not only in 1 + ('"group with space"', ["group with space"]), + ("'group with space'", ["group with space"]), ("group with space", ["group", "with", "space"]) ] )