Изменил сообщения

This commit is contained in:
urec56 2024-06-12 22:05:10 +05:00
parent 3d8dfe4910
commit c2224ae9c1
5 changed files with 54 additions and 82 deletions

View file

@ -1,5 +1,5 @@
from pydantic import HttpUrl
from sqlalchemy import update, select, insert, func
from pydantic import HttpUrl, EmailStr
from sqlalchemy import update, select, insert, func, or_
from sqlalchemy.exc import MultipleResultsFound, IntegrityError, NoResultFound
from app.chat.shemas import SAllowedChats
@ -41,6 +41,19 @@ class UserDAO(BaseDAO):
except NoResultFound:
raise UserNotFoundException
async def find_one_by_username_or_email(self, username: str, email: EmailStr) -> SUser:
try:
query = select(Users.__table__.columns).where(
or_(Users.username == username, Users.email == email)
)
result = await self.session.execute(query)
result = result.mappings().one()
return SUser.model_validate(result)
except MultipleResultsFound:
raise IncorrectDataException
except NoResultFound:
raise UserNotFoundException
async def find_all(self) -> SUsers:
query = (
select(

View file

@ -5,11 +5,7 @@ from pydantic import EmailStr
from app.config import settings
def create_registration_confirmation_template(
username: str,
email_to: EmailStr,
confirmation_link: str,
):
def create_registration_confirmation_template(username: str, email_to: EmailStr, confirmation_link: str):
email = EmailMessage()
email["Subject"] = "Подтверждение регистрации"
@ -26,41 +22,34 @@ def create_registration_confirmation_template(
return email
def create_password_change_confirmation_template(
username: str,
email_to: EmailStr,
):
def create_data_change_confirmation_email(username: str, email_to: EmailStr, confirmation_code: str):
email = EmailMessage()
email["Subject"] = "Смена пароля к аккаунту"
email["Subject"] = "Подтверждение изменения данных"
email["From"] = settings.SMTP_USER
email["To"] = email_to
email.set_content(
f"""
<h1>{username}, ты менял пароль?</h1>
<h2>Если нет, то пидора ответ</h2>
<h1>{username}, лови аптечку</h1>
{confirmation_code}
""",
subtype="html",
)
return email
def create_password_recover_template(
username: str,
email_to: EmailStr,
confirmation_code: str,
):
def create_data_change_email(username: str, email_to: EmailStr):
email = EmailMessage()
email["Subject"] = "Восстановление пароля"
email["Subject"] = "Изменение данных"
email["From"] = settings.SMTP_USER
email["To"] = email_to
email.set_content(
f"""
<h1>{username}, ты тут хотел восстановить пароль?</h1>
<h2>{confirmation_code}</h2>
<h1>{username}, данные менял?</h1>
Вот то-то и оно.
""",
subtype="html",
)

View file

@ -9,8 +9,8 @@ from app.config import settings
from app.tasks.celery import celery
from app.tasks.email_templates import (
create_registration_confirmation_template,
create_password_change_confirmation_template,
create_password_recover_template,
create_data_change_confirmation_email,
create_data_change_email,
)
from app.utils.auth import encode_confirmation_token
from app.users.schemas import SConfirmationData
@ -23,7 +23,7 @@ def generate_confirmation_code(length=6) -> str:
@celery.task
def send_registration_confirmation_email(user_data: dict):
def send_registration_confirmation_email(user_data: dict) -> None:
user_data = SConfirmationData.model_validate(user_data)
invitation_token = encode_confirmation_token(user_data)
@ -39,37 +39,22 @@ def send_registration_confirmation_email(user_data: dict):
@celery.task
def send_password_change_email(username: str, email_to: EmailStr, MODE: str):
if MODE == "TEST":
return True
msg_content = create_password_change_confirmation_template(username=username, email_to=email_to)
def send_data_change_confirmation_email(user_data: dict) -> None:
user_data = SConfirmationData.model_validate(user_data)
msg_content = create_data_change_confirmation_email(
username=user_data.username, email_to=user_data.email_to, confirmation_code=user_data.confirmation_code
)
with smtplib.SMTP_SSL(settings.SMTP_HOST, settings.SMTP_PORT) as server:
server.login(settings.SMTP_USER, settings.SMTP_PASS)
server.send_message(msg_content)
return True
@celery.task
def send_password_recover_email(username: str, email_to: EmailStr, MODE: str):
confirmation_code = generate_confirmation_code()
if MODE == "TEST":
return confirmation_code
msg_content = create_password_recover_template(username=username, email_to=email_to, confirmation_code=confirmation_code)
def send_data_change_email(username: str, email_to: EmailStr) -> None:
msg_content = create_data_change_email(username=username, email_to=email_to)
with smtplib.SMTP_SSL(settings.SMTP_HOST, settings.SMTP_PORT) as server:
server.login(settings.SMTP_USER, settings.SMTP_PASS)
server.send_message(msg_content)
return confirmation_code
@celery.task
def send_data_change_confirmation_email(username: str, email_to: EmailStr, MODE: str):
pass
@celery.task
def send_data_change_email(username: str, email_to: EmailStr, MODE: str):
pass

View file

@ -35,7 +35,8 @@ from app.users.schemas import (
from app.tasks.tasks import (
send_registration_confirmation_email,
send_data_change_confirmation_email,
generate_confirmation_code
generate_confirmation_code,
send_data_change_email
)
router = APIRouter(prefix="/users", tags=["Пользователи"])
@ -152,13 +153,15 @@ async def get_user_avatars_history(user=Depends(get_current_user), uow=Depends(U
)
async def send_confirmation_code(user_data: SUserSendConfirmationCode, user: SUser = Depends(get_current_user)):
redis_session = get_redis_session()
if verify_password(user_data.current_password, user.hashed_password):
verification_code = send_data_change_confirmation_email.delay(
username=user.username, email_to=user_data.email, MODE=settings.MODE
)
verification_code = verification_code.get()
await RedisService.set_verification_code(redis=redis_session, user_id=user.id, verification_code=verification_code)
raise IncorrectAuthDataException
if not verify_password(user_data.current_password, user.hashed_password):
raise IncorrectAuthDataException
user_code = generate_confirmation_code()
user_mail_data = SConfirmationData.model_validate(
{"user_id": user.id, "username": user_data.username, "email_to": user_data.email, "confirmation_code": user_code}
)
send_data_change_confirmation_email.delay(user_mail_data)
await RedisService.set_verification_code(redis=redis_session, user_id=user.id, verification_code=user_code)
@router.post(
@ -185,6 +188,7 @@ async def change_user_data(user_data: SUserChangeData, user=Depends(get_current_
)
await uow.user.add_user_avatar(user_id=user.id, avatar=user_data.avatar_url)
await uow.commit()
send_data_change_email.delay(user_data.username, user_data.email)
await RedisService.delete_verification_code(redis=redis_session, user_id=user.id)

View file

@ -59,36 +59,17 @@ def decode_confirmation_token(invitation_token: str) -> SConfirmationData:
class AuthService:
@staticmethod
async def authenticate_user_by_email(uow: UnitOfWork, email: EmailStr, password: str) -> SUser | None:
try:
async with uow:
user = await uow.user.find_one(email=email)
if not verify_password(password, user.hashed_password):
return
return user
except UserNotFoundException:
return
@staticmethod
async def authenticate_user_by_username(uow: UnitOfWork, username: str, password: str) -> SUser | None:
try:
async with uow:
user = await uow.user.find_one(username=username)
if not verify_password(password, user.hashed_password):
return
return user
except UserNotFoundException:
return
@classmethod
async def authenticate_user(cls, uow: UnitOfWork, email_or_username: str, password: str) -> SUser:
user = await cls.authenticate_user_by_email(uow, email_or_username, password)
if not user:
user = await cls.authenticate_user_by_username(uow, email_or_username, password)
if not user:
try:
async with uow:
user = await uow.user.find_one_by_username_or_email(username=email_or_username, email=email_or_username)
if not verify_password(password, user.hashed_password):
raise IncorrectAuthDataException
return user
except UserNotFoundException:
raise IncorrectAuthDataException
return user
@staticmethod
async def check_verificated_user(uow: UnitOfWork, user_id: int) -> bool: