import hmac import streamlit as st from streamlit_gsheets import GSheetsConnection conn = st.connection("gsheets", type=GSheetsConnection) def get_user_id_from_email_if_exists(email: str) -> int: # returns -1 if id not found df_email = conn.read( worksheet="users", usecols=[0, 1], ) df_email = df_email[df_email.email.notna()] for row in df_email.itertuples(): if row.email.lower() == email.lower(): return row.id return -1 def get_password_from_user_id(user_id: int) -> str | None: try: df_pass = conn.read( worksheet=f"user-{user_id}", usecols=[0], ) return df_pass.password[0] except Exception: return None def check_password(): """Returns `True` if the user had a correct password.""" def login_form(): """Form with widgets to collect user information""" with st.form("Credentials"): st.text_input("Email", key="email") st.text_input("Password", type="password", key="password") st.form_submit_button("Log in", on_click=password_entered) def password_entered(): """Checks whether a password entered by the user is correct.""" # check if email exists if user_id := get_user_id_from_email_if_exists(st.session_state["email"]): if password := get_password_from_user_id(user_id): if hmac.compare_digest( st.session_state["password"], password, ): st.session_state["password_correct"] = True del st.session_state["password"] # Don't store the email or password. del st.session_state["email"] del password return st.session_state["password_correct"] = False # Return True if the email + password is validated. if st.session_state.get("password_correct", False): return True # Show inputs for email + password. login_form() if st.session_state.get("password_correct", True) is False: st.error("😕 User not known or password incorrect") return False