pnp-chatbot-v1 / pages /reset_password.py
FauziIsyrinApridal
..
4d7e1af
raw
history blame
6.14 kB
import os
import base64
import streamlit as st
from app.db import supabase
def main():
"""Dedicated reset password page."""
st.set_page_config(
page_title="Reset Password - PNP Bot",
page_icon="assets/favicon.ico",
initial_sidebar_state="collapsed",
)
# Hide sidebar and hamburger completely
st.markdown(
"""
<style>
[data-testid="stSidebar"] { display: none !important; }
[data-testid="collapsedControl"] { display: none !important; }
</style>
""",
unsafe_allow_html=True,
)
# Center the content
left, center, right = st.columns([1, 2, 1])
with center:
# Header with logo
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;">Reset Password</h1>
<p style="color: #666; margin-bottom: 2rem;">Masukkan password baru Anda</p>
</div>
""",
unsafe_allow_html=True
)
# Get query parameters for recovery tokens
try:
qp = st.query_params # Streamlit >= 1.30
get_q = lambda k: qp.get(k, None)
except Exception:
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, None))
access_token = get_q("access_token")
refresh_token = get_q("refresh_token")
q_type = get_q("type")
# Validate that this is a recovery request
if q_type != "recovery" or not access_token or not refresh_token:
st.error("⚠️ Link reset password tidak valid atau sudah kedaluwarsa.")
st.info("Silakan kembali ke halaman login dan minta link reset password yang baru.")
if st.button("← Kembali ke Login", type="primary"):
# Redirect to root (main app)
st.markdown(
"""
<script>
window.location.href = window.location.origin +
(window.location.pathname.replace(/\/?pages\/?reset_password\/?$/,'/') || '/');
</script>
""",
unsafe_allow_html=True,
)
return
# Reset password form
with st.form("reset_password_form", clear_on_submit=False):
st.markdown("### πŸ” Password Baru")
new_password = st.text_input(
"Password Baru",
type="password",
placeholder="Minimal 6 karakter",
help="Password harus minimal 6 karakter"
)
confirm_password = st.text_input(
"Konfirmasi Password Baru",
type="password",
placeholder="Ulangi password baru"
)
col1, col2 = st.columns([1, 1])
with col1:
submit_reset = st.form_submit_button("πŸ”„ Update Password", type="primary", use_container_width=True)
with col2:
cancel_reset = st.form_submit_button("❌ Batal", use_container_width=True)
if cancel_reset:
st.markdown(
"""
<script>
window.location.href = window.location.origin +
(window.location.pathname.replace(/\/?pages\/?reset_password\/?$/,'/') || '/');
</script>
""",
unsafe_allow_html=True,
)
if submit_reset:
# Validation
if not new_password:
st.error("❌ Password tidak boleh kosong.")
return
if len(new_password) < 6:
st.error("❌ Password minimal 6 karakter.")
return
if new_password != confirm_password:
st.error("❌ Konfirmasi password tidak sama.")
return
# Update password
try:
with st.spinner("Mengupdate password..."):
# Set current session using tokens from redirect
supabase.auth.set_session(access_token, refresh_token)
# Update user password
result = supabase.auth.update_user({"password": new_password})
if result:
st.success("βœ… Password berhasil diubah!")
st.info("Silakan login dengan password baru Anda.")
# Show countdown and auto-redirect to main app
st.markdown(
"""
<script>
setTimeout(function(){
window.location.href = window.location.origin +
(window.location.pathname.replace(/\/?pages\/?reset_password\/?$/,'/') || '/');
}, 1500);
</script>
""",
unsafe_allow_html=True,
)
st.caption("Mengalihkan ke halaman login...")
else:
st.error("❌ Gagal mengubah password. Silakan coba lagi.")
except Exception as e:
st.error(f"❌ Gagal mengubah password: {str(e)}")
st.info("Link mungkin sudah kedaluwarsa. Silakan minta link reset password yang baru.")
if __name__ == "__main__":
main()