Skip to content

Commit

Permalink
fix: register custom config model (#189)
Browse files Browse the repository at this point in the history
* validate model path

* do normalization in path and add tests

* fix flake8 errors
  • Loading branch information
alohamora committed Dec 4, 2023
1 parent 80f0136 commit 2c89ba8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
29 changes: 27 additions & 2 deletions foca/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
from pathlib import Path
from typing import (Any, Dict, List, Optional, Union)

from pkg_resources import resource_filename

from pydantic import (BaseModel, Field, validator) # pylint: disable=E0611
import pymongo

from foca.security.access_control.constants import DEFAULT_MODEL_FILE
from foca.security.access_control.constants import (
ACCESS_CONTROL_BASE_PATH,
DEFAULT_MODEL_FILE
)


def _validate_log_level_choices(level: int) -> int:
Expand Down Expand Up @@ -693,10 +698,30 @@ class AccessControlConfig(FOCABaseConfig):
api_controllers: Optional[str] = None
db_name: Optional[str] = None
collection_name: Optional[str] = None
model: Optional[str] = DEFAULT_MODEL_FILE
model: Optional[str] = None
owner_headers: Optional[set] = None
user_headers: Optional[set] = None

@validator('model', always=True, allow_reuse=True)
def validate_model_path(cls, v: Optional[Path]): # pylint: disable=E0213
"""
Resolve path relative to caller's current working directory if no
absolute path provided for model or Set to default file path for model
if path is not provided.
"""
if v is None:
return str(
resource_filename(
ACCESS_CONTROL_BASE_PATH, DEFAULT_MODEL_FILE
)
)

model_path = Path(v)
if not model_path.is_absolute():
return str(model_path.resolve())

return v


class AuthConfig(FOCABaseConfig):
"""Model for parameters used to configure JSON Web Token (JWT)-based
Expand Down
8 changes: 1 addition & 7 deletions foca/security/access_control/register_access_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,7 @@ def register_casbin_enforcer(
Connexion application instance with registered casbin configuration.
"""
# Check if default, get package path variables for model.
access_control_config_model = str(access_control_config.model)
if access_control_config.api_specs is None:
casbin_model = str(resource_filename(
ACCESS_CONTROL_BASE_PATH, access_control_config_model
))
else:
casbin_model = access_control_config_model
casbin_model = access_control_config.model

logger.info("Setting casbin model.")
app.app.config["CASBIN_MODEL"] = casbin_model
Expand Down
37 changes: 37 additions & 0 deletions tests/security/access_control/test_access_control_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

from copy import deepcopy
from unittest import TestCase


from flask import Flask
import mongomock
import os
from pkg_resources import resource_filename
from pymongo import MongoClient
import pytest

Expand All @@ -15,8 +19,12 @@
putPermission
)
from foca.security.access_control.foca_casbin_adapter.adapter import Adapter
from foca.security.access_control.constants import (
ACCESS_CONTROL_BASE_PATH, DEFAULT_MODEL_FILE
)
from foca.errors.exceptions import BadRequest, InternalServerError, NotFound
from foca.models.config import (AccessControlConfig, Config, MongoConfig)

from tests.mock_data import (
ACCESS_CONTROL_CONFIG,
MOCK_ID,
Expand Down Expand Up @@ -332,3 +340,32 @@ def test_putPermission_BadRequest(self):
with app.test_request_context(json=""):
with pytest.raises(BadRequest):
putPermission.__wrapped__(id=MOCK_ID)


class TestModelPathResolution(TestCase):
"""Test class for checking access control model input resolution"""

def test_no_model_input(self):
config = AccessControlConfig()
default_model_path = str(
resource_filename(
ACCESS_CONTROL_BASE_PATH, DEFAULT_MODEL_FILE
)
)
assert config.model == default_model_path

def test_relative_path_model_input(self):
file_path = "access_model.conf"
config = AccessControlConfig(model=file_path)
assert config.model == os.path.abspath(file_path)

# testing relative paths with relative parent directory notation used
file_path = "../../test/access_model.conf"
config = AccessControlConfig(model=file_path)
assert config.model == os.path.abspath(file_path)

def test_absolute_path_model_input(self):
file_path = "/test/access_model.conf"
config = AccessControlConfig(model=file_path)
assert config.model == file_path
assert config.model == os.path.abspath(file_path)

0 comments on commit 2c89ba8

Please sign in to comment.