Add authorization

This commit is contained in:
2025-10-23 11:22:27 +02:00
parent a1563b53ac
commit e1c8b4ebeb
7 changed files with 82 additions and 9 deletions

4
dev-server.sh Normal file
View File

@@ -0,0 +1,4 @@
if [ -z "${APS_username}" ]; then
export APS_username="testuser"
fi
fastapi dev src/allmende_payment_system/app.py

View File

@@ -22,6 +22,7 @@ build-backend = "uv_build"
[dependency-groups] [dependency-groups]
dev = [ dev = [
"black>=25.9.0", "black>=25.9.0",
"httpx>=0.28.1",
"isort>=7.0.0", "isort>=7.0.0",
"pytest>=8.4.2", "pytest>=8.4.2",
] ]

View File

@@ -1,9 +1,25 @@
# backend/app/main.py import os
from fastapi import FastAPI, Request from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
app = FastAPI()
async def get_user(request: Request) -> dict:
if username := os.environ.get("APS_username", None):
return {"username": username}
if "ynh_user" not in request.headers:
raise HTTPException(status_code=401, detail="Missing ynh_user header")
return {"username": request.headers["ynh_user"]}
UserDep = Annotated[dict, Depends(get_user)]
app = FastAPI(dependencies=[Depends(get_user)])
templates = Jinja2Templates(directory="src/allmende_payment_system/templates") templates = Jinja2Templates(directory="src/allmende_payment_system/templates")
app.mount( app.mount(
"/static", "/static",

30
test/conftest.py Normal file
View File

@@ -0,0 +1,30 @@
import pytest
from fastapi import Request
from fastapi.testclient import TestClient
from allmende_payment_system.app import create_app
@pytest.fixture(scope="session")
def client():
app = create_app()
async def add_ynh_headers(request: Request, call_next):
username = request.headers.get("APS-TEST-username", "test")
# This seems to work although headers are immutable
# If this ever turns out to be a problem, we can use request.state instead,
# but will have to modify app.get_user
request.headers._list.append((b"ynh_user", username.encode("utf-8")))
response = await call_next(request)
return response
app.middleware("http")(add_ynh_headers)
return TestClient(app)
@pytest.fixture(scope="session")
def unauthorized_client():
app = create_app()
return TestClient(app)

12
test/test_auth.py Normal file
View File

@@ -0,0 +1,12 @@
from allmende_payment_system.models import Account
def test_unauthorized_access(unauthorized_client):
response = unauthorized_client.get("/")
assert response.status_code == 401
def test_unauthorized_access(unauthorized_client):
response = unauthorized_client.get("/")
print(response.text)
assert response.status_code == 401

View File

@@ -1,8 +1,9 @@
# tests/conftest.py
import pytest import pytest
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base from sqlalchemy.orm import sessionmaker
from allmende_payment_system.models import Base, User
from allmende_payment_system.models import Account, Base, User
# Create an in-memory SQLite database # Create an in-memory SQLite database
@pytest.fixture @pytest.fixture
@@ -19,9 +20,16 @@ def in_memory_db():
db.close() db.close()
def test_create_user(in_memory_db): def test_user_model(in_memory_db):
user = User(username="test", display_name="Test User") user = User(username="test", display_name="Test User")
in_memory_db.add(user) in_memory_db.add(user)
in_memory_db.commit() in_memory_db.commit()
assert user.id is not None assert user.id is not None
account = Account(name="Test Account")
account.users.append(user)
in_memory_db.add(account)
in_memory_db.commit()
assert len(user.accounts) == 1

2
uv.lock generated
View File

@@ -14,6 +14,7 @@ dependencies = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "black" }, { name = "black" },
{ name = "httpx" },
{ name = "isort" }, { name = "isort" },
{ name = "pytest" }, { name = "pytest" },
] ]
@@ -27,6 +28,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "black", specifier = ">=25.9.0" }, { name = "black", specifier = ">=25.9.0" },
{ name = "httpx", specifier = ">=0.28.1" },
{ name = "isort", specifier = ">=7.0.0" }, { name = "isort", specifier = ">=7.0.0" },
{ name = "pytest", specifier = ">=8.4.2" }, { name = "pytest", specifier = ">=8.4.2" },
] ]