feat(admin): add Users management (list/create/reset/delete/toggle), seed test users; improve UI with modern styles

This commit is contained in:
2025-09-04 14:08:15 +03:00
parent e22823cbbd
commit d54e12123b
4 changed files with 202 additions and 0 deletions

104
main.py
View File

@@ -54,6 +54,110 @@ def ensure_default_admin():
if os.environ.get('SEED_ADMIN_DISABLED') != '1':
ensure_default_admin()
# Seed two test users (non-admin) for demos
def ensure_test_users():
tests = [
('test1', 'test1@example.com', 'Пользователь 1'),
('test2', 'test2@example.com', 'Пользователь 2'),
]
for username, email, full_name in tests:
u = User.get_or_none(User.username == username)
if not u:
User.create(
username=username,
email=email,
full_name=full_name,
password_hash=generate_password_hash(os.environ.get('TEST_USER_PASSWORD', '1234')),
is_admin=False,
)
if os.environ.get('SEED_TEST_USERS_DISABLED') != '1':
ensure_test_users()
@app.route('/admin/users', methods=['GET', 'POST'])
@admin_required
def manage_users():
if request.method == 'POST':
# Create user
username = request.form['username'].strip()
email = request.form['email'].strip()
full_name = request.form.get('full_name', '').strip()
password = request.form['password']
is_admin_flag = request.form.get('is_admin') == 'on'
if not username or not email or not password:
flash('Заполните обязательные поля', 'danger')
return redirect(url_for('manage_users'))
if User.select().where((User.username == username) | (User.email == email)).exists():
flash('Пользователь с таким логином или email уже существует', 'danger')
return redirect(url_for('manage_users'))
User.create(
username=username,
email=email,
full_name=full_name or None,
password_hash=generate_password_hash(password),
is_admin=is_admin_flag,
)
flash('Пользователь создан', 'success')
return redirect(url_for('manage_users'))
users = User.select().order_by(User.id)
return render_template('admin/users.html', users=users, title='Пользователи')
@app.route('/admin/users/<int:user_id>/reset_password', methods=['POST'])
@admin_required
def admin_reset_password(user_id):
user = User.get_or_none(User.id == user_id)
if not user:
flash('Пользователь не найден', 'danger')
return redirect(url_for('manage_users'))
new_password = request.form.get('new_password')
if not new_password:
flash('Укажите новый пароль', 'danger')
return redirect(url_for('manage_users'))
user.password_hash = generate_password_hash(new_password)
user.save()
flash('Пароль обновлён', 'success')
return redirect(url_for('manage_users'))
@app.route('/admin/users/<int:user_id>/toggle_admin', methods=['POST'])
@admin_required
def admin_toggle_admin(user_id):
if current_user.id == user_id:
flash('Нельзя менять свои собственные права', 'warning')
return redirect(url_for('manage_users'))
user = User.get_or_none(User.id == user_id)
if not user:
flash('Пользователь не найден', 'danger')
return redirect(url_for('manage_users'))
user.is_admin = not user.is_admin
user.save()
flash('Права обновлены', 'success')
return redirect(url_for('manage_users'))
@app.route('/admin/users/<int:user_id>/delete', methods=['POST'])
@admin_required
def admin_delete_user(user_id):
if current_user.id == user_id:
flash('Нельзя удалить самого себя', 'warning')
return redirect(url_for('manage_users'))
user = User.get_or_none(User.id == user_id)
if not user:
flash('Пользователь не найден', 'danger')
return redirect(url_for('manage_users'))
try:
user.delete_instance(recursive=True)
flash('Пользователь удалён', 'success')
except Exception:
flash('Не удалось удалить пользователя', 'danger')
return redirect(url_for('manage_users'))
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'