Добавил редис

This commit is contained in:
urec56 2024-07-17 16:52:00 +04:00
parent ad1fe5487c
commit 857ff4c780
3 changed files with 103 additions and 30 deletions

View file

@ -1,8 +1,12 @@
from datetime import timedelta
from urllib.parse import urljoin from urllib.parse import urljoin
from pydantic import ValidationError
from app.chat.exceptions import UserDontHavePermissionException, UserCanNotReadThisChatException from app.chat.exceptions import UserDontHavePermissionException, UserCanNotReadThisChatException
from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat from app.chat.shemas import SAllowedChats, SChangeData, SPinnedChats, SChat
from app.config import settings from app.config import settings
from app.services.redis_service import RedisService
from app.services.user_service import UserService from app.services.user_service import UserService
from app.utils.unit_of_work import UnitOfWork from app.utils.unit_of_work import UnitOfWork
from app.users.schemas import SInvitationData from app.users.schemas import SInvitationData
@ -18,8 +22,19 @@ class ChatService:
@staticmethod @staticmethod
async def get_all_chats(uow: UnitOfWork, user_id: int) -> SAllowedChats: async def get_all_chats(uow: UnitOfWork, user_id: int) -> SAllowedChats:
try:
async with RedisService() as redis:
allowed_chats = await redis.get_value(key=f"user_allowed_chats: {user_id}", model=SAllowedChats)
return allowed_chats
except ValidationError:
async with uow: async with uow:
allowed_chats = await uow.user.get_user_allowed_chats(user_id=user_id) allowed_chats = await uow.user.get_user_allowed_chats(user_id=user_id)
async with RedisService() as redis:
await redis.set_key(
key=f"user_allowed_chats: {user_id}",
expire_time=timedelta(minutes=30),
value=allowed_chats.model_dump_json()
)
return allowed_chats return allowed_chats
@staticmethod @staticmethod
@ -36,6 +51,8 @@ class ChatService:
) )
await uow.chat.add_user_to_chat(user_id, chat_id) await uow.chat.add_user_to_chat(user_id, chat_id)
await uow.chat.add_user_to_chat(settings.ADMIN_USER_ID, chat_id) await uow.chat.add_user_to_chat(settings.ADMIN_USER_ID, chat_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit() await uow.commit()
return chat_id return chat_id
@ -48,6 +65,8 @@ class ChatService:
await uow.chat.change_data( await uow.chat.change_data(
chat_id=user_data.chat_id, chat_name=user_data.chat_name, avatar_image=user_data.avatar_image chat_id=user_data.chat_id, chat_name=user_data.chat_name, avatar_image=user_data.avatar_image
) )
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit() await uow.commit()
@staticmethod @staticmethod
@ -65,6 +84,8 @@ class ChatService:
raise UserCanNotReadThisChatException raise UserCanNotReadThisChatException
async with uow: async with uow:
await uow.chat.add_user_to_chat(chat_id=invitation_data.chat_id, user_id=user_id) await uow.chat.add_user_to_chat(chat_id=invitation_data.chat_id, user_id=user_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit() await uow.commit()
@classmethod @classmethod
@ -74,6 +95,8 @@ class ChatService:
raise UserDontHavePermissionException raise UserDontHavePermissionException
async with uow: async with uow:
await uow.chat.delete_chat(chat_id) await uow.chat.delete_chat(chat_id)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id}")
await uow.commit() await uow.commit()
@classmethod @classmethod
@ -83,6 +106,8 @@ class ChatService:
raise UserDontHavePermissionException raise UserDontHavePermissionException
async with uow: async with uow:
await uow.chat.delete_user_from_chat(chat_id=chat_id, user_id=user_id_for_delete) await uow.chat.delete_user_from_chat(chat_id=chat_id, user_id=user_id_for_delete)
async with RedisService(is_raise=True) as redis:
await redis.delete_key(key=f"user_allowed_chats: {user_id_for_delete}")
await uow.commit() await uow.commit()
@staticmethod @staticmethod

View file

@ -1,8 +1,11 @@
from datetime import timedelta from datetime import timedelta
from pydantic import BaseModel
from redis.asyncio.client import Redis from redis.asyncio.client import Redis
from redis.exceptions import RedisError
from app.config import settings from app.config import settings
from app.exceptions import BlackPhoenixException
def get_redis_session() -> Redis: def get_redis_session() -> Redis:
@ -10,17 +13,26 @@ def get_redis_session() -> Redis:
class RedisService: class RedisService:
@staticmethod def __init__(self, is_raise=None):
async def set_verification_code(redis: Redis, user_id: int, verification_code: str) -> None: self.redis_session_factory = get_redis_session
await redis.setex(f"user_verification_code: {user_id}", timedelta(minutes=5), verification_code) self.is_raise = is_raise
@staticmethod async def __aenter__(self):
async def get_verification_code(redis: Redis, user_id: int) -> str: self.redis_session = self.redis_session_factory()
verification_code = await redis.get(f"user_verification_code: {user_id}") return self
return verification_code.decode()
@staticmethod async def __aexit__(self, exc_type, exc, tb):
async def delete_verification_code(redis: Redis, user_id: int) -> None: if isinstance(exc, RedisError):
await redis.delete(f"user_verification_code: {user_id}") if self.is_raise:
raise BlackPhoenixException
return True
async def set_key(self, key: str, expire_time: timedelta, value: str) -> None:
await self.redis_session.setex(key, expire_time, value)
async def get_value[T: type[BaseModel]](self, key: str, model: T | None = None) -> T | str:
value = await self.redis_session.get(key)
return model.model_validate_json(value) if model else value.decode()
async def delete_key(self, key: str) -> None:
await self.redis_session.delete(key)

View file

@ -1,5 +1,9 @@
from datetime import timedelta
from pydantic import ValidationError
from app.config import settings from app.config import settings
from app.services.redis_service import get_redis_session, RedisService from app.services.redis_service import RedisService
from app.tasks.tasks import generate_confirmation_code, send_confirmation_email, send_data_change_email from app.tasks.tasks import generate_confirmation_code, send_confirmation_email, send_data_change_email
from app.utils.unit_of_work import UnitOfWork from app.utils.unit_of_work import UnitOfWork
from app.users.exceptions import PasswordsMismatchException, WrongCodeException from app.users.exceptions import PasswordsMismatchException, WrongCodeException
@ -10,14 +14,32 @@ from app.services.auth_service import AuthService
class UserService: class UserService:
@staticmethod @staticmethod
async def find_user(uow: UnitOfWork, **find_by) -> SUser: async def find_user(uow: UnitOfWork, **find_by) -> SUser:
try:
async with RedisService() as redis:
user = await redis.get_value(key=f"user: {find_by}", model=SUser)
return user
except ValidationError:
async with uow: async with uow:
user = await uow.user.find_one(**find_by) user = await uow.user.find_one(**find_by)
async with RedisService() as redis:
await redis.set_key(
key=f"user: {find_by}", expire_time=timedelta(hours=1), value=user.model_dump_json()
)
return user return user
@staticmethod @staticmethod
async def find_all(uow: UnitOfWork, username: str) -> SUsers: async def find_all(uow: UnitOfWork, username: str) -> SUsers:
try:
async with RedisService() as redis:
users = await redis.get_value(key=f"users: {username}", model=SUsers)
return users
except ValidationError:
async with uow: async with uow:
users = await uow.user.find_all(username=username) users = await uow.user.find_all(username=username)
async with RedisService() as redis:
await redis.set_key(
key=f"users: {username}", expire_time=timedelta(hours=1), value=users.model_dump_json()
)
return users return users
@staticmethod @staticmethod
@ -39,10 +61,10 @@ class UserService:
@staticmethod @staticmethod
async def send_confirmation_email(user: SUser, mail_type: str, email: str | None = None) -> None: async def send_confirmation_email(user: SUser, mail_type: str, email: str | None = None) -> None:
redis_session = get_redis_session()
user_code = generate_confirmation_code() user_code = generate_confirmation_code()
await RedisService.delete_verification_code(redis=redis_session, user_id=user.id) async with RedisService(is_raise=True) as redis:
await RedisService.set_verification_code(redis=redis_session, user_id=user.id, verification_code=user_code) await redis.delete_key(key=f"user_verification_code: {user.id}")
await redis.set_key(key=f"user_verification_code: {user.id}", expire_time=timedelta(minutes=5), value=user_code)
user_mail_data = SConfirmationData.model_validate( user_mail_data = SConfirmationData.model_validate(
{ {
@ -57,13 +79,20 @@ class UserService:
@staticmethod @staticmethod
async def verificate_user(uow: UnitOfWork, user: SUser, confirmation_code: str) -> None: async def verificate_user(uow: UnitOfWork, user: SUser, confirmation_code: str) -> None:
redis_session = get_redis_session() try:
verification_code = await RedisService.get_verification_code(redis=redis_session, user_id=user.id) async with RedisService(is_raise=True) as redis:
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
except AttributeError:
raise WrongCodeException
if verification_code != confirmation_code: if verification_code != confirmation_code:
raise WrongCodeException raise WrongCodeException
async with uow: async with uow:
await uow.user.change_data(user_id=user.id, role=settings.VERIFICATED_USER) await uow.user.change_data(user_id=user.id, role=settings.VERIFICATED_USER)
async with RedisService() as redis:
await redis.delete_key(key=f"user: {dict(id=user.id)}")
await redis.set_key(
key=f"user: {dict(id=user.id)}", expire_time=timedelta(hours=1), value=user.model_dump_json()
)
await uow.commit() await uow.commit()
@staticmethod @staticmethod
@ -74,11 +103,16 @@ class UserService:
@staticmethod @staticmethod
async def change_data(uow: UnitOfWork, user: SUser, user_data: SUserChangeData) -> None: async def change_data(uow: UnitOfWork, user: SUser, user_data: SUserChangeData) -> None:
redis_session = get_redis_session() try:
verification_code = await RedisService.get_verification_code(redis=redis_session, user_id=user.id) async with RedisService(is_raise=True) as redis:
verification_code = await redis.get_value(key=f"user_verification_code: {user.id}")
except AttributeError:
raise WrongCodeException
if verification_code != user_data.verification_code: if verification_code != user_data.verification_code:
raise WrongCodeException raise WrongCodeException
hashed_password = AuthService.get_password_hash(user_data.new_password) if user_data.new_password else user.hashed_password hashed_password = (
AuthService.get_password_hash(user_data.new_password) if user_data.new_password else user.hashed_password
)
async with uow: async with uow:
await uow.user.change_data( await uow.user.change_data(
user_id=user.id, user_id=user.id,
@ -90,5 +124,7 @@ class UserService:
(await uow.user.add_user_avatar(user_id=user.id, avatar=str(user_data.avatar_url))) if user_data.avatar_url else None (await uow.user.add_user_avatar(user_id=user.id, avatar=str(user_data.avatar_url))) if user_data.avatar_url else None
await uow.commit() await uow.commit()
async with RedisService() as redis:
await redis.delete_key(key=f"user: {dict(id=user.id)}")
send_data_change_email.delay(user_data.username, user_data.email) send_data_change_email.delay(user_data.username, user_data.email)
await RedisService.delete_verification_code(redis=redis_session, user_id=user.id)