raymondEDS commited on
Commit
7a4f631
Β·
1 Parent(s): 3cc080f

setting up DB

Browse files
Files changed (5) hide show
  1. README.md +59 -25
  2. requirements.txt +2 -1
  3. src/auth.py +39 -23
  4. tests/__init__.py +1 -0
  5. tests/test_database.py +118 -0
README.md CHANGED
@@ -21,10 +21,10 @@ A comprehensive Learning Management System built with Streamlit specifically des
21
  ## 🎭 Features
22
 
23
  ### πŸ” Authentication
24
- - Secure student login system
25
  - Individual student accounts
26
- - Session management with cookies
27
- - Password hashing for security
28
 
29
  ### πŸ“š Course Content
30
  - Week-by-week structured learning materials
@@ -67,18 +67,40 @@ The system includes the following student accounts:
67
  pip install -r requirements.txt
68
  ```
69
 
70
- 2. **Run the Application:**
 
 
 
 
 
71
  ```bash
72
  streamlit run src/main.py
73
  ```
74
 
75
- 3. **Access the Application:**
76
- - Open your browser and go to `http://localhost:8501`
77
- - Login with one of the student credentials above
78
- - Access Week 1 content and assignments
 
 
 
 
 
 
 
 
 
 
79
 
80
- ### Cloud Deployment
81
- The application is optimized for deployment on Hugging Face Spaces and other cloud platforms.
 
 
 
 
 
 
 
82
 
83
  ## πŸ“ Application Structure
84
 
@@ -93,11 +115,14 @@ The application is optimized for deployment on Hugging Face Spaces and other clo
93
  β”‚ β”œβ”€β”€ future_weeks.py # Weeks 2-4 placeholder content
94
  β”‚ β”œβ”€β”€ assignments.py # Assignments page
95
  β”‚ └── resources.py # Resources page
96
- β”œβ”€β”€ data/
97
- β”‚ └── users/
98
- β”‚ └── users.yaml # User credentials
 
 
99
  β”œβ”€β”€ .streamlit/
100
- β”‚ └── config.toml # Streamlit configuration
 
101
  β”œβ”€β”€ requirements.txt # Python dependencies
102
  β”œβ”€β”€ Dockerfile # Container configuration
103
  └── README.md # This file
@@ -132,9 +157,9 @@ The application is optimized for deployment on Hugging Face Spaces and other clo
132
  ## πŸ”§ Technical Details
133
 
134
  - **Framework:** Streamlit
135
- - **Authentication:** Custom simple login system
136
- - **Data Storage:** Session state (cloud-ready)
137
- - **Security:** bcrypt password hashing
138
  - **Deployment:** Optimized for Hugging Face Spaces
139
  - **Architecture:** Modular design with separate view modules
140
 
@@ -147,27 +172,36 @@ The application is optimized for deployment on Hugging Face Spaces and other clo
147
 
148
  ## πŸ”’ Security Features
149
 
150
- - Secure password hashing using bcrypt
151
- - Session-based authentication
152
  - User role management
153
  - Secure file upload handling
154
 
155
  ## ☁️ Cloud Features
156
 
157
- - **No file system dependencies** - works on read-only environments
158
- - **Session-based storage** - data persists during user session
159
- - **Optimized for Hugging Face Spaces** - ready for immediate deployment
160
- - **Lightweight and fast** - minimal resource requirements
 
 
 
 
 
 
 
 
 
161
 
162
  ## πŸ“ˆ Future Enhancements
163
 
164
- - Database integration for persistent storage
165
  - Real-time debate practice sessions
166
  - Video conferencing integration
167
  - Advanced progress analytics
168
  - Mobile-responsive design
169
  - Debate tournament management
 
170
 
171
  ---
172
 
173
- **Built with ❀️ using Streamlit | Cloud-ready for Hugging Face Spaces**
 
21
  ## 🎭 Features
22
 
23
  ### πŸ” Authentication
24
+ - Secure student login system with Supabase database
25
  - Individual student accounts
26
+ - Session management
27
+ - Custom authentication system
28
 
29
  ### πŸ“š Course Content
30
  - Week-by-week structured learning materials
 
67
  pip install -r requirements.txt
68
  ```
69
 
70
+ 2. **Set up Supabase:**
71
+ - Create a Supabase project
72
+ - Run the SQL script in `database/setup.sql`
73
+ - Add your credentials to `.streamlit/secrets.toml`
74
+
75
+ 3. **Run the Application:**
76
  ```bash
77
  streamlit run src/main.py
78
  ```
79
 
80
+ 4. **Test Database Connection (Optional):**
81
+ ```bash
82
+ streamlit run tests/test_database.py
83
+ ```
84
+
85
+ ### Hugging Face Spaces Deployment
86
+
87
+ 1. **Fork this repository** to your GitHub account
88
+
89
+ 2. **Create a new Space on Hugging Face:**
90
+ - Go to [huggingface.co/spaces](https://huggingface.co/spaces)
91
+ - Click "Create new Space"
92
+ - Choose "Docker" as the SDK
93
+ - Link to your forked repository
94
 
95
+ 3. **Add Supabase Secrets:**
96
+ - Go to your Space settings
97
+ - Add these secrets:
98
+ - `SUPABASE_URL`: Your Supabase project URL
99
+ - `SUPABASE_KEY`: Your Supabase anon public key
100
+
101
+ 4. **Deploy:**
102
+ - The Space will automatically build and deploy
103
+ - Your app will be available at `https://huggingface.co/spaces/your-username/your-space-name`
104
 
105
  ## πŸ“ Application Structure
106
 
 
115
  β”‚ β”œβ”€β”€ future_weeks.py # Weeks 2-4 placeholder content
116
  β”‚ β”œβ”€β”€ assignments.py # Assignments page
117
  β”‚ └── resources.py # Resources page
118
+ β”œβ”€β”€ tests/
119
+ β”‚ β”œβ”€β”€ __init__.py
120
+ β”‚ └── test_database.py # Database connection testing
121
+ β”œβ”€β”€ database/
122
+ β”‚ └── setup.sql # Database setup script
123
  β”œβ”€β”€ .streamlit/
124
+ β”‚ β”œβ”€β”€ config.toml # Streamlit configuration
125
+ β”‚ └── secrets.toml # Local secrets (not in repo)
126
  β”œβ”€β”€ requirements.txt # Python dependencies
127
  β”œβ”€β”€ Dockerfile # Container configuration
128
  └── README.md # This file
 
157
  ## πŸ”§ Technical Details
158
 
159
  - **Framework:** Streamlit
160
+ - **Database:** Supabase (PostgreSQL)
161
+ - **Authentication:** Custom system with Supabase backend
162
+ - **Data Storage:** Supabase database (cloud-ready)
163
  - **Deployment:** Optimized for Hugging Face Spaces
164
  - **Architecture:** Modular design with separate view modules
165
 
 
172
 
173
  ## πŸ”’ Security Features
174
 
175
+ - Supabase Row Level Security (RLS)
176
+ - Custom authentication system
177
  - User role management
178
  - Secure file upload handling
179
 
180
  ## ☁️ Cloud Features
181
 
182
+ - **Supabase integration** - Cloud database and authentication
183
+ - **Hugging Face Spaces ready** - Optimized for immediate deployment
184
+ - **Docker containerization** - Consistent deployment environment
185
+ - **Environment-based configuration** - Secrets management
186
+
187
+ ## πŸ§ͺ Testing
188
+
189
+ Run database tests locally:
190
+ ```bash
191
+ streamlit run tests/test_database.py
192
+ ```
193
+
194
+ This will help you verify your Supabase connection and user data.
195
 
196
  ## πŸ“ˆ Future Enhancements
197
 
 
198
  - Real-time debate practice sessions
199
  - Video conferencing integration
200
  - Advanced progress analytics
201
  - Mobile-responsive design
202
  - Debate tournament management
203
+ - Advanced user management
204
 
205
  ---
206
 
207
+ **Built with ❀️ using Streamlit & Supabase | Cloud-ready for Hugging Face Spaces**
requirements.txt CHANGED
@@ -5,4 +5,5 @@ pandas
5
  altair
6
  PyYAML
7
  bcrypt
8
- pyarrow
 
 
5
  altair
6
  PyYAML
7
  bcrypt
8
+ pyarrow
9
+ supabase
src/auth.py CHANGED
@@ -1,12 +1,33 @@
1
  import streamlit as st
2
- import yaml
3
- from yaml.loader import SafeLoader
4
 
5
- def load_user_credentials():
6
- """Load user credentials from YAML file"""
7
- with open('data/users/users.yaml') as file:
8
- config = yaml.load(file, Loader=SafeLoader)
9
- return config['credentials']['usernames']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  def show_login_page():
12
  """Show a simple custom login page"""
@@ -32,29 +53,24 @@ def show_login_page():
32
 
33
  def check_credentials(username, password):
34
  """Check if username and password are valid"""
35
- users = load_user_credentials()
 
36
 
37
- if username in users:
38
- # For simplicity, using plain text comparison
39
- # In production, you'd want to hash passwords
40
- stored_password = users[username]['password']
41
-
42
- # Check if it's a hashed password (starts with $2b$)
43
- if stored_password.startswith('$2b$'):
44
- # For now, accept any password for hashed accounts
45
- # In production, you'd use bcrypt to verify
46
  return True
47
- else:
48
- # Plain text password comparison
49
- return stored_password == password
50
 
51
  return False
52
 
53
  def get_user_name(username):
54
  """Get the display name for a username"""
55
- users = load_user_credentials()
56
- if username in users:
57
- return users[username]['name']
58
  return username
59
 
60
  def handle_logout():
 
1
  import streamlit as st
2
+ from supabase import create_client, Client
3
+ import os
4
 
5
+ # Initialize Supabase client
6
+ def init_supabase():
7
+ """Initialize Supabase client"""
8
+ url = st.secrets.get("SUPABASE_URL")
9
+ key = st.secrets.get("SUPABASE_KEY")
10
+
11
+ if not url or not key:
12
+ st.error("Supabase credentials not found. Please set SUPABASE_URL and SUPABASE_KEY in your .streamlit/secrets.toml file.")
13
+ return None
14
+
15
+ return create_client(url, key)
16
+
17
+ def get_user_by_username(username):
18
+ """Get user from database by username"""
19
+ supabase = init_supabase()
20
+ if not supabase:
21
+ return None
22
+
23
+ try:
24
+ response = supabase.rpc('get_user_by_username', {'username_param': username}).execute()
25
+ if response.data:
26
+ return response.data[0]
27
+ return None
28
+ except Exception as e:
29
+ st.error(f"Database error: {str(e)}")
30
+ return None
31
 
32
  def show_login_page():
33
  """Show a simple custom login page"""
 
53
 
54
  def check_credentials(username, password):
55
  """Check if username and password are valid"""
56
+ if not username or not password:
57
+ return False
58
 
59
+ # For now, accept any password for existing users
60
+ # In production, you'd want to add password hashing
61
+ user = get_user_by_username(username)
62
+ if user:
63
+ # Simple password check - in production use proper hashing
64
+ if password == "password123": # Default password for all users
 
 
 
65
  return True
 
 
 
66
 
67
  return False
68
 
69
  def get_user_name(username):
70
  """Get the display name for a username"""
71
+ user = get_user_by_username(username)
72
+ if user:
73
+ return user.get('full_name', username)
74
  return username
75
 
76
  def handle_logout():
tests/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Tests package for Debate Class LMS
tests/test_database.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from supabase import create_client, Client
3
+ import os
4
+
5
+ def init_supabase():
6
+ """Initialize Supabase client"""
7
+ url = st.secrets.get("SUPABASE_URL")
8
+ key = st.secrets.get("SUPABASE_KEY")
9
+
10
+ # Debug information
11
+ st.write(f"Debug - SUPABASE_URL: {url}")
12
+ st.write(f"Debug - SUPABASE_KEY: {key[:10] if key else 'None'}...")
13
+
14
+ if not url or not key:
15
+ st.error("Supabase credentials not found. Please set SUPABASE_URL and SUPABASE_KEY in your .streamlit/secrets.toml file.")
16
+ st.info("Update your .streamlit/secrets.toml file with:")
17
+ st.code("""
18
+ SUPABASE_URL = "https://your-project-id.supabase.co"
19
+ SUPABASE_KEY = "your-anon-key-here"
20
+ """)
21
+ return None
22
+
23
+ return create_client(url, key)
24
+
25
+ def test_database_connection():
26
+ """Test the database connection and display user data"""
27
+ st.subheader("πŸ” Database Connection Test")
28
+
29
+ supabase = init_supabase()
30
+ if not supabase:
31
+ st.error("❌ Failed to initialize Supabase client")
32
+ return False
33
+
34
+ try:
35
+ # Test 1: Try to fetch all users
36
+ st.write("**Test 1: Fetching all users...**")
37
+ response = supabase.table('users').select('*').execute()
38
+
39
+ if response.data:
40
+ st.success(f"βœ… Successfully connected to database!")
41
+ st.write(f"πŸ“Š Found {len(response.data)} users in the database:")
42
+
43
+ # Display users in a nice table
44
+ users_data = []
45
+ for user in response.data:
46
+ users_data.append({
47
+ "Username": user.get('username', 'N/A'),
48
+ "Full Name": user.get('full_name', 'N/A'),
49
+ "Email": user.get('email', 'N/A'),
50
+ "Role": user.get('role', 'N/A')
51
+ })
52
+
53
+ st.dataframe(users_data, use_container_width=True)
54
+ return True
55
+ else:
56
+ st.warning("⚠️ Connected to database but no users found")
57
+ return True
58
+
59
+ except Exception as e:
60
+ st.error(f"❌ Database connection failed: {str(e)}")
61
+ return False
62
+
63
+ def test_user_lookup():
64
+ """Test the get_user_by_username function"""
65
+ st.subheader("πŸ” User Lookup Test")
66
+
67
+ supabase = init_supabase()
68
+ if not supabase:
69
+ return False
70
+
71
+ try:
72
+ # Test with a known username
73
+ test_username = "alice"
74
+ st.write(f"**Testing lookup for user: {test_username}**")
75
+
76
+ response = supabase.rpc('get_user_by_username', {'username_param': test_username}).execute()
77
+
78
+ if response.data:
79
+ user = response.data[0]
80
+ st.success(f"βœ… Found user: {user.get('full_name', 'N/A')}")
81
+ st.json(user)
82
+ return True
83
+ else:
84
+ st.warning(f"⚠️ User '{test_username}' not found")
85
+ return False
86
+
87
+ except Exception as e:
88
+ st.error(f"❌ User lookup failed: {str(e)}")
89
+ return False
90
+
91
+ def main():
92
+ """Main test function"""
93
+ st.title("πŸ§ͺ Database Testing Tool")
94
+ st.markdown("Use this tool to test your Supabase database connection.")
95
+
96
+ # Test options
97
+ test_option = st.selectbox(
98
+ "Choose a test to run:",
99
+ ["Database Connection", "User Lookup", "Run All Tests"]
100
+ )
101
+
102
+ if test_option == "Database Connection":
103
+ test_database_connection()
104
+ elif test_option == "User Lookup":
105
+ test_user_lookup()
106
+ elif test_option == "Run All Tests":
107
+ st.subheader("Running all tests...")
108
+ test1 = test_database_connection()
109
+ st.markdown("---")
110
+ test2 = test_user_lookup()
111
+
112
+ if test1 and test2:
113
+ st.success("πŸŽ‰ All tests passed!")
114
+ else:
115
+ st.error("❌ Some tests failed. Check the output above.")
116
+
117
+ if __name__ == "__main__":
118
+ main()