"""Onboard device updates (credentials / port tweaks).""" from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.core.crypto import encrypt_secret from app.core.deps import require_readonly, require_support from app.database import get_db from app.models.inventory import Device from app.models.user import User from app.schemas import DeviceOut, DeviceUpdate from app.services.vessel_devices import device_to_out router = APIRouter(prefix="/api/devices", tags=["devices"]) @router.get("", response_model=list[DeviceOut]) async def list_devices(db: AsyncSession = Depends(get_db), _: User = Depends(require_readonly)): res = await db.execute(select(Device).order_by(Device.vessel_id, Device.name)) return [device_to_out(d) for d in res.scalars().all()] @router.patch("/{device_id}", response_model=DeviceOut) async def update_device( device_id: int, body: DeviceUpdate, db: AsyncSession = Depends(get_db), _: User = Depends(require_support), ): res = await db.execute(select(Device).where(Device.id == device_id)) device = res.scalar_one_or_none() if not device: raise HTTPException(status_code=404, detail="Device not found") data = body.model_dump(exclude_unset=True) if "secret" in data: device.secret_enc = encrypt_secret(data.pop("secret")) for k, v in data.items(): setattr(device, k, v) await db.commit() await db.refresh(device) return device_to_out(device)