diff --git a/routes/auth_routes.py b/routes/auth_routes.py index 59ff8c7..ca89d3f 100644 --- a/routes/auth_routes.py +++ b/routes/auth_routes.py @@ -1,10 +1,9 @@ -"""Authentication routes - Login, Logout, Register""" +"""Authentication routes - Login, Logout""" -from flask import Blueprint, render_template, request, redirect, url_for, session, jsonify, flash +from flask import Blueprint, render_template, request, redirect, url_for, session, jsonify from functools import wraps from database import db from database.models import User -from datetime import datetime import logging auth_bp = Blueprint('auth', __name__) @@ -12,91 +11,94 @@ logger = logging.getLogger(__name__) def login_required(f): - """Decorator to require login""" - @wraps(f) - def decorated_function(*args, **kwargs): - if 'user_id' not in session: - return redirect(url_for('auth.login', next=request.url)) - return f(*args, **kwargs) - return decorated_function - - -def admin_required(f): - """Decorator to require admin role""" + """Decorator - require user to be logged in""" @wraps(f) def decorated_function(*args, **kwargs): if 'user_id' not in session: return redirect(url_for('auth.login')) - - user = User.query.get(session['user_id']) - if not user or not user.is_admin: - flash('Admin access required', 'danger') - return redirect(url_for('main.index')) - return f(*args, **kwargs) return decorated_function @auth_bp.route('/login', methods=['GET', 'POST']) def login(): - """Login page""" - if request.method == 'POST': - username = request.form.get('username') - password = request.form.get('password') - - if not username or not password: - flash('Username and password required', 'warning') - return redirect(url_for('auth.login')) - - user = User.query.filter_by(username=username).first() - - if user and user.check_password(password): - session['user_id'] = user.id - session['username'] = user.username - session['is_admin'] = user.is_admin - session.permanent = True - - user.last_login = datetime.utcnow() - db.session.commit() - - logger.info(f"[AUTH] User '{username}' logged in", flush=True) - - next_page = request.args.get('next') - if next_page and next_page.startswith('/'): - return redirect(next_page) + """Login page and authentication""" + if request.method == 'GET': + if 'user_id' in session: return redirect(url_for('main.index')) - logger.warning(f"[AUTH] Failed login attempt for '{username}'", flush=True) - flash('Invalid username or password', 'danger') + return render_template('auth/login.html') - return render_template('login.html') + # POST - process login + username = request.form.get('username', '').strip() + password = request.form.get('password', '').strip() + + if not username or not password: + return render_template('auth/login.html', error='Username and password required'), 400 + + try: + # Find user + user = User.query.filter_by(username=username).first() + + if not user: + logger.warning(f"[AUTH] Login failed - user '{username}' not found", flush=True) + return render_template('auth/login.html', error='Invalid credentials'), 401 + + # Check password + if not user.check_password(password): + logger.warning(f"[AUTH] Login failed - wrong password for '{username}'", flush=True) + return render_template('auth/login.html', error='Invalid credentials'), 401 + + session.clear() + session['user_id'] = user.id + session['username'] = user.username + session['is_admin'] = user.is_admin + session.permanent = True + + from datetime import datetime + user.last_login = datetime.utcnow() + db.session.commit() + + logger.info(f"[AUTH] User '{username}' logged in successfully", flush=True) + + return redirect(url_for('main.index')) + + except Exception as e: + logger.error(f"[AUTH] Login error: {e}", flush=True) + return render_template('auth/login.html', error='Login error'), 500 -@auth_bp.route('/logout') +@auth_bp.route('/logout', methods=['GET', 'POST']) def logout(): """Logout""" - username = session.get('username', 'Unknown') + username = session.get('username', 'unknown') session.clear() logger.info(f"[AUTH] User '{username}' logged out", flush=True) - flash('You have been logged out', 'info') return redirect(url_for('auth.login')) -@auth_bp.route('/api/current-user') -def api_current_user(): - """Get current user info (API)""" +@auth_bp.route('/api/current-user', methods=['GET']) +def current_user(): + """Get current logged in user info""" if 'user_id' not in session: - return jsonify({'error': 'Not authenticated'}), 401 + return jsonify({'error': 'Not authenticated', 'success': False}), 401 - user = User.query.get(session['user_id']) - if not user: - session.clear() - return jsonify({'error': 'User not found'}), 404 + try: + user = User.query.get(session['user_id']) + + if not user: + session.clear() + return jsonify({'error': 'User not found', 'success': False}), 401 + + return jsonify({ + 'success': True, + 'user': { + 'id': user.id, + 'username': user.username, + 'is_admin': user.is_admin + } + }) - return jsonify({ - 'id': user.id, - 'username': user.username, - 'is_admin': user.is_admin, - 'created_at': user.created_at.isoformat() if user.created_at else None, - 'last_login': user.last_login.isoformat() if user.last_login else None - }) + except Exception as e: + logger.error(f"[AUTH] Error getting current user: {e}", flush=True) + return jsonify({'error': str(e), 'success': False}), 500