Изменил сообщения
This commit is contained in:
parent
3d8dfe4910
commit
c2224ae9c1
5 changed files with 54 additions and 82 deletions
|
@ -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(
|
||||
|
|
|
@ -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",
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue