import streamlit as st # Do not load st-gsheets-connection # from streamlit_gsheets import GSheetsConnection import gspread from oauth2client.service_account import ServiceAccountCredentials import hmac # Standard imports import pandas as pd # Custom and other imports import project_config # from utils import add_logo from menu import menu # Insert logo # add_logo(project_config.MEDIA_DIR / 'gravity_logo.png') # Initialize st.session_state.role to None if "role" not in st.session_state: st.session_state.role = None # # Retrieve the role from Session State to initialize the widget # st.session_state._role = st.session_state.role # def set_role(): # # Callback function to save the role selection to Session State # st.session_state.role = st.session_state._role # From https://stackoverflow.com/questions/55961295/serviceaccountcredentials-from-json-keyfile-name-equivalent-for-remote-json # See also https://www.slingacademy.com/article/pandas-how-to-read-and-update-google-sheet-files/ # See also https://docs.streamlit.io/develop/tutorials/databases/private-gsheet # Note that the secrets cannot be passed in a group in HuggingFace Spaces, # which is required for the native Streamlit implementation def create_keyfile_dict(): variables_keys = { # "spreadsheet": st.secrets['spreadsheet'], # spreadsheet "type": st.secrets['type'], # type "project_id": st.secrets['project_id'], # project_id "private_key_id": st.secrets['private_key_id'], # private_key_id # Have to replace \n with new lines (^l in Word) by hand "private_key": st.secrets['private_key'], # private_key "client_email": st.secrets['client_email'], # client_email "client_id": st.secrets['client_id'], # client_id "auth_uri": st.secrets['auth_uri'], # auth_uri "token_uri": st.secrets['token_uri'], # token_uri "auth_provider_x509_cert_url": st.secrets['auth_provider_x509_cert_url'], # auth_provider_x509_cert_url "client_x509_cert_url": st.secrets['client_x509_cert_url'], # client_x509_cert_url "universe_domain": st.secrets['universe_domain'] # universe_domain } return variables_keys def check_password(): """Returns `True` if the user had a correct password.""" def login_form(): """Form with widgets to collect user information""" # Header col1, col2, col3 = st.columns(3) with col2: st.image(str(project_config.MEDIA_DIR / 'gravity_logo.svg'), width=300) # col1, col2, col3 = st.columns(3) # with col1: # st.header("Log In") with st.form("Credentials"): st.text_input("Username", key="username") 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.""" # Define the scope scope = [ 'https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive' ] # Add credentials to the account creds = ServiceAccountCredentials.from_json_keyfile_dict(create_keyfile_dict(), scope) # Authenticate and create the client client = gspread.authorize(creds) # Open the spreadsheet sheet = client.open_by_url(st.secrets['spreadsheet']).worksheet("user_db") data = sheet.get_all_records() user_db = pd.DataFrame(data) # # Create a connection object to Google Sheets # conn = st.connection("gsheets", type=GSheetsConnection) # # Read the user database # user_db = conn.read() # user_db.dropna(axis=0, how="all", inplace=True) # user_db.dropna(axis=1, how="all", inplace=True) # Check if the username is in the database if st.session_state["username"] in user_db.username.values: st.session_state["username_correct"] = True # Check if the password is correct if hmac.compare_digest( st.session_state["password"], user_db.loc[user_db.username == st.session_state["username"], "password"].values[0], ): st.session_state["password_correct"] = True # Check if the username is an admin if st.session_state["username"] in user_db[user_db.role == "admin"].username.values: st.session_state["role"] = "admin" else: st.session_state["role"] = "user" # Retrieve and store user name and team st.session_state["name"] = user_db.loc[user_db.username == st.session_state["username"], "name"].values[0] st.session_state["team"] = user_db.loc[user_db.username == st.session_state["username"], "team"].values[0] # st.session_state["profile_pic"] = user_db.loc[user_db.username == st.session_state["username"], "profile_pic"].values[0] st.session_state["profile_pic"] = st.session_state["username"] # Don't store the username or password del st.session_state["password"] # del st.session_state["username"] else: st.session_state["password_correct"] = False else: st.session_state["username_correct"] = False st.session_state["password_correct"] = False # Return True if the username + password is validated if st.session_state.get("password_correct", False): return True # Show inputs for username + password login_form() if "password_correct" in st.session_state: if not st.session_state["username_correct"]: st.error("User not found.") elif not st.session_state["password_correct"]: st.error("The password you entered is incorrect.") else: st.error("An unexpected error occurred.") return False menu() # Render the dynamic menu! if not check_password(): st.stop() st.switch_page("pages/about.py")