refactor: streamline configuration loading and enhance admin checks
All checks were successful
CI / lint-and-test (push) Successful in 20s
All checks were successful
CI / lint-and-test (push) Successful in 20s
- Refactored the configuration loading in `config.py` to utilize a single source of truth through the `Settings` class, improving maintainability and clarity. - Introduced the `is_admin_for_telegram_user` function in `repository.py` to centralize admin checks based on usernames and phone numbers. - Updated command handlers to use the new admin check function, ensuring consistent access control across the application. - Enhanced error handling in the `error_handler` to log exceptions when sending error replies to users, improving debugging capabilities. - Improved the handling of user phone updates in `repository.py` to ensure proper normalization and validation of phone numbers.
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
"""Repository: get_or_create_user, get_duties, insert_duty, get_current_duty, group_duty_pins."""
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
import secrets
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import duty_teller.config as config
|
||||
from duty_teller.db.models import User, Duty, GroupDutyPin, CalendarSubscriptionToken
|
||||
|
||||
|
||||
@@ -23,6 +23,22 @@ def get_user_by_telegram_id(session: Session, telegram_user_id: int) -> User | N
|
||||
return session.query(User).filter(User.telegram_user_id == telegram_user_id).first()
|
||||
|
||||
|
||||
def is_admin_for_telegram_user(session: Session, telegram_user_id: int) -> bool:
|
||||
"""Check if the Telegram user is admin (by username or by stored phone).
|
||||
|
||||
Args:
|
||||
session: DB session.
|
||||
telegram_user_id: Telegram user id.
|
||||
|
||||
Returns:
|
||||
True if user is in ADMIN_USERNAMES or their stored phone is in ADMIN_PHONES.
|
||||
"""
|
||||
user = get_user_by_telegram_id(session, telegram_user_id)
|
||||
if not user:
|
||||
return False
|
||||
return config.is_admin(user.username or "") or config.is_admin_by_phone(user.phone)
|
||||
|
||||
|
||||
def get_or_create_user(
|
||||
session: Session,
|
||||
telegram_user_id: int,
|
||||
@@ -279,9 +295,6 @@ def get_user_by_calendar_token(session: Session, token: str) -> User | None:
|
||||
)
|
||||
if row is None:
|
||||
return None
|
||||
# Constant-time compare to avoid timing leaks (token_hash is already hashed).
|
||||
if not hmac.compare_digest(row[0].token_hash, token_hash_val):
|
||||
return None
|
||||
return row[1]
|
||||
|
||||
|
||||
@@ -466,7 +479,10 @@ def set_user_phone(
|
||||
user = session.query(User).filter(User.telegram_user_id == telegram_user_id).first()
|
||||
if not user:
|
||||
return None
|
||||
user.phone = phone
|
||||
if phone is None or (isinstance(phone, str) and not phone.strip()):
|
||||
user.phone = None
|
||||
else:
|
||||
user.phone = config.normalize_phone(phone)
|
||||
session.commit()
|
||||
session.refresh(user)
|
||||
return user
|
||||
|
||||
Reference in New Issue
Block a user