Talk-Trace-AI / components /teacher_auth.py
Claude
fix: 유효성 검사 오류 메시지에서 영문 에러코드 제거
e109735 unverified
Raw History Blame Contribute Delete
5.36 kB
import streamlit as st
from auth import _is_hashed, _verify_password
from db import (
fetch_teacher_account,
request_teacher_account,
upgrade_teacher_password,
)
from validators import validate_teacher_credential
from utils import to_bool_flag
def _reset_auth_state():
st.session_state['teacher_auth'] = False
st.session_state['admin_auth'] = False
st.session_state['teacher_id'] = ""
def _redirect_from_admin_if_needed():
if st.session_state.get('page') == "admin_approval" and not st.session_state.get('admin_auth', False):
st.session_state['page'] = "lobby"
def _handle_login(supabase, teacher_id_input, teacher_pw_input):
id_ok, safe_teacher_id, id_error_code, id_error_message = validate_teacher_credential(
teacher_id_input, field_name="교사 ID", max_len=60
)
pw_ok, safe_pw, pw_error_code, pw_error_message = validate_teacher_credential(
teacher_pw_input, field_name="교사 PW", max_len=60
)
if not id_ok:
st.error(f"❌ {id_error_message}")
st.stop()
if not pw_ok:
st.error(f"❌ {pw_error_message}")
st.stop()
account = fetch_teacher_account(supabase, safe_teacher_id)
if isinstance(account, dict) and account.get("_query_failed"):
_reset_auth_state()
_redirect_from_admin_if_needed()
st.error("🚨 교사 계정 조회에 실패했습니다. Supabase RLS 정책/권한 및 DB 연결 상태를 확인해 주세요.")
elif not account:
_reset_auth_state()
_redirect_from_admin_if_needed()
st.error("🚨 등록되지 않은 교사 ID입니다.")
elif not _verify_password(safe_pw, account.get("teacher_pw", "")):
_reset_auth_state()
_redirect_from_admin_if_needed()
st.error("❌ 비밀번호가 일치하지 않습니다.")
elif not account.get("is_approved"):
_reset_auth_state()
_redirect_from_admin_if_needed()
st.warning("⏳ 최고관리자 승인 후 로그인할 수 있습니다.")
else:
st.session_state['teacher_auth'] = True
st.session_state['admin_auth'] = to_bool_flag(account.get("is_admin", False))
st.session_state['teacher_id'] = safe_teacher_id
_redirect_from_admin_if_needed()
if not _is_hashed(account.get("teacher_pw", "")):
upgrade_teacher_password(supabase, account["id"], safe_pw)
if st.session_state['admin_auth']:
st.session_state['page'] = "admin_approval"
st.toast("✅ 관리자 계정 로그인 성공", icon="✅")
st.rerun()
else:
st.toast("✅ 교사 로그인 성공", icon="✅")
st.rerun()
def _render_signup(supabase):
req_teacher_id = st.text_input("신청할 교사 ID", key="req_teacher_id")
req_teacher_pw = st.text_input("신청할 교사 PW", type="password", key="req_teacher_pw")
if st.button("교사 계정 신청", type="primary", use_container_width=True):
id_ok, safe_id, id_error_code, id_error_message = validate_teacher_credential(
req_teacher_id, field_name="교사 ID", max_len=60
)
pw_ok, safe_pw, pw_error_code, pw_error_message = validate_teacher_credential(
req_teacher_pw, field_name="교사 PW", max_len=60
)
if not id_ok:
st.error(f"❌ {id_error_message}")
elif not pw_ok:
st.error(f"❌ {pw_error_message}")
elif fetch_teacher_account(supabase, safe_id):
st.warning("이미 존재하는 ID입니다. 다른 ID를 사용해 주세요.")
else:
req_res = request_teacher_account(supabase, safe_id, safe_pw)
if req_res is not None:
st.success("신청 완료! 최고관리자 승인 후 로그인할 수 있습니다.")
def render_teacher_auth(supabase) -> None:
"""교사 로그인/회원가입/로그아웃 UI를 렌더링하고 session_state를 업데이트합니다."""
already_logged_in = st.session_state.get('teacher_auth', False)
if not already_logged_in:
auth_mode = st.radio("교사 계정", ["로그인", "ID/PW 신청"], horizontal=True)
else:
auth_mode = "로그인"
if auth_mode == "로그인" and not already_logged_in:
with st.form("teacher_login_form"):
teacher_id_input = st.text_input("교사 ID", key="teacher_id_input")
teacher_pw_input = st.text_input("교사 PW", type="password", key="teacher_pw_input")
login_submitted = st.form_submit_button("교사 로그인", use_container_width=True)
if login_submitted:
_handle_login(supabase, teacher_id_input, teacher_pw_input)
elif auth_mode == "ID/PW 신청":
_render_signup(supabase)
if st.session_state.get('teacher_auth', False):
teacher_id = st.session_state.get("teacher_id", "")
st.caption(f"🔐 {teacher_id} 로그인 중")
if st.button("🚪 로그아웃", use_container_width=True):
_reset_auth_state()
st.session_state['teacher_id_input'] = ""
st.session_state['teacher_pw_input'] = ""
st.session_state['joined'] = False
st.session_state['page'] = "lobby"
st.session_state.pop('_admin_redirected', None)
st.rerun()
st.divider()