Compare commits

...

5 commits

Author SHA1 Message Date
bc3f7984f5 some fun with db_new 2022-03-28 00:50:21 +00:00
c7f93d468e rename 2022-03-28 00:50:00 +00:00
24ade65bb0 db_new interface 2022-03-28 00:48:59 +00:00
04a5798258 capabilities rework 2022-03-28 00:48:44 +00:00
730c7ab966 add devices 2022-03-28 00:43:28 +00:00
5 changed files with 140 additions and 50 deletions

View file

@ -0,0 +1,7 @@
from .capability import Capability
from .connection import Connection
from .device import Device, DeviceBase, DeviceCreate
from .user import User, UserBase, UserCreate, UserRead
__all__ = ["Capability", "Connection", "Device", "DeviceBase", "DeviceCreate",
"User", "UserBase", "UserCreate", "UserRead"]

View file

@ -13,9 +13,11 @@ class Capability(Enum):
issue = "issue" issue = "issue"
renew = "renew" renew = "renew"
def __repr__(self) -> str:
return self.value
class UserCapabilityBase(SQLModel): class UserCapabilityBase(SQLModel):
user_name: str = Field(primary_key=True, foreign_key="user.name")
capability_name: str = Field(primary_key=True) capability_name: str = Field(primary_key=True)
@property @property
@ -27,6 +29,8 @@ class UserCapabilityBase(SQLModel):
class UserCapability(UserCapabilityBase, table=True): class UserCapability(UserCapabilityBase, table=True):
user_name: str = Field(primary_key=True, foreign_key="user.name")
user: "User" = Relationship( user: "User" = Relationship(
back_populates="capabilities" back_populates="capabilities",
) )

View file

@ -0,0 +1,75 @@
from __future__ import annotations
from datetime import datetime
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 DeviceBase(SQLModel):
name: str
type: str
expiry: datetime | None
class DeviceCreate(DeviceBase):
owner_name: str | None
class Device(DeviceBase, table=True, ):
__table_args__ = (UniqueConstraint(
"owner_name",
"name",
),)
id: int | None = Field(primary_key=True)
owner_name: str | None = Field(foreign_key="user.name")
owner: User = Relationship(
back_populates="devices",
)
@classmethod
def create(cls, **kwargs) -> Device | None:
"""
Create a new device in the database.
"""
try:
with Connection.session as db:
device = cls.from_orm(DeviceCreate(**kwargs))
db.add(device)
db.commit()
db.refresh(device)
return device
except IntegrityError:
# device already existed
return None
def update(self) -> None:
"""
Update this device in the database.
"""
with Connection.session as db:
db.add(self)
db.commit()
db.refresh(self)
def delete(self) -> bool:
"""
Delete this device from the database.
"""
with Connection.session as db:
db.delete(self)
db.commit()

View file

@ -1,14 +1,15 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Sequence from typing import Any
from pydantic import root_validator from pydantic import root_validator
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlmodel import Field, Relationship, SQLModel from sqlmodel import Field, Relationship, SQLModel
from ..config import Config from ..config import Config
from .capabilities import Capability, UserCapability from .capability import Capability, UserCapability
from .connection import Connection from .connection import Connection
from .device import Device
class UserBase(SQLModel): class UserBase(SQLModel):
@ -33,6 +34,10 @@ class User(UserBase, table=True):
}, },
) )
devices: list[Device] = Relationship(
back_populates="owner",
)
@classmethod @classmethod
def create(cls, **kwargs) -> User | None: def create(cls, **kwargs) -> User | None:
""" """
@ -104,34 +109,19 @@ class User(UserBase, table=True):
db.delete(self) db.delete(self)
db.commit() db.commit()
def extend_capabilities(self, capabilities: Sequence[Capability]) -> None: def get_capabilities(self) -> set[Capability]:
""" return set(
Extend this user's capabilities capability._
""" for capability in self.capabilities
)
for capability in capabilities: def set_capabilities(self, capabilities: set[Capability]) -> None:
user_capability = UserCapability( self.capabilities = [
UserCapability(
user_name=self.name, user_name=self.name,
capability_name=capability.value, capability_name=capability.value,
) ) for capability in capabilities
]
if user_capability not in self.capabilities:
self.capabilities.append(user_capability)
def remove_capabilities(self, capabilities: Sequence[Capability]) -> None:
"""
Remove from this user's capabilities
"""
for capability in capabilities:
try:
self.capabilities.remove(UserCapability(
user_name=self.name,
capability_name=capability.value,
))
except ValueError:
pass
class UserCreate(UserBase): class UserCreate(UserBase):

View file

@ -14,8 +14,10 @@ from fastapi import FastAPI
from .config import Config, Settings from .config import Config, Settings
from .db import Connection from .db import Connection
from .db.schemata import User # from .db.schemata import User
from .db_new import capabilities, connection, user from .db_new import Capability
from .db_new import Connection as Connection_new
from .db_new import Device, User
from .routers import main_router from .routers import main_router
settings = Settings.get() settings = Settings.get()
@ -47,31 +49,43 @@ async def on_startup() -> None:
# connect to database # connect to database
Connection.connect(await current_config.db.db_engine) Connection.connect(await current_config.db.db_engine)
# some testing # # some testing
with Connection.use() as db: # with Connection.use() as db:
print(User.from_db(db, "admin")) # print(User.from_db(db, "admin"))
print(User.from_db(db, "nonexistent")) # print(User.from_db(db, "nonexistent"))
connection.Connection.connect("sqlite:///tmp/v2.db") Connection_new.connect("sqlite:///tmp/v2.db")
user.User.create( User.create(
name="Uwe", name="Uwe",
password_clear="ulf", password_clear="ulf",
email="uwe@feh.de", email="uwe@feh.de",
) )
print(user.User.get("Uwe")) print(User.get(name="Uwe"))
print(user.User.authenticate("Uwe", "uwe")) print(User.authenticate("Uwe", "uwe"))
uwe = user.User.authenticate("Uwe", "ulf") uwe = User.authenticate("Uwe", "ulf")
uwe.extend_capabilities([capabilities.Capability.admin]) uwe.set_capabilities([Capability.admin])
uwe.update() uwe.update()
print(uwe) print(uwe.get_capabilities())
uwe.remove_capabilities([capabilities.Capability.admin]) uwe.set_capabilities([])
uwe.update() uwe.update()
print(uwe) print(uwe.get_capabilities())
with Connection_new.session as db:
db.add(uwe)
print(uwe.devices)
ipad = Device.create(
owner_name="Uwe",
name="iPad",
type="tablet",
)
# ipad = Device.
print(ipad)
def main() -> None: def main() -> None: