API key come hash SHA-256, una per sessione, TTL rinnovabile (#41)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ NOT protected by API Key auth (standalone access).
|
||||
"""
|
||||
import hmac
|
||||
import random
|
||||
import secrets
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
@@ -25,7 +24,7 @@ from src.backend.models.orm import (
|
||||
User, Recipe, RecipeVersion, RecipeTask, RecipeSubtask, Measurement,
|
||||
)
|
||||
from src.backend.models.orm.station import Station, StationRecipeAssignment
|
||||
from src.backend.services.auth_service import hash_password
|
||||
from src.backend.services.auth_service import hash_password, issue_api_key, revoke_all_keys
|
||||
from src.backend.services.measurement_service import calculate_pass_fail
|
||||
|
||||
router = APIRouter(prefix="/api/setup", tags=["setup"])
|
||||
@@ -321,8 +320,6 @@ async def create_admin(body: CreateAdminBody):
|
||||
"""Create an admin user with all roles."""
|
||||
_check_password(body.password)
|
||||
|
||||
api_key = secrets.token_hex(32)
|
||||
|
||||
async with async_session_factory() as session:
|
||||
async with session.begin():
|
||||
user = User(
|
||||
@@ -332,9 +329,10 @@ async def create_admin(body: CreateAdminBody):
|
||||
display_name=body.admin_display_name,
|
||||
roles=["Maker", "MeasurementTec", "Metrologist"],
|
||||
is_admin=True,
|
||||
api_key=api_key,
|
||||
)
|
||||
session.add(user)
|
||||
await session.flush()
|
||||
api_key = await issue_api_key(session, user)
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
@@ -404,7 +402,6 @@ async def seed_demo_data(body: PasswordBody):
|
||||
email=u["email"],
|
||||
roles=u["roles"],
|
||||
is_admin=u["is_admin"],
|
||||
api_key=secrets.token_hex(32),
|
||||
)
|
||||
session.add(user)
|
||||
created_users.append(user)
|
||||
@@ -652,7 +649,6 @@ async def manage_user(body: ManageUserBody):
|
||||
email=body.email,
|
||||
roles=body.roles,
|
||||
is_admin=body.is_admin,
|
||||
api_key=secrets.token_hex(32),
|
||||
)
|
||||
session.add(user)
|
||||
await session.flush()
|
||||
@@ -707,7 +703,7 @@ async def change_user_password(body: ChangeUserPasswordBody):
|
||||
detail=f"User ID {body.user_id} not found",
|
||||
)
|
||||
user.password_hash = hash_password(body.new_password)
|
||||
user.api_key = None # Invalidate sessions
|
||||
await revoke_all_keys(session, user.id) # Invalidate sessions
|
||||
|
||||
return {"status": "ok", "message": f"Password changed for '{user.username}'"}
|
||||
|
||||
@@ -730,7 +726,7 @@ async def toggle_user_active(body: ToggleUserActiveBody):
|
||||
)
|
||||
user.active = not user.active
|
||||
if not user.active:
|
||||
user.api_key = None # Invalidate sessions on deactivation
|
||||
await revoke_all_keys(session, user.id) # on deactivation
|
||||
new_status = "active" if user.active else "inactive"
|
||||
|
||||
return {"status": "ok", "message": f"User '{user.username}' is now {new_status}", "active": user.active}
|
||||
|
||||
Reference in New Issue
Block a user