diff --git a/scopes/api/auth/config.py b/scopes/api/auth/config.py new file mode 100644 index 0000000..9b63f8d --- /dev/null +++ b/scopes/api/auth/config.py @@ -0,0 +1,17 @@ +# scopes.api.auth.config + +from pydantic_settings import BaseSettings, SettingsConfigDict +from typing import Any +from scopes.storage.db.postgres import StorageFactory + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_file='.env', extra='ignore') + #, env_prefix='SCOPES_') + auth_method: str = 'oauth2' + jwt_key: str | None = None + jwt_atlgorithm: str = 'HS256' + +settings = Settings() + +auth_methods: dict[str, Any] = {} + diff --git a/scopes/api/deps.py b/scopes/api/deps.py index 01349e5..13fd638 100644 --- a/scopes/api/deps.py +++ b/scopes/api/deps.py @@ -6,15 +6,17 @@ from fastapi import Depends from typing import Annotated from scopes import config +from scopes.api.auth import config as auth_config from scopes.storage import common type Storage = Annotated[common.Storage, Depends(storage)] -type Auth = Annotated[str, Depends(authenticator)] +type Auth = Annotated[str, Depends(auth_method())] def storage(): stf = config.StorageFactory(config.settings) return stf(config.settings.dbschema) -def authenticator(): - return config.Authenticator() +def auth_method(): + auth = auth_config.auth_methods.get(auth_config.settings.auth_method) + return auth diff --git a/scopes/config.py b/scopes/config.py index 077f008..0b4ab24 100644 --- a/scopes/config.py +++ b/scopes/config.py @@ -1,4 +1,5 @@ # scopes.config.py + from pydantic_settings import BaseSettings, SettingsConfigDict from scopes.storage.db.postgres import StorageFactory diff --git a/tests/test.env b/tests/test.env index 0433048..b8a1832 100644 --- a/tests/test.env +++ b/tests/test.env @@ -9,7 +9,7 @@ DBUSER=testuser DBPASSWORD=secret DBSCHEMA=testing -AUTHENTICATOR=testing +AUTH_METHOD=testing # openssl rand -hex 32: JWT_KEY=391a521ee5ba2b6ce67b8fdbb9f0ca88f40a87d3bc1e82974381b647bb0fc776 diff --git a/tests/test_api.py b/tests/test_api.py index fc8c354..60d584f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -10,6 +10,7 @@ from fastapi.testclient import TestClient from httpx2 import ASGITransport, AsyncClient from scopes.api import main +from scopes.api.auth import config as auth_config from scopes.api.main import app from scopes.storage import tracking, user as st_user from scopes.api.auth import user as api_user @@ -22,6 +23,10 @@ def storage(): storage.commit() return storage +def dummy_auth(): + return api_user.User(name='tester', login='tester', display_name='Tester') +auth_config.auth_methods['testing'] = dummy_auth + def async_client(): return AsyncClient(transport=ASGITransport(app=app), base_url='http://test') @@ -72,11 +77,20 @@ def test_user(storage, caplog): assert len(users) == 1 u01i = users[0] assert u01i.get(pw_hash) is None - resp = clt.post('/users', json={'name': 'jane', 'login': 'jane', - 'display_name': 'Jane', 'email': 'jane@xmpl.org', - 'password': 'secret'}) + inp = {'name': 'jane', 'login': 'jane', 'display_name': 'Jane', + 'email': 'jane@xmpl.org', 'password': 'secret'} + resp = clt.post('/users', json=inp) assert resp.status_code == 200 u02 = resp.json() assert u02['uid'] == 'user-2' - assert u02.get('timeStamp') is not None + ts02 = u02.get('timeStamp') + assert ts02 is not None + del inp['password'] + inp['display_name'] = 'Jane Doe' + resp = clt.post('/users', json=inp) + assert resp.status_code == 200 + u02a = resp.json() + assert u02a['uid'] == 'user-2' + ts02a = u02a.get('timeStamp') + assert ts02a is not None