ayushnoori's picture
Initial commit
d4ca2d2
import streamlit as st
# User authentication
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import hmac
# Standard imports
import pandas as pd
# Custom and other imports
import project_config
from menu import menu
# Initialize st.session_state.role to None
if "role" not in st.session_state:
st.session_state.role = None
# 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)
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."""
if project_config.VDI or project_config.LOCAL:
# Read the user database
user_db = pd.read_csv(project_config.AUTH_DIR / "crd_user_db.csv")
else:
# 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)
# 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"] = st.session_state["username"]
# Don't store the password
del st.session_state["password"]
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")