deleting a device

This commit is contained in:
Jörn-Michael Miehe 2022-03-29 15:56:12 +00:00
parent 0c8298871f
commit 617ae92d72
4 changed files with 75 additions and 2 deletions

View file

@ -85,6 +85,15 @@ class Device(DeviceBase, table=True):
# device already existed # device already existed
return None return None
@classmethod
def get(cls, id: int) -> Device | None:
"""
Load device from database by id.
"""
with Connection.session as db:
return db.get(cls, id)
def update(self) -> None: def update(self) -> None:
""" """
Update this device in the database. Update this device in the database.

View file

@ -202,3 +202,17 @@ class User(UserBase, table=True):
capability_name=capability.value, capability_name=capability.value,
) for capability in capabilities ) for capability in capabilities
] ]
def owns(
self,
device: Device,
) -> bool:
"""
Check if this user owns a device.
"""
return (
device.owner_name == self.name
# admin owns everything
or self.can(UserCapabilityType.admin)
)

View file

@ -7,7 +7,7 @@ from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from ..config import Config, Settings from ..config import Config, Settings
from ..db import User, UserCapabilityType from ..db import Device, User, UserCapabilityType
oauth2_scheme = OAuth2PasswordBearer( oauth2_scheme = OAuth2PasswordBearer(
tokenUrl=f"{Settings._.api_v1_prefix}/user/authenticate" tokenUrl=f"{Settings._.api_v1_prefix}/user/authenticate"
@ -128,3 +128,31 @@ async def get_user_by_name(
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN) raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
return user return user
async def get_device_by_id(
device_id: int,
current_config: Config | None = Depends(Config.load),
) -> Device | None:
# can't connect to an unconfigured database
if current_config is None:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
return Device.get(device_id)
async def get_device_by_id_if_editable(
device: Device | None = Depends(get_device_by_id),
current_user: User = Depends(get_current_user_if_exists),
) -> Device:
# fail if device doesn't exist
if device is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
# fail if device is not owned by current user
if not current_user.owns(device):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
return device

View file

@ -5,7 +5,7 @@
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from ..db import Device, DeviceCreate, DeviceRead, User from ..db import Device, DeviceCreate, DeviceRead, User
from ._common import Responses, get_user_by_name from ._common import Responses, get_device_by_id_if_editable, get_user_by_name
router = APIRouter(prefix="/device", tags=["device"]) router = APIRouter(prefix="/device", tags=["device"])
@ -42,3 +42,25 @@ async def add_device(
# return the created device on success # return the created device on success
return new_device return new_device
@router.delete(
"/{device_id}",
responses={
status.HTTP_200_OK: Responses.OK,
status.HTTP_400_BAD_REQUEST: Responses.NOT_INSTALLED,
status.HTTP_401_UNAUTHORIZED: Responses.NEEDS_USER,
status.HTTP_403_FORBIDDEN: Responses.NEEDS_ADMIN,
status.HTTP_404_NOT_FOUND: Responses.ENTRY_DOESNT_EXIST,
},
response_model=User,
)
async def remove_device(
device: Device = Depends(get_device_by_id_if_editable),
):
"""
DELETE ./{device_id}: Remove a device from the database.
"""
# delete device
device.delete()