Add DB version with alimbic and add log system
This commit is contained in:
@ -1,27 +1,54 @@
|
||||
from collections.abc import AsyncGenerator
|
||||
from contextlib import asynccontextmanager
|
||||
from mimetypes import init
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
|
||||
from fuware.core.config import get_app_settings
|
||||
from fuware import __version__
|
||||
from fuware.core.root_logger import get_logger
|
||||
from fuware.routes import router
|
||||
from fuware import __version__
|
||||
import uvicorn
|
||||
|
||||
settings = get_app_settings()
|
||||
logger = get_logger()
|
||||
|
||||
description = f"""
|
||||
fuware is a web application for managing your hours items and tracking them.
|
||||
"""
|
||||
|
||||
# event.listen(models.User.__table__, 'after_create', initialize_table)
|
||||
@asynccontextmanager
|
||||
async def lifespan_fn(_: FastAPI) -> AsyncGenerator[None, None]:
|
||||
logger.info("start: database initialization")
|
||||
import fuware.db.init_db as init_db
|
||||
|
||||
init_db.main()
|
||||
logger.info("end: database initialization")
|
||||
|
||||
logger.info("-----SYSTEM STARTUP-----")
|
||||
# logger.info("------APP SETTINGS------")
|
||||
# logger.info(
|
||||
# settings.model_dump_json(
|
||||
# indent=4,
|
||||
# exclude={
|
||||
# "SECRET",
|
||||
# "DB_URL", # replace by DB_URL_PUBLIC for logs
|
||||
# "DB_PROVIDER",
|
||||
# },
|
||||
# )
|
||||
# )
|
||||
yield
|
||||
logger.info("-----SYSTEM SHUTDOWN-----")
|
||||
|
||||
app = FastAPI(
|
||||
title="Fuware",
|
||||
description=description,
|
||||
version=__version__,
|
||||
docs_url=settings.DOCS_URL,
|
||||
redoc_url=settings.REDOC_URL
|
||||
redoc_url=settings.REDOC_URL,
|
||||
lifespan=lifespan_fn,
|
||||
)
|
||||
|
||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||
|
@ -7,7 +7,6 @@ from logging import config as logging_config
|
||||
__dir = pathlib.Path(__file__).parent
|
||||
__conf: dict[str, str] | None = None
|
||||
|
||||
|
||||
def _load_config(path: pathlib.Path, substitutions: dict[str, str] | None = None) -> dict[str, typing.Any]:
|
||||
with open(path) as file:
|
||||
if substitutions:
|
||||
|
15
fuware/core/logger/logconf.dev.json
Normal file
15
fuware/core/logger/logconf.dev.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": false,
|
||||
"handlers": {
|
||||
"rich": {
|
||||
"class": "rich.logging.RichHandler"
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"root": {
|
||||
"level": "DEBUG",
|
||||
"handlers": ["rich"]
|
||||
}
|
||||
}
|
||||
}
|
63
fuware/core/logger/logconf.prod.json
Normal file
63
fuware/core/logger/logconf.prod.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": false,
|
||||
"formatters": {
|
||||
"simple": {
|
||||
"format": "%(levelname)-8s %(asctime)s - %(message)s",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%S"
|
||||
},
|
||||
"detailed": {
|
||||
"format": "[%(levelname)s|%(module)s|L%(lineno)d] %(asctime)s: %(message)s",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%S"
|
||||
},
|
||||
"access": {
|
||||
"()": "uvicorn.logging.AccessFormatter",
|
||||
"fmt": "%(levelname)-8s %(asctime)s - [%(client_addr)s] %(status_code)s \"%(request_line)s\"",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%S"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"stderr": {
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "WARNING",
|
||||
"formatter": "simple",
|
||||
"stream": "ext://sys.stderr"
|
||||
},
|
||||
"stdout": {
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "${LOG_LEVEL}",
|
||||
"formatter": "simple",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
"access": {
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "${LOG_LEVEL}",
|
||||
"formatter": "access",
|
||||
"stream": "ext://sys.stdout"
|
||||
},
|
||||
"file": {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"level": "DEBUG",
|
||||
"formatter": "detailed",
|
||||
"filename": "${DATA_DIR}/mealie.log",
|
||||
"maxBytes": 10000,
|
||||
"backupCount": 3
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"root": {
|
||||
"level": "${LOG_LEVEL}",
|
||||
"handlers": ["stderr", "file", "stdout"]
|
||||
},
|
||||
"uvicorn.error": {
|
||||
"handlers": ["stderr", "file", "stdout"],
|
||||
"level": "${LOG_LEVEL}",
|
||||
"propagate": false
|
||||
},
|
||||
"uvicorn.access": {
|
||||
"handlers": ["access", "file"],
|
||||
"level": "${LOG_LEVEL}",
|
||||
"propagate": false
|
||||
}
|
||||
}
|
||||
}
|
24
fuware/core/logger/logconf.test.json
Normal file
24
fuware/core/logger/logconf.test.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": false,
|
||||
"formatters": {
|
||||
"detailed": {
|
||||
"format": "[%(levelname)s|%(module)s|L%(lineno)d] %(asctime)s: %(message)s",
|
||||
"datefmt": "%Y-%m-%dT%H:%M:%S"
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"stdout": {
|
||||
"class": "logging.StreamHandler",
|
||||
"level": "DEBUG",
|
||||
"formatter": "detailed",
|
||||
"stream": "ext://sys.stdout"
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"root": {
|
||||
"level": "${LOG_LEVEL}",
|
||||
"handlers": ["stdout"]
|
||||
}
|
||||
}
|
||||
}
|
43
fuware/core/root_logger.py
Normal file
43
fuware/core/root_logger.py
Normal file
@ -0,0 +1,43 @@
|
||||
import logging
|
||||
|
||||
from .config import get_app_settings
|
||||
from .logger.config import configured_logger
|
||||
|
||||
__root_logger: None | logging.Logger = None
|
||||
|
||||
|
||||
def get_logger(module=None) -> logging.Logger:
|
||||
"""
|
||||
Get a logger instance for a module, in most cases module should not be
|
||||
provided. Simply using the root logger is sufficient.
|
||||
|
||||
Cases where you would want to use a module specific logger might be a background
|
||||
task or a long running process where you want to easily identify the source of
|
||||
those messages
|
||||
"""
|
||||
global __root_logger
|
||||
|
||||
if __root_logger is None:
|
||||
app_settings = get_app_settings()
|
||||
|
||||
mode = "development"
|
||||
|
||||
if app_settings.TESTING:
|
||||
mode = "testing"
|
||||
elif app_settings.PRODUCTION:
|
||||
mode = "production"
|
||||
|
||||
substitutions = {
|
||||
"LOG_LEVEL": app_settings.LOG_LEVEL.upper(),
|
||||
}
|
||||
|
||||
__root_logger = configured_logger(
|
||||
mode=mode,
|
||||
config_override=app_settings.LOG_CONFIG_OVERRIDE,
|
||||
substitutions=substitutions,
|
||||
)
|
||||
|
||||
if module is None:
|
||||
return __root_logger
|
||||
|
||||
return __root_logger.getChild(module)
|
@ -32,6 +32,12 @@ class AppSettings(BaseSettings):
|
||||
SECRET: str
|
||||
COOKIE_KEY: str
|
||||
|
||||
LOG_CONFIG_OVERRIDE: Path | None = None
|
||||
"""path to custom logging configuration file"""
|
||||
|
||||
LOG_LEVEL: str = "info"
|
||||
"""corresponds to standard Python log levels"""
|
||||
|
||||
@property
|
||||
def DOCS_URL(self) -> str | None:
|
||||
return "/docs" if self.API_DOCS else None
|
||||
|
@ -1,8 +1,8 @@
|
||||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from sqlalchemy.orm.session import Session
|
||||
from sqlalchemy import create_engine, event, Engine, text
|
||||
from sqlalchemy import create_engine, event, Engine
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
|
||||
from fuware.core.config import get_app_settings
|
||||
|
||||
settings = get_app_settings()
|
||||
@ -10,13 +10,13 @@ settings = get_app_settings()
|
||||
def sql_global_init(db_url: str):
|
||||
connect_args = {"check_same_thread": False}
|
||||
|
||||
engine = create_engine(db_url, echo=True, connect_args=connect_args, pool_pre_ping=True, future=True)
|
||||
engine = create_engine(db_url, echo=False, connect_args=connect_args, pool_pre_ping=True, future=True)
|
||||
|
||||
SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine, future=True))
|
||||
|
||||
return SessionLocal, engine
|
||||
|
||||
SessionLocal, engine = sql_global_init(settings.DB_URL) # type: ignore
|
||||
SessionLocal, engine = sql_global_init(settings.DB_URL)
|
||||
|
||||
@event.listens_for(Engine, "connect")
|
||||
def set_sqlite_pragma(dbapi_connection, connection_record):
|
||||
@ -24,10 +24,21 @@ def set_sqlite_pragma(dbapi_connection, connection_record):
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
|
||||
# with engine.connect() as connection:
|
||||
# result = connection.execute(text('select "Hello"'))
|
||||
@contextmanager
|
||||
def session_context() -> Session: # type: ignore
|
||||
"""
|
||||
session_context() provides a managed session to the database that is automatically
|
||||
closed when the context is exited. This is the preferred method of accessing the
|
||||
database.
|
||||
|
||||
# print(result.all())
|
||||
Note: use `generate_session` when using the `Depends` function from FastAPI
|
||||
"""
|
||||
global SessionLocal
|
||||
sess = SessionLocal()
|
||||
try:
|
||||
yield sess
|
||||
finally:
|
||||
sess.close()
|
||||
|
||||
def generate_session() -> Generator[Session, None, None]:
|
||||
db = SessionLocal()
|
||||
|
@ -1,9 +1,87 @@
|
||||
from db_setup import engine
|
||||
from fuware.db.seeder import initialize_table
|
||||
from models._model_base import Model
|
||||
from sqlalchemy import event
|
||||
from models.users import User
|
||||
import os
|
||||
from pathlib import Path
|
||||
from time import sleep
|
||||
|
||||
event.listen(User.__table__, 'after_create', initialize_table)
|
||||
from sqlalchemy import engine, orm, text
|
||||
|
||||
Model.metadata.create_all(bind=engine)
|
||||
from alembic import command, config, script
|
||||
from alembic.config import Config
|
||||
from alembic.runtime import migration
|
||||
from fuware.core import root_logger
|
||||
from fuware.core.config import get_app_settings
|
||||
from fuware.db.db_setup import session_context
|
||||
from fuware.repos.repository_users import RepositoryUsers
|
||||
from fuware.repos.seeder import default_users_init
|
||||
from fuware.db.models._model_base import Model
|
||||
# from fuware.db.models import User
|
||||
|
||||
PROJECT_DIR = Path(__file__).parent.parent.parent
|
||||
|
||||
logger = root_logger.get_logger()
|
||||
|
||||
def init_db(db) -> None:
|
||||
logger.info("Initializing user data...")
|
||||
default_users_init(db)
|
||||
|
||||
def db_is_at_head(alembic_cfg: config.Config) -> bool:
|
||||
settings = get_app_settings()
|
||||
url = settings.DB_URL
|
||||
|
||||
if not url:
|
||||
raise ValueError("No database url found")
|
||||
|
||||
connectable = engine.create_engine(url)
|
||||
directory = script.ScriptDirectory.from_config(alembic_cfg)
|
||||
with connectable.begin() as connection:
|
||||
context = migration.MigrationContext.configure(connection)
|
||||
return set(context.get_current_heads()) == set(directory.get_heads())
|
||||
|
||||
def connect(session: orm.Session) -> bool:
|
||||
try:
|
||||
session.execute(text("SELECT 1"))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error connecting to database: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
max_retry = 10
|
||||
wait_seconds = 1
|
||||
|
||||
with session_context() as session:
|
||||
while True:
|
||||
if connect(session):
|
||||
logger.info("Database connection established.")
|
||||
break
|
||||
|
||||
logger.error(f"Database connection failed. Retrying in {wait_seconds} seconds...")
|
||||
max_retry -= 1
|
||||
|
||||
sleep(wait_seconds)
|
||||
|
||||
if max_retry == 0:
|
||||
raise ConnectionError("Database connection failed - exiting application.")
|
||||
|
||||
alembic_cfg_path = os.getenv("ALEMBIC_CONFIG_FILE", default=str(PROJECT_DIR / "alembic.ini"))
|
||||
if not os.path.isfile(alembic_cfg_path):
|
||||
raise Exception("Provided alembic config path doesn't exist")
|
||||
|
||||
alembic_cfg = Config(alembic_cfg_path)
|
||||
if db_is_at_head(alembic_cfg):
|
||||
logger.debug("Migration not needed.")
|
||||
else:
|
||||
logger.info("Migration needed. Performing migration...")
|
||||
command.upgrade(alembic_cfg, "head")
|
||||
|
||||
if session.get_bind().name == "postgresql": # needed for fuzzy search and fast GIN text indices
|
||||
session.execute(text("CREATE EXTENSION IF NOT EXISTS pg_trgm;"))
|
||||
|
||||
users = RepositoryUsers()
|
||||
if users.get_all():
|
||||
logger.info("Database already seeded.")
|
||||
else:
|
||||
logger.info("Seeding database...")
|
||||
init_db(session)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import uuid
|
||||
from sqlalchemy import Boolean, Column, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from uuid import uuid4
|
||||
from sqlalchemy import Boolean, ForeignKey, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
|
||||
@ -9,12 +9,26 @@ from .._model_base import SqlAlchemyBase
|
||||
class User(SqlAlchemyBase):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id: Mapped[UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4, index=True)
|
||||
id: Mapped[UUID] = mapped_column(UUID, primary_key=True, default=uuid4, 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)
|
||||
is_admin: Mapped[bool | None] = mapped_column(Boolean, default=False)
|
||||
is_lock: Mapped[bool | None] = mapped_column(Boolean, default=False)
|
||||
|
||||
session_login = relationship("SessionLogin", back_populates="user", uselist=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}, name: {self.name}, username: {self.username}"
|
||||
|
||||
class SessionLogin(SqlAlchemyBase):
|
||||
__tablename__ = 'session_login'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
session: Mapped[str] = mapped_column(UUID, default=uuid4, index=True, nullable=False)
|
||||
user_id: Mapped[str] = mapped_column(ForeignKey("users.id"), unique=True, index=True, nullable=False)
|
||||
|
||||
user = relationship("User", back_populates="session_login")
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}, session: {self.session}, user_id: {self.user_id}"
|
||||
|
@ -1,5 +1,5 @@
|
||||
from fuware.core.security.hasher import get_hasher
|
||||
from fuware.db.models.users.users import User
|
||||
from fuware.db.models import SessionLogin, User
|
||||
from fuware.schemas import UserCreate
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
|
||||
class RepositoryUsers:
|
||||
def __init__(self):
|
||||
self.user = User()
|
||||
self.sessionLogin = SessionLogin()
|
||||
|
||||
def get_all(self, skip: int = 0, limit: int = 100):
|
||||
return self.user.query.offset(skip).limit(limit).all()
|
||||
@ -26,3 +27,34 @@ class RepositoryUsers:
|
||||
|
||||
db.refresh(db_user)
|
||||
return db_user
|
||||
|
||||
def get_session_by_user_id(self, user_id: str):
|
||||
return self.sessionLogin.query.filter_by(user_id=user_id).first()
|
||||
|
||||
def create_session(self, db: Session, user_id: str):
|
||||
try:
|
||||
db_ss = SessionLogin(user_id=user_id)
|
||||
db.add(db_ss)
|
||||
db.commit()
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
db.refresh(db_ss)
|
||||
return db_ss
|
||||
|
||||
def login(self, db: Session, user_id: str):
|
||||
db_ss = self.get_session_by_user_id(user_id)
|
||||
if not db_ss:
|
||||
db_ss = self.create_session(db=db, user_id=user_id)
|
||||
return db_ss
|
||||
|
||||
def logout(self, db: Session, user_ss: str):
|
||||
db_ss = self.sessionLogin.query.filter_by(session=user_ss).first()
|
||||
try:
|
||||
db.delete(db_ss)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise e
|
||||
pass
|
||||
|
1
fuware/repos/seeder/__init__.py
Normal file
1
fuware/repos/seeder/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .init_users import default_users_init
|
33
fuware/repos/seeder/init_users.py
Normal file
33
fuware/repos/seeder/init_users.py
Normal file
@ -0,0 +1,33 @@
|
||||
from fuware.core.config import get_app_settings
|
||||
from fuware.core.root_logger import get_logger
|
||||
from fuware.repos.repository_users import RepositoryUsers
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from fuware.schemas.user.user import UserCreate
|
||||
|
||||
|
||||
logger = get_logger("init_users")
|
||||
settings = get_app_settings()
|
||||
|
||||
def dev_users() -> list[dict]:
|
||||
return [
|
||||
{
|
||||
"username": "sam",
|
||||
"password": "admin",
|
||||
"name": "Sam",
|
||||
"is_admin": 1,
|
||||
"is_lock": 0,
|
||||
},
|
||||
{
|
||||
"username": "sam1",
|
||||
"password": "admin",
|
||||
"name": "Sam1",
|
||||
"is_admin": 0,
|
||||
"is_lock": 1
|
||||
},
|
||||
]
|
||||
|
||||
def default_users_init(session: Session):
|
||||
users = RepositoryUsers()
|
||||
for user in dev_users():
|
||||
users.create(session, UserCreate(**user))
|
@ -3,9 +3,10 @@ from fastapi import APIRouter, Depends, HTTPException, Response
|
||||
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from sqlalchemy.orm import Session
|
||||
from fuware.core.config import get_app_settings
|
||||
from fuware.core.security.hasher import get_hasher
|
||||
from fuware.db.db_setup import generate_session
|
||||
from fuware.schemas import ReturnValue, PrivateUser, UserRequest
|
||||
from fuware.schemas import ReturnValue, UserRequest
|
||||
from fuware.schemas.user.user import UserCreate
|
||||
from fuware.services import UserService
|
||||
|
||||
@ -13,6 +14,7 @@ from fuware.services import UserService
|
||||
public_router = APIRouter(tags=["Users: Authentication"])
|
||||
user_service = UserService()
|
||||
hasher = get_hasher()
|
||||
settings = get_app_settings()
|
||||
|
||||
@public_router.put('/register')
|
||||
def register_user(user: UserCreate, db: Session = Depends(generate_session)) -> ReturnValue[Any]:
|
||||
@ -22,16 +24,15 @@ def register_user(user: UserCreate, db: Session = Depends(generate_session)) ->
|
||||
user_return = user_service.create(db=db, user=user)
|
||||
return ReturnValue(status=200, data=jsonable_encoder(user_return))
|
||||
|
||||
# @public_router.post('/login', response_model=ReturnValue[PrivateUser])
|
||||
@public_router.post('/login', response_model=ReturnValue[Any])
|
||||
def user_login(user: UserRequest, response: Response) -> ReturnValue[Any]:
|
||||
def user_login(user: UserRequest, response: Response, db: Session = Depends(generate_session)) -> ReturnValue[Any]:
|
||||
db_user = user_service.get_by_username(username=user.username)
|
||||
if not db_user:
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if not hasher.verify(password=user.password, hashed=db_user.password):
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if db_user.is_lock is True:
|
||||
raise HTTPException(status_code=401, detail="Your Account is banned")
|
||||
# cookieEncode = encryptString(user.username + ',' + user.password)
|
||||
# response.set_cookie(key=COOKIE_KEY, value=cookieEncode.decode('utf-8'))
|
||||
raise HTTPException(status_code=401, detail="Your Account was locked")
|
||||
cookieEncode = user_service.check_login(db=db, user_id=db_user.id)
|
||||
response.set_cookie(key=settings.COOKIE_KEY, value=cookieEncode.session)
|
||||
return ReturnValue(status=200, data=jsonable_encoder(db_user))
|
||||
|
@ -1,9 +1,12 @@
|
||||
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from fuware.core.security.hasher import get_hasher
|
||||
from fuware.repos import RepositoryUsers
|
||||
from fuware.schemas import UserRequest, UserCreate
|
||||
from fuware.services._base_service import BaseService
|
||||
from fuware.schemas import UserCreate
|
||||
|
||||
hasher = get_hasher()
|
||||
|
||||
class UserService(BaseService):
|
||||
def __init__(self):
|
||||
@ -17,3 +20,17 @@ class UserService(BaseService):
|
||||
|
||||
def create(self, db: Session, user: UserCreate):
|
||||
return self.repos.create(db=db, user=user)
|
||||
|
||||
def check_exist(self, db: Session, user: UserRequest):
|
||||
db_user = self.get_by_username(username=user.username)
|
||||
if not db_user:
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if not hasher.verify(password=user.password, hashed=db_user.password):
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if db_user.is_lock is True:
|
||||
raise HTTPException(status_code=401, detail="Your Account is banned")
|
||||
return db_user
|
||||
|
||||
def check_login(self, db: Session, user_id: str):
|
||||
db_session = self.repos.login(db=db, user_id=user_id)
|
||||
return db_session
|
||||
|
Reference in New Issue
Block a user