Spaces:
Sleeping
Sleeping
File size: 5,541 Bytes
2d25973 623afbc 2d25973 623afbc 2d25973 9379bde 2d25973 623afbc 2d25973 623afbc 2d25973 623afbc 2d25973 623afbc 2d25973 623afbc 01a77aa 623afbc | 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 | import streamlit as st
import re
import time
from ..database import database
from ..auth import oauth
def validate_email(email):
pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
return re.match(pattern, email) is not None
def validate_password_complexity(password):
if len(password) < 8:
return False, "Password must be at least 8 characters long."
if not re.search(r"[A-Z]", password):
return False, "Password must contain at least one uppercase letter."
if not re.search(r"[a-z]", password):
return False, "Password must contain at least one lowercase letter."
if not re.search(r"\d", password):
return False, "Password must contain at least one digit."
return True, ""
def handle_oauth_callback():
query_params = st.query_params
if "code" in query_params and "state" in query_params and st.session_state.user_id is None:
code = query_params["code"]
state = query_params["state"]
st.write(f"Authenticating with {state.capitalize()}...")
if state == "github":
email = oauth.get_github_user(code)
else:
email = None
if email:
try:
success, uid = database.authenticate_oauth_user(email, state)
if success:
st.session_state.user_id = uid
st.query_params.clear()
st.rerun()
else:
st.error("Failed to authenticate with provider.")
st.query_params.clear()
except Exception as e:
st.error("Database connection failed. Please try again.")
st.query_params.clear()
else:
st.error(f"Failed to authenticate with {state.capitalize()}")
st.query_params.clear()
def render_login_signup_form():
st.title("AI Study Notes Agent 📚")
st.write("Please log in or sign up to continue.")
# Initialize rate limiting state
if "login_attempts" not in st.session_state:
st.session_state.login_attempts = 0
if "lockout_time" not in st.session_state:
st.session_state.lockout_time = None
# Check if locked out
if st.session_state.lockout_time:
if time.time() < st.session_state.lockout_time:
st.error(f"Too many failed attempts. Please try again in {int(st.session_state.lockout_time - time.time())} seconds.")
return
else:
# Reset lockout
st.session_state.login_attempts = 0
st.session_state.lockout_time = None
st.markdown(f'<a href="{oauth.get_github_auth_url()}" target="_self"><button style="width:100%; padding:10px; background-color:#333; color:white; border:none; border-radius:5px; cursor:pointer;">⚫ Continue with GitHub</button></a>', unsafe_allow_html=True)
st.divider()
st.write("Or use Email and Password:")
tab1, tab2 = st.tabs(["Login", "Sign Up"])
with tab1:
with st.form("login_form"):
email = st.text_input("Email")
password = st.text_input("Password", type="password")
if st.form_submit_button("Login"):
email = email.strip().lower()
if not email or not password:
st.error("Please fill in both fields.")
else:
try:
success, result = database.authenticate_user(email, password)
if success:
st.session_state.login_attempts = 0
st.session_state.user_id = result
st.rerun()
else:
st.session_state.login_attempts += 1
if st.session_state.login_attempts >= 5:
st.session_state.lockout_time = time.time() + 180 # 3 minutes lockout
st.error("Too many failed attempts. You have been locked out for 3 minutes.")
else:
st.error(result)
except Exception as e:
st.error("Could not reach the database. Please try again.")
with tab2:
with st.form("signup_form"):
new_email = st.text_input("New Email")
new_password = st.text_input("New Password", type="password")
if st.form_submit_button("Sign Up"):
new_email = new_email.strip().lower()
if not validate_email(new_email):
st.error("Please enter a valid email address.")
else:
is_valid, msg = validate_password_complexity(new_password)
if not is_valid:
st.error(msg)
else:
try:
success, result = database.create_user(new_email, new_password)
if success:
user = database.get_user_by_email(new_email)
st.session_state.login_attempts = 0
st.session_state.user_id = user["id"]
st.rerun()
else:
st.error(result)
except Exception as e:
st.error("Could not reach the database. Please try again.")
|