Skip to content

Commit cd3133b

Browse files
committed
chore(auth):fix the bcrypt library error of 72 bytes
1 parent e4894a7 commit cd3133b

8 files changed

Lines changed: 113 additions & 94 deletions

File tree

‎app/core/logger.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import logging
2+
3+
4+
DEFAULT_LOG_FORMAT = "%(asctime)s | %(levelname)s | %(name)s | %(message)s"
5+
6+
7+
logger = logging.getLogger("multAI")
8+
9+
10+
def configure_logger(level: int = logging.INFO) -> None:
11+
logging.basicConfig(
12+
level=level,
13+
format=DEFAULT_LOG_FORMAT,
14+
force=True,
15+
)

‎app/core/securite.py‎

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,48 @@
55
import pyotp
66
from app.core.config import settings
77
from app.core.exceptions import AppException
8+
from app.core.logger import logger
9+
810

911
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
1012
_BCRYPT_MAX_LEN = 72
1113

1214

13-
def _normalize_password(password: str) -> str:
14-
return password[:_BCRYPT_MAX_LEN]
15+
def _normalize_password(password: str) -> bytes:
16+
return password.encode("utf-8")[:_BCRYPT_MAX_LEN]
1517

1618

1719
def hash_password(password: str) -> str:
1820
normalized = _normalize_password(password)
21+
logger.debug("hashing password (normalized %s bytes)", len(normalized))
1922
return pwd_context.hash(normalized)
2023

2124

2225
def verify_password(password: str, hashed: str) -> bool:
2326
normalized = _normalize_password(password)
24-
return pwd_context.verify(normalized, hashed)
27+
result = pwd_context.verify(normalized, hashed)
28+
logger.debug("password verification result: %s", result)
29+
return result
2530

26-
def Get_expiry_time()->int :
27-
if settings.environment == "dev":
28-
expirty = 60 * 60 * 24 * 7
29-
else :
30-
expirty = 60 * 60 * 24
31-
return expirty
3231

32+
def Get_expiry_time() -> int:
33+
if settings.environment == "dev":
34+
expiry = 60 * 60 * 24 * 7
35+
else:
36+
expiry = 60 * 60 * 24
37+
return expiry
3338

3439

35-
def create_acces_mobile_token(session_id:str) -> str:
36-
payload :dict [str,Any]= {
40+
def create_acces_mobile_token(session_id: str) -> str:
41+
payload: dict[str, Any] = {
3742
"session_id": session_id,
38-
"exp": int((datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time())).timestamp())
43+
"exp": int(
44+
(datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time())).timestamp()
45+
),
3946
}
4047
return jwt.encode(payload, key=settings.jwt_secret, algorithm=settings.jwt_algorithm)
4148

49+
4250
def decode_access_mobile_token(token: str) -> dict[str, Any]:
4351
try:
4452
payload = jwt.decode(token, key=settings.jwt_secret, algorithms=[settings.jwt_algorithm])
@@ -48,13 +56,17 @@ def decode_access_mobile_token(token: str) -> dict[str, Any]:
4856
except jwt.InvalidTokenError:
4957
raise AppException.unauthorized("Invalid token")
5058

51-
def create_refresh_mobile_token(session_id:str) -> str:
52-
payload :dict [str,Any]= {
59+
60+
def create_refresh_mobile_token(session_id: str) -> str:
61+
payload: dict[str, Any] = {
5362
"session_id": session_id,
54-
"exp": int((datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time()*4)).timestamp())
63+
"exp": int(
64+
(datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time() * 4)).timestamp()
65+
),
5566
}
5667
return jwt.encode(payload, key=settings.jwt_secret, algorithm=settings.jwt_algorithm)
5768

69+
5870
def decode_refresh_mobile_token(token: str) -> dict[str, Any]:
5971
try:
6072
payload = jwt.decode(token, key=settings.jwt_secret, algorithms=[settings.jwt_algorithm])
@@ -69,19 +81,22 @@ def create_totp_secret() -> str:
6981
return pyotp.random_base32()
7082

7183

72-
7384
def get_totp_uri(secret: str, email: str) -> str:
7485
totp = pyotp.TOTP(secret)
7586
return totp.provisioning_uri(name=email, issuer_name=settings.totp_issuer)
7687

88+
7789
def verify_totp_token_with_window(secret: str, token: str, valid_window: int = 8) -> bool:
7890
totp = pyotp.TOTP(secret)
7991
return totp.verify(token, valid_window=valid_window)
8092

81-
def generate_Acces_token_stuff(user_id:str ,role:str) -> str:
82-
payload :dict [str,Any]= {
93+
94+
def generate_Acces_token_stuff(user_id: str, role: str) -> str:
95+
payload: dict[str, Any] = {
8396
"user_id": user_id,
8497
"role": role,
85-
"exp": int((datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time())).timestamp())
98+
"exp": int(
99+
(datetime.now(timezone.utc) + timedelta(seconds=Get_expiry_time())).timestamp()
100+
),
86101
}
87102
return jwt.encode(payload, key=settings.jwt_secret, algorithm=settings.jwt_algorithm)

‎app/infra/nats.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async def connect() -> None:
3030
password=settings.NATS_PASSWORD,
3131
)
3232
NatsClient._nc = nc
33-
NatsClient._js = nc.jetstream()
33+
NatsClient._js = nc.jetstream() # type: ignore
3434

3535
@staticmethod
3636
async def close() -> None:
@@ -58,7 +58,7 @@ async def subscribe(subject: NatsSubjects, callback: Callable[[Any], Any]) -> No
5858
async def _wrapper(msg: Msg) -> None:
5959
await callback(msg.data)
6060

61-
await nc.subscribe(subject.value, cb=_wrapper)
61+
await nc.subscribe(subject.value, cb=_wrapper) # type: ignore
6262

6363

6464
@staticmethod

‎app/infra/redis.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> "RedisClient":
1515

1616
def __init__(self, host: str, port: int, password: str) -> None:
1717
if not hasattr(self, "client"):
18-
self.client = Redis.from_url(
18+
self.client = Redis.from_url( # type: ignore
1919
f"redis://{host}:{port}", password=password, decode_responses=True
2020
)
2121

‎app/main.py‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import logging
21
import time
32
from contextlib import asynccontextmanager
43
import asyncio
@@ -13,16 +12,9 @@
1312
from app.infra.redis import RedisClient
1413
from app.router.mobile.auth import router as mobile_auth_router
1514
from app.router.staff.drive import router as staff_drive_router
15+
from app.core.logger import configure_logger, logger
1616

17-
18-
19-
logging.basicConfig(
20-
level=logging.INFO,
21-
format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
22-
)
23-
24-
logger = logging.getLogger("api")
25-
17+
configure_logger()
2618

2719

2820
class RequestLoggingMiddleware(BaseHTTPMiddleware):

‎app/service/users.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from db.generated import devices as device_queries
2020
from db.generated import session as session_queries
2121
from db.generated.models import User
22+
from app.core.logger import logger
2223

2324

2425
class AuthService:
@@ -43,15 +44,18 @@ async def mobile_register_login(
4344
redis: RedisClient,
4445
req: MobileAuthRequest,
4546
) -> MobileAuthResponse:
47+
logger.info("mobile register/login attempt for %s", req.email)
4648
existing_user = await self.user_querier.get_user_by_email(email=req.email)
4749
user: User | None = None
4850

4951
if existing_user is not None:
5052
if not verify_password(req.password, existing_user.hashed_password or ""):
5153
raise AppException.unauthorized("Invalid credentials")
5254
user = existing_user
55+
logger.info("existing user login: %s", req.email)
5356
else:
5457
hashed = hash_password(req.password)
58+
logger.info("creating new user for %s", req.email)
5559
user = await self.user_querier.create_user(
5660
email=req.email, hashed_password=hashed
5761
)
@@ -68,6 +72,11 @@ async def mobile_register_login(
6872

6973
session_count = await self.session_querier.count_user_sessions(user_id=user_id)
7074
if session_count and session_count >= AuthService.SESSION_LIMIT:
75+
logger.warning(
76+
"user %s reached session limit %s",
77+
req.email,
78+
AuthService.SESSION_LIMIT,
79+
)
7180
raise AppException.forbidden("Maximum session limit reached")
7281

7382
device_id = uuid.UUID(req.device_id)
@@ -99,6 +108,7 @@ async def mobile_register_login(
99108
access_token = create_acces_mobile_token(str(session.id))
100109
refresh_token = create_refresh_mobile_token(str(session.id))
101110
expiry = Get_expiry_time()
111+
logger.info("created session %s for user %s", session.id, user_id)
102112

103113
return MobileAuthResponse(
104114
access_token=access_token,

‎pyproject.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies = [
1313
"miniopy-async>=1.23.4",
1414
"nats-py>=2.14.0",
1515
"passlib[bcrypt]>=1.7.4",
16+
"bcrypt==4.3.0",
1617
"psycopg>=3.3.3",
1718
"pydantic>=2.12.5",
1819
"pydantic-settings>=2.13.1",

0 commit comments

Comments
 (0)