SimplifAI / app.py
JSenkCC's picture
Update app.py
8d23e61 verified
raw
history blame
7.76 kB
import streamlit as st
import sqlite3
import hashlib
import os
import zipfile
from git import Repo
# Database setup
DB_FILE = "users.db"
def create_user_table():
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
username TEXT PRIMARY KEY,
password TEXT
)
""")
conn.commit()
conn.close()
def add_user(username, password):
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
hashed_password = hashlib.sha256(password.encode()).hexdigest()
try:
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
conn.commit()
except sqlite3.IntegrityError:
st.error("Username already exists. Please choose a different username.")
conn.close()
def authenticate_user(username, password):
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
hashed_password = hashlib.sha256(password.encode()).hexdigest()
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, hashed_password))
user = cursor.fetchone()
conn.close()
return user
# Main application
def main():
st.title("SimplifAI")
# Initialize database
create_user_table()
# Manage session state
if "authenticated" not in st.session_state:
st.session_state.authenticated = False
if "username" not in st.session_state:
st.session_state.username = None
if "page" not in st.session_state:
st.session_state.page = "login"
# Page routing logic
if st.session_state.page == "login":
login_page()
elif st.session_state.page == "workspace":
workspace_page()
def login_page():
st.subheader("Please Log In or Register to Continue")
auth_mode = st.radio("Choose an Option", ["Log In", "Register"], horizontal=True)
if auth_mode == "Log In":
st.subheader("Log In")
username = st.text_input("Username", key="login_username")
password = st.text_input("Password", type="password", key="login_password")
# Handle single-click login
if st.button("Log In"):
if authenticate_user(username, password):
st.session_state.authenticated = True
st.session_state.username = username
st.session_state.page = "workspace"
else:
st.error("Invalid username or password. Please try again.")
elif auth_mode == "Register":
st.subheader("Register")
username = st.text_input("Create Username", key="register_username")
password = st.text_input("Create Password", type="password", key="register_password")
# Handle single-click registration
if st.button("Register"):
if username and password:
add_user(username, password)
st.success("Account created successfully! You can now log in.")
else:
st.error("Please fill in all fields.")
def workspace_page():
# Sidebar with logout button
st.sidebar.title(f"Hello, {st.session_state.username}!")
if st.sidebar.button("Log Out"):
st.session_state.authenticated = False
st.session_state.username = None
st.session_state.page = "login"
# User's folder for projects
user_folder = os.path.join("user_projects", st.session_state.username)
os.makedirs(user_folder, exist_ok=True)
# Refresh project list dynamically
projects = [d for d in os.listdir(user_folder) if os.path.isdir(os.path.join(user_folder, d))]
# Display "Projects" dropdown
selected_project = st.sidebar.selectbox("Projects", ["Select a project"] + projects)
if selected_project != "Select a project":
st.session_state.current_project = selected_project
st.session_state.page = "project_view"
# Main content area
st.subheader("Workspace")
st.write("You can create a new project by uploading files or folders, or by cloning a GitHub repository.")
# User action selection
action = st.radio("Choose an action", ["Upload Files or Folders", "Clone GitHub Repository"], horizontal=True)
project_name = st.text_input("Enter a project name")
if action == "Upload Files or Folders":
st.subheader("Upload Files or Folders")
uploaded_files = st.file_uploader(
"Upload one or more files or a .zip archive for folders", accept_multiple_files=True
)
if uploaded_files and project_name:
if st.button("Upload Project"):
project_folder = os.path.join(user_folder, project_name)
os.makedirs(project_folder, exist_ok=True)
for uploaded_file in uploaded_files:
# Save uploaded .zip files or regular files
file_path = os.path.join(project_folder, uploaded_file.name)
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
# If a .zip file is uploaded, extract its contents
if uploaded_file.name.endswith(".zip"):
try:
with zipfile.ZipFile(file_path, "r") as zip_ref:
zip_ref.extractall(project_folder)
os.remove(file_path) # Remove the .zip file after extraction
st.success(f"Folder from {uploaded_file.name} extracted successfully!")
except zipfile.BadZipFile:
st.error(f"File {uploaded_file.name} is not a valid .zip file.")
else:
st.success(f"File {uploaded_file.name} saved successfully!")
st.success(f"Project '{project_name}' uploaded successfully!")
# Trigger a rerun to update the dropdown
st.rerun()
elif action == "Clone GitHub Repository":
st.subheader("Clone GitHub Repository")
repo_url = st.text_input("Enter the GitHub repository URL")
if repo_url and project_name:
if st.button("Upload Project"):
project_folder = os.path.join(user_folder, project_name)
os.makedirs(project_folder, exist_ok=True)
try:
Repo.clone_from(repo_url, project_folder)
st.success(f"Project '{project_name}' cloned successfully!")
# Trigger a rerun to update the dropdown
st.rerun()
except Exception as e:
st.error(f"Failed to clone repository: {e}")
def project_view_page():
# Sidebar with logout and return buttons
st.sidebar.title(f"Project: {st.session_state.current_project}")
if st.sidebar.button("Back to Workspace"):
st.session_state.page = "workspace"
if st.sidebar.button("Log Out"):
st.session_state.authenticated = False
st.session_state.username = None
st.session_state.page = "login"
# Display project file structure
st.subheader(f"Project: {st.session_state.current_project}")
user_folder = os.path.join("user_projects", st.session_state.username)
project_folder = os.path.join(user_folder, st.session_state.current_project)
st.write("File structure:")
for root, dirs, files in os.walk(project_folder):
level = root.replace(project_folder, "").count(os.sep)
indent = " " * 4 * level
st.text(f"{indent}{os.path.basename(root)}/")
sub_indent = " " * 4 * (level + 1)
for file in files:
st.text(f"{sub_indent}{file}")
if __name__ == "__main__":
main()