Jon Solow
commited on
Commit
·
050fd9f
1
Parent(s):
f66425a
Get a client per session to help with expiry
Browse files- src/data_storage.py +15 -25
- src/login.py +7 -7
- src/pages/10_Set_Your_Lineup.py +2 -2
- src/pages/11_Scoreboard.py +2 -2
- src/pages/99_Admin.py +5 -3
- src/queries/supabase_db/client.py +3 -1
- src/shared_page.py +9 -1
src/data_storage.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1 |
-
from postgrest.exceptions import APIError
|
2 |
from secrets import token_urlsafe
|
3 |
import streamlit as st
|
4 |
-
import time
|
5 |
|
6 |
-
from
|
7 |
|
8 |
|
9 |
USERS_TABLE = "npcs_users"
|
@@ -11,15 +9,7 @@ USER_ROSTERS_TABLE = "npcs_user_rosters"
|
|
11 |
TOKENS_TABLE = "npcs_tokens"
|
12 |
|
13 |
|
14 |
-
|
15 |
-
user_count = supabase_client.table(USERS_TABLE).select("*", count="exact").execute().count
|
16 |
-
except APIError:
|
17 |
-
# automatic retry
|
18 |
-
time.sleep(0.5)
|
19 |
-
user_count = supabase_client.table(USERS_TABLE).select("*", count="exact").execute().count
|
20 |
-
|
21 |
-
|
22 |
-
def update_selection(user_id: str | int, position_id: str, player_id: str):
|
23 |
existing_record = (
|
24 |
supabase_client.table(USER_ROSTERS_TABLE)
|
25 |
.select("*")
|
@@ -42,7 +32,7 @@ def update_selection(user_id: str | int, position_id: str, player_id: str):
|
|
42 |
)
|
43 |
|
44 |
|
45 |
-
def get_user_team(user_id):
|
46 |
team = (
|
47 |
supabase_client.table(USER_ROSTERS_TABLE)
|
48 |
.select("position_id", "player_id")
|
@@ -56,11 +46,11 @@ def get_user_team(user_id):
|
|
56 |
return {}
|
57 |
|
58 |
|
59 |
-
def add_new_user(email: str, name: str):
|
60 |
(supabase_client.table(USERS_TABLE).insert({"email": email.lower(), "name": name}).execute())
|
61 |
|
62 |
|
63 |
-
def get_user(user_id: int):
|
64 |
user_data = (
|
65 |
supabase_client.table("npcs_users").select("user_id", "email", "name").eq("user_id", user_id).execute().data
|
66 |
)
|
@@ -69,7 +59,7 @@ def get_user(user_id: int):
|
|
69 |
return user_data[0]
|
70 |
|
71 |
|
72 |
-
def get_user_id_if_email_exists(email: str) -> int | None:
|
73 |
query_result = supabase_client.table(USERS_TABLE).select("user_id").eq("email", email.lower()).execute().data
|
74 |
if query_result:
|
75 |
user_id = query_result[0]["user_id"]
|
@@ -78,7 +68,7 @@ def get_user_id_if_email_exists(email: str) -> int | None:
|
|
78 |
return user_id
|
79 |
|
80 |
|
81 |
-
def is_admin(user_id: int | None):
|
82 |
if user_id is None:
|
83 |
return False
|
84 |
query_result = supabase_client.table(USERS_TABLE).select("admin").eq("user_id", user_id).execute().data
|
@@ -87,7 +77,7 @@ def is_admin(user_id: int | None):
|
|
87 |
return False
|
88 |
|
89 |
|
90 |
-
def login_by_token(token: str):
|
91 |
# returns true if logged in successfully
|
92 |
query_result = supabase_client.table(TOKENS_TABLE).select("user_id").eq("token", token).execute().data
|
93 |
if query_result:
|
@@ -98,24 +88,24 @@ def login_by_token(token: str):
|
|
98 |
return user_id
|
99 |
|
100 |
|
101 |
-
def create_new_token_for_user(user_id: int, existing_user: bool = False):
|
102 |
# returns true if logged in successfully
|
103 |
token = token_urlsafe(32)
|
104 |
supabase_client.table(TOKENS_TABLE).upsert({"user_id": user_id, "token": token}).execute()
|
105 |
return token
|
106 |
|
107 |
|
108 |
-
def get_all_users(columns_included: list[str] = ["user_id", "name", "email"]):
|
109 |
all_users = supabase_client.table(USERS_TABLE).select(*columns_included).execute().data
|
110 |
return all_users
|
111 |
|
112 |
|
113 |
-
def get_all_rosters() -> list[dict[str, int | str]]:
|
114 |
all_rosters = supabase_client.table(USER_ROSTERS_TABLE).select("user_id", "position_id", "player_id").execute().data
|
115 |
return all_rosters
|
116 |
|
117 |
|
118 |
-
def get_all_rosters_week(week: int) -> list[dict[str, int | str]]:
|
119 |
week_rosters = (
|
120 |
supabase_client.table(USER_ROSTERS_TABLE)
|
121 |
.select("user_id", "position_id", "player_id")
|
@@ -126,14 +116,14 @@ def get_all_rosters_week(week: int) -> list[dict[str, int | str]]:
|
|
126 |
return week_rosters
|
127 |
|
128 |
|
129 |
-
def migrate_players_from_week(migrate_from_week: int):
|
130 |
"""
|
131 |
Migrate players from the week = migrate_from_week to the week = migrate_from_week + 1
|
132 |
"""
|
133 |
-
rosters = get_all_rosters_week(migrate_from_week)
|
134 |
for roster_slot_map in rosters:
|
135 |
position_id = str(roster_slot_map["position_id"])
|
136 |
player_id = str(roster_slot_map["player_id"])
|
137 |
user_id = int(roster_slot_map["user_id"])
|
138 |
new_position_id = f"""{migrate_from_week + 1}-{position_id.split("-", 1)[1]}"""
|
139 |
-
update_selection(user_id, new_position_id, player_id)
|
|
|
|
|
1 |
from secrets import token_urlsafe
|
2 |
import streamlit as st
|
|
|
3 |
|
4 |
+
from supabase import Client
|
5 |
|
6 |
|
7 |
USERS_TABLE = "npcs_users"
|
|
|
9 |
TOKENS_TABLE = "npcs_tokens"
|
10 |
|
11 |
|
12 |
+
def update_selection(user_id: str | int, position_id: str, player_id: str, supabase_client: Client):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
existing_record = (
|
14 |
supabase_client.table(USER_ROSTERS_TABLE)
|
15 |
.select("*")
|
|
|
32 |
)
|
33 |
|
34 |
|
35 |
+
def get_user_team(user_id, supabase_client: Client):
|
36 |
team = (
|
37 |
supabase_client.table(USER_ROSTERS_TABLE)
|
38 |
.select("position_id", "player_id")
|
|
|
46 |
return {}
|
47 |
|
48 |
|
49 |
+
def add_new_user(email: str, name: str, supabase_client: Client):
|
50 |
(supabase_client.table(USERS_TABLE).insert({"email": email.lower(), "name": name}).execute())
|
51 |
|
52 |
|
53 |
+
def get_user(user_id: int, supabase_client: Client):
|
54 |
user_data = (
|
55 |
supabase_client.table("npcs_users").select("user_id", "email", "name").eq("user_id", user_id).execute().data
|
56 |
)
|
|
|
59 |
return user_data[0]
|
60 |
|
61 |
|
62 |
+
def get_user_id_if_email_exists(email: str, supabase_client: Client) -> int | None:
|
63 |
query_result = supabase_client.table(USERS_TABLE).select("user_id").eq("email", email.lower()).execute().data
|
64 |
if query_result:
|
65 |
user_id = query_result[0]["user_id"]
|
|
|
68 |
return user_id
|
69 |
|
70 |
|
71 |
+
def is_admin(user_id: int | None, supabase_client: Client):
|
72 |
if user_id is None:
|
73 |
return False
|
74 |
query_result = supabase_client.table(USERS_TABLE).select("admin").eq("user_id", user_id).execute().data
|
|
|
77 |
return False
|
78 |
|
79 |
|
80 |
+
def login_by_token(token: str, supabase_client: Client):
|
81 |
# returns true if logged in successfully
|
82 |
query_result = supabase_client.table(TOKENS_TABLE).select("user_id").eq("token", token).execute().data
|
83 |
if query_result:
|
|
|
88 |
return user_id
|
89 |
|
90 |
|
91 |
+
def create_new_token_for_user(user_id: int, supabase_client: Client, existing_user: bool = False):
|
92 |
# returns true if logged in successfully
|
93 |
token = token_urlsafe(32)
|
94 |
supabase_client.table(TOKENS_TABLE).upsert({"user_id": user_id, "token": token}).execute()
|
95 |
return token
|
96 |
|
97 |
|
98 |
+
def get_all_users(supabase_client: Client, columns_included: list[str] = ["user_id", "name", "email"]):
|
99 |
all_users = supabase_client.table(USERS_TABLE).select(*columns_included).execute().data
|
100 |
return all_users
|
101 |
|
102 |
|
103 |
+
def get_all_rosters(supabase_client: Client) -> list[dict[str, int | str]]:
|
104 |
all_rosters = supabase_client.table(USER_ROSTERS_TABLE).select("user_id", "position_id", "player_id").execute().data
|
105 |
return all_rosters
|
106 |
|
107 |
|
108 |
+
def get_all_rosters_week(week: int, supabase_client: Client) -> list[dict[str, int | str]]:
|
109 |
week_rosters = (
|
110 |
supabase_client.table(USER_ROSTERS_TABLE)
|
111 |
.select("user_id", "position_id", "player_id")
|
|
|
116 |
return week_rosters
|
117 |
|
118 |
|
119 |
+
def migrate_players_from_week(migrate_from_week: int, supabase_client: Client):
|
120 |
"""
|
121 |
Migrate players from the week = migrate_from_week to the week = migrate_from_week + 1
|
122 |
"""
|
123 |
+
rosters = get_all_rosters_week(migrate_from_week, supabase_client)
|
124 |
for roster_slot_map in rosters:
|
125 |
position_id = str(roster_slot_map["position_id"])
|
126 |
player_id = str(roster_slot_map["player_id"])
|
127 |
user_id = int(roster_slot_map["user_id"])
|
128 |
new_position_id = f"""{migrate_from_week + 1}-{position_id.split("-", 1)[1]}"""
|
129 |
+
update_selection(user_id, new_position_id, player_id, supabase_client)
|
src/login.py
CHANGED
@@ -82,10 +82,10 @@ def generate_new_token_request():
|
|
82 |
if not check_email(email := st.session_state["reset_token_user_email"]):
|
83 |
st.warning("Sorry email is invalid. Please try a valid email address.")
|
84 |
return
|
85 |
-
user_id = get_user_id_if_email_exists(email)
|
86 |
if not user_id:
|
87 |
return
|
88 |
-
token = create_new_token_for_user(user_id, existing_user=True)
|
89 |
insert_new_token_to_sheet(email, token)
|
90 |
|
91 |
st.info("Request submitted. Please check your email for a login url with a few minutes.")
|
@@ -106,10 +106,10 @@ def insert_new_token_to_sheet(email: str, token: str):
|
|
106 |
|
107 |
|
108 |
def create_new_user_request(email: str, name: str):
|
109 |
-
add_new_user(email, name)
|
110 |
-
user_id = get_user_id_if_email_exists(email)
|
111 |
assert user_id
|
112 |
-
token = create_new_token_for_user(user_id)
|
113 |
insert_new_token_to_sheet(email, token)
|
114 |
st.info("New user request submitted. Please check your email for a login url with a few minutes.")
|
115 |
|
@@ -123,7 +123,7 @@ def new_user_submitted():
|
|
123 |
st.warning("No name entered. Please enter your name for display.")
|
124 |
return
|
125 |
|
126 |
-
if get_user_id_if_email_exists(email):
|
127 |
st.warning(
|
128 |
"User with that email already exists. If you would like a new login url, please click the New Login URL button."
|
129 |
)
|
@@ -149,7 +149,7 @@ def get_logged_in_user_name_email() -> tuple[str | None, str | None]:
|
|
149 |
# if not logged
|
150 |
return (None, None)
|
151 |
|
152 |
-
user_info_map = get_user(user_id)
|
153 |
email = user_info_map.get("email")
|
154 |
name = user_info_map.get("name")
|
155 |
return email, name
|
|
|
82 |
if not check_email(email := st.session_state["reset_token_user_email"]):
|
83 |
st.warning("Sorry email is invalid. Please try a valid email address.")
|
84 |
return
|
85 |
+
user_id = get_user_id_if_email_exists(email, st.session_state["db_client"])
|
86 |
if not user_id:
|
87 |
return
|
88 |
+
token = create_new_token_for_user(user_id, st.session_state["db_client"], existing_user=True)
|
89 |
insert_new_token_to_sheet(email, token)
|
90 |
|
91 |
st.info("Request submitted. Please check your email for a login url with a few minutes.")
|
|
|
106 |
|
107 |
|
108 |
def create_new_user_request(email: str, name: str):
|
109 |
+
add_new_user(email, name, st.session_state["db_client"])
|
110 |
+
user_id = get_user_id_if_email_exists(email, st.session_state["db_client"])
|
111 |
assert user_id
|
112 |
+
token = create_new_token_for_user(user_id, st.session_state["db_client"])
|
113 |
insert_new_token_to_sheet(email, token)
|
114 |
st.info("New user request submitted. Please check your email for a login url with a few minutes.")
|
115 |
|
|
|
123 |
st.warning("No name entered. Please enter your name for display.")
|
124 |
return
|
125 |
|
126 |
+
if get_user_id_if_email_exists(email, st.session_state["db_client"]):
|
127 |
st.warning(
|
128 |
"User with that email already exists. If you would like a new login url, please click the New Login URL button."
|
129 |
)
|
|
|
149 |
# if not logged
|
150 |
return (None, None)
|
151 |
|
152 |
+
user_info_map = get_user(user_id, st.session_state["db_client"])
|
153 |
email = user_info_map.get("email")
|
154 |
name = user_info_map.get("name")
|
155 |
return email, name
|
src/pages/10_Set_Your_Lineup.py
CHANGED
@@ -96,7 +96,7 @@ def position_cell(
|
|
96 |
|
97 |
|
98 |
def update_and_save_selection(pos_label: str, selection_id: str):
|
99 |
-
update_selection(st.session_state["logged_in_user"], pos_label, selection_id)
|
100 |
st.rerun()
|
101 |
|
102 |
|
@@ -140,7 +140,7 @@ def get_page():
|
|
140 |
if st.button("Refresh Data"):
|
141 |
st.rerun()
|
142 |
try:
|
143 |
-
existing_selections = get_user_team(st.session_state["logged_in_user"])
|
144 |
except Exception:
|
145 |
st.write("Sorry error occurred loading team. Please try refreshing page.")
|
146 |
st.stop()
|
|
|
96 |
|
97 |
|
98 |
def update_and_save_selection(pos_label: str, selection_id: str):
|
99 |
+
update_selection(st.session_state["logged_in_user"], pos_label, selection_id, st.session_state["db_client"])
|
100 |
st.rerun()
|
101 |
|
102 |
|
|
|
140 |
if st.button("Refresh Data"):
|
141 |
st.rerun()
|
142 |
try:
|
143 |
+
existing_selections = get_user_team(st.session_state["logged_in_user"], st.session_state["db_client"])
|
144 |
except Exception:
|
145 |
st.write("Sorry error occurred loading team. Please try refreshing page.")
|
146 |
st.stop()
|
src/pages/11_Scoreboard.py
CHANGED
@@ -16,7 +16,7 @@ from stats import get_scores_map
|
|
16 |
|
17 |
def get_users_df():
|
18 |
columns = ["user_id", "name"]
|
19 |
-
all_users = pd.DataFrame(get_all_users(columns_included=columns), columns=columns)
|
20 |
return all_users
|
21 |
|
22 |
|
@@ -24,7 +24,7 @@ def get_users_df():
|
|
24 |
def load_masked_rosters() -> dict[int, dict[str, PlayerOption]]:
|
25 |
options_map = get_map_week_player_id_option()
|
26 |
roster_user_position_map: dict[int, dict[str, PlayerOption]] = {}
|
27 |
-
for roster_slot_map in get_all_rosters():
|
28 |
position_id = str(roster_slot_map["position_id"])
|
29 |
player_id = str(roster_slot_map["player_id"])
|
30 |
user_id = int(roster_slot_map["user_id"])
|
|
|
16 |
|
17 |
def get_users_df():
|
18 |
columns = ["user_id", "name"]
|
19 |
+
all_users = pd.DataFrame(get_all_users(st.session_state["db_client"], columns_included=columns), columns=columns)
|
20 |
return all_users
|
21 |
|
22 |
|
|
|
24 |
def load_masked_rosters() -> dict[int, dict[str, PlayerOption]]:
|
25 |
options_map = get_map_week_player_id_option()
|
26 |
roster_user_position_map: dict[int, dict[str, PlayerOption]] = {}
|
27 |
+
for roster_slot_map in get_all_rosters(st.session_state["db_client"]):
|
28 |
position_id = str(roster_slot_map["position_id"])
|
29 |
player_id = str(roster_slot_map["player_id"])
|
30 |
user_id = int(roster_slot_map["user_id"])
|
src/pages/99_Admin.py
CHANGED
@@ -7,7 +7,9 @@ from data_storage import add_new_user, is_admin, migrate_players_from_week
|
|
7 |
|
8 |
|
9 |
def admin_add_new_user():
|
10 |
-
add_new_user(
|
|
|
|
|
11 |
|
12 |
|
13 |
def admin_add_new_user_form():
|
@@ -27,7 +29,7 @@ def migrate_players_week():
|
|
27 |
st.text_input("Enter week to confirm", key="week_migrate_from")
|
28 |
if st.button("Migrate Week"):
|
29 |
if st.session_state.get("week_migrate_from") == str(week_migrate_from):
|
30 |
-
migrate_players_from_week(week_migrate_from)
|
31 |
st.warning("Week migrated")
|
32 |
else:
|
33 |
st.warning("Must confirm migration by entering matching week")
|
@@ -37,7 +39,7 @@ def get_page():
|
|
37 |
page_title = "Admin"
|
38 |
st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide")
|
39 |
common_page_config()
|
40 |
-
if not is_admin(st.session_state.get("logged_in_user")):
|
41 |
st.write("Not authorized")
|
42 |
st.stop()
|
43 |
|
|
|
7 |
|
8 |
|
9 |
def admin_add_new_user():
|
10 |
+
add_new_user(
|
11 |
+
st.session_state["admin_new_user_email"], st.session_state["admin_new_user_name"], st.session_state["db_client"]
|
12 |
+
)
|
13 |
|
14 |
|
15 |
def admin_add_new_user_form():
|
|
|
29 |
st.text_input("Enter week to confirm", key="week_migrate_from")
|
30 |
if st.button("Migrate Week"):
|
31 |
if st.session_state.get("week_migrate_from") == str(week_migrate_from):
|
32 |
+
migrate_players_from_week(week_migrate_from, st.session_state["db_client"])
|
33 |
st.warning("Week migrated")
|
34 |
else:
|
35 |
st.warning("Must confirm migration by entering matching week")
|
|
|
39 |
page_title = "Admin"
|
40 |
st.set_page_config(page_title=page_title, page_icon=DEFAULT_ICON, layout="wide")
|
41 |
common_page_config()
|
42 |
+
if not is_admin(st.session_state.get("logged_in_user"), st.session_state["db_client"]):
|
43 |
st.write("Not authorized")
|
44 |
st.stop()
|
45 |
|
src/queries/supabase_db/client.py
CHANGED
@@ -5,4 +5,6 @@ from supabase import create_client, Client
|
|
5 |
url: str = str(os.environ.get("SUPABASE_URL"))
|
6 |
key: str = str(os.environ.get("SUPABASE_KEY"))
|
7 |
|
8 |
-
|
|
|
|
|
|
5 |
url: str = str(os.environ.get("SUPABASE_URL"))
|
6 |
key: str = str(os.environ.get("SUPABASE_KEY"))
|
7 |
|
8 |
+
|
9 |
+
def get_new_supabase_client() -> Client:
|
10 |
+
return create_client(url, key)
|
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
|
|
|
5 |
from data_storage import login_by_token
|
6 |
|
7 |
|
@@ -24,13 +25,20 @@ def login_token_arg_if_exists():
|
|
24 |
url_params = st.query_params
|
25 |
if arg_token := url_params.get("token"):
|
26 |
try:
|
27 |
-
login_by_token(arg_token)
|
28 |
except Exception:
|
29 |
st.write("Sorry, error logging in. Please refresh to try again.")
|
30 |
st.stop()
|
31 |
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
def common_page_config():
|
34 |
local_css()
|
35 |
load_assets()
|
|
|
36 |
login_token_arg_if_exists()
|
|
|
2 |
import streamlit as st
|
3 |
|
4 |
from queries.nflverse.github_data import load_assets
|
5 |
+
from queries.supabase_db.client import get_new_supabase_client
|
6 |
from data_storage import login_by_token
|
7 |
|
8 |
|
|
|
25 |
url_params = st.query_params
|
26 |
if arg_token := url_params.get("token"):
|
27 |
try:
|
28 |
+
login_by_token(arg_token, st.session_state["db_client"])
|
29 |
except Exception:
|
30 |
st.write("Sorry, error logging in. Please refresh to try again.")
|
31 |
st.stop()
|
32 |
|
33 |
|
34 |
+
def set_session_db_client():
|
35 |
+
session_db_key = "db_client"
|
36 |
+
if not st.session_state.get(session_db_key):
|
37 |
+
st.session_state[session_db_key] = get_new_supabase_client()
|
38 |
+
|
39 |
+
|
40 |
def common_page_config():
|
41 |
local_css()
|
42 |
load_assets()
|
43 |
+
set_session_db_client()
|
44 |
login_token_arg_if_exists()
|