Spaces:
Sleeping
Sleeping
| 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 | |
| # 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 / 'cipher_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") |