Compare commits

..

No commits in common. "fc0616ce6a8fd0c946b2f560b451b57fcd6179a2" and "1709290ea9c9347a3bfa18d74964a4516e388601" have entirely different histories.

8 changed files with 15 additions and 54 deletions

View file

@ -1,17 +0,0 @@
# 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] = {}

View file

@ -12,19 +12,17 @@ from scopes.config import settings
from scopes.storage import user as st_user from scopes.storage import user as st_user
from scopes.storage.common import Storage from scopes.storage.common import Storage
class UserBase(BaseModel): class User(BaseModel):
uid: str | None = None
timeStamp: datetime | None = None
name: str name: str
login: str login: str
display_name: str display_name: str
email: str | None = None email: str | None = None
pw_hash: str | None = Field(exclude=True, default=None)
groups: List[str] = Field(default_factory=list) groups: List[str] = Field(default_factory=list)
class User(UserBase): class UserIn(User):
uid: str | None = None
timeStamp: datetime | None = None
pw_hash: str | None = Field(exclude=True, default=None)
class UserIn(UserBase):
password: str | None = None password: str | None = None
def hashPassword(self) -> str | None: def hashPassword(self) -> str | None:

View file

@ -6,17 +6,15 @@ from fastapi import Depends
from typing import Annotated from typing import Annotated
from scopes import config from scopes import config
from scopes.api.auth import config as auth_config
from scopes.storage import common from scopes.storage import common
type Storage = Annotated[common.Storage, Depends(storage)] type Storage = Annotated[common.Storage, Depends(storage)]
type Auth = Annotated[str, Depends(auth_method())] type Auth = Annotated[str, Depends(authenticator)]
def storage(): def storage():
stf = config.StorageFactory(config.settings) stf = config.StorageFactory(config.settings)
return stf(config.settings.dbschema) return stf(config.settings.dbschema)
def auth_method(): def authenticator():
auth = auth_config.auth_methods.get(auth_config.settings.auth_method) return config.Authenticator()
return auth

View file

@ -1,5 +1,4 @@
# scopes.config.py # scopes.config.py
from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict
from scopes.storage.db.postgres import StorageFactory from scopes.storage.db.postgres import StorageFactory

View file

@ -120,15 +120,13 @@ class Container:
changed = False changed = False
if found.data != track.data: if found.data != track.data:
found.update(track.data) found.update(track.data)
track.data = found.data
changed = True changed = True
if track.timeStamp is not None and found.timeStamp != track.timeStamp: if track.timeStamp is not None and found.timeStamp != track.timeStamp:
found.timeStamp = track.timeStamp found.timeStamp = track.timeStamp
changed = True changed = True
if changed: if changed:
self.update(found, not track.timeStamp) self.update(found)
track.trackId = found.trackId track.trackId = found.trackId
track.timeStamp = found.timeStamp
return found.trackId return found.trackId
def insert(self, track, withTrackId=False): def insert(self, track, withTrackId=False):

View file

@ -12,7 +12,6 @@ class User(concept.Concept):
def prepareData(data, obj): def prepareData(data, obj):
data = concept.Concept.prepareData(data, obj) data = concept.Concept.prepareData(data, obj)
pw = data.pop('password', None) pw = data.pop('password', None)
if pw:
data['pw_hash'] = obj.hashPassword() data['pw_hash'] = obj.hashPassword()
return data return data

View file

@ -9,7 +9,7 @@ DBUSER=testuser
DBPASSWORD=secret DBPASSWORD=secret
DBSCHEMA=testing DBSCHEMA=testing
AUTH_METHOD=testing AUTHENTICATOR=testing
# openssl rand -hex 32: # openssl rand -hex 32:
JWT_KEY=391a521ee5ba2b6ce67b8fdbb9f0ca88f40a87d3bc1e82974381b647bb0fc776 JWT_KEY=391a521ee5ba2b6ce67b8fdbb9f0ca88f40a87d3bc1e82974381b647bb0fc776

View file

@ -10,7 +10,6 @@ from fastapi.testclient import TestClient
from httpx2 import ASGITransport, AsyncClient from httpx2 import ASGITransport, AsyncClient
from scopes.api import main from scopes.api import main
from scopes.api.auth import config as auth_config
from scopes.api.main import app from scopes.api.main import app
from scopes.storage import tracking, user as st_user from scopes.storage import tracking, user as st_user
from scopes.api.auth import user as api_user from scopes.api.auth import user as api_user
@ -23,10 +22,6 @@ def storage():
storage.commit() storage.commit()
return storage 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(): def async_client():
return AsyncClient(transport=ASGITransport(app=app), base_url='http://test') return AsyncClient(transport=ASGITransport(app=app), base_url='http://test')
@ -77,20 +72,11 @@ def test_user(storage, caplog):
assert len(users) == 1 assert len(users) == 1
u01i = users[0] u01i = users[0]
assert u01i.get(pw_hash) is None assert u01i.get(pw_hash) is None
inp = {'name': 'jane', 'login': 'jane', 'display_name': 'Jane', resp = clt.post('/users', json={'name': 'jane', 'login': 'jane',
'email': 'jane@xmpl.org', 'password': 'secret'} 'display_name': 'Jane', 'email': 'jane@xmpl.org',
resp = clt.post('/users', json=inp) 'password': 'secret'})
assert resp.status_code == 200 assert resp.status_code == 200
u02 = resp.json() u02 = resp.json()
assert u02['uid'] == 'user-2' assert u02['uid'] == 'user-2'
ts02 = u02.get('timeStamp') assert u02.get('timeStamp') is not None
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