File size: 5,100 Bytes
a3a8bab
 
 
fc77903
 
4ebbf72
fc77903
a3a8bab
 
 
4ebbf72
 
 
 
 
a3a8bab
fc77903
 
a3a8bab
fc77903
 
 
 
a3a8bab
 
 
 
fc77903
 
 
 
 
 
 
 
 
a3a8bab
 
 
 
4ebbf72
a3a8bab
 
4ebbf72
 
a3a8bab
 
4ebbf72
 
a3a8bab
 
4ebbf72
 
a3a8bab
 
4ebbf72
 
a3a8bab
4ebbf72
 
a3a8bab
4ebbf72
a3a8bab
 
4ebbf72
 
 
 
 
 
a3a8bab
 
4ebbf72
 
 
 
 
 
a3a8bab
 
4ebbf72
 
a3a8bab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fc77903
a3a8bab
 
 
 
 
 
 
fc77903
a3a8bab
fc77903
a3a8bab
 
b3ad474
fc77903
 
 
a3a8bab
fc77903
 
d4bc82a
a3a8bab
 
 
 
fc77903
a3a8bab
 
fc77903
 
 
 
 
a3a8bab
fc77903
a3a8bab
4ebbf72
 
 
a3a8bab
 
 
 
 
 
 
 
4ebbf72
fc77903
 
a3a8bab
4ebbf72
fc77903
a3a8bab
 
 
 
 
 
 
 
 
 
 
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# =========================================================
#  AUTHENTICATION MODULE FOR STREAMLIT (HF SPACES SAFE)
# =========================================================
import streamlit as st
import hashlib
from typing import Optional, Dict, Any

# =========================================================
#  LOAD PASSWORD HASH FROM SECRETS
# =========================================================
def _get_password_hash() -> Optional[str]:
    try:
        raw = st.secrets.get("APP_PASSWORD", None)
    except Exception:
        raw = None

    if not raw:
        return None

    return hashlib.sha256(raw.encode("utf-8")).hexdigest()

PASSWORD_HASH = _get_password_hash()


# =========================================================
#  SESSION UTILITIES
# =========================================================
def is_logged_in() -> bool:
    return bool(st.session_state.get("_logged_in", False))

def set_logged_in(value: bool = True):
    st.session_state["_logged_in"] = bool(value)

def logout():
    st.session_state["_logged_in"] = False


# =========================================================
#  QUERY PARAM COMPATIBILITY LAYER
# =========================================================
def _get_query_params() -> Dict[str, Any]:
    """Return query params safely across Streamlit versions"""
    # New Streamlit API
    try:
        if hasattr(st, "query_params"):
            qp = dict(st.query_params or {})
            return qp
    except Exception:
        pass

    # Old experimental API
    try:
        if hasattr(st, "experimental_get_query_params"):
            qp = st.experimental_get_query_params() or {}
            return dict(qp)
    except Exception:
        pass

    return {}


def _set_query_params(**kwargs):
    """Set query params safely across Streamlit versions"""
    # New Streamlit API
    try:
        if hasattr(st, "set_query_params"):
            st.set_query_params(**kwargs)
            return
    except Exception:
        pass

    # Old experimental API
    try:
        if hasattr(st, "experimental_set_query_params"):
            st.experimental_set_query_params(**kwargs)
            return
    except Exception:
        pass

    # No query-param API available → do nothing
    return


# =========================================================
#  SAFE RERUN (works on all HF Streamlit builds)
# =========================================================
def _safe_rerun():
    """Try every known rerun mechanism."""
    try:
        if hasattr(st, "experimental_rerun"):
            st.experimental_rerun()
            return
    except Exception:
        pass

    try:
        if hasattr(st, "rerun"):
            st.rerun()
            return
    except Exception:
        pass

    # Fallback for environments where rerun is blocked
    try:
        st.markdown('<meta http-equiv="refresh" content="0">', unsafe_allow_html=True)
    except Exception:
        pass


# =========================================================
#  LOGIN UI (Used ONLY on /pages/auth.py)
# =========================================================
def login_ui() -> bool:
    """Returns True ONLY when login succeeds."""
    st.title("🔒 Authentication")

    if PASSWORD_HASH is None:
        st.error("APP_PASSWORD not defined in Secrets.")
        return False

    pwd = st.text_input("Password", type="password")
    if st.button("Login"):
        entered_hash = hashlib.sha256(pwd.encode("utf-8")).hexdigest()

        if entered_hash == PASSWORD_HASH:
            set_logged_in(True)
            st.success("Login successful! Redirecting…")
            st.markdown("Login Successful - Click on any option from Left sidebar")
            return True
        else:
            st.error("Incorrect password")

    return False


# =========================================================
#  AUTH ENFORCER FOR ALL OTHER PAGES
# =========================================================
def require_login(auth_page_name: str = "auth", redirect_page: str = "HOW TO USE"):
    """
    Call this at TOP of every protected page.
    If not logged in → redirect to auth page.
    """
    if "_logged_in" not in st.session_state:
        st.session_state["_logged_in"] = False

    if is_logged_in():
        return  # Already authenticated

    # Find current page
    params = _get_query_params()
    cur_page = None

    if "page" in params:
        p = params["page"]
        if isinstance(p, list):
            cur_page = p[0] if p else None
        else:
            cur_page = p

    # Allow rendering of auth page itself
    if cur_page == auth_page_name:
        return

    # Redirect user to AUTH page
    _set_query_params(page=auth_page_name)
    st.stop()


# =========================================================
#  AUTH PAGE HANDLER (CALLED ONLY INSIDE pages/auth.py)
# =========================================================
def auth_page_handler(redirect_page="HOW TO USE"):
    succeeded = login_ui()
    if succeeded:
        _set_query_params(page=redirect_page)
        _safe_rerun()
        st.stop()