# app.py # 0bin Label App 인증 서버 (Flask) from flask import Flask, request, jsonify, render_template, redirect, url_for, session from models import db, User, LoginLog from datetime import datetime import os app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key-change-this-in-production' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///auth_db.sqlite' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # DB 초기화 db.init_app(app) # ============================================================ # API 엔드포인트 (클라이언트용) # ============================================================ @app.route('/api/login', methods=['POST']) def api_login(): """클라이언트 로그인 API""" try: data = request.get_json() username = data.get('username', '').strip() password = data.get('password', '').strip() if not username or not password: return jsonify({ 'success': False, 'message': '아이디와 비밀번호를 입력하세요' }), 400 # 사용자 조회 user = User.query.filter_by(username=username).first() # 로그인 시도 기록 ip_address = request.remote_addr user_agent = request.headers.get('User-Agent', '') if user and user.is_active and user.check_password(password): # 로그인 성공 log = LoginLog( user_id=user.id, ip_address=ip_address, user_agent=user_agent, success=True ) db.session.add(log) db.session.commit() return jsonify({ 'success': True, 'message': '로그인 성공', 'username': user.username }), 200 else: # 로그인 실패 if user: log = LoginLog( user_id=user.id, ip_address=ip_address, user_agent=user_agent, success=False ) db.session.add(log) db.session.commit() return jsonify({ 'success': False, 'message': '아이디 또는 비밀번호가 올바르지 않습니다' }), 401 except Exception as e: return jsonify({ 'success': False, 'message': f'서버 오류: {str(e)}' }), 500 @app.route('/api/health', methods=['GET']) def api_health(): """서버 상태 확인""" return jsonify({ 'status': 'ok', 'timestamp': datetime.utcnow().isoformat() }), 200 # ============================================================ # Admin 페이지 (웹 UI) # ============================================================ @app.route('/') def index(): """메인 페이지 - Admin 로그인으로 리다이렉트""" return redirect(url_for('admin_login')) @app.route('/admin', methods=['GET']) def admin_login(): """Admin 로그인 페이지""" if 'admin_logged_in' in session: return redirect(url_for('admin_dashboard')) return render_template('login.html') @app.route('/admin/login', methods=['POST']) def admin_login_post(): """Admin 로그인 처리""" username = request.form.get('username', '').strip() password = request.form.get('password', '').strip() # 간단한 admin 계정 (하드코딩) # 실제 운영 시에는 별도 Admin 테이블 사용 권장 if username == 'admin' and password == 'admin1234': session['admin_logged_in'] = True session['admin_username'] = username return redirect(url_for('admin_dashboard')) else: return render_template('login.html', error='잘못된 관리자 계정입니다') @app.route('/admin/logout') def admin_logout(): """Admin 로그아웃""" session.pop('admin_logged_in', None) session.pop('admin_username', None) return redirect(url_for('admin_login')) @app.route('/admin/dashboard') def admin_dashboard(): """Admin 대시보드""" if 'admin_logged_in' not in session: return redirect(url_for('admin_login')) # 사용자 목록 users = User.query.all() # 최근 로그인 기록 (최대 50개) recent_logs = LoginLog.query.order_by( LoginLog.login_time.desc() ).limit(50).all() # 통계 total_users = User.query.count() total_logins = LoginLog.query.filter_by(success=True).count() failed_logins = LoginLog.query.filter_by(success=False).count() return render_template( 'dashboard.html', users=users, recent_logs=recent_logs, total_users=total_users, total_logins=total_logins, failed_logins=failed_logins ) # ============================================================ # DB 초기화 # ============================================================ def init_db(): """데이터베이스 초기화 및 test 계정 생성""" with app.app_context(): # 테이블 생성 db.create_all() # test 계정이 없으면 생성 test_user = User.query.filter_by(username='test').first() if not test_user: test_user = User(username='test') test_user.set_password('test') db.session.add(test_user) db.session.commit() print('[DB] test/test 계정 생성 완료') else: print('[DB] test 계정 이미 존재') if __name__ == '__main__': # DB 초기화 if not os.path.exists('auth_db.sqlite'): print('[DB] 데이터베이스 생성 중...') init_db() else: print('[DB] 기존 데이터베이스 사용') # Flask 서버 실행 (8898 포트) print('[서버] 인증 서버 시작: http://0.0.0.0:8898') print('[서버] Admin 페이지: http://localhost:8898/admin') print('[서버] API 엔드포인트: http://localhost:8898/api/login') app.run(host='0.0.0.0', port=8898, debug=True)