Добавил редис
This commit is contained in:
parent
ad1fe5487c
commit
857ff4c780
3 changed files with 103 additions and 30 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue