Add reset password to admin panel
This commit is contained in:
@@ -8,10 +8,11 @@ from app.api.deps import DbSession, CurrentUser, require_admin_with_2fa
|
||||
from app.models import User, UserRole, Marathon, MarathonStatus, Participant, Game, AdminLog, AdminActionType, StaticContent
|
||||
from app.schemas import (
|
||||
UserPublic, MessageResponse,
|
||||
AdminUserResponse, BanUserRequest, AdminLogResponse, AdminLogsListResponse,
|
||||
AdminUserResponse, BanUserRequest, AdminResetPasswordRequest, AdminLogResponse, AdminLogsListResponse,
|
||||
BroadcastRequest, BroadcastResponse, StaticContentResponse, StaticContentUpdate,
|
||||
StaticContentCreate, DashboardStats
|
||||
)
|
||||
from app.core.security import get_password_hash
|
||||
from app.services.telegram_notifier import telegram_notifier
|
||||
from app.core.rate_limit import limiter
|
||||
|
||||
@@ -431,6 +432,66 @@ async def unban_user(
|
||||
)
|
||||
|
||||
|
||||
# ============ Reset Password ============
|
||||
@router.post("/users/{user_id}/reset-password", response_model=AdminUserResponse)
|
||||
async def reset_user_password(
|
||||
request: Request,
|
||||
user_id: int,
|
||||
data: AdminResetPasswordRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DbSession,
|
||||
):
|
||||
"""Reset user password. Admin only."""
|
||||
require_admin_with_2fa(current_user)
|
||||
|
||||
result = await db.execute(select(User).where(User.id == user_id))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
# Hash and save new password
|
||||
user.password_hash = get_password_hash(data.new_password)
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
|
||||
# Log action
|
||||
await log_admin_action(
|
||||
db, current_user.id, AdminActionType.USER_PASSWORD_RESET.value,
|
||||
"user", user_id,
|
||||
{"nickname": user.nickname},
|
||||
request.client.host if request.client else None
|
||||
)
|
||||
|
||||
# Notify user via Telegram if linked
|
||||
if user.telegram_id:
|
||||
await telegram_notifier.send_message(
|
||||
user.telegram_id,
|
||||
"🔐 <b>Ваш пароль был сброшен</b>\n\n"
|
||||
"Администратор установил вам новый пароль. "
|
||||
"Если это были не вы, свяжитесь с поддержкой."
|
||||
)
|
||||
|
||||
marathons_count = await db.scalar(
|
||||
select(func.count()).select_from(Participant).where(Participant.user_id == user.id)
|
||||
)
|
||||
|
||||
return AdminUserResponse(
|
||||
id=user.id,
|
||||
login=user.login,
|
||||
nickname=user.nickname,
|
||||
role=user.role,
|
||||
avatar_url=user.avatar_url,
|
||||
telegram_id=user.telegram_id,
|
||||
telegram_username=user.telegram_username,
|
||||
marathons_count=marathons_count,
|
||||
created_at=user.created_at.isoformat(),
|
||||
is_banned=user.is_banned,
|
||||
banned_at=user.banned_at.isoformat() if user.banned_at else None,
|
||||
banned_until=user.banned_until.isoformat() if user.banned_until else None,
|
||||
ban_reason=user.ban_reason,
|
||||
)
|
||||
|
||||
|
||||
# ============ Force Finish Marathon ============
|
||||
@router.post("/marathons/{marathon_id}/force-finish", response_model=MessageResponse)
|
||||
async def force_finish_marathon(
|
||||
|
||||
Reference in New Issue
Block a user