[haiz] haiz
This commit is contained in:
@ -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
|
||||
|
1
backend/db/migration_types.py
Normal file
1
backend/db/migration_types.py
Normal file
@ -0,0 +1 @@
|
||||
from backend.db.models.guid import GUID # noqa: F401
|
@ -1 +1,2 @@
|
||||
from .users import *
|
||||
from .houses import *
|
||||
|
56
backend/db/models/guid.py
Normal file
56
backend/db/models/guid.py
Normal 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)
|
1
backend/db/models/houses/__init__.py
Normal file
1
backend/db/models/houses/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .houses import *
|
33
backend/db/models/houses/houses.py
Normal file
33
backend/db/models/houses/houses.py
Normal 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}"
|
@ -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)
|
||||
|
@ -1 +1,2 @@
|
||||
from .repository_users import *
|
||||
from .repository_houses import *
|
||||
|
26
backend/repos/repository_houses.py
Normal file
26
backend/repos/repository_houses.py
Normal 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
|
@ -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()
|
||||
|
@ -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)
|
||||
|
7
backend/routes/house/__init__.py
Normal file
7
backend/routes/house/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
from fastapi import APIRouter
|
||||
from . import house
|
||||
|
||||
router = APIRouter(prefix='/house')
|
||||
|
||||
router.include_router(house.public_router)
|
21
backend/routes/house/house.py
Normal file
21
backend/routes/house/house.py
Normal 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")
|
@ -1,2 +1,3 @@
|
||||
from .common import *
|
||||
from .user import *
|
||||
from .house import *
|
||||
|
1
backend/schemas/house/__init__.py
Normal file
1
backend/schemas/house/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .house import *
|
17
backend/schemas/house/house.py
Normal file
17
backend/schemas/house/house.py
Normal 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]
|
1
backend/services/house/__init__.py
Normal file
1
backend/services/house/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .house_service import *
|
11
backend/services/house/house_service.py
Normal file
11
backend/services/house/house_service.py
Normal 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)
|
@ -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
|
||||
|
Reference in New Issue
Block a user