File size: 9,376 Bytes
daa81fb
 
 
 
b17b0dd
daa81fb
 
 
 
486c2a9
daa81fb
 
245e2db
daa81fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba4a352
5b8619b
b17b0dd
 
 
 
 
4119d3c
 
 
b17b0dd
 
 
 
 
 
 
 
 
 
5b8619b
b17b0dd
ba4a352
 
5b8619b
 
 
b17b0dd
 
 
 
5b8619b
 
 
 
 
 
 
 
 
 
 
 
b17b0dd
 
 
 
 
 
5dd6e15
245e2db
 
 
 
 
 
 
1b6f6c4
245e2db
0a5edbb
245e2db
 
 
 
 
 
 
0a5edbb
245e2db
1b6f6c4
245e2db
1b6f6c4
245e2db
 
0a5edbb
 
ba4a352
245e2db
 
ba4a352
 
 
 
 
 
 
 
 
 
 
 
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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
        )

        # --- Auto convert hash (#) to query (?) using streamlit-url-fragment ---
        fragment_detected = False
        try:
            from streamlit_url_fragment import get_fragment
            fragment = get_fragment()
            
            if fragment and not st.session_state.get("hash_migrated"):
                # Remove leading # if present and parse fragment parameters
                clean_fragment = fragment.lstrip('#')
                params = dict(parse_qsl(clean_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
                    fragment_detected = True
                    st.rerun()
        except Exception:
            pass
        
        # Always run JS fallback for reliability
        if not fragment_detected:
            st.markdown(
                """
                <script>
                (function() {
                    try {
                        const hash = window.location.hash;
                        console.log('DEBUG: Hash found:', 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();
                        }
                    } catch (e) {
                        console.error('Hash migration error:', e);
                    }
                })();
                </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:
                        # Set session temporarily to update password
                        supabase.auth.set_session(access_token, refresh_token)
                        supabase.auth.update_user({"password": npw})
                        
                        # Sign out after password update
                        supabase.auth.sign_out()
                        
                        st.success("Password berhasil diubah. Silakan login dengan password baru.")
                        
                        # Clear session and query params
                        if hasattr(st, "query_params"):
                            st.query_params.clear()
                        else:
                            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 "demo@example.com"}
                    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}")