File size: 6,915 Bytes
2382288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# --- Flask 라우트 μ •μ˜ ---

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    next_url = request.args.get('next')
    logger.info(f"-------------- 둜그인 νŽ˜μ΄μ§€ 접속 (Next: {next_url}) --------------")
    logger.info(f"Method: {request.method}")

    if request.method == 'POST':
        logger.info("둜그인 μ‹œλ„ λ°›μŒ")
        username = request.form.get('username', '')
        password = request.form.get('password', '')
        logger.info(f"μž…λ ₯된 μ‚¬μš©μžλͺ…: {username}")
        logger.info(f"λΉ„λ°€λ²ˆν˜Έ μž…λ ₯ μ—¬λΆ€: {len(password) > 0}")

        # ν™˜κ²½ λ³€μˆ˜ λ˜λŠ” κΈ°λ³Έκ°’κ³Ό 비ꡐ
        valid_username = ADMIN_USERNAME
        valid_password = ADMIN_PASSWORD
        logger.info(f"κ²€μ¦μš© μ‚¬μš©μžλͺ…: {valid_username}")
        logger.info(f"κ²€μ¦μš© λΉ„λ°€λ²ˆν˜Έ 쑴재 μ—¬λΆ€: {valid_password is not None and len(valid_password) > 0}")

        if username == valid_username and password == valid_password:
            logger.info(f"둜그인 성곡: {username}")
            # μ„Έμ…˜ μ„€μ • μ „ ν˜„μž¬ μ„Έμ…˜ μƒνƒœ λ‘œκΉ…
            logger.debug(f"μ„Έμ…˜ μ„€μ • μ „: {session}")

            # μ„Έμ…˜μ— 둜그인 정보 μ €μž₯
            session.permanent = True
            session['logged_in'] = True
            session['username'] = username
            session.modified = True

            logger.info(f"μ„Έμ…˜ μ„€μ • ν›„: {session}")
            logger.info("μ„Έμ…˜ μ„€μ • μ™„λ£Œ, λ¦¬λ””λ ‰μ…˜ μ‹œλ„")

            # 둜그인 성곡 ν›„ λ¦¬λ””λ ‰μ…˜
            redirect_to = next_url or url_for('index')
            logger.info(f"λ¦¬λ””λ ‰μ…˜ λŒ€μƒ: {redirect_to}")
            response = redirect(redirect_to)
            return response
        else:
            logger.warning("둜그인 μ‹€νŒ¨: 아이디 λ˜λŠ” λΉ„λ°€λ²ˆν˜Έ 뢈일치")
            if username != valid_username: logger.warning("μ‚¬μš©μžλͺ… 뢈일치")
            if password != valid_password: logger.warning("λΉ„λ°€λ²ˆν˜Έ 뢈일치")
            error = '아이디 λ˜λŠ” λΉ„λ°€λ²ˆν˜Έκ°€ μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.'
    else:
        logger.info("둜그인 νŽ˜μ΄μ§€ GET μš”μ²­")
        if 'logged_in' in session:
            logger.info("이미 둜그인된 μ‚¬μš©μž, 메인 νŽ˜μ΄μ§€λ‘œ λ¦¬λ””λ ‰μ…˜")
            return redirect(url_for('index'))

    logger.info("---------- 둜그인 νŽ˜μ΄μ§€ λ Œλ”λ§ ----------")
    return render_template('login.html', error=error, next=next_url)


@app.route('/logout')
def logout():
    logger.info("-------------- λ‘œκ·Έμ•„μ›ƒ μš”μ²­ --------------")
    logger.info(f"λ‘œκ·Έμ•„μ›ƒ μ „ μ„Έμ…˜ μƒνƒœ: {session}")

    if 'logged_in' in session:
        username = session.get('username', 'unknown')
        logger.info(f"μ‚¬μš©μž {username} λ‘œκ·Έμ•„μ›ƒ 처리 μ‹œμž‘")
        session.pop('logged_in', None)
        session.pop('username', None)
        session.modified = True
        logger.info(f"μ„Έμ…˜ 정보 μ‚­μ œ μ™„λ£Œ. ν˜„μž¬ μ„Έμ…˜: {session}")
    else:
        logger.warning("λ‘œκ·ΈμΈλ˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ λ‘œκ·Έμ•„μ›ƒ μ‹œλ„")

    logger.info("둜그인 νŽ˜μ΄μ§€λ‘œ λ¦¬λ””λ ‰μ…˜")
    response = redirect(url_for('login'))
    return response


@app.route('/')
@login_required
def index():
    """메인 νŽ˜μ΄μ§€"""
    global app_ready
    
    # μ•± μ€€λΉ„ μƒνƒœ 확인 - 30초 이상 μ§€λ‚¬μœΌλ©΄ κ°•μ œλ‘œ ready μƒνƒœλ‘œ λ³€κ²½
    current_time = datetime.now()
    start_time = datetime.fromtimestamp(os.path.getmtime(__file__))
    time_diff = (current_time - start_time).total_seconds()
    
    if not app_ready and time_diff > 30:
        logger.warning(f"앱이 30초 이상 μ΄ˆκΈ°ν™” 쀑 μƒνƒœμž…λ‹ˆλ‹€. κ°•μ œλ‘œ ready μƒνƒœλ‘œ λ³€κ²½ν•©λ‹ˆλ‹€.")
        app_ready = True
    
    if not app_ready:
        logger.info("앱이 아직 μ€€λΉ„λ˜μ§€ μ•Šμ•„ λ‘œλ”© νŽ˜μ΄μ§€ ν‘œμ‹œ")
        return render_template('loading.html'), 503  # μ„œλΉ„μŠ€ μ€€λΉ„ μ•ˆλ¨ μƒνƒœ μ½”λ“œ
    
    logger.info("메인 νŽ˜μ΄μ§€ μš”μ²­")
    return render_template('index.html')


@app.route('/api/status')
@login_required
def app_status():
    """μ•± μ΄ˆκΈ°ν™” μƒνƒœ 확인 API"""
    logger.info(f"μ•± μƒνƒœ 확인 μš”μ²­: {'Ready' if app_ready else 'Not Ready'}")
    return jsonify({"ready": app_ready})


@app.route('/api/llm', methods=['GET', 'POST'])
@login_required
def llm_api():
    """μ‚¬μš© κ°€λŠ₯ν•œ LLM λͺ©λ‘ 및 선택 API"""
    global llm_interface

    if not app_ready:
        return jsonify({"error": "앱이 아직 μ΄ˆκΈ°ν™” μ€‘μž…λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."}), 503

    if request.method == 'GET':
        logger.info("LLM λͺ©λ‘ μš”μ²­")
        try:
            current_details = llm_interface.get_current_llm_details() if hasattr(llm_interface, 'get_current_llm_details') else {"id": "unknown", "name": "Unknown"}
            supported_llms_dict = llm_interface.SUPPORTED_LLMS if hasattr(llm_interface, 'SUPPORTED_LLMS') else {}
            supported_list = [{
                "name": name, "id": id, "current": id == current_details.get("id")
            } for name, id in supported_llms_dict.items()]

            return jsonify({
                "supported_llms": supported_list,
                "current_llm": current_details
            })
        except Exception as e:
            logger.error(f"LLM 정보 쑰회 였λ₯˜: {e}")
            return jsonify({"error": "LLM 정보 쑰회 쀑 였λ₯˜ λ°œμƒ"}), 500

    elif request.method == 'POST':
        data = request.get_json()
        if not data or 'llm_id' not in data:
            return jsonify({"error": "LLM IDκ°€ μ œκ³΅λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."}), 400

        llm_id = data['llm_id']
        logger.info(f"LLM λ³€κ²½ μš”μ²­: {llm_id}")

        try:
            if not hasattr(llm_interface, 'set_llm') or not hasattr(llm_interface, 'llm_clients'):
                raise NotImplementedError("LLM μΈν„°νŽ˜μ΄μŠ€μ— ν•„μš”ν•œ λ©”μ†Œλ“œ/속성 μ—†μŒ")

            if llm_id not in llm_interface.llm_clients:
                return jsonify({"error": f"μ§€μ›λ˜μ§€ μ•ŠλŠ” LLM ID: {llm_id}"}), 400

            success = llm_interface.set_llm(llm_id)
            if success:
                new_details = llm_interface.get_current_llm_details()
                logger.info(f"LLM이 '{new_details.get('name', llm_id)}'둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
                return jsonify({
                    "success": True,
                    "message": f"LLM이 '{new_details.get('name', llm_id)}'둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.",
                    "current_llm": new_details
                })
            else:
                logger.error(f"LLM λ³€κ²½ μ‹€νŒ¨ (ID: {llm_id})")
                return jsonify({"error": "LLM λ³€κ²½ 쀑 λ‚΄λΆ€ 였λ₯˜ λ°œμƒ"}), 500
        except Exception as e:
            logger.error(f"LLM λ³€κ²½ 처리 쀑 였λ₯˜: {e}", exc_info=True)
            return jsonify({"error": f"LLM λ³€κ²½ 쀑 였λ₯˜ λ°œμƒ: {str(e)}"}), 500