206 lines
7.3 KiB
Python
206 lines
7.3 KiB
Python
import os
|
||
import sys
|
||
from typing import Optional
|
||
from fastapi.responses import JSONResponse
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from sqlalchemy.future import select
|
||
from sqlalchemy.orm import joinedload
|
||
from datetime import datetime, timedelta
|
||
from db.models import User, Session
|
||
from exc import UpdateQuestionException
|
||
from schemas import UserCreate, UserInDB
|
||
import secrets
|
||
from sqlalchemy import delete
|
||
from passlib.context import CryptContext
|
||
from models import CreateUpdateOtdel
|
||
import config
|
||
|
||
from bot.db.models import Otdels, Questions
|
||
|
||
|
||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||
|
||
def verify_password(plain_password, hashed_password):
|
||
return pwd_context.verify(plain_password, hashed_password)
|
||
|
||
def get_password_hash(password):
|
||
return pwd_context.hash(password)
|
||
|
||
async def create_user(db_session: AsyncSession, user: UserCreate):
|
||
hashed_password = get_password_hash(user.password)
|
||
new_user = User(username=user.username, password=hashed_password, full_name=user.full_name)
|
||
db_session.add(new_user)
|
||
await db_session.commit()
|
||
return new_user
|
||
|
||
async def get_user_by_username(db_session: AsyncSession, username: str) -> UserInDB:
|
||
result = await db_session.execute(select(User).filter_by(username=username))
|
||
user = result.scalars().first()
|
||
return user
|
||
|
||
async def create_session(db_session: AsyncSession, user_id: int, expiration_time: int) -> Session:
|
||
session_token = secrets.token_urlsafe(16)
|
||
expires_at = datetime.utcnow() + timedelta(seconds=expiration_time)
|
||
session = Session(user_id=user_id, session_token=session_token, expires_at=expires_at)
|
||
db_session.add(session)
|
||
await db_session.commit()
|
||
await db_session.refresh(session)
|
||
return session
|
||
|
||
async def get_session_by_token(db_session: AsyncSession, session_token: str) -> Session:
|
||
result = await db_session.execute(
|
||
select(Session).options(joinedload(Session.user)).filter_by(session_token=session_token)
|
||
)
|
||
|
||
session = result.scalars().first()
|
||
if session and session.expires_at < datetime.utcnow():
|
||
await db_session.delete(session)
|
||
await db_session.commit()
|
||
return None
|
||
return session
|
||
|
||
async def delete_session(db_session: AsyncSession, session_token: str) -> None:
|
||
result = await db_session.execute(select(Session).filter_by(session_token=session_token))
|
||
session_to_delete = result.scalars().first()
|
||
if session_to_delete:
|
||
await db_session.execute(delete(Session).where(Session.id == session_to_delete.id))
|
||
await db_session.commit()
|
||
|
||
|
||
async def create_otdel(db_session: AsyncSession, otdel: CreateUpdateOtdel) -> Otdels:
|
||
new_otdel = Otdels(name=otdel.name)
|
||
db_session.add(new_otdel)
|
||
await db_session.commit()
|
||
return new_otdel
|
||
|
||
async def delete_otdel(db_session: AsyncSession, otdel_id: int):
|
||
async with db_session.begin(): # Начало транзакции
|
||
try:
|
||
query = select(Otdels).where(Otdels.id == otdel_id)
|
||
result = await db_session.execute(query)
|
||
otdel = result.scalar_one_or_none()
|
||
|
||
if not otdel:
|
||
return JSONResponse(
|
||
content={"status": "error", "message": "Otdel not found"},
|
||
status_code=404
|
||
)
|
||
|
||
await db_session.delete(otdel) # Удаление объекта
|
||
# Не требуется явного commit, так как begin автоматически обрабатывает commit или rollback
|
||
except Exception as e:
|
||
await db_session.rollback()
|
||
return JSONResponse(
|
||
content={"status": "error", "message": f"Database error: {str(e)}"},
|
||
status_code=500
|
||
)
|
||
|
||
return JSONResponse(
|
||
content={"status": "success", "otdel_id": otdel_id},
|
||
status_code=200
|
||
)
|
||
|
||
|
||
async def update_otdel(db_session: AsyncSession, otdel_id: int, otdel: CreateUpdateOtdel) -> None:
|
||
# Создаем запрос для получения объекта отдела по ID
|
||
query = select(Otdels).filter(Otdels.id == otdel_id)
|
||
|
||
try:
|
||
# Выполняем запрос для поиска отдела
|
||
result = await db_session.execute(query)
|
||
existing_otdel = result.scalars().one()
|
||
|
||
# Обновляем атрибуты отдела
|
||
existing_otdel.name = otdel.name
|
||
|
||
# Фиксируем изменения
|
||
await db_session.commit()
|
||
|
||
return JSONResponse(
|
||
content={"status": "success", "otdel_id": otdel_id},
|
||
status_code=200
|
||
)
|
||
|
||
except Exception as ex:
|
||
# В случае других ошибок откатываем изменения
|
||
await db_session.rollback()
|
||
return JSONResponse(
|
||
content={"status": "error", "message": f"Database error: {str(ex)}"},
|
||
status_code=500
|
||
)
|
||
|
||
|
||
|
||
|
||
async def create_question(
|
||
db_session: AsyncSession,
|
||
title: str,
|
||
text: Optional[str],
|
||
file_data: Optional[str],
|
||
otdel_id: int,
|
||
):
|
||
new_question = Questions(
|
||
name=title,
|
||
answer=text,
|
||
file=file_data,
|
||
otdel_id=otdel_id,
|
||
)
|
||
|
||
db_session.add(new_question)
|
||
await db_session.commit()
|
||
return new_question
|
||
|
||
|
||
|
||
async def update_question(
|
||
db_session: AsyncSession,
|
||
question_id: int,
|
||
title: Optional[str] = None,
|
||
text: Optional[str] = None,
|
||
file_data: Optional[str] = None,
|
||
):
|
||
try:
|
||
# Получаем существующий вопрос по его ID
|
||
result = await db_session.execute(select(Questions).where(Questions.id == question_id))
|
||
question = result.scalar_one()
|
||
|
||
# Обновляем поля, даже если они None
|
||
question.name = title
|
||
question.answer = text
|
||
question.file = file_data
|
||
|
||
# Сохраняем изменения в базе данных
|
||
await db_session.commit()
|
||
return question
|
||
|
||
except Exception as ex:
|
||
# Если вопрос с данным ID не найден, можно вернуть None или выбросить исключение
|
||
raise UpdateQuestionException(f'ERROR - {ex}')
|
||
|
||
|
||
async def delete_question(db_session: AsyncSession, question_id: int):
|
||
async with db_session.begin(): # Начало транзакции
|
||
try:
|
||
query = select(Questions).where(Questions.id == question_id)
|
||
result = await db_session.execute(query)
|
||
question = result.scalar_one_or_none()
|
||
|
||
if not question:
|
||
return JSONResponse(
|
||
content={"status": "error", "message": "Question not found"},
|
||
status_code=404
|
||
)
|
||
|
||
await db_session.delete(question) # Удаление объекта
|
||
# Не требуется явного commit, так как begin автоматически обрабатывает commit или rollback
|
||
except Exception as e:
|
||
await db_session.rollback()
|
||
return JSONResponse(
|
||
content={"status": "error", "message": f"Database error: {str(e)}"},
|
||
status_code=500
|
||
)
|
||
|
||
return JSONResponse(
|
||
content={"status": "success", "question_id": question_id},
|
||
status_code=200
|
||
) |