Add subcription feature 5
This commit is contained in:
124
services/auth/app/repositories/password_reset_repository.py
Normal file
124
services/auth/app/repositories/password_reset_repository.py
Normal file
@@ -0,0 +1,124 @@
|
||||
# services/auth/app/repositories/password_reset_repository.py
|
||||
"""
|
||||
Password reset token repository
|
||||
Repository for password reset token operations
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, and_, text
|
||||
from datetime import datetime, timezone
|
||||
import structlog
|
||||
import uuid
|
||||
|
||||
from .base import AuthBaseRepository
|
||||
from app.models.password_reset_tokens import PasswordResetToken
|
||||
from shared.database.exceptions import DatabaseError
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
|
||||
class PasswordResetTokenRepository(AuthBaseRepository):
|
||||
"""Repository for password reset token operations"""
|
||||
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(PasswordResetToken, session)
|
||||
|
||||
async def create_token(self, user_id: str, token: str, expires_at: datetime) -> PasswordResetToken:
|
||||
"""Create a new password reset token"""
|
||||
try:
|
||||
token_data = {
|
||||
"user_id": user_id,
|
||||
"token": token,
|
||||
"expires_at": expires_at,
|
||||
"is_used": False
|
||||
}
|
||||
|
||||
reset_token = await self.create(token_data)
|
||||
|
||||
logger.debug("Password reset token created",
|
||||
user_id=user_id,
|
||||
token_id=reset_token.id,
|
||||
expires_at=expires_at)
|
||||
|
||||
return reset_token
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to create password reset token",
|
||||
user_id=user_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to create password reset token: {str(e)}")
|
||||
|
||||
async def get_token_by_value(self, token: str) -> Optional[PasswordResetToken]:
|
||||
"""Get password reset token by token value"""
|
||||
try:
|
||||
stmt = select(PasswordResetToken).where(
|
||||
and_(
|
||||
PasswordResetToken.token == token,
|
||||
PasswordResetToken.is_used == False,
|
||||
PasswordResetToken.expires_at > datetime.now(timezone.utc)
|
||||
)
|
||||
)
|
||||
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get password reset token by value", error=str(e))
|
||||
raise DatabaseError(f"Failed to get password reset token: {str(e)}")
|
||||
|
||||
async def mark_token_as_used(self, token_id: str) -> Optional[PasswordResetToken]:
|
||||
"""Mark a password reset token as used"""
|
||||
try:
|
||||
return await self.update(token_id, {
|
||||
"is_used": True,
|
||||
"used_at": datetime.now(timezone.utc)
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error("Failed to mark password reset token as used",
|
||||
token_id=token_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to mark token as used: {str(e)}")
|
||||
|
||||
async def cleanup_expired_tokens(self) -> int:
|
||||
"""Clean up expired password reset tokens"""
|
||||
try:
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# Delete expired tokens
|
||||
query = text("""
|
||||
DELETE FROM password_reset_tokens
|
||||
WHERE expires_at < :now OR is_used = true
|
||||
""")
|
||||
|
||||
result = await self.session.execute(query, {"now": now})
|
||||
deleted_count = result.rowcount
|
||||
|
||||
logger.info("Cleaned up expired password reset tokens",
|
||||
deleted_count=deleted_count)
|
||||
|
||||
return deleted_count
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to cleanup expired password reset tokens", error=str(e))
|
||||
raise DatabaseError(f"Token cleanup failed: {str(e)}")
|
||||
|
||||
async def get_valid_token_for_user(self, user_id: str) -> Optional[PasswordResetToken]:
|
||||
"""Get a valid (unused, not expired) password reset token for a user"""
|
||||
try:
|
||||
stmt = select(PasswordResetToken).where(
|
||||
and_(
|
||||
PasswordResetToken.user_id == user_id,
|
||||
PasswordResetToken.is_used == False,
|
||||
PasswordResetToken.expires_at > datetime.now(timezone.utc)
|
||||
)
|
||||
).order_by(PasswordResetToken.created_at.desc())
|
||||
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get valid token for user",
|
||||
user_id=user_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to get valid token for user: {str(e)}")
|
||||
Reference in New Issue
Block a user