api: improvements, storage users as dependency
This commit is contained in:
parent
a139fd784e
commit
8963c2ac87
4 changed files with 23 additions and 18 deletions
|
|
@ -9,7 +9,7 @@ class Settings(BaseSettings):
|
||||||
#, env_prefix='SCOPES_')
|
#, env_prefix='SCOPES_')
|
||||||
auth_method: str = 'oauth2'
|
auth_method: str = 'oauth2'
|
||||||
jwt_key: str | None = None
|
jwt_key: str | None = None
|
||||||
jwt_atlgorithm: str = 'HS256'
|
jwt_algorithm: str = 'HS256'
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class User(UserBase):
|
||||||
timeStamp: datetime | None = None
|
timeStamp: datetime | None = None
|
||||||
pw_hash: str | None = Field(exclude=True, default=None)
|
pw_hash: str | None = Field(exclude=True, default=None)
|
||||||
|
|
||||||
class UserIn(UserBase):
|
class UserEdit(UserBase):
|
||||||
password: str | None = None
|
password: str | None = None
|
||||||
|
|
||||||
def hashPassword(self) -> str | None:
|
def hashPassword(self) -> str | None:
|
||||||
|
|
@ -41,15 +41,10 @@ def hashPassword(pw):
|
||||||
def verifyPassword(plain, hashed):
|
def verifyPassword(plain, hashed):
|
||||||
return pw_hash.verify(plain, hashed)
|
return pw_hash.verify(plain, hashed)
|
||||||
|
|
||||||
def getUser(storage: Storage, userName: str) -> User:
|
def userFromToken(users: deps.Users, token: deps.AuthToken):
|
||||||
users = storage.create(st_user.Users)
|
|
||||||
user = users.queryLast(name=userName)
|
|
||||||
return user.toObject(User)
|
|
||||||
|
|
||||||
async def authenticate(storage: deps.Storage, token: deps.AuthUser):
|
|
||||||
payload = jwt.decode(token, settings.jwt_key, algorithms=[settings.jwt_algorithm])
|
payload = jwt.decode(token, settings.jwt_key, algorithms=[settings.jwt_algorithm])
|
||||||
userName = payload.get('sub')
|
userName = payload.get('sub')
|
||||||
user = getUser(storage, userName)
|
user = users.queryLast(name=userName)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
# routes
|
# routes
|
||||||
|
|
@ -57,16 +52,14 @@ async def authenticate(storage: deps.Storage, token: deps.AuthUser):
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get('/users', response_model=list[User])
|
@router.get('/users', response_model=list[User])
|
||||||
async def get_users(storage: deps.Storage):
|
async def get_users(users: deps.Users):
|
||||||
users = storage.create(st_user.Users)
|
|
||||||
result = [tr.toObject(User) for tr in users.query()]
|
result = [tr.toObject(User) for tr in users.query()]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@router.post('/users', response_model=User)
|
@router.post('/users', response_model=User)
|
||||||
async def post_user(user: Annotated[UserIn, Body()], storage: deps.Storage,
|
async def post_user(user: Annotated[UserEdit, Body()], users: deps.Users,
|
||||||
auth_user: deps.AuthUser):
|
auth_user: deps.AuthUser):
|
||||||
print('*** post_user', auth_user)
|
print('*** post_user', auth_user)
|
||||||
users = storage.create(st_user.Users)
|
|
||||||
tr = st_user.User.fromObject(user)
|
tr = st_user.User.fromObject(user)
|
||||||
users.save(tr)
|
users.save(tr)
|
||||||
return tr.toObject(User)
|
return tr.toObject(User)
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,30 @@ from typing import Annotated
|
||||||
from scopes import config
|
from scopes import config
|
||||||
from scopes.api.auth import config as auth_config
|
from scopes.api.auth import config as auth_config
|
||||||
from scopes.storage import common
|
from scopes.storage import common
|
||||||
|
from scopes.storage import user as st_user
|
||||||
|
|
||||||
type Storage = Annotated[common.Storage, Depends(storage)]
|
type Storage = Annotated[common.Storage, Depends(storage)]
|
||||||
|
type Users = Annotated[st_user.Users, Depends(users)]
|
||||||
|
|
||||||
type AuthUser = Annotated[str, Depends(auth_user)]
|
type AuthUser = Annotated[str, Depends(auth_user)]
|
||||||
|
type AuthToken = Annotated[str, Depends(auth_token)]
|
||||||
|
|
||||||
|
# storage
|
||||||
|
|
||||||
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 users(storage: Storage):
|
||||||
|
return storage.create(st_user.Users)
|
||||||
|
|
||||||
|
# auth
|
||||||
|
|
||||||
def auth_user():
|
def auth_user():
|
||||||
auth = auth_config.auth_methods.get(auth_config.settings.auth_method)
|
auth = auth_config.auth_methods.get(auth_config.settings.auth_method)
|
||||||
if auth:
|
if auth is not None:
|
||||||
return auth()
|
return auth()
|
||||||
|
|
||||||
|
def auth_token():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,19 @@
|
||||||
"""Tests for the fastapi- (and asyncio-) based stuff"""
|
"""Tests for the fastapi- (and asyncio-) based stuff"""
|
||||||
|
|
||||||
from scopes import config
|
from scopes import config
|
||||||
|
from scopes.api.auth import config as auth_config
|
||||||
config.settings = config.Settings(_env_file='tests/test.env')
|
config.settings = config.Settings(_env_file='tests/test.env')
|
||||||
|
auth_config.settings = auth_config.Settings(_env_file='tests/test.env')
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from httpx2 import ASGITransport, AsyncClient, BasicAuth
|
from httpx2 import ASGITransport, AsyncClient, BasicAuth
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
config.settings = config.Settings(_env_file='tests/test.env')
|
|
||||||
auth_config.settings = auth_config.Settings(_env_file='tests/test.env')
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture(scope='module')
|
||||||
def storage():
|
def storage():
|
||||||
storage = config.StorageFactory(config.settings)(config.settings.dbschema)
|
storage = config.StorageFactory(config.settings)(config.settings.dbschema)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue