Jon Solow
commited on
Commit
Β·
720467c
1
Parent(s):
7858dd3
Implement a token login system to replace passwords
Browse files- src/login.py +23 -43
- src/shared_page.py +8 -0
src/login.py
CHANGED
@@ -39,67 +39,30 @@ class HFFriendlyGSheetsConnection(GSheetsConnection):
|
|
39 |
conn = st.connection("gsheets", type=HFFriendlyGSheetsConnection)
|
40 |
|
41 |
|
42 |
-
def get_user_id_from_email_if_exists(email: str) -> int:
|
43 |
-
# returns -1 if id not found
|
44 |
-
df_email = conn.read(
|
45 |
-
worksheet="users",
|
46 |
-
usecols=[0, 1],
|
47 |
-
ttl=3600,
|
48 |
-
)
|
49 |
-
df_email = df_email[df_email.email.notna()]
|
50 |
-
for row in df_email.itertuples():
|
51 |
-
if row.email.lower() == email.lower():
|
52 |
-
return row.id
|
53 |
-
return -1
|
54 |
-
|
55 |
-
|
56 |
-
def get_password_from_user_id(user_id: int) -> str | None:
|
57 |
-
try:
|
58 |
-
df_pass = conn.read(
|
59 |
-
worksheet=f"user-{user_id}-password",
|
60 |
-
usecols=[0],
|
61 |
-
ttl=1,
|
62 |
-
)
|
63 |
-
return df_pass.password[0]
|
64 |
-
except Exception:
|
65 |
-
return None
|
66 |
-
|
67 |
-
|
68 |
def check_password():
|
69 |
"""Returns `True` if the user had a correct password."""
|
70 |
|
71 |
def login_form():
|
72 |
"""Form with widgets to collect user information"""
|
73 |
with st.form("Credentials"):
|
74 |
-
st.text_input("
|
75 |
-
st.text_input("Password", type="password", key="password")
|
76 |
st.form_submit_button("Log in", on_click=password_entered)
|
77 |
|
78 |
def password_entered():
|
79 |
"""Checks whether a password entered by the user is correct."""
|
80 |
-
# check if
|
81 |
-
if
|
82 |
-
|
83 |
-
if hmac.compare_digest(
|
84 |
-
st.session_state["password"],
|
85 |
-
password,
|
86 |
-
):
|
87 |
-
st.session_state["password_correct"] = True
|
88 |
-
st.session_state["logged_in_user"] = user_id
|
89 |
-
del st.session_state["password"] # Don't store the email or password.
|
90 |
-
del st.session_state["email"]
|
91 |
-
del password
|
92 |
-
return
|
93 |
st.session_state["password_correct"] = False
|
94 |
|
95 |
-
# Return True if the
|
96 |
if st.session_state.get("password_correct", False):
|
97 |
return True
|
98 |
|
99 |
# Show inputs for email + password.
|
100 |
login_form()
|
101 |
if st.session_state.get("password_correct", True) is False:
|
102 |
-
st.error("π
|
103 |
return False
|
104 |
|
105 |
|
@@ -120,3 +83,20 @@ def save_user_team(team_selections):
|
|
120 |
worksheet=f"user-{user_id}-roster",
|
121 |
data=pd.DataFrame(team_selections, index=[0]),
|
122 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
conn = st.connection("gsheets", type=HFFriendlyGSheetsConnection)
|
40 |
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
def check_password():
|
43 |
"""Returns `True` if the user had a correct password."""
|
44 |
|
45 |
def login_form():
|
46 |
"""Form with widgets to collect user information"""
|
47 |
with st.form("Credentials"):
|
48 |
+
st.text_input("Login token", type="password", key="password")
|
|
|
49 |
st.form_submit_button("Log in", on_click=password_entered)
|
50 |
|
51 |
def password_entered():
|
52 |
"""Checks whether a password entered by the user is correct."""
|
53 |
+
# check if token exists
|
54 |
+
if login_by_token(st.session_state["password"]):
|
55 |
+
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
st.session_state["password_correct"] = False
|
57 |
|
58 |
+
# Return True if the token is validated.
|
59 |
if st.session_state.get("password_correct", False):
|
60 |
return True
|
61 |
|
62 |
# Show inputs for email + password.
|
63 |
login_form()
|
64 |
if st.session_state.get("password_correct", True) is False:
|
65 |
+
st.error("π Token incorrect")
|
66 |
return False
|
67 |
|
68 |
|
|
|
83 |
worksheet=f"user-{user_id}-roster",
|
84 |
data=pd.DataFrame(team_selections, index=[0]),
|
85 |
)
|
86 |
+
|
87 |
+
|
88 |
+
def login_by_token(token: str):
|
89 |
+
# returns true if logged in successfully
|
90 |
+
df = conn.read(
|
91 |
+
worksheet="user-tokens",
|
92 |
+
usecols=[0, 1],
|
93 |
+
ttl=3600,
|
94 |
+
)
|
95 |
+
df = df[df.token.notna()]
|
96 |
+
for row in df.itertuples():
|
97 |
+
if hmac.compare_digest(row.token, token):
|
98 |
+
user_id = int(row.id)
|
99 |
+
st.session_state["password_correct"] = True
|
100 |
+
st.session_state["logged_in_user"] = user_id
|
101 |
+
return True
|
102 |
+
return False
|
src/shared_page.py
CHANGED
@@ -2,6 +2,7 @@ import os
|
|
2 |
import streamlit as st
|
3 |
|
4 |
from queries.nflverse.github_data import load_assets_if_no_tables
|
|
|
5 |
|
6 |
|
7 |
def get_local_style():
|
@@ -15,6 +16,13 @@ def local_css():
|
|
15 |
return st.markdown(get_local_style(), unsafe_allow_html=True)
|
16 |
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
def common_page_config():
|
19 |
local_css()
|
20 |
load_assets_if_no_tables()
|
|
|
|
2 |
import streamlit as st
|
3 |
|
4 |
from queries.nflverse.github_data import load_assets_if_no_tables
|
5 |
+
from login import login_by_token
|
6 |
|
7 |
|
8 |
def get_local_style():
|
|
|
16 |
return st.markdown(get_local_style(), unsafe_allow_html=True)
|
17 |
|
18 |
|
19 |
+
def login_token_arg_if_exists():
|
20 |
+
url_params = st.experimental_get_query_params()
|
21 |
+
if arg_token_list := url_params.get("token"):
|
22 |
+
login_by_token(arg_token_list[0])
|
23 |
+
|
24 |
+
|
25 |
def common_page_config():
|
26 |
local_css()
|
27 |
load_assets_if_no_tables()
|
28 |
+
login_token_arg_if_exists()
|