feat: admin can create users from /admin/users page
Adds a dialog form on the users list. Validates email uniqueness, password length. Creates user as active with confirmed email. System role can assign admin role; admin role can only create users. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,75 @@ async def admin_user_detail(user_id: int, request: Request, db: Session = Depend
|
||||
return _render(request, "admin/user_detail.html", {"user": admin, "target": target})
|
||||
|
||||
|
||||
# ── Create user ───────────────────────────────────────────────────────────────
|
||||
|
||||
@router.post("/users/create")
|
||||
async def admin_create_user(request: Request, db: Session = Depends(get_db)):
|
||||
try:
|
||||
admin = _admin_user(request, db)
|
||||
except Exception:
|
||||
return RedirectResponse("/login", 303)
|
||||
|
||||
form = await request.form()
|
||||
first_name = str(form.get("first_name", "")).strip()
|
||||
last_name = str(form.get("last_name", "")).strip()
|
||||
email = str(form.get("email", "")).strip().lower()
|
||||
phone = str(form.get("phone", "")).strip() or None
|
||||
password = str(form.get("password", ""))
|
||||
role_str = str(form.get("role", "user"))
|
||||
|
||||
errors = []
|
||||
if not first_name:
|
||||
errors.append("Имя обязательно")
|
||||
if not email:
|
||||
errors.append("Email обязателен")
|
||||
if not password or len(password) < 8:
|
||||
errors.append("Пароль должен содержать минимум 8 символов")
|
||||
if role_str not in ("user", "admin") and admin.role != UserRoleEnum.system:
|
||||
role_str = "user"
|
||||
|
||||
if not errors:
|
||||
existing = db.query(User).filter(User.email == email).first()
|
||||
if existing:
|
||||
errors.append("Пользователь с таким email уже существует")
|
||||
|
||||
if errors:
|
||||
# Re-render list page with errors and dialog open
|
||||
q = db.query(User)
|
||||
total = q.count()
|
||||
users = q.order_by(User.created_at.desc()).limit(PAGE_SIZE).all()
|
||||
return _render(request, "admin/users.html", {
|
||||
"user": admin,
|
||||
"users": users,
|
||||
"search": "",
|
||||
"status_filter": "",
|
||||
"role_filter": "",
|
||||
"page": 1,
|
||||
"total_pages": max(1, (total + PAGE_SIZE - 1) // PAGE_SIZE),
|
||||
"total": total,
|
||||
"create_errors": errors,
|
||||
})
|
||||
|
||||
try:
|
||||
role = UserRoleEnum(role_str)
|
||||
except ValueError:
|
||||
role = UserRoleEnum.user
|
||||
|
||||
new_user = User(
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
email=email,
|
||||
phone=phone,
|
||||
password_hash=hash_password(password),
|
||||
role=role,
|
||||
status=UserStatusEnum.active,
|
||||
is_email_confirmed=True,
|
||||
)
|
||||
db.add(new_user)
|
||||
db.commit()
|
||||
return RedirectResponse(f"/admin/users/{new_user.id}?success=saved", 303)
|
||||
|
||||
|
||||
# ── View-as ───────────────────────────────────────────────────────────────────
|
||||
|
||||
@router.post("/users/{user_id}/view-as")
|
||||
|
||||
Reference in New Issue
Block a user