-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
200 lines (166 loc) · 8.63 KB
/
app.py
File metadata and controls
200 lines (166 loc) · 8.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
"""
Main entry point for the Expense Tracker application.
Handles login, signup, forgot password, and main navigation for the application.
This file serves as the landing page and manages user authentication state.
"""
import streamlit as st
import json
from auth import signup, logout, initialize_session_state, login, reset_password, hash_password, load_users, save_users, hash_answer, check_password
from utils import load_user_data, save_user_data, get_transactions
st.set_page_config(page_title="Expense Tracker", page_icon="💰", layout="wide")
st.title("💼 Welcome to Expense Tracker")
st.markdown("Easily track your income, expenses, and more.")
# Initialize session state
initialize_session_state()
def forgot_password():
st.subheader("Forgot Password")
# Initialize session state variables
if "fp_email_verified" not in st.session_state:
st.session_state.fp_email_verified = False
if "fp_verified_user" not in st.session_state:
st.session_state.fp_verified_user = None
# Email entry step
if not st.session_state.fp_email_verified:
email = st.text_input("Enter your email", key="forgot_email").strip()
if st.button("Verify Email", key="verify_email_button"):
users = load_users()
# Check both as direct key and in email field
user_email = None
if email in users:
user_email = email
else:
for username, user in users.items():
if user.get("email") == email:
user_email = username
break
if not user_email:
st.error("Email does not exist.")
return
st.session_state.fp_verified_user = user_email
st.session_state.fp_email_verified = True
st.success("Email verified. Please answer your secret question.")
# Secret question and password reset step
if st.session_state.fp_email_verified and st.session_state.fp_verified_user:
user_email = st.session_state.fp_verified_user
users = load_users()
# Get user data
user_data = users.get(user_email, {})
secret_question = user_data.get("secret_question", "Secret Question")
st.text(f"Your Secret Question: {secret_question}")
secret_answer = st.text_input("Answer Your Secret Question", key="forgot_answer").strip()
# Add warning for capitalization
if secret_answer and not secret_answer.islower():
st.warning("Warning: Your answer contains capital letters. Ensure it matches exactly.")
new_password = st.text_input("Enter New Password", type="password", key="forgot_new_password").strip()
confirm_new_password = st.text_input("Confirm New Password", type="password", key="forgot_confirm_password").strip()
if st.button("Reset Password", key="reset_password_button"):
if hash_answer(secret_answer) != user_data.get("secret_answer"):
st.error("Incorrect answer to the secret question.")
return
if new_password != confirm_new_password:
st.error("Passwords do not match. Please try again.")
return
# Update password in user data
if user_email in users:
users[user_email]["password"] = hash_password(new_password)
save_users(users)
st.success("Password reset successful! You can now log in.")
st.session_state.fp_email_verified = False
st.session_state.fp_verified_user = None
else:
st.error("User not found.")
if not st.session_state.get("authenticated"):
tabs = st.tabs(["Login", "Sign Up", "Forgot Password"])
# Login Tab
with tabs[0]:
login_choice = st.selectbox("Choose Login Type", ["User", "Admin"], key="login_type")
# Add admin credentials info when Admin is selected
if login_choice == "Admin":
st.info("For admin access, use these credentials:\n- Email: admin@example.com\n- Password: Admin@123456\n\nNote: Admin accounts can only log in via Admin login.")
if login(role="admin"):
st.session_state["authenticated"] = True
st.session_state["auth_status"] = True
st.session_state["role"] = "admin"
try:
st.switch_page("pages/admin_panel.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit. Please update Streamlit.")
else:
st.info("Regular user login. Note: Admin accounts must use the Admin login option.")
if login(role="user"):
st.session_state["authenticated"] = True
st.session_state["auth_status"] = True
# Load user's transaction data immediately after login
if "user" in st.session_state:
try:
get_transactions() # This will load data into session state
except Exception as e:
st.warning(f"Could not load your saved data: {e}")
try:
st.switch_page("pages/1_Upload.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit. Please update Streamlit.")
# Signup Tab
with tabs[1]:
signup()
# Forgot Password Tab
with tabs[2]:
forgot_password()
else:
st.success(f"Welcome back, {st.session_state.get('user', 'User')}!")
# Show data persistence status if available
if "transactions" in st.session_state and not st.session_state["transactions"].empty:
st.info(f"🔄 Your data is ready: {len(st.session_state['transactions'])} transactions loaded.")
# Show admin options if user is an admin
if st.session_state.get("role") == "admin":
st.info("🔑 You have administrator privileges.")
col1, col2, col3 = st.columns(3)
with col1:
if st.button("Go to Upload Page", key="go_to_upload"):
try:
st.switch_page("pages/1_Upload.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit.")
with col2:
if st.button("Go to Dashboard", key="go_to_dashboard"):
try:
st.switch_page("pages/2_Dashboard.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit.")
with col3:
if st.button("Go to Admin Panel", key="go_to_admin"):
try:
st.switch_page("pages/admin_panel.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit.")
else:
# Regular user navigation
col1, col2 = st.columns(2)
with col1:
if st.button("Go to Upload Page", key="go_to_upload"):
try:
st.switch_page("pages/1_Upload.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit.")
with col2:
if st.button("Go to Dashboard", key="go_to_dashboard"):
try:
st.switch_page("pages/2_Dashboard.py")
except AttributeError:
st.warning("Navigation is not supported in this version of Streamlit.")
if st.button("Sign Out", type="primary", key="sign_out"):
# Save any data before logging out
if "transactions" in st.session_state and "user" in st.session_state:
try:
email = st.session_state["user"]
metadata = {
"last_upload_filename": st.session_state.get("uploaded_file_name", "Unknown"),
"last_upload_timestamp": st.session_state.get("upload_timestamp", "Unknown"),
"upload_history": st.session_state.get("upload_history", [])
}
save_user_data(email, st.session_state["transactions"], metadata)
st.success("Your data has been saved.")
except Exception as e:
st.error(f"Could not save your data: {e}")
logout() # Immediately sign out the user/admin
st.rerun() # Use st.rerun() instead of st.stop() for cleaner page refresh