File size: 8,496 Bytes
daa81fb
 
 
 
b17b0dd
daa81fb
 
 
 
486c2a9
daa81fb
 
245e2db
daa81fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b17b0dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5dd6e15
245e2db
 
 
 
 
 
 
1b6f6c4
245e2db
0a5edbb
245e2db
 
 
 
 
 
 
0a5edbb
245e2db
1b6f6c4
245e2db
1b6f6c4
245e2db
 
0a5edbb
 
245e2db
 
 
 
 
 
 
0a5edbb
245e2db
 
daa81fb
245e2db
1b6f6c4
daa81fb
245e2db
daa81fb
 
245e2db
1b6f6c4
245e2db
daa81fb
 
 
 
1b6f6c4
daa81fb
 
245e2db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
daa81fb
245e2db
daa81fb
245e2db
daa81fb
245e2db
daa81fb
245e2db
 
1b6f6c4
245e2db
daa81fb
245e2db
 
daa81fb
 
245e2db
 
d99d7ed
245e2db
 
 
 
 
 
 
daa81fb
245e2db
daa81fb
245e2db
daa81fb
245e2db
daa81fb
245e2db
 
daa81fb
245e2db
 
 
d99d7ed
245e2db
 
 
 
 
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
180
181
182
183
184
185
186
import os
import base64
import streamlit as st
from app.db import supabase
from urllib.parse import parse_qsl


def auth_view():
    """Render Supabase authentication with Login, Register, and Forgot Password tabs."""
    # Wrapper (centered) for all auth content
    left, center, right = st.columns([1, 2, 1])
    with center:
        # Header: PNP logo + title
        logo_path = os.path.join("assets", "pnp-logo.png")

        def get_base64_image(path):
            with open(path, "rb") as f:
                return base64.b64encode(f.read()).decode()

        encoded_logo = get_base64_image(logo_path)

        st.markdown(
            f"""
            <div style="text-align:center;">
                <img src="data:image/png;base64,{encoded_logo}" width="100">
                <h1 style="margin-top:0.25rem;">PNP bot</h1>
            </div>
            """,
            unsafe_allow_html=True
        )

        # --- FIX: Auto convert hash (#) to query (?) using streamlit-url-fragment ---
        try:
            from streamlit_url_fragment import get_fragment
            fragment = get_fragment()
            
            if fragment and not st.session_state.get("hash_migrated"):
                # Parse fragment parameters
                params = dict(parse_qsl(fragment))
                
                if params.get("type") == "recovery" and params.get("access_token"):
                    # Set query params so existing recovery flow works
                    if hasattr(st, "query_params"):
                        for key, value in params.items():
                            st.query_params[key] = value
                    else:
                        st.experimental_set_query_params(**params)
                    
                    st.session_state["hash_migrated"] = True
                    st.rerun()
        except ImportError:
            # Fallback to JS if library not available
            st.markdown(
                """
                <script>
                (function() {
                    const hash = window.location.hash;
                    if (hash && hash.length > 1 && !sessionStorage.getItem("hash_migrated")) {
                        const query = hash.substring(1); 
                        const newUrl = window.location.pathname + "?" + query;
                        sessionStorage.setItem("hash_migrated", "true");
                        window.history.replaceState(null, "", newUrl);
                        window.location.reload();
                    }
                })();
                </script>
                """,
                unsafe_allow_html=True
            )

        # --- Recovery flow ---
        if hasattr(st, "query_params"):
            qp = st.query_params
            get_q = lambda k: qp.get(k)
        else:
            qp = st.experimental_get_query_params()
            get_q = lambda k: (qp.get(k, [None])[0] if isinstance(qp.get(k, None), list) else qp.get(k))

        q_type = get_q("type")
        if q_type == "recovery":
            st.info("Reset password: silakan masukkan password baru Anda.")
            access_token = get_q("access_token")
            refresh_token = get_q("refresh_token")
            with st.form("reset_password_form"):
                npw = st.text_input("Password Baru", type="password")
                npw2 = st.text_input("Konfirmasi Password Baru", type="password")
                submit_reset = st.form_submit_button("Set Password Baru")
            if submit_reset:
                if not npw or len(npw) < 6:
                    st.error("Password minimal 6 karakter.")
                elif npw != npw2:
                    st.error("Konfirmasi password tidak sama.")
                elif not access_token or not refresh_token:
                    st.error("Token pemulihan tidak ditemukan. Coba klik ulang tautan dari email.")
                else:
                    try:
                        supabase.auth.set_session(access_token, refresh_token)
                        supabase.auth.update_user({"password": npw})
                        st.success("Password berhasil diubah. Anda akan diarahkan ke login...")
                        # bersihkan query params setelah reset
                        st.experimental_set_query_params()
                        st.session_state.clear()
                        st.rerun()
                    except Exception as e:
                        st.error(f"Gagal mengubah password: {e}")
            return

        # --- Auth tabs ---
        tab_login, tab_register, tab_forgot = st.tabs(["Login", "Register", "Forgot Password"])

        # LOGIN
        with tab_login:
            with st.form("login_form"):
                email = st.text_input("Email")
                password = st.text_input("Password", type="password")
                submitted = st.form_submit_button("Login")
            if submitted:
                shared_pw = os.getenv("APP_DEMO_PASSWORD")
                if shared_pw and password == shared_pw:
                    st.session_state["user"] = {"id": "demo-user", "email": email or "[email protected]"}
                    st.success("Login demo berhasil")
                    st.rerun()
                try:
                    auth_res = supabase.auth.sign_in_with_password({
                        "email": email,
                        "password": password,
                    })
                    user = getattr(auth_res, "user", None)
                    if user:
                        st.session_state["user"] = {"id": user.id, "email": getattr(user, "email", email)}
                        session_obj = getattr(auth_res, "session", None)
                        if session_obj:
                            st.session_state["sb_session"] = {
                                "access_token": getattr(session_obj, "access_token", None),
                                "refresh_token": getattr(session_obj, "refresh_token", None),
                            }
                        st.success("Login berhasil")
                        st.rerun()
                    else:
                        st.error("Email atau password salah.")
                except Exception as e:
                    st.error(f"Gagal login: {e}")

        # REGISTER
        with tab_register:
            st.caption("Buat akun baru. Anda akan menerima email konfirmasi.")
            with st.form("register_form"):
                r_email = st.text_input("Email", key="reg_email")
                r_password = st.text_input("Password", type="password", key="reg_password")
                r_password2 = st.text_input("Konfirmasi Password", type="password", key="reg_password2")
                submitted_r = st.form_submit_button("Register")
            if submitted_r:
                if r_password != r_password2:
                    st.error("Password tidak sama.")
                else:
                    try:
                        redirect_url = os.getenv(
                            "SUPABASE_EMAIL_REDIRECT",
                            os.getenv("NEXT_PUBLIC_SITE_URL", "https://yozora721-pnp-chatbot-v1.hf.space"),
                        )
                        supabase.auth.sign_up({
                            "email": r_email,
                            "password": r_password,
                            "options": {"email_redirect_to": redirect_url}
                        })
                        st.success("Registrasi berhasil. Silakan cek email untuk konfirmasi.")
                    except Exception as e:
                        st.error(f"Gagal registrasi: {e}")

        # FORGOT PASSWORD
        with tab_forgot:
            st.caption("Kirim tautan reset password ke email Anda.")
            with st.form("forgot_form"):
                f_email = st.text_input("Email", key="forgot_email")
                submitted_f = st.form_submit_button("Kirim Link Reset")
            if submitted_f:
                try:
                    redirect_url = os.getenv(
                        "SUPABASE_EMAIL_REDIRECT",
                        os.getenv("NEXT_PUBLIC_SITE_URL", "https://yozora721-pnp-chatbot-v1.hf.space"),
                    )
                    supabase.auth.reset_password_for_email(f_email, {"redirect_to": redirect_url})
                    st.success("Email reset password telah dikirim. Periksa kotak masuk Anda.")
                except Exception as e:
                    st.error(f"Gagal mengirim email reset password: {e}")