diff --git a/server/models/__init__.py b/server/models/__init__.py index 699f52a..4f7e785 100644 --- a/server/models/__init__.py +++ b/server/models/__init__.py @@ -2,3 +2,4 @@ from .info import * from .reg_request import * from .residents import * +from .snowflake import * diff --git a/server/models/info.py b/server/models/info.py index 8754439..b2506c4 100644 --- a/server/models/info.py +++ b/server/models/info.py @@ -5,10 +5,10 @@ import pydantic -from .auth import Authorization, HashedAuthorization +from .snowflake import Snowflake -__all__ = ("PersonalInfo", "AccountInfo", "HashedAccountInfo") +__all__ = ("PersonalInfo", "PublicInfo") class PersonalInfo(pydantic.BaseModel): @@ -30,11 +30,15 @@ def to_personal_info(self) -> PersonalInfo: ) -class AccountInfo(PersonalInfo, Authorization): - """Data model for objects holding resident account information""" - pass +class PublicInfo(Snowflake, PersonalInfo): + """Data model for objects holding personal info along with a snowflake ID.""" - -class HashedAccountInfo(PersonalInfo, HashedAuthorization): - """Data model for objects holding resident account information with hashed password.""" - pass + def to_public_info(self) -> PublicInfo: + return PublicInfo( + id=self.id, + name=self.name, + room=self.room, + birthday=self.birthday, + phone=self.phone, + email=self.email, + ) diff --git a/server/models/reg_request.py b/server/models/reg_request.py index e985b89..44dd3c2 100644 --- a/server/models/reg_request.py +++ b/server/models/reg_request.py @@ -6,23 +6,22 @@ import aioodbc # type: ignore # dead PR: https://github.com/aio-libs/aioodbc/pull/429 import pyodbc # type: ignore -from .info import HashedAccountInfo +from .auth import HashedAuthorization +from .info import PublicInfo from .residents import Resident from ..database import Database -from ..utils import generate_id, hash_password, snowflake_time +from ..utils import generate_id, hash_password __all__ = ("RegisterRequest",) -class RegisterRequest(HashedAccountInfo): - """Data model for objects holding information about a registration request.""" +class RegisterRequest(PublicInfo, HashedAuthorization): + """Data model for objects holding information about a registration request. - id: int + Each object of this class corresponds to a database row.""" - @property - def created_at(self) -> datetime: - return snowflake_time(self.id) + id: int async def __remove_from_db(self, *, cursor: aioodbc.Cursor) -> None: await cursor.execute("DELETE FROM register_queue WHERE request_id = ?", self.id) diff --git a/server/models/residents.py b/server/models/residents.py index ba796c6..f88f97a 100644 --- a/server/models/residents.py +++ b/server/models/residents.py @@ -1,26 +1,21 @@ from __future__ import annotations import asyncio -from datetime import datetime from typing import Any, ClassVar, Dict, Optional, TypeVar -from .info import HashedAccountInfo +from .auth import HashedAuthorization +from .info import PublicInfo from ..database import Database -from ..utils import snowflake_time __all__ = ("Resident",) T = TypeVar("T") -class Resident(HashedAccountInfo): - """Data model for objects holding information about a resident.""" +class Resident(PublicInfo, HashedAuthorization): + """Data model for objects holding information about a resident. - id: int - - @property - def created_at(self) -> datetime: - return snowflake_time(self.id) + Each object of this class corresponds to a database row.""" __cache_by_id: ClassVar[Dict[int, Resident]] = {} __cache_by_username: ClassVar[Dict[str, Resident]] = {} diff --git a/server/models/snowflake.py b/server/models/snowflake.py new file mode 100644 index 0000000..ba24c4c --- /dev/null +++ b/server/models/snowflake.py @@ -0,0 +1,21 @@ +from __future__ import annotations + +from datetime import datetime + +import pydantic + +from ..utils import snowflake_time + + +__all__ = ("Snowflake",) + + +class Snowflake(pydantic.BaseModel): + """Data model for snowflake IDs""" + + id: int + + @property + def created_at(self) -> datetime: + """The time at which this snowflake was created""" + return snowflake_time(self.id) diff --git a/server/routes/api/login.py b/server/routes/api/login.py index 9c60517..b24b9a1 100644 --- a/server/routes/api/login.py +++ b/server/routes/api/login.py @@ -4,7 +4,7 @@ from fastapi import HTTPException, Header, status -from ...models import Authorization, PersonalInfo, Resident +from ...models import Authorization, PublicInfo, Resident from ...routers import api_router from ...utils import check_password @@ -17,7 +17,7 @@ responses={status.HTTP_403_FORBIDDEN: {}}, status_code=status.HTTP_200_OK, ) -async def login(headers: Annotated[Authorization, Header()]) -> PersonalInfo: +async def login(headers: Annotated[Authorization, Header()]) -> PublicInfo: """Verify authorization data, return resident information on success.""" resident = await Resident.from_username(headers.username) if resident is None: @@ -32,4 +32,4 @@ async def login(headers: Annotated[Authorization, Header()]) -> PersonalInfo: detail="Incorrect password", ) - return resident.to_personal_info() + return resident.to_public_info() diff --git a/server/snowflake.py b/server/snowflake.py deleted file mode 100644 index 409bb0c..0000000 --- a/server/snowflake.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import annotations - -from typing import Protocol, runtime_checkable - - -__all__ = ("Snowflake",) - - -@runtime_checkable -class Snowflake(Protocol): - """Base class for objects holding an ID.""" - id: int