kiwi-vpn/api/kiwi_vpn_api/db/device.py

134 lines
2.8 KiB
Python
Raw Permalink Normal View History

2022-03-28 20:58:40 +00:00
"""
2022-03-28 21:54:39 +00:00
Python representation of `device` table.
2022-03-28 20:58:40 +00:00
"""
2022-03-28 00:43:28 +00:00
from __future__ import annotations
from datetime import datetime
from enum import Enum
2022-03-28 00:43:28 +00:00
from typing import TYPE_CHECKING
from sqlalchemy.exc import IntegrityError
from sqlmodel import Field, Relationship, SQLModel, UniqueConstraint
from .connection import Connection
if TYPE_CHECKING:
from .user import User
class DeviceStatus(Enum):
uncertified = "uncertified"
pending = "pending"
certified = "certified"
def __repr__(self) -> str:
return self.value
2022-03-28 00:43:28 +00:00
class DeviceBase(SQLModel):
2022-03-28 20:58:40 +00:00
"""
Common to all representations of devices
"""
2022-03-28 00:43:28 +00:00
name: str
type: str
class DeviceCreate(DeviceBase):
2022-03-28 20:58:40 +00:00
"""
Representation of a newly created device
"""
class DeviceRead(DeviceBase):
"""
Representation of a device read via the API
"""
2022-04-02 21:24:44 +00:00
id: int | None = Field(primary_key=True)
status_str: str = Field(default=repr(DeviceStatus.uncertified))
2022-04-02 21:24:44 +00:00
expiry: datetime | None = Field(default=None)
owner_name: str = Field(foreign_key="user.name")
2022-03-28 00:43:28 +00:00
@property
def status(self) -> DeviceStatus:
return DeviceStatus(self.status_str)
# property setters don't work with sqlmodel
def set_status(self, status: DeviceStatus) -> None:
self.status_str = repr(status)
2022-03-28 00:43:28 +00:00
2022-04-02 21:24:44 +00:00
class Device(DeviceRead, table=True):
2022-03-28 20:58:40 +00:00
"""
2022-03-28 21:54:39 +00:00
Representation of `device` table
2022-03-28 20:58:40 +00:00
"""
2022-03-28 00:43:28 +00:00
__table_args__ = (UniqueConstraint(
"owner_name",
"name",
),)
2022-03-28 00:59:53 +00:00
# no idea, but "User" (in quotes) doesn't work here
# might be a future problem?
2022-03-28 00:43:28 +00:00
owner: User = Relationship(
back_populates="devices",
2022-04-05 01:26:48 +00:00
sa_relationship_kwargs={
"lazy": "joined",
},
2022-03-28 00:43:28 +00:00
)
@classmethod
2022-03-29 00:01:12 +00:00
def create(
cls,
*,
owner: User,
device: DeviceCreate,
) -> Device | None:
2022-03-28 00:43:28 +00:00
"""
Create a new device in the database.
"""
try:
with Connection.session as db:
2022-04-02 21:24:44 +00:00
new_device = cls.from_orm(device, {"owner_name": owner.name})
2022-03-28 00:43:28 +00:00
2022-03-29 00:01:12 +00:00
db.add(new_device)
2022-03-28 00:43:28 +00:00
db.commit()
2022-03-29 00:01:12 +00:00
db.refresh(new_device)
2022-03-28 00:43:28 +00:00
2022-03-29 00:01:12 +00:00
return new_device
2022-03-28 00:43:28 +00:00
except IntegrityError:
# device already existed
return None
2022-03-29 15:56:12 +00:00
@classmethod
def get(cls, id: int) -> Device | None:
"""
Load device from database by id.
"""
with Connection.session as db:
return db.get(cls, id)
2022-03-28 00:43:28 +00:00
def update(self) -> None:
"""
Update this device in the database.
"""
with Connection.session as db:
db.add(self)
db.commit()
db.refresh(self)
2022-03-31 16:32:07 +00:00
def delete(self) -> None:
2022-03-28 00:43:28 +00:00
"""
Delete this device from the database.
"""
with Connection.session as db:
db.delete(self)
db.commit()