From 99765d572825eeca12a25a01c9487e430e1b83af Mon Sep 17 00:00:00 2001 From: Jens Luedicke Date: Sat, 28 Jun 2025 11:10:22 +0200 Subject: [PATCH] Enable blocking and unblocking of users. --- app.py | 46 +++++++++++++++++++++++++++++--------- migrate_db.py | 5 +++++ models.py | 3 +++ static/css/style.css | 19 ++++++++++++++++ templates/admin_users.html | 13 ++++++++++- 5 files changed, 75 insertions(+), 11 deletions(-) diff --git a/app.py b/app.py index f33616c..77e9565 100644 --- a/app.py +++ b/app.py @@ -7,6 +7,7 @@ from sqlalchemy import func from functools import wraps from flask_mail import Mail, Message from dotenv import load_dotenv +from werkzeug.security import check_password_hash # Load environment variables from .env file load_dotenv() @@ -96,17 +97,21 @@ def login(): user = User.query.filter_by(username=username).first() - if user is None or not user.check_password(password): + if user and user.check_password(password): # Use the check_password method + # Check if user is blocked + if user.is_blocked: + flash('Your account has been disabled. Please contact an administrator.', 'error') + return render_template('login.html') + + # Continue with normal login process + session['user_id'] = user.id + session['username'] = user.username + session['is_admin'] = user.is_admin + + flash('Login successful!', 'success') + return redirect(url_for('home')) + else: flash('Invalid username or password', 'error') - return redirect(url_for('login')) - - if not user.is_verified: - flash('Please verify your email address before logging in. Check your inbox for the verification link.', 'warning') - return redirect(url_for('login')) - - session.clear() - session['user_id'] = user.id - return redirect(url_for('home')) return render_template('login.html', title='Login') @@ -655,5 +660,26 @@ def test(): def inject_current_year(): return {'current_year': datetime.now().year} +@app.route('/admin/users/toggle-status/') +@admin_required +def toggle_user_status(user_id): + user = User.query.get_or_404(user_id) + + # Prevent blocking yourself + if user.id == session.get('user_id'): + flash('You cannot block your own account', 'error') + return redirect(url_for('admin_users')) + + # Toggle the blocked status + user.is_blocked = not user.is_blocked + db.session.commit() + + if user.is_blocked: + flash(f'User {user.username} has been blocked', 'success') + else: + flash(f'User {user.username} has been unblocked', 'success') + + return redirect(url_for('admin_users')) + if __name__ == '__main__': app.run(debug=True) \ No newline at end of file diff --git a/migrate_db.py b/migrate_db.py index 3d99229..d94d51e 100644 --- a/migrate_db.py +++ b/migrate_db.py @@ -98,6 +98,11 @@ def migrate_database(): if 'token_expiry' not in user_columns: print("Adding token_expiry column to user table...") cursor.execute("ALTER TABLE user ADD COLUMN token_expiry TIMESTAMP") + + # Add is_blocked column to user table if it doesn't exist + if 'is_blocked' not in user_columns: + print("Adding is_blocked column to user table...") + cursor.execute("ALTER TABLE user ADD COLUMN is_blocked BOOLEAN DEFAULT 0") # Commit changes and close connection conn.commit() diff --git a/models.py b/models.py index 6f07cdd..8ffc96a 100644 --- a/models.py +++ b/models.py @@ -22,6 +22,9 @@ class User(db.Model): time_entries = db.relationship('TimeEntry', backref='user', lazy=True) work_config = db.relationship('WorkConfig', backref='user', lazy=True, uselist=False) + # New field for blocking users + is_blocked = db.Column(db.Boolean, default=False) + def set_password(self, password): self.password_hash = generate_password_hash(password) diff --git a/static/css/style.css b/static/css/style.css index a06eb35..f5a5061 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -503,4 +503,23 @@ input[type="time"]::-webkit-datetime-edit { .admin-card p { color: #666; margin-bottom: 20px; +} + +/* User status badges */ +.status-badge { + display: inline-block; + padding: 3px 8px; + border-radius: 12px; + font-size: 0.85em; + font-weight: 500; +} + +.status-active { + background-color: #d4edda; + color: #155724; +} + +.status-blocked { + background-color: #f8d7da; + color: #721c24; } \ No newline at end of file diff --git a/templates/admin_users.html b/templates/admin_users.html index ed6cd72..df6b1f8 100644 --- a/templates/admin_users.html +++ b/templates/admin_users.html @@ -23,6 +23,7 @@ Username Email Role + Status Created Actions @@ -33,11 +34,21 @@ {{ user.username }} {{ user.email }} {% if user.is_admin %}Admin{% else %}User{% endif %} + + + {% if user.is_blocked %}Blocked{% else %}Active{% endif %} + + {{ user.created_at.strftime('%Y-%m-%d') }} Edit {% if user.id != g.user.id %} - + {% if user.is_blocked %} + Unblock + {% else %} + Block + {% endif %} + {% endif %}