[haiz] haiz

This commit is contained in:
2024-06-27 04:35:56 +00:00
parent e6923277ed
commit 1c205c69ac
51 changed files with 958 additions and 279 deletions

View File

@ -15,7 +15,7 @@ settings = get_app_settings()
logger = get_logger()
description = f"""
fuware is a web application for managing your hours items and tracking them.
fuware is a web application for managing your house items and tracking them.
"""
@asynccontextmanager

View File

@ -0,0 +1 @@
from backend.db.models.guid import GUID # noqa: F401

View File

@ -1 +1,2 @@
from .users import *
from .houses import *

56
backend/db/models/guid.py Normal file
View File

@ -0,0 +1,56 @@
import uuid
from typing import Any
from sqlalchemy import Dialect
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.types import CHAR, TypeDecorator
class GUID(TypeDecorator):
"""Platform-independent GUID type.
Uses PostgreSQL's UUID type, otherwise uses
CHAR(32), storing as stringified hex values.
"""
impl = CHAR
cache_ok = True
@staticmethod
def generate():
return uuid.uuid4()
@staticmethod
def convert_value_to_guid(value: Any, dialect: Dialect) -> str | None:
if value is None:
return value
elif dialect.name == "postgresql":
return str(value)
else:
if not isinstance(value, uuid.UUID):
return "%.32x" % uuid.UUID(value).int
else:
# hexstring
return "%.32x" % value.int
def load_dialect_impl(self, dialect):
if dialect.name == "postgresql":
return dialect.type_descriptor(UUID())
else:
return dialect.type_descriptor(CHAR(32))
def process_bind_param(self, value, dialect):
return self.convert_value_to_guid(value, dialect)
def _uuid_value(self, value):
if value is None:
return value
else:
if not isinstance(value, uuid.UUID):
value = uuid.UUID(value)
return value
def process_result_value(self, value, dialect):
return self._uuid_value(value)
def sort_key_function(self, value):
return self._uuid_value(value)

View File

@ -0,0 +1 @@
from .houses import *

View File

@ -0,0 +1,33 @@
from typing import List
from sqlalchemy import ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from backend.db.models.guid import GUID
from .._model_base import SqlAlchemyBase
class Houses(SqlAlchemyBase):
__tablename__ = 'houses'
id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate, index=True)
icon: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
name: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
address: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
areas: Mapped[List["Areas"]] = relationship()
def __repr__(self):
return f"{self.__class__.__name__}, name: {self.name}"
class Areas(SqlAlchemyBase):
__tablename__ = 'areas'
id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate, index=True)
house_id: Mapped[GUID] = mapped_column(GUID, ForeignKey('houses.id'), index=True, nullable=False)
name: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
desc: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
user: Mapped['Houses'] = relationship(back_populates="areas")
def __repr__(self):
return f"{self.__class__.__name__}, name: {self.name}"

View File

@ -1,15 +1,14 @@
from uuid import uuid4
from sqlalchemy import Boolean, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import Boolean, String
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.dialects.postgresql import UUID
from backend.db.models.guid import GUID
from .._model_base import SqlAlchemyBase
class User(SqlAlchemyBase):
class Users(SqlAlchemyBase):
__tablename__ = 'users'
id: Mapped[UUID] = mapped_column(UUID, primary_key=True, default=uuid4, index=True)
id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate, index=True)
username: Mapped[str | None] = mapped_column(String, unique=True, index=True, nullable=False)
password: Mapped[str | None] = mapped_column(String, index=True, nullable=False)
name: Mapped[str | None] = mapped_column(String, index=True, nullable=True)

View File

@ -1 +1,2 @@
from .repository_users import *
from .repository_houses import *

View File

@ -0,0 +1,26 @@
from backend.db.models.houses import Houses
from sqlalchemy.orm import Session
from backend.schemas.house import HouseCreate
class RepositoryHouses:
def __init__(self):
self.houses = Houses()
def get_all(self, skip: int = 0, limit: int = 100):
return self.houses.query.offset(skip).limit(limit).all()
def get_by_id(self, house_id: str):
return self.houses.query.filter_by(id=house_id).one()
def create(self, db: Session, house: HouseCreate):
try:
db_house = Houses(**house.dict())
db.add(db_house)
db.commit()
except Exception:
db.rollback()
raise
db.refresh(db_house)
return db_house

View File

@ -1,6 +1,6 @@
from backend.core.config import get_app_settings
from backend.core.security.security import hash_password
from backend.db.models import User
from backend.db.models import Users
from backend.schemas import UserCreate, UserProfile
from sqlalchemy.orm import Session
from uuid import UUID
@ -11,7 +11,7 @@ settings = get_app_settings()
class RepositoryUsers:
def __init__(self):
self.user = User()
self.user = Users()
def get_all(self, skip: int = 0, limit: int = 100):
return self.user.query.offset(skip).limit(limit).all()
@ -25,7 +25,7 @@ class RepositoryUsers:
def create(self, db: Session, user: UserCreate | UserSeeds):
try:
password = getattr(user, "password")
db_user = User(**user.dict(exclude={"password"}), password=hash_password(password))
db_user = Users(**user.dict(exclude={"password"}), password=hash_password(password))
db.add(db_user)
db.commit()
except Exception:
@ -41,7 +41,7 @@ class RepositoryUsers:
return None
try:
user.update_password()
self.user.query.where(User.id == user_id).update(user.dict(exclude_unset=True, exclude_none=True))
self.user.query.where(Users.id == user_id).update(user.dict(exclude_unset=True, exclude_none=True))
db.commit()
except Exception:
db.rollback()

View File

@ -1,9 +1,10 @@
from fastapi import APIRouter
from . import (auth, user)
from . import (auth, user, house)
router = APIRouter(prefix='/api')
router.include_router(auth.router)
router.include_router(user.router)
router.include_router(house.router)

View File

@ -0,0 +1,7 @@
from fastapi import APIRouter
from . import house
router = APIRouter(prefix='/house')
router.include_router(house.public_router)

View File

@ -0,0 +1,21 @@
from typing import Annotated, Any
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from backend.core.config import get_app_settings
from backend.core.dependencies import is_logged_in
from backend.db.db_setup import generate_session
from backend.schemas.common import ReturnValue
from backend.schemas.house import HouseCreate
from backend.schemas.user import ProfileResponse
from backend.services.house import HouseService
public_router = APIRouter(tags=["Houses: Control"])
house_service = HouseService()
settings = get_app_settings()
db_dependency = Annotated[Session, Depends(generate_session)]
current_user_token = Annotated[ProfileResponse, Depends(is_logged_in)]
@public_router.get("/create", response_model=ReturnValue[Any])
def create_house(house: HouseCreate, db: db_dependency, current_user: current_user_token) -> ReturnValue[Any]:
return ReturnValue(status=200, data="created")

View File

@ -1,2 +1,3 @@
from .common import *
from .user import *
from .house import *

View File

@ -0,0 +1 @@
from .house import *

View File

@ -0,0 +1,17 @@
from backend.schemas.main_model import MainModel
class HouseBase(MainModel):
pass
class AreaBase(MainModel):
pass
class AreaCreate(AreaBase):
name: str
desc: str
class HouseCreate(HouseBase):
icon: str
name: str
address: str
areas: list[AreaCreate]

View File

@ -0,0 +1 @@
from .house_service import *

View File

@ -0,0 +1,11 @@
from sqlalchemy.orm import Session
from backend.repos import RepositoryHouses
from backend.schemas import HouseCreate
from backend.services._base_service import BaseService
class HouseService(BaseService):
def __init__(self):
self.repos = RepositoryHouses()
def create(self, db: Session, house: HouseCreate):
return self.repos.create(db=db, house=house)

View File

@ -31,7 +31,6 @@ class UserService(BaseService):
return self.repos.create(db=db, user=user)
def check_exist(self, user: UserRequest):
print(f"user: {user}")
db_user = self.get_by_username(username=user.username)
if not db_user:
return False